subgraph/data_sources/sql/services/update_many/
mod.rs

1use log::{debug, error, trace};
2use sqlx::Row;
3
4use crate::{
5    configuration::subgraph::entities::ServiceEntityConfig,
6    data_sources::sql::{PoolEnum, SqlQuery},
7    sql_value::SqlValue,
8    utils::clean_string::{clean_string, CleanOptions},
9};
10
11use super::{ResponseRow, Services};
12
13impl Services {
14    pub async fn update_many(
15        entity: &ServiceEntityConfig,
16        pool_enum: &PoolEnum,
17        sql_query: &SqlQuery,
18    ) -> Result<Vec<Option<ResponseRow>>, async_graphql::Error> {
19        debug!("Update Many SQL Data Source");
20
21        let clean_options = CleanOptions {
22            newline: Some(false),
23            quotes: Some(true),
24        };
25        match pool_enum {
26            PoolEnum::MySql(pool) => {
27                let identifier_query = match &sql_query.identifier_query {
28                    Some(query) => query,
29                    None => {
30                        error!(
31                            "Identifier query not found for update_many on {}",
32                            entity.name
33                        );
34                        return Err(async_graphql::Error::new(format!(
35                            "Identifier query not found for update_many on {}",
36                            entity.name
37                        )));
38                    }
39                };
40
41                let mut identifier_query = sqlx::query(&identifier_query);
42
43                let mut update_query = sqlx::query(&sql_query.query);
44                for value in &sql_query.values {
45                    match value {
46                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
47                            let v = clean_string(v, Some(clean_options.clone()));
48                            update_query = update_query.bind(v.clone());
49                        }
50                        SqlValue::Int(v) => {
51                            update_query = update_query.bind(v);
52                        }
53                        SqlValue::Bool(v) => {
54                            update_query = update_query.bind(v);
55                        }
56                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
57                            for v in values {
58                                let v = clean_string(v, Some(clean_options.clone()));
59                                update_query = update_query.bind(v.clone());
60                            }
61                        }
62                        SqlValue::IntList(values) => {
63                            for int in values {
64                                update_query = update_query.bind(int);
65                            }
66                        }
67                        SqlValue::BoolList(values) => {
68                            for bool in values {
69                                update_query = update_query.bind(bool);
70                            }
71                        }
72                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
73                        SqlValue::UUIDList(uuids) => {
74                            for uuid in uuids {
75                                update_query = update_query.bind(uuid);
76                            }
77                        }
78                        SqlValue::DateTime(date_time) => {
79                            update_query = update_query.bind(date_time);
80                        }
81                        SqlValue::DateTimeList(date_times) => {
82                            for date_time in date_times {
83                                update_query = update_query.bind(date_time);
84                            }
85                        }
86                    }
87                }
88                for value in &sql_query.where_values {
89                    match value {
90                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
91                            let v = clean_string(v, Some(clean_options.clone()));
92                            update_query = update_query.bind(v.clone());
93                            identifier_query = identifier_query.bind(v);
94                        }
95                        SqlValue::Int(v) => {
96                            update_query = update_query.bind(v);
97                            identifier_query = identifier_query.bind(v);
98                        }
99                        SqlValue::Bool(v) => {
100                            update_query = update_query.bind(v);
101                            identifier_query = identifier_query.bind(v);
102                        }
103                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
104                            for v in values {
105                                let v = clean_string(v, Some(clean_options.clone()));
106                                update_query = update_query.bind(v.clone());
107                                identifier_query = identifier_query.bind(v);
108                            }
109                        }
110                        SqlValue::IntList(values) => {
111                            for int in values {
112                                update_query = update_query.bind(int);
113                                identifier_query = identifier_query.bind(int);
114                            }
115                        }
116                        SqlValue::BoolList(values) => {
117                            for bool in values {
118                                update_query = update_query.bind(bool);
119                                identifier_query = identifier_query.bind(bool);
120                            }
121                        }
122                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
123                        SqlValue::UUIDList(uuids) => {
124                            for uuid in uuids {
125                                update_query = update_query.bind(uuid);
126                                identifier_query = identifier_query.bind(uuid);
127                            }
128                        }
129                        SqlValue::DateTime(date_time) => {
130                            update_query = update_query.bind(date_time);
131                            identifier_query = identifier_query.bind(date_time);
132                        }
133                        SqlValue::DateTimeList(date_times) => {
134                            for date_time in date_times {
135                                update_query = update_query.bind(date_time);
136                                identifier_query = identifier_query.bind(date_time);
137                            }
138                        }
139                    }
140                }
141
142                let identifier_results = identifier_query.fetch_all(pool).await.map_err(|e| {
143                    error!("Error executing identifier query: {}", e);
144                    e
145                })?;
146
147                update_query.execute(pool).await.map_err(|e| {
148                    error!("Error executing update many query: {}", e);
149                    e
150                })?;
151
152                let mut ids = Vec::new();
153                for row in identifier_results {
154                    trace!("Row: {:?}", row);
155                    let identifier: i64 = row.try_get("id").map_err(|e| {
156                        error!("Error getting primary key from row: {}", e);
157                        e
158                    })?;
159                    ids.push(identifier);
160                }
161
162                trace!("Identifiers: {:?}", ids);
163
164                if ids.is_empty() {
165                    return Ok(Vec::new());
166                }
167
168                let query = format!(
169                    "SELECT * FROM {} WHERE id IN ({});",
170                    sql_query.table,
171                    ids.iter()
172                        .map(|id| id.to_string())
173                        .collect::<Vec<String>>()
174                        .join(",")
175                );
176                trace!("Query: {}", query);
177
178                let response_query = sqlx::query(&query);
179
180                let rows = response_query.fetch_all(pool).await.map_err(|e| {
181                    error!("Error finding data: {}", e);
182                    e
183                })?;
184
185                let mut response_rows = Vec::new();
186
187                for row in rows {
188                    response_rows.push(Some(ResponseRow::MySql(row)));
189                }
190
191                Ok(response_rows)
192            }
193            PoolEnum::Postgres(pool) => {
194                let mut update_query = sqlx::query(&sql_query.query);
195                debug!("PG VALUES: {:?}", sql_query);
196                for value in &sql_query.values {
197                    match value {
198                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
199                            let v = clean_string(v, Some(clean_options.clone()));
200                            update_query = update_query.bind(v);
201                        }
202                        SqlValue::Int(v) => {
203                            update_query = update_query.bind(v);
204                        }
205                        SqlValue::Bool(v) => {
206                            update_query = update_query.bind(v);
207                        }
208                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
209                            for v in values {
210                                let v = clean_string(v, Some(clean_options.clone()));
211                                update_query = update_query.bind(v)
212                            }
213                        }
214                        SqlValue::IntList(values) => {
215                            for int in values {
216                                update_query = update_query.bind(int)
217                            }
218                        }
219                        SqlValue::BoolList(values) => {
220                            for bool in values {
221                                update_query = update_query.bind(bool)
222                            }
223                        }
224                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
225                        SqlValue::UUIDList(uuids) => {
226                            for uuid in uuids {
227                                update_query = update_query.bind(uuid)
228                            }
229                        }
230                        SqlValue::DateTime(date_time) => {
231                            update_query = update_query.bind(date_time)
232                        }
233                        SqlValue::DateTimeList(date_times) => {
234                            for date_time in date_times {
235                                update_query = update_query.bind(date_time)
236                            }
237                        }
238                    }
239                }
240                for value in &sql_query.where_values {
241                    match value {
242                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
243                            let v = clean_string(v, Some(clean_options.clone()));
244                            update_query = update_query.bind(v);
245                        }
246                        SqlValue::Int(v) => {
247                            update_query = update_query.bind(v);
248                        }
249                        SqlValue::Bool(v) => {
250                            update_query = update_query.bind(v);
251                        }
252                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
253                            for v in values {
254                                let v = clean_string(v, Some(clean_options.clone()));
255                                update_query = update_query.bind(v)
256                            }
257                        }
258                        SqlValue::IntList(values) => {
259                            for int in values {
260                                update_query = update_query.bind(int)
261                            }
262                        }
263                        SqlValue::BoolList(values) => {
264                            for bool in values {
265                                update_query = update_query.bind(bool)
266                            }
267                        }
268                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
269                        SqlValue::UUIDList(uuids) => {
270                            for uuid in uuids {
271                                update_query = update_query.bind(uuid)
272                            }
273                        }
274                        SqlValue::DateTime(date_time) => {
275                            update_query = update_query.bind(date_time)
276                        }
277                        SqlValue::DateTimeList(date_times) => {
278                            for date_time in date_times {
279                                update_query = update_query.bind(date_time)
280                            }
281                        }
282                    }
283                }
284
285                let rows = update_query.fetch_all(pool).await.map_err(|e| {
286                    error!("Error: {:?}", e);
287                    e
288                })?;
289
290                let mut response_rows = Vec::new();
291                for row in rows {
292                    response_rows.push(Some(ResponseRow::Postgres(row)));
293                }
294                Ok(response_rows)
295            }
296            PoolEnum::SqLite(pool) => {
297                let identifier_query = match &sql_query.identifier_query {
298                    Some(identifier_query) => identifier_query,
299                    None => {
300                        return Err(async_graphql::Error::new(
301                            "No identifier query provided for SQLite",
302                        ))
303                    }
304                };
305                let mut identifier_query = sqlx::query(identifier_query);
306                let mut update_query = sqlx::query(&sql_query.query);
307
308                //Bind the values first, example: SET title = ?
309                for value in &sql_query.values {
310                    match value {
311                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
312                            let v = clean_string(v, Some(clean_options.clone()));
313                            update_query = update_query.bind(v.clone());
314                        }
315                        SqlValue::Int(v) => {
316                            update_query = update_query.bind(v.clone());
317                        }
318                        SqlValue::Bool(v) => {
319                            update_query = update_query.bind(v);
320                        }
321                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
322                            for v in values {
323                                let v = clean_string(v, Some(clean_options.clone()));
324                                update_query = update_query.bind(v.clone());
325                            }
326                        }
327                        SqlValue::IntList(values) => {
328                            for int in values {
329                                update_query = update_query.bind(int);
330                            }
331                        }
332                        SqlValue::BoolList(values) => {
333                            for bool in values {
334                                update_query = update_query.bind(bool);
335                            }
336                        }
337                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
338                        SqlValue::UUIDList(uuids) => {
339                            for uuid in uuids {
340                                update_query = update_query.bind(uuid);
341                            }
342                        }
343                        SqlValue::DateTime(date_time) => {
344                            update_query = update_query.bind(date_time);
345                        }
346                        SqlValue::DateTimeList(date_times) => {
347                            for date_time in date_times {
348                                update_query = update_query.bind(date_time);
349                            }
350                        }
351                    }
352                }
353
354                // Bind the where values, example: WHERE id = ?
355                for value in &sql_query.where_values {
356                    match value {
357                        SqlValue::String(v) | SqlValue::ObjectID(v) => {
358                            let v = clean_string(v, Some(clean_options.clone()));
359                            update_query = update_query.bind(v.clone());
360                            identifier_query = identifier_query.bind(v);
361                        }
362                        SqlValue::Int(v) => {
363                            update_query = update_query.bind(v);
364                            identifier_query = identifier_query.bind(v);
365                        }
366                        SqlValue::Bool(v) => {
367                            update_query = update_query.bind(v);
368                            identifier_query = identifier_query.bind(v);
369                        }
370                        SqlValue::StringList(values) | SqlValue::ObjectIDList(values) => {
371                            for v in values {
372                                update_query = update_query.bind(v);
373                                identifier_query = identifier_query.bind(v);
374                            }
375                        }
376                        SqlValue::IntList(values) => {
377                            for int in values {
378                                update_query = update_query.bind(int);
379                                identifier_query = identifier_query.bind(int);
380                            }
381                        }
382                        SqlValue::BoolList(values) => {
383                            for bool in values {
384                                update_query = update_query.bind(bool);
385                                identifier_query = identifier_query.bind(bool);
386                            }
387                        }
388                        SqlValue::UUID(uuid) => update_query = update_query.bind(uuid),
389                        SqlValue::UUIDList(uuids) => {
390                            for uuid in uuids {
391                                update_query = update_query.bind(uuid);
392                                identifier_query = identifier_query.bind(uuid);
393                            }
394                        }
395                        SqlValue::DateTime(date_time) => {
396                            update_query = update_query.bind(date_time);
397                            identifier_query = identifier_query.bind(date_time);
398                        }
399                        SqlValue::DateTimeList(date_times) => {
400                            for date_time in date_times {
401                                update_query = update_query.bind(date_time);
402                                identifier_query = identifier_query.bind(date_time);
403                            }
404                        }
405                    }
406                }
407
408                // Construct a query to get the updated data
409                let identifer_results = identifier_query.fetch_all(pool).await.map_err(|e| {
410                    error!("Error: {:?}", e);
411                    e
412                })?;
413
414                update_query.execute(pool).await.map_err(|e| {
415                    error!("Error: {:?}", e);
416                    e
417                })?;
418
419                let mut ids = vec![];
420                for row in identifer_results {
421                    let id: i64 = row.try_get("id")?;
422                    ids.push(id);
423                }
424
425                if ids.is_empty() {
426                    return Ok(vec![]);
427                }
428
429                let query = format!(
430                    "SELECT * FROM {} WHERE id IN ({})",
431                    sql_query.table,
432                    ids.iter()
433                        .map(|id| id.to_string())
434                        .collect::<Vec<String>>()
435                        .join(",")
436                );
437
438                let response_query = sqlx::query(&query);
439
440                let rows = response_query.fetch_all(pool).await.map_err(|e| {
441                    error!("Error finding data: {}", e);
442                    e
443                })?;
444
445                let mut response_rows = Vec::new();
446
447                for row in rows {
448                    response_rows.push(Some(ResponseRow::SqLite(row)));
449                }
450
451                Ok(response_rows)
452            }
453        }
454    }
455}