A simple ORM for use with sqlx and postgres
use model::{Model, Enum, Related, RelationDef};
#[derive(Clone, sqlx::FromRow, Model)]
#[model(table_name = "bakery", has_relations)]
struct Bakery {
#[model(id)]
id: Uuid,
#[model(primary_key)]
name: String
}
#[derive(Clone, sqlx::FromRow, Model)]
#[model(table_name = "cake", has_relations)]
struct Cake {
#[model(id)]
id: Uuid,
bakery_id: Uuid,
#[model(enum, primary_key)]
cake_type: CakeType
#[model(primary_key)]
name: String
}
#[derive(Clone, Enum)]
enum CakeType {
ButterCake,
SpongeCake,
}
#[derive(Clone, sqlx::FromRow, Model)]
#[model(table_name = "topping", has_relations)]
struct Topping {
#[model(id, primary_key)]
id: Uuid,
name: String
}
// ...continued from above
impl Related for Bakery {
fn relation_definitions() -> Vec<RelationDef> {
vec![
Self::has_many::<Cake>("cakes", "bakery_id")
]
}
}
impl Related for Cake {
fn relation_definitions() -> Vec<RelationDef> {
vec![
Self::belongs_to::<Bakery>("bakery", "bakery_id"),
Self::has_many_via::<Topping>("toppings", "cake_topping"),
]
}
}
impl Related for Topping {
fn relation_definitions() -> Vec<RelationDef> {
vec![
Self::has_many_via::<Cake>("cakes", "cake_topping"),
]
}
}
// ...continued from above
let pool = sqlx::PgPool::connect("db_uri").await.unwrap();
let mut conn = pool.acquire().await.unwrap();
let bakery = Bakery {
id: Uuid::new_v4(),
name: "Awesome Bakery".into()
};
let bakery = bakery
.create()
.execute(&mut conn)
.await
.unwrap();
let mut another_bakery_with_same_primary_key = Bakery {
id: Uuid::new_v4(),
name: "Awesome Bakery".into()
};
assert_neq!(bakery.id, another_bakery_with_same_primary_key.id);
let another_bakery_with_same_primary_key = another_bakery_with_same_primary_key
.upsert()
.execute(&mut conn)
.await
.unwrap();
assert_eq!(bakery.id, another_bakery_with_same_primary_key.id);
let cake = Cake {
id: Uuid::new_v4(),
bakery_id: bakery.id.clone(),
cake_type: CakeType::ButterCake,
name: "Southern Coconut Cake".into(),
}
let mut cake = cake.create()
.execute(&mut conn)
.await
.unwrap();
cake.name = "Western Coconut Cake".into();
cake
.update(&mut conn)
.await
.unwrap();
let topping = Topping {
id: Uuid::new_v4(),
name: "Coconut Flakes"
}
let topping = topping
.create()
.execute(&mut conn)
.await
.unwrap();
cake
.create_association("toppings", topping.id.clone())
.execute(&mut conn)
.await
.unwrap();
let butter_cakes_with_coconut_flakes = Cake::select()
.with_filter(
model::Filter::new()
.field("cake_type").eq(CakeType::ButterCake)
.and()
.field("toppings.name").eq("Coconut Flakes".to_string())
)
.fetch_page(&mut conn)
.await
.unwrap();
for cake in butter_cakes_with_coconut_flakes.nodes {
println!("{}", cake.name);
}
cake.delete().execute(&mut conn)
.await
.unwrap();