use serde::Deserialize; use anyhow::Error; use anyhow::Result; use diesel::ExpressionMethods; use diesel::RunQueryDsl; use diesel::query_dsl::methods::FilterDsl; use diesel::Connection; use crate::db::DbPool; use crate::schema::streets; #[derive(Debug, Deserialize, diesel::Identifiable, diesel::Queryable, getset::Getters)] #[table_name = "streets"] pub struct Street { pub(super) id: i32, #[getset(get = "pub")] name: String, } #[derive(Insertable)] #[table_name = "streets"] struct NewStreet<'a> { name: &'a str } impl Street { pub fn create_or_fetch(db: &DbPool, name: &str) -> Result { use crate::schema; let conn = db.get()?; conn.transaction::<_, Error, _>(|| { let new_street = NewStreet { name }; diesel::insert_into(schema::streets::table) .values(&new_street) .on_conflict_do_nothing() .execute(&conn)?; schema::streets::table .filter(schema::streets::name.eq(name)) .first::(&conn) .map_err(Error::from) }) } }