gluesql_core/executor/
delete.rs1use {
2 super::{
3 Payload, Referencing,
4 fetch::{fetch, fetch_columns},
5 },
6 crate::{
7 ast::{BinaryOperator, Expr, ForeignKey, ReferentialAction},
8 result::{Error, Result},
9 store::{GStore, GStoreMut},
10 },
11 futures::stream::{StreamExt, TryStreamExt},
12 serde::Serialize,
13 std::sync::Arc,
14 thiserror::Error as ThisError,
15};
16
17#[derive(ThisError, Serialize, Debug, PartialEq, Eq)]
18pub enum DeleteError {
19 #[error("referencing column exists: {0}")]
20 ReferencingColumnExists(String),
21
22 #[error("Value not found on column: {0}")]
23 ValueNotFound(String),
24}
25
26pub async fn delete<T: GStore + GStoreMut>(
27 storage: &mut T,
28 table_name: &str,
29 selection: Option<&Expr>,
30) -> Result<Payload> {
31 let columns = fetch_columns(storage, table_name).await?.map(Arc::from);
32 let referencings = storage.fetch_referencings(table_name).await?;
33 let keys = fetch(storage, table_name, columns, selection)
34 .await?
35 .into_stream()
36 .then(|item| async {
37 let (key, row) = item?;
38
39 for Referencing {
40 table_name: referencing_table_name,
41 foreign_key:
42 ForeignKey {
43 referencing_column_name,
44 referenced_column_name,
45 on_delete,
46 ..
47 },
48 } in &referencings
49 {
50 let value = row
51 .get_value(referenced_column_name)
52 .ok_or(DeleteError::ValueNotFound(referenced_column_name.clone()))?
53 .clone();
54
55 let expr = &Expr::BinaryOp {
56 left: Box::new(Expr::Identifier(referencing_column_name.clone())),
57 op: BinaryOperator::Eq,
58 right: Box::new(Expr::Value(value)),
59 };
60
61 let columns = Some(Arc::from(Vec::new()));
62 let referencing_rows =
63 fetch(storage, referencing_table_name, columns, Some(expr)).await?;
64
65 let referencing_row_exists = Box::pin(referencing_rows).next().await.is_some();
66 if referencing_row_exists && on_delete == &ReferentialAction::NoAction {
67 return Err(DeleteError::ReferencingColumnExists(format!(
68 "{referencing_table_name}.{referencing_column_name}"
69 ))
70 .into());
71 }
72 }
73
74 Ok::<_, Error>(key)
75 })
76 .try_collect::<Vec<_>>()
77 .await?;
78 let num_keys = keys.len();
79
80 storage
81 .delete_data(table_name, keys)
82 .await
83 .map(|()| Payload::Delete(num_keys))
84}