backend/model/entity/
drawings_impl.rs1use crate::model::dto::drawings_impl::{DrawingWithProps, UpdateDrawingWithProps};
4use crate::model::entity::drawings::Drawing;
5
6use crate::schema::{drawings, layers};
7
8use crate::model::entity::drawing_properties_impl::{insert_props, load_props_for, update_props};
9use diesel::pg::Pg;
10use diesel::query_dsl::methods::FilterDsl;
11use diesel::{debug_query, ExpressionMethods, QueryDsl, QueryResult};
12use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
13use log::debug;
14use uuid::Uuid;
15
16impl Drawing {
17 pub async fn find(
22 map_id: i64,
23 conn: &mut AsyncPgConnection,
24 ) -> QueryResult<Vec<DrawingWithProps>> {
25 let query = FilterDsl::filter(
26 drawings::table.left_join(layers::table),
27 layers::map_id.eq(map_id),
28 )
29 .select(drawings::all_columns)
30 .into_boxed::<Pg>();
31
32 debug!("{}", debug_query::<Pg, _>(&query));
33
34 let base_rows: Vec<Self> = query.load::<Self>(conn).await?;
35
36 let mut out = Vec::with_capacity(base_rows.len());
37 for drawing in base_rows {
38 let variants = load_props_for(&drawing, conn).await?;
39
40 out.push(DrawingWithProps { drawing, variants });
41 }
42
43 Ok(out)
44 }
45
46 pub async fn find_in_layer(
51 layer_id: Uuid,
52 conn: &mut AsyncPgConnection,
53 ) -> QueryResult<Vec<DrawingWithProps>> {
54 let base_rows: Vec<Self> =
55 FilterDsl::filter(drawings::table, drawings::layer_id.eq(layer_id))
56 .load::<Self>(conn)
57 .await?;
58
59 let mut out = Vec::with_capacity(base_rows.len());
61
62 for drawing in base_rows {
63 let variants = load_props_for(&drawing, conn).await?;
64 out.push(DrawingWithProps { drawing, variants });
65 }
66
67 Ok(out)
68 }
69
70 pub async fn create(
75 drawings: Vec<DrawingWithProps>,
76 conn: &mut AsyncPgConnection,
77 ) -> QueryResult<Vec<DrawingWithProps>> {
78 conn.transaction(|tx| {
79 Box::pin(async move {
80 let only_drawings: Vec<Self> =
81 drawings.iter().map(|dwp| dwp.drawing.clone()).collect();
82
83 let query = diesel::insert_into(drawings::table).values(&only_drawings);
84
85 debug!("{}", debug_query::<Pg, _>(&query));
86
87 let inserted: Vec<Self> = query.get_results(tx).await?;
88
89 for dwp in &drawings {
90 insert_props(tx, &dwp.variants).await?;
91 }
92
93 let result: Vec<DrawingWithProps> = inserted
94 .into_iter()
95 .zip(drawings.into_iter().map(|dwp| dwp.variants))
96 .map(|(drawing, props)| DrawingWithProps {
97 drawing,
98 variants: props,
99 })
100 .collect();
101
102 Ok(result)
103 })
104 })
105 .await
106 }
107
108 pub async fn update(
113 drawing_updates: Vec<UpdateDrawingWithProps>,
114 conn: &mut AsyncPgConnection,
115 ) -> QueryResult<Vec<DrawingWithProps>> {
116 conn.transaction(|tx| {
117 let drawing_updates = drawing_updates;
118 Box::pin(async move {
119 let ids: Vec<Uuid> = drawing_updates
120 .iter()
121 .map(|u| u.update_drawing.id)
122 .collect();
123
124 for u in drawing_updates {
125 diesel::update(drawings::table.find(u.update_drawing.id))
126 .set(&u.update_drawing)
127 .execute(tx)
128 .await?;
129 if let Some(props) = u.properties {
130 update_props(tx, props).await?;
131 }
132 }
133
134 let query = FilterDsl::filter(
135 drawings::table.select(drawings::all_columns),
136 drawings::id.eq_any(&ids),
137 );
138
139 debug!("{}", debug_query::<Pg, _>(&query));
140
141 let base_rows: Vec<Self> = query.load::<Self>(tx).await?;
142
143 let mut out = Vec::with_capacity(base_rows.len());
144 for drawing in base_rows {
145 let props = load_props_for(&drawing, tx).await?;
146 out.push(DrawingWithProps {
147 drawing,
148 variants: props,
149 });
150 }
151
152 Ok(out) as QueryResult<Vec<DrawingWithProps>>
153 })
154 })
155 .await
156 }
157
158 pub async fn delete_by_ids(ids: Vec<Uuid>, conn: &mut AsyncPgConnection) -> QueryResult<usize> {
163 let query = diesel::delete(FilterDsl::filter(drawings::table, drawings::id.eq_any(ids)));
164 debug!("{}", debug_query::<Pg, _>(&query));
165 query.execute(conn).await
166 }
167}