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 diesel::BoolExpressionMethods; use crate::db::DbPool; use crate::model::City; use crate::model::Country; use crate::model::Street; use crate::schema::address; #[derive(Debug, Deserialize, diesel::Associations, diesel::Queryable, getset::CopyGetters)] #[belongs_to(Country)] #[belongs_to(City)] #[belongs_to(Street)] #[table_name = "address"] pub struct Address { id: i32, country_id: i32, city_id: i32, street_id: i32, #[getset(get_copy = "pub")] addr_number: i32, } #[derive(Insertable)] #[table_name = "address"] struct NewAddress { country_id: i32, city_id: i32, street_id: i32, addr_number: i32, } impl Address { pub fn create_or_fetch(db: &DbPool, country: &Country, city: &City, street: &Street, number: i32) -> Result { use crate::schema; let conn = db.get()?; conn.transaction::<_, Error, _>(|| { let new_address = NewAddress { country_id: country.id, city_id: city.id, street_id: street.id, addr_number: number, }; diesel::insert_into(schema::address::table) .values(&new_address) .on_conflict_do_nothing() .execute(&conn)?; schema::address::table .filter({ schema::address::country_id.eq(country.id) .and(schema::address::city_id.eq(city.id)) .and(schema::address::street_id.eq(street.id)) .and(schema::address::addr_number.eq(number)) }) .first::
(&conn) .map_err(Error::from) }) } }