08_composite/
08-composite.rs1#[derive(Clone, Debug, elephantry::Composite)]
2pub struct Department {
3 department_id: i32,
4 name: String,
5 parent_id: Option<i32>,
6}
7
8mod employee {
9 #[derive(Debug, elephantry::Entity)]
10 #[elephantry(model = "Model", structure = "Structure", relation = "employee")]
11 pub struct Entity {
12 #[elephantry(pk)]
13 pub employee_id: i32,
14 pub first_name: String,
15 pub last_name: String,
16 pub birth_date: chrono::NaiveDate,
17 pub is_manager: bool,
18 pub day_salary: bigdecimal::BigDecimal,
19 #[elephantry(virtual)]
20 pub departments: Vec<super::Department>,
21 }
22
23 impl Model {
24 pub fn employee_with_department(&self, id: i32) -> elephantry::Result<Entity> {
25 use elephantry::{Model, Projectable};
26
27 let employee_projection = Self::create_projection()
28 .unset_field("department_id")
29 .add_field("departments", "array_agg(depts)")
30 .alias("e")
31 .to_string();
32
33 let employee = <Self as elephantry::Model>::Structure::relation();
34
35 let sql = format!(
36 r#"
37with recursive
38 depts (department_id, name, parent_id) as (
39 select d.department_id, d.name, d.parent_id from department d join {employee} e using(department_id) where e.employee_id = $1
40 union all
41 select d.department_id, d.name, d.parent_id from depts parent join department d on parent.parent_id = d.department_id
42 )
43select {employee_projection}
44 from {employee} e, depts
45 where e.employee_id = $1
46 group by e.employee_id
47"#
48 );
49
50 Ok(self.connection.query::<Entity>(&sql, &[&id])?.get(0))
51 }
52 }
53}
54
55fn main() -> elephantry::Result {
56 env_logger::init();
57
58 let database_url =
59 std::env::var("DATABASE_URL").unwrap_or_else(|_| "postgres://localhost".to_string());
60 let elephantry = elephantry::Pool::new(&database_url)?;
61 elephantry.execute(include_str!("structure.sql"))?;
62
63 let employee_with_department = elephantry
64 .model::<employee::Model>()
65 .employee_with_department(1)?;
66 dbg!(employee_with_department);
67
68 Ok(())
69}