sql_middleware/
executor.rs

1use std::borrow::Cow;
2
3use crate::error::SqlMiddlewareDbError;
4use crate::pool::MiddlewarePoolConnection;
5use crate::query_builder::QueryBuilder;
6use crate::results::ResultSet;
7use crate::translation::{PlaceholderStyle, QueryOptions, translate_placeholders};
8use crate::types::RowValues;
9
10#[cfg(feature = "libsql")]
11use crate::libsql;
12#[cfg(feature = "mssql")]
13use crate::mssql;
14#[cfg(feature = "postgres")]
15use crate::postgres;
16#[cfg(feature = "sqlite")]
17use crate::sqlite;
18#[cfg(feature = "turso")]
19use crate::turso;
20
21impl MiddlewarePoolConnection {
22    /// Executes a batch of SQL queries within a transaction by delegating to the specific database module.
23    ///
24    /// # Errors
25    /// Returns an error if the selected backend cannot execute the batch or the database responds with an error.
26    pub async fn execute_batch(&mut self, query: &str) -> Result<(), SqlMiddlewareDbError> {
27        match self {
28            #[cfg(feature = "postgres")]
29            MiddlewarePoolConnection::Postgres {
30                client: pg_client, ..
31            } => postgres::execute_batch(pg_client, query).await,
32            #[cfg(feature = "sqlite")]
33            MiddlewarePoolConnection::Sqlite {
34                conn: sqlite_client,
35                ..
36            } => sqlite::execute_batch(sqlite_client, query).await,
37            #[cfg(feature = "mssql")]
38            MiddlewarePoolConnection::Mssql {
39                conn: mssql_client, ..
40            } => mssql::execute_batch(mssql_client, query).await,
41            #[cfg(feature = "libsql")]
42            MiddlewarePoolConnection::Libsql {
43                conn: libsql_client,
44                ..
45            } => libsql::execute_batch(libsql_client, query).await,
46            #[cfg(feature = "turso")]
47            MiddlewarePoolConnection::Turso {
48                conn: turso_conn, ..
49            } => turso::execute_batch(turso_conn, query).await,
50            #[allow(unreachable_patterns)]
51            _ => Err(SqlMiddlewareDbError::Unimplemented(
52                "This database type is not enabled in the current build".to_string(),
53            )),
54        }
55    }
56
57    /// Start a fluent query builder that can translate placeholders before executing.
58    pub fn query<'a>(&'a mut self, query: &'a str) -> QueryBuilder<'a, 'a> {
59        QueryBuilder::new(self, query)
60    }
61}
62
63pub(crate) async fn execute_select_dispatch(
64    conn: &mut MiddlewarePoolConnection,
65    query: &str,
66    params: &[RowValues],
67) -> Result<ResultSet, SqlMiddlewareDbError> {
68    match conn {
69        #[cfg(feature = "postgres")]
70        MiddlewarePoolConnection::Postgres {
71            client: pg_client, ..
72        } => postgres::execute_select(pg_client, query, params).await,
73        #[cfg(feature = "sqlite")]
74        MiddlewarePoolConnection::Sqlite {
75            conn: sqlite_client,
76            ..
77        } => sqlite::execute_select(sqlite_client, query, params).await,
78        #[cfg(feature = "mssql")]
79        MiddlewarePoolConnection::Mssql {
80            conn: mssql_client, ..
81        } => mssql::execute_select(mssql_client, query, params).await,
82        #[cfg(feature = "libsql")]
83        MiddlewarePoolConnection::Libsql {
84            conn: libsql_client,
85            ..
86        } => libsql::execute_select(libsql_client, query, params).await,
87        #[cfg(feature = "turso")]
88        MiddlewarePoolConnection::Turso {
89            conn: turso_conn, ..
90        } => turso::execute_select(turso_conn, query, params).await,
91        #[allow(unreachable_patterns)]
92        _ => Err(SqlMiddlewareDbError::Unimplemented(
93            "This database type is not enabled in the current build".to_string(),
94        )),
95    }
96}
97
98pub(crate) async fn execute_dml_dispatch(
99    conn: &mut MiddlewarePoolConnection,
100    query: &str,
101    params: &[RowValues],
102) -> Result<usize, SqlMiddlewareDbError> {
103    match conn {
104        #[cfg(feature = "postgres")]
105        MiddlewarePoolConnection::Postgres {
106            client: pg_client, ..
107        } => postgres::execute_dml(pg_client, query, params).await,
108        #[cfg(feature = "sqlite")]
109        MiddlewarePoolConnection::Sqlite {
110            conn: sqlite_client,
111            ..
112        } => sqlite::execute_dml(sqlite_client, query, params).await,
113        #[cfg(feature = "mssql")]
114        MiddlewarePoolConnection::Mssql {
115            conn: mssql_client, ..
116        } => mssql::execute_dml(mssql_client, query, params).await,
117        #[cfg(feature = "libsql")]
118        MiddlewarePoolConnection::Libsql {
119            conn: libsql_client,
120            ..
121        } => libsql::execute_dml(libsql_client, query, params).await,
122        #[cfg(feature = "turso")]
123        MiddlewarePoolConnection::Turso {
124            conn: turso_conn, ..
125        } => turso::execute_dml(turso_conn, query, params).await,
126        #[allow(unreachable_patterns)]
127        _ => Err(SqlMiddlewareDbError::Unimplemented(
128            "This database type is not enabled in the current build".to_string(),
129        )),
130    }
131}
132
133pub(crate) fn translation_target(conn: &MiddlewarePoolConnection) -> Option<PlaceholderStyle> {
134    match conn {
135        #[cfg(feature = "postgres")]
136        MiddlewarePoolConnection::Postgres { .. } => Some(PlaceholderStyle::Postgres),
137        #[cfg(feature = "sqlite")]
138        MiddlewarePoolConnection::Sqlite { .. } => Some(PlaceholderStyle::Sqlite),
139        #[cfg(feature = "libsql")]
140        MiddlewarePoolConnection::Libsql { .. } => Some(PlaceholderStyle::Sqlite),
141        #[cfg(feature = "turso")]
142        MiddlewarePoolConnection::Turso { .. } => Some(PlaceholderStyle::Sqlite),
143        #[cfg(feature = "mssql")]
144        MiddlewarePoolConnection::Mssql { .. } => None,
145        #[allow(unreachable_patterns)]
146        _ => None,
147    }
148}
149
150pub(crate) fn translate_query<'a>(
151    conn: &MiddlewarePoolConnection,
152    query: &'a str,
153    params: &[RowValues],
154    options: QueryOptions,
155) -> Cow<'a, str> {
156    if params.is_empty() {
157        return Cow::Borrowed(query);
158    }
159
160    let Some(target) = translation_target(conn) else {
161        return Cow::Borrowed(query);
162    };
163
164    let enabled = options.translation.resolve(conn.translation_default());
165    translate_placeholders(query, target, enabled)
166}