backend/model/entity/
drawings_impl.rs

1//! Contains the implementation of [`Drawing`].
2
3use diesel::pg::Pg;
4use diesel::query_dsl::methods::FilterDsl;
5use diesel::{debug_query, ExpressionMethods, QueryDsl, QueryResult};
6use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl};
7use futures_util::Future;
8use log::debug;
9use uuid::Uuid;
10
11use crate::model::entity::drawings::{Drawing, UpdateDrawing};
12use crate::schema::{drawings, layers};
13
14impl Drawing {
15    /// Get all drawings assosicated with one map.
16    ///
17    /// # Errors
18    /// * Unknown, diesel doesn't say why it might error.
19    pub async fn find(map_id: i32, conn: &mut AsyncPgConnection) -> QueryResult<Vec<Self>> {
20        let query = FilterDsl::filter(
21            drawings::table.left_join(layers::table),
22            layers::map_id.eq(map_id),
23        )
24        .select(drawings::all_columns)
25        .into_boxed();
26
27        debug!("{}", debug_query::<Pg, _>(&query));
28
29        query.load::<Self>(conn).await
30    }
31
32    /// Get all drawings saved in one layer.
33    ///
34    /// # Errors
35    /// * Unknown, diesel doesn't say why it might error.
36    pub async fn find_in_layer(
37        layer_id: Uuid,
38        conn: &mut AsyncPgConnection,
39    ) -> QueryResult<Vec<Self>> {
40        let query = FilterDsl::filter(drawings::table, drawings::layer_id.eq(layer_id));
41
42        debug!("{}", debug_query::<Pg, _>(&query));
43
44        query.load::<Self>(conn).await
45    }
46
47    /// Save new drawings into the database.
48    ///
49    /// # Errors
50    /// * Unknown, diesel doesn't say why it might error.
51    pub async fn create(
52        drawings: Vec<Self>,
53        conn: &mut AsyncPgConnection,
54    ) -> QueryResult<Vec<Self>> {
55        let query = diesel::insert_into(drawings::table).values(&drawings);
56
57        debug!("{}", debug_query::<Pg, _>(&query));
58
59        query.get_results::<Self>(conn).await
60    }
61
62    /// Replace existing drawings in the database.
63    ///
64    /// # Errors
65    /// * Unknown, diesel doesn't say why it might error.
66    pub async fn update(
67        drawing_updates: Vec<UpdateDrawing>,
68        conn: &mut AsyncPgConnection,
69    ) -> QueryResult<Vec<Self>> {
70        conn.transaction(|transaction| {
71            Box::pin(async {
72                let ids: Vec<Uuid> = drawing_updates.iter().map(|u| u.id).collect();
73
74                let futures = Self::do_update(drawing_updates, transaction);
75
76                futures_util::future::try_join_all(futures).await?;
77
78                let results = FilterDsl::filter(
79                    drawings::table.select(drawings::all_columns),
80                    drawings::id.eq_any(ids),
81                )
82                .load::<Self>(transaction)
83                .await?;
84
85                Ok(results) as QueryResult<Vec<Self>>
86            })
87        })
88        .await
89    }
90
91    /// Helper that performs the actual update of the drawings.
92    fn do_update(
93        updates: Vec<UpdateDrawing>,
94        conn: &mut AsyncPgConnection,
95    ) -> Vec<impl Future<Output = QueryResult<Self>>> {
96        let mut futures = Vec::with_capacity(updates.len());
97
98        for update in updates {
99            let updated_drawings = diesel::update(drawings::table.find(update.id))
100                .set(update)
101                .get_result::<Self>(conn);
102
103            futures.push(updated_drawings);
104        }
105
106        futures
107    }
108
109    /// Delete the drawings from the database.
110    ///
111    /// # Errors
112    /// * Unknown, diesel doesn't say why it might error.
113    pub async fn delete_by_ids(ids: Vec<Uuid>, conn: &mut AsyncPgConnection) -> QueryResult<usize> {
114        let query = diesel::delete(FilterDsl::filter(drawings::table, drawings::id.eq_any(ids)));
115        debug!("{}", debug_query::<Pg, _>(&query));
116        query.execute(conn).await
117    }
118}