Skip to main content

sql_middleware/query_builder/
select.rs

1use crate::error::SqlMiddlewareDbError;
2use crate::executor::{
3    QueryTarget, QueryTargetKind, execute_select_dispatch, execute_select_prepared_dispatch,
4};
5use crate::pool::MiddlewarePoolConnection;
6use crate::results::ResultSet;
7use crate::translation::PrepareMode;
8use crate::types::{RowValues, StatementCacheMode};
9
10#[cfg(feature = "postgres")]
11use crate::postgres::typed::PgManager;
12#[cfg(feature = "sqlite")]
13use crate::sqlite::config::SqliteManager;
14#[cfg(feature = "mssql")]
15use crate::typed_mssql::MssqlManager;
16#[cfg(feature = "turso")]
17use crate::typed_turso::TursoManager;
18#[cfg(any(
19    feature = "postgres",
20    feature = "sqlite",
21    feature = "turso",
22    feature = "mssql"
23))]
24use bb8::PooledConnection;
25
26use super::{QueryBuilder, translate_query_for_target};
27
28impl QueryBuilder<'_, '_> {
29    /// Execute a SELECT and return the result set.
30    ///
31    /// # Errors
32    /// Returns an error if placeholder translation fails or the backend query execution fails.
33    pub async fn select(self) -> Result<ResultSet, SqlMiddlewareDbError> {
34        let translated = translate_query_for_target(
35            &self.target,
36            self.sql.as_ref(),
37            self.params.as_ref(),
38            self.options,
39        );
40        let use_prepare = matches!(self.options.prepare, PrepareMode::Prepared);
41        let statement_cache_mode = self
42            .options
43            .statement_cache
44            .unwrap_or(self.target.statement_cache_mode);
45
46        match self.target {
47            QueryTarget {
48                kind: QueryTargetKind::Connection(conn),
49                ..
50            } => {
51                select_on_connection(
52                    conn,
53                    translated.as_ref(),
54                    self.params.as_ref(),
55                    use_prepare,
56                    statement_cache_mode,
57                )
58                .await
59            }
60            #[cfg(feature = "sqlite")]
61            QueryTarget {
62                kind:
63                    QueryTargetKind::TypedSqlite { conn } | QueryTargetKind::TypedSqliteTx { conn },
64                ..
65            } => {
66                select_typed_sqlite(
67                    conn,
68                    translated.as_ref(),
69                    self.params.as_ref(),
70                    statement_cache_mode,
71                )
72                .await
73            }
74            #[cfg(feature = "postgres")]
75            QueryTarget {
76                kind:
77                    QueryTargetKind::TypedPostgres { conn } | QueryTargetKind::TypedPostgresTx { conn },
78                ..
79            } => {
80                select_typed_postgres(conn, translated.as_ref(), self.params.as_ref(), use_prepare)
81                    .await
82            }
83            #[cfg(feature = "turso")]
84            QueryTarget {
85                kind: QueryTargetKind::TypedTurso { conn } | QueryTargetKind::TypedTursoTx { conn },
86                ..
87            } => {
88                select_typed_turso(
89                    conn,
90                    translated.as_ref(),
91                    self.params.as_ref(),
92                    statement_cache_mode,
93                )
94                .await
95            }
96            #[cfg(feature = "mssql")]
97            QueryTarget {
98                kind: QueryTargetKind::TypedMssql { conn } | QueryTargetKind::TypedMssqlTx { conn },
99                ..
100            } => select_typed_mssql(conn, translated.as_ref(), self.params.as_ref()).await,
101            #[cfg(feature = "postgres")]
102            QueryTarget {
103                kind: QueryTargetKind::PostgresTx(tx),
104                ..
105            } => {
106                if use_prepare {
107                    let prepared = tx.prepare(translated.as_ref()).await?;
108                    tx.query_prepared(&prepared, self.params.as_ref()).await
109                } else {
110                    tx.query(translated.as_ref(), self.params.as_ref()).await
111                }
112            }
113            #[cfg(feature = "mssql")]
114            QueryTarget {
115                kind: QueryTargetKind::MssqlTx(tx),
116                ..
117            } => {
118                if use_prepare {
119                    let prepared = tx.prepare(translated.as_ref())?;
120                    tx.query_prepared(&prepared, self.params.as_ref()).await
121                } else {
122                    tx.query(translated.as_ref(), self.params.as_ref()).await
123                }
124            }
125            #[cfg(feature = "turso")]
126            QueryTarget {
127                kind: QueryTargetKind::TursoTx(tx),
128                ..
129            } => {
130                if use_prepare {
131                    let mut prepared = tx.prepare(translated.as_ref()).await?;
132                    tx.query_prepared(&mut prepared, self.params.as_ref()).await
133                } else {
134                    tx.execute_select(translated.as_ref(), self.params.as_ref())
135                        .await
136                }
137            }
138        }
139    }
140}
141
142async fn select_on_connection(
143    conn: &mut MiddlewarePoolConnection,
144    query: &str,
145    params: &[RowValues],
146    use_prepare: bool,
147    statement_cache_mode: StatementCacheMode,
148) -> Result<ResultSet, SqlMiddlewareDbError> {
149    if use_prepare {
150        execute_select_prepared_dispatch(conn, query, params, statement_cache_mode).await
151    } else {
152        execute_select_dispatch(conn, query, params, statement_cache_mode).await
153    }
154}
155
156#[cfg(feature = "sqlite")]
157async fn select_typed_sqlite(
158    conn: &mut PooledConnection<'static, SqliteManager>,
159    query: &str,
160    params: &[RowValues],
161    statement_cache_mode: StatementCacheMode,
162) -> Result<ResultSet, SqlMiddlewareDbError> {
163    crate::sqlite::connection::select_with_cache_mode(conn, query, params, statement_cache_mode)
164        .await
165}
166
167#[cfg(feature = "postgres")]
168async fn select_typed_postgres(
169    conn: &mut PooledConnection<'static, PgManager>,
170    query: &str,
171    params: &[RowValues],
172    use_prepare: bool,
173) -> Result<ResultSet, SqlMiddlewareDbError> {
174    if use_prepare {
175        crate::typed_postgres::select_prepared(conn, query, params).await
176    } else {
177        crate::typed_postgres::select(conn, query, params).await
178    }
179}
180
181#[cfg(feature = "turso")]
182async fn select_typed_turso(
183    conn: &mut PooledConnection<'static, TursoManager>,
184    query: &str,
185    params: &[RowValues],
186    statement_cache_mode: StatementCacheMode,
187) -> Result<ResultSet, SqlMiddlewareDbError> {
188    crate::typed_turso::select_with_cache_mode(conn, query, params, statement_cache_mode).await
189}
190
191#[cfg(feature = "mssql")]
192async fn select_typed_mssql(
193    conn: &mut PooledConnection<'static, MssqlManager>,
194    query: &str,
195    params: &[RowValues],
196) -> Result<ResultSet, SqlMiddlewareDbError> {
197    crate::typed_mssql::select(conn, query, params).await
198}