sql_middleware/executor/
dispatch.rs

1use crate::error::SqlMiddlewareDbError;
2use crate::pool::MiddlewarePoolConnection;
3use crate::query_builder::QueryBuilder;
4use crate::results::ResultSet;
5use crate::types::RowValues;
6
7#[cfg(feature = "libsql")]
8use crate::libsql;
9#[cfg(feature = "mssql")]
10use crate::mssql;
11#[cfg(feature = "postgres")]
12use crate::postgres;
13#[cfg(feature = "sqlite")]
14use crate::sqlite;
15#[cfg(feature = "turso")]
16use crate::turso;
17
18use super::targets::{BatchTarget, QueryTarget};
19
20/// Execute a batch against either a connection or a transaction.
21///
22/// # Errors
23/// Returns an error propagated from the underlying backend execution or transaction context.
24pub async fn execute_batch(
25    target: impl Into<BatchTarget<'_>>,
26    query: &str,
27) -> Result<(), SqlMiddlewareDbError> {
28    match target.into() {
29        BatchTarget::Connection(conn) => conn.execute_batch(query).await,
30        #[cfg(feature = "postgres")]
31        BatchTarget::PostgresTx(tx) => tx.execute_batch(query).await,
32        #[cfg(feature = "mssql")]
33        BatchTarget::MssqlTx(tx) => tx.execute_batch(query).await,
34        #[cfg(feature = "libsql")]
35        BatchTarget::LibsqlTx(tx) => tx.execute_batch(query).await,
36        #[cfg(feature = "turso")]
37        BatchTarget::TursoTx(tx) => tx.execute_batch(query).await,
38        #[cfg(feature = "turso")]
39        BatchTarget::TypedTurso { conn } => {
40            crate::typed_turso::dml(conn, query, &[]).await?;
41            Ok(())
42        }
43        #[cfg(feature = "turso")]
44        BatchTarget::TypedTursoTx { conn } => {
45            crate::typed_turso::dml(conn, query, &[]).await?;
46            Ok(())
47        }
48    }
49}
50
51/// Start a fluent builder for either a connection or a transaction.
52pub fn query<'a>(target: impl Into<QueryTarget<'a>>, sql: &'a str) -> QueryBuilder<'a, 'a> {
53    QueryBuilder::new_target(target.into(), sql)
54}
55
56impl MiddlewarePoolConnection {
57    /// Executes a batch of SQL queries within a transaction by delegating to the specific database module.
58    ///
59    /// # Errors
60    /// Returns an error if the selected backend cannot execute the batch or the database responds with an error.
61    pub async fn execute_batch(&mut self, query: &str) -> Result<(), SqlMiddlewareDbError> {
62        match self {
63            #[cfg(feature = "postgres")]
64            MiddlewarePoolConnection::Postgres {
65                client: pg_client, ..
66            } => postgres::execute_batch(pg_client, query).await,
67            #[cfg(feature = "sqlite")]
68            MiddlewarePoolConnection::Sqlite { .. } => {
69                let sqlite_client = self.sqlite_conn_mut()?;
70                sqlite::execute_batch(sqlite_client, query).await
71            }
72            #[cfg(feature = "mssql")]
73            MiddlewarePoolConnection::Mssql {
74                conn: mssql_client, ..
75            } => mssql::execute_batch(mssql_client, query).await,
76            #[cfg(feature = "libsql")]
77            MiddlewarePoolConnection::Libsql {
78                conn: libsql_client,
79                ..
80            } => libsql::execute_batch(libsql_client, query).await,
81            #[cfg(feature = "turso")]
82            MiddlewarePoolConnection::Turso {
83                conn: turso_conn, ..
84            } => turso::execute_batch(turso_conn, query).await,
85            #[allow(unreachable_patterns)]
86            _ => Err(SqlMiddlewareDbError::Unimplemented(
87                "This database type is not enabled in the current build".to_string(),
88            )),
89        }
90    }
91
92    /// Start a fluent query builder that can translate placeholders before executing.
93    ///
94    /// # Examples
95    /// ```rust,no_run
96    /// use sql_middleware::prelude::*;
97    ///
98    /// # async fn demo() -> Result<(), SqlMiddlewareDbError> {
99    /// let cap = ConfigAndPool::new_sqlite("file::memory:?cache=shared".into()).await?;
100    /// let mut conn = cap.get_connection().await?;
101    /// conn.execute_batch("CREATE TABLE t (id INTEGER)").await?;
102    ///
103    /// let rows = conn
104    ///     .query("SELECT id FROM t WHERE id = ?1")
105    ///     .params(&[RowValues::Int(1)])
106    ///     .select()
107    ///     .await?;
108    /// assert!(rows.results.is_empty());
109    /// # Ok(()) }
110    /// ```
111    pub fn query<'a>(&'a mut self, query: &'a str) -> QueryBuilder<'a, 'a> {
112        QueryBuilder::new(self, query)
113    }
114}
115
116pub(crate) async fn execute_select_dispatch(
117    conn: &mut MiddlewarePoolConnection,
118    query: &str,
119    params: &[RowValues],
120) -> Result<ResultSet, SqlMiddlewareDbError> {
121    match conn {
122        #[cfg(feature = "postgres")]
123        MiddlewarePoolConnection::Postgres {
124            client: pg_client, ..
125        } => postgres::execute_select(pg_client, query, params).await,
126        #[cfg(feature = "sqlite")]
127        MiddlewarePoolConnection::Sqlite { .. } => {
128            let sqlite_client = conn.sqlite_conn_mut()?;
129            sqlite::execute_select(sqlite_client, query, params).await
130        }
131        #[cfg(feature = "mssql")]
132        MiddlewarePoolConnection::Mssql {
133            conn: mssql_client, ..
134        } => mssql::execute_select(mssql_client, query, params).await,
135        #[cfg(feature = "libsql")]
136        MiddlewarePoolConnection::Libsql {
137            conn: libsql_client,
138            ..
139        } => libsql::execute_select(libsql_client, query, params).await,
140        #[cfg(feature = "turso")]
141        MiddlewarePoolConnection::Turso {
142            conn: turso_conn, ..
143        } => turso::execute_select(turso_conn, query, params).await,
144        #[allow(unreachable_patterns)]
145        _ => Err(SqlMiddlewareDbError::Unimplemented(
146            "This database type is not enabled in the current build".to_string(),
147        )),
148    }
149}
150
151pub(crate) async fn execute_dml_dispatch(
152    conn: &mut MiddlewarePoolConnection,
153    query: &str,
154    params: &[RowValues],
155) -> Result<usize, SqlMiddlewareDbError> {
156    match conn {
157        #[cfg(feature = "postgres")]
158        MiddlewarePoolConnection::Postgres {
159            client: pg_client, ..
160        } => postgres::execute_dml(pg_client, query, params).await,
161        #[cfg(feature = "sqlite")]
162        MiddlewarePoolConnection::Sqlite { .. } => {
163            let sqlite_client = conn.sqlite_conn_mut()?;
164            sqlite::execute_dml(sqlite_client, query, params).await
165        }
166        #[cfg(feature = "mssql")]
167        MiddlewarePoolConnection::Mssql {
168            conn: mssql_client, ..
169        } => mssql::execute_dml(mssql_client, query, params).await,
170        #[cfg(feature = "libsql")]
171        MiddlewarePoolConnection::Libsql {
172            conn: libsql_client,
173            ..
174        } => libsql::execute_dml(libsql_client, query, params).await,
175        #[cfg(feature = "turso")]
176        MiddlewarePoolConnection::Turso {
177            conn: turso_conn, ..
178        } => turso::execute_dml(turso_conn, query, params).await,
179        #[allow(unreachable_patterns)]
180        _ => Err(SqlMiddlewareDbError::Unimplemented(
181            "This database type is not enabled in the current build".to_string(),
182        )),
183    }
184}