Skip to main content

sql_middleware/query_builder/
dml.rs

1use crate::error::SqlMiddlewareDbError;
2use crate::executor::{
3    QueryTarget, QueryTargetKind, execute_dml_dispatch, execute_dml_prepared_dispatch,
4};
5use crate::pool::MiddlewarePoolConnection;
6use crate::translation::PrepareMode;
7use crate::types::RowValues;
8
9#[cfg(feature = "postgres")]
10use crate::postgres::typed::PgManager;
11#[cfg(feature = "sqlite")]
12use crate::sqlite::config::SqliteManager;
13#[cfg(feature = "turso")]
14use crate::typed_turso::TursoManager;
15#[cfg(any(feature = "postgres", feature = "sqlite", feature = "turso"))]
16use bb8::PooledConnection;
17
18use super::{QueryBuilder, translate_query_for_target};
19
20impl QueryBuilder<'_, '_> {
21    /// Execute a DML statement and return rows affected.
22    ///
23    /// # Errors
24    /// Returns an error if placeholder translation fails or the backend DML execution fails.
25    pub async fn dml(self) -> Result<usize, SqlMiddlewareDbError> {
26        let translated = translate_query_for_target(
27            &self.target,
28            self.sql.as_ref(),
29            self.params.as_ref(),
30            self.options,
31        );
32        let use_prepare = matches!(self.options.prepare, PrepareMode::Prepared);
33
34        match self.target {
35            QueryTarget {
36                kind: QueryTargetKind::Connection(conn),
37                ..
38            } => {
39                dml_on_connection(conn, translated.as_ref(), self.params.as_ref(), use_prepare)
40                    .await
41            }
42            #[cfg(feature = "sqlite")]
43            QueryTarget {
44                kind:
45                    QueryTargetKind::TypedSqlite { conn } | QueryTargetKind::TypedSqliteTx { conn },
46                ..
47            } => dml_typed_sqlite(conn, translated.as_ref(), self.params.as_ref()).await,
48            #[cfg(feature = "postgres")]
49            QueryTarget {
50                kind:
51                    QueryTargetKind::TypedPostgres { conn } | QueryTargetKind::TypedPostgresTx { conn },
52                ..
53            } => {
54                dml_typed_postgres(conn, translated.as_ref(), self.params.as_ref(), use_prepare)
55                    .await
56            }
57            #[cfg(feature = "turso")]
58            QueryTarget {
59                kind: QueryTargetKind::TypedTurso { conn } | QueryTargetKind::TypedTursoTx { conn },
60                ..
61            } => dml_typed_turso(conn, translated.as_ref(), self.params.as_ref()).await,
62            #[cfg(feature = "postgres")]
63            QueryTarget {
64                kind: QueryTargetKind::PostgresTx(tx),
65                ..
66            } => {
67                if use_prepare {
68                    let prepared = tx.prepare(translated.as_ref()).await?;
69                    tx.execute_prepared(&prepared, self.params.as_ref()).await
70                } else {
71                    tx.execute_dml(translated.as_ref(), self.params.as_ref())
72                        .await
73                }
74            }
75            #[cfg(feature = "mssql")]
76            QueryTarget {
77                kind: QueryTargetKind::MssqlTx(tx),
78                ..
79            } => {
80                if use_prepare {
81                    let prepared = tx.prepare(translated.as_ref())?;
82                    tx.execute_prepared(&prepared, self.params.as_ref()).await
83                } else {
84                    tx.execute_dml(translated.as_ref(), self.params.as_ref())
85                        .await
86                }
87            }
88            #[cfg(feature = "turso")]
89            QueryTarget {
90                kind: QueryTargetKind::TursoTx(tx),
91                ..
92            } => {
93                if use_prepare {
94                    let mut prepared = tx.prepare(translated.as_ref()).await?;
95                    tx.execute_prepared(&mut prepared, self.params.as_ref())
96                        .await
97                } else {
98                    tx.execute_dml(translated.as_ref(), self.params.as_ref())
99                        .await
100                }
101            }
102        }
103    }
104}
105
106async fn dml_on_connection(
107    conn: &mut MiddlewarePoolConnection,
108    query: &str,
109    params: &[RowValues],
110    use_prepare: bool,
111) -> Result<usize, SqlMiddlewareDbError> {
112    if use_prepare {
113        execute_dml_prepared_dispatch(conn, query, params).await
114    } else {
115        execute_dml_dispatch(conn, query, params).await
116    }
117}
118
119#[cfg(feature = "sqlite")]
120async fn dml_typed_sqlite(
121    conn: &mut PooledConnection<'static, SqliteManager>,
122    query: &str,
123    params: &[RowValues],
124) -> Result<usize, SqlMiddlewareDbError> {
125    crate::sqlite::connection::dml(conn, query, params).await
126}
127
128#[cfg(feature = "postgres")]
129async fn dml_typed_postgres(
130    conn: &mut PooledConnection<'static, PgManager>,
131    query: &str,
132    params: &[RowValues],
133    use_prepare: bool,
134) -> Result<usize, SqlMiddlewareDbError> {
135    if use_prepare {
136        crate::typed_postgres::dml_prepared(conn, query, params).await
137    } else {
138        crate::typed_postgres::dml(conn, query, params).await
139    }
140}
141
142#[cfg(feature = "turso")]
143async fn dml_typed_turso(
144    conn: &mut PooledConnection<'static, TursoManager>,
145    query: &str,
146    params: &[RowValues],
147) -> Result<usize, SqlMiddlewareDbError> {
148    crate::typed_turso::dml(conn, query, params).await
149}