1use std::sync::Arc;
2
3use crate::adapters::params::convert_params;
4use crate::middleware::{ConversionMode, CustomDbRow, ResultSet, RowValues, SqlMiddlewareDbError};
5use crate::types::StatementCacheMode;
6
7use super::connection::{SqliteConnection, run_blocking};
8use super::params::{Params, SqliteParamsBuf};
9use super::query::sqlite_extract_value_sync;
10
11pub struct SqlitePreparedStatement<'conn> {
13 connection: &'conn mut SqliteConnection,
14 query: Arc<String>,
15 statement_cache_mode: StatementCacheMode,
16}
17
18impl<'conn> SqlitePreparedStatement<'conn> {
19 pub(crate) fn new(
20 connection: &'conn mut SqliteConnection,
21 query: Arc<String>,
22 statement_cache_mode: StatementCacheMode,
23 ) -> Self {
24 Self {
25 connection,
26 query,
27 statement_cache_mode,
28 }
29 }
30
31 #[must_use]
33 pub fn select(&mut self) -> SqlitePreparedSelect<'_, 'conn, '_> {
34 SqlitePreparedSelect {
35 statement: self,
36 params: SqlitePreparedParams::None,
37 }
38 }
39
40 #[must_use]
42 pub fn execute(&mut self) -> SqlitePreparedExecute<'_, 'conn, '_> {
43 SqlitePreparedExecute {
44 statement: self,
45 params: SqlitePreparedParams::None,
46 }
47 }
48
49 pub(crate) async fn query(
54 &mut self,
55 params: &[RowValues],
56 ) -> Result<ResultSet, SqlMiddlewareDbError> {
57 let params_owned = convert_params::<Params>(params, ConversionMode::Query)?.0;
58 self.connection
59 .execute_select(
60 self.query.as_ref(),
61 ¶ms_owned,
62 super::query::build_result_set,
63 self.statement_cache_mode,
64 )
65 .await
66 }
67
68 pub(crate) async fn query_params(
73 &mut self,
74 params: &SqliteParamsBuf,
75 ) -> Result<ResultSet, SqlMiddlewareDbError> {
76 self.connection
77 .execute_select(
78 self.query.as_ref(),
79 params.as_values(),
80 super::query::build_result_set,
81 self.statement_cache_mode,
82 )
83 .await
84 }
85
86 pub(crate) async fn query_optional(
93 &mut self,
94 params: &[RowValues],
95 ) -> Result<Option<CustomDbRow>, SqlMiddlewareDbError> {
96 let params_owned = convert_params::<Params>(params, ConversionMode::Query)?.0;
97 self.query_optional_values(params_owned).await
98 }
99
100 pub(crate) async fn query_optional_params(
106 &mut self,
107 params: &SqliteParamsBuf,
108 ) -> Result<Option<CustomDbRow>, SqlMiddlewareDbError> {
109 self.query_optional_values(params.as_values().to_vec())
110 .await
111 }
112
113 async fn query_optional_values(
114 &mut self,
115 params_owned: Vec<rusqlite::types::Value>,
116 ) -> Result<Option<CustomDbRow>, SqlMiddlewareDbError> {
117 let sql = Arc::clone(&self.query);
118 let statement_cache_mode = self.statement_cache_mode;
119 run_blocking(
120 self.connection.conn_handle(),
121 move |guard| match statement_cache_mode {
122 StatementCacheMode::Cached => {
123 let mut stmt = guard
124 .prepare_cached(sql.as_ref())
125 .map_err(SqlMiddlewareDbError::SqliteError)?;
126 query_optional_with_statement(&mut stmt, ¶ms_owned)
127 }
128 StatementCacheMode::Uncached => {
129 let mut stmt = guard
130 .prepare(sql.as_ref())
131 .map_err(SqlMiddlewareDbError::SqliteError)?;
132 query_optional_with_statement(&mut stmt, ¶ms_owned)
133 }
134 },
135 )
136 .await
137 }
138
139 pub(crate) async fn query_one(
145 &mut self,
146 params: &[RowValues],
147 ) -> Result<CustomDbRow, SqlMiddlewareDbError> {
148 self.query_optional(params)
149 .await?
150 .ok_or_else(|| SqlMiddlewareDbError::SqliteError(rusqlite::Error::QueryReturnedNoRows))
151 }
152
153 pub(crate) async fn query_one_params(
159 &mut self,
160 params: &SqliteParamsBuf,
161 ) -> Result<CustomDbRow, SqlMiddlewareDbError> {
162 self.query_optional_params(params)
163 .await?
164 .ok_or_else(|| SqlMiddlewareDbError::SqliteError(rusqlite::Error::QueryReturnedNoRows))
165 }
166
167 pub(crate) async fn query_map_one<T, F>(
176 &mut self,
177 params: &[RowValues],
178 mapper: F,
179 ) -> Result<T, SqlMiddlewareDbError>
180 where
181 T: Send + 'static,
182 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
183 {
184 self.query_map_optional(params, mapper)
185 .await?
186 .ok_or_else(|| SqlMiddlewareDbError::SqliteError(rusqlite::Error::QueryReturnedNoRows))
187 }
188
189 pub(crate) async fn query_map_one_params<T, F>(
196 &mut self,
197 params: &SqliteParamsBuf,
198 mapper: F,
199 ) -> Result<T, SqlMiddlewareDbError>
200 where
201 T: Send + 'static,
202 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
203 {
204 self.query_map_optional_params(params, mapper)
205 .await?
206 .ok_or_else(|| SqlMiddlewareDbError::SqliteError(rusqlite::Error::QueryReturnedNoRows))
207 }
208
209 pub(crate) async fn query_map_optional<T, F>(
215 &mut self,
216 params: &[RowValues],
217 mapper: F,
218 ) -> Result<Option<T>, SqlMiddlewareDbError>
219 where
220 T: Send + 'static,
221 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
222 {
223 let params_owned = convert_params::<Params>(params, ConversionMode::Query)?.0;
224 self.query_map_optional_values(params_owned, mapper).await
225 }
226
227 pub(crate) async fn query_map_optional_params<T, F>(
233 &mut self,
234 params: &SqliteParamsBuf,
235 mapper: F,
236 ) -> Result<Option<T>, SqlMiddlewareDbError>
237 where
238 T: Send + 'static,
239 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
240 {
241 self.query_map_optional_values(params.as_values().to_vec(), mapper)
242 .await
243 }
244
245 async fn query_map_optional_values<T, F>(
246 &mut self,
247 params_owned: Vec<rusqlite::types::Value>,
248 mapper: F,
249 ) -> Result<Option<T>, SqlMiddlewareDbError>
250 where
251 T: Send + 'static,
252 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
253 {
254 let sql = Arc::clone(&self.query);
255 let statement_cache_mode = self.statement_cache_mode;
256 run_blocking(
257 self.connection.conn_handle(),
258 move |guard| match statement_cache_mode {
259 StatementCacheMode::Cached => {
260 let mut stmt = guard
261 .prepare_cached(sql.as_ref())
262 .map_err(SqlMiddlewareDbError::SqliteError)?;
263 query_map_optional_with_statement(&mut stmt, ¶ms_owned, mapper)
264 }
265 StatementCacheMode::Uncached => {
266 let mut stmt = guard
267 .prepare(sql.as_ref())
268 .map_err(SqlMiddlewareDbError::SqliteError)?;
269 query_map_optional_with_statement(&mut stmt, ¶ms_owned, mapper)
270 }
271 },
272 )
273 .await
274 }
275
276 pub(crate) async fn execute_values(
281 &mut self,
282 params: &[RowValues],
283 ) -> Result<usize, SqlMiddlewareDbError> {
284 let params_owned = convert_params::<Params>(params, ConversionMode::Execute)?.0;
285 self.connection
286 .execute_dml(
287 self.query.as_ref(),
288 ¶ms_owned,
289 self.statement_cache_mode,
290 )
291 .await
292 }
293
294 pub(crate) async fn execute_params(
299 &mut self,
300 params: &SqliteParamsBuf,
301 ) -> Result<usize, SqlMiddlewareDbError> {
302 self.connection
303 .execute_dml(
304 self.query.as_ref(),
305 params.as_values(),
306 self.statement_cache_mode,
307 )
308 .await
309 }
310
311 #[must_use]
313 pub fn sql(&self) -> &str {
314 self.query.as_str()
315 }
316}
317
318pub struct SqlitePreparedExecute<'stmt, 'conn, 'params> {
320 statement: &'stmt mut SqlitePreparedStatement<'conn>,
321 params: SqlitePreparedParams<'params>,
322}
323
324impl<'stmt, 'conn, 'params> SqlitePreparedExecute<'stmt, 'conn, 'params> {
325 #[must_use]
327 pub fn params<'next>(
328 self,
329 params: &'next [RowValues],
330 ) -> SqlitePreparedExecute<'stmt, 'conn, 'next> {
331 SqlitePreparedExecute {
332 statement: self.statement,
333 params: SqlitePreparedParams::RowValues(params),
334 }
335 }
336
337 #[must_use]
339 pub fn params_buf<'next>(
340 self,
341 params: &'next SqliteParamsBuf,
342 ) -> SqlitePreparedExecute<'stmt, 'conn, 'next> {
343 SqlitePreparedExecute {
344 statement: self.statement,
345 params: SqlitePreparedParams::Buffer(params),
346 }
347 }
348
349 pub async fn run(self) -> Result<usize, SqlMiddlewareDbError> {
354 match self.params {
355 SqlitePreparedParams::None => self.statement.execute_values(&[]).await,
356 SqlitePreparedParams::RowValues(params) => self.statement.execute_values(params).await,
357 SqlitePreparedParams::Buffer(params) => self.statement.execute_params(params).await,
358 }
359 }
360}
361
362enum SqlitePreparedParams<'params> {
363 None,
364 RowValues(&'params [RowValues]),
365 Buffer(&'params SqliteParamsBuf),
366}
367
368pub struct SqlitePreparedSelect<'stmt, 'conn, 'params> {
370 statement: &'stmt mut SqlitePreparedStatement<'conn>,
371 params: SqlitePreparedParams<'params>,
372}
373
374impl<'stmt, 'conn, 'params> SqlitePreparedSelect<'stmt, 'conn, 'params> {
375 #[must_use]
377 pub fn params<'next>(
378 self,
379 params: &'next [RowValues],
380 ) -> SqlitePreparedSelect<'stmt, 'conn, 'next> {
381 SqlitePreparedSelect {
382 statement: self.statement,
383 params: SqlitePreparedParams::RowValues(params),
384 }
385 }
386
387 #[must_use]
389 pub fn params_buf<'next>(
390 self,
391 params: &'next SqliteParamsBuf,
392 ) -> SqlitePreparedSelect<'stmt, 'conn, 'next> {
393 SqlitePreparedSelect {
394 statement: self.statement,
395 params: SqlitePreparedParams::Buffer(params),
396 }
397 }
398
399 pub async fn all(self) -> Result<ResultSet, SqlMiddlewareDbError> {
404 match self.params {
405 SqlitePreparedParams::None => self.statement.query(&[]).await,
406 SqlitePreparedParams::RowValues(params) => self.statement.query(params).await,
407 SqlitePreparedParams::Buffer(params) => self.statement.query_params(params).await,
408 }
409 }
410
411 pub async fn optional(self) -> Result<Option<CustomDbRow>, SqlMiddlewareDbError> {
416 match self.params {
417 SqlitePreparedParams::None => self.statement.query_optional(&[]).await,
418 SqlitePreparedParams::RowValues(params) => self.statement.query_optional(params).await,
419 SqlitePreparedParams::Buffer(params) => {
420 self.statement.query_optional_params(params).await
421 }
422 }
423 }
424
425 pub async fn one(self) -> Result<CustomDbRow, SqlMiddlewareDbError> {
430 match self.params {
431 SqlitePreparedParams::None => self.statement.query_one(&[]).await,
432 SqlitePreparedParams::RowValues(params) => self.statement.query_one(params).await,
433 SqlitePreparedParams::Buffer(params) => self.statement.query_one_params(params).await,
434 }
435 }
436
437 pub async fn map_one<T, F>(self, mapper: F) -> Result<T, SqlMiddlewareDbError>
442 where
443 T: Send + 'static,
444 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
445 {
446 match self.params {
447 SqlitePreparedParams::None => self.statement.query_map_one(&[], mapper).await,
448 SqlitePreparedParams::RowValues(params) => {
449 self.statement.query_map_one(params, mapper).await
450 }
451 SqlitePreparedParams::Buffer(params) => {
452 self.statement.query_map_one_params(params, mapper).await
453 }
454 }
455 }
456
457 pub async fn map_optional<T, F>(self, mapper: F) -> Result<Option<T>, SqlMiddlewareDbError>
462 where
463 T: Send + 'static,
464 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError> + Send + 'static,
465 {
466 match self.params {
467 SqlitePreparedParams::None => self.statement.query_map_optional(&[], mapper).await,
468 SqlitePreparedParams::RowValues(params) => {
469 self.statement.query_map_optional(params, mapper).await
470 }
471 SqlitePreparedParams::Buffer(params) => {
472 self.statement
473 .query_map_optional_params(params, mapper)
474 .await
475 }
476 }
477 }
478}
479
480fn query_optional_with_statement(
481 stmt: &mut rusqlite::Statement<'_>,
482 params: &[rusqlite::types::Value],
483) -> Result<Option<CustomDbRow>, SqlMiddlewareDbError> {
484 let column_names = Arc::new(
485 stmt.column_names()
486 .into_iter()
487 .map(str::to_string)
488 .collect::<Vec<_>>(),
489 );
490 let col_count = column_names.len();
491 let param_refs = params
492 .iter()
493 .map(|value| value as &dyn rusqlite::ToSql)
494 .collect::<Vec<_>>();
495 let mut rows = stmt.query(¶m_refs[..])?;
496
497 rows.next()?
498 .map(|row| row_to_custom_db_row(row, Arc::clone(&column_names), col_count))
499 .transpose()
500}
501
502fn query_map_optional_with_statement<T, F>(
503 stmt: &mut rusqlite::Statement<'_>,
504 params: &[rusqlite::types::Value],
505 mapper: F,
506) -> Result<Option<T>, SqlMiddlewareDbError>
507where
508 F: FnOnce(&rusqlite::Row<'_>) -> Result<T, SqlMiddlewareDbError>,
509{
510 let param_refs = params
511 .iter()
512 .map(|value| value as &dyn rusqlite::ToSql)
513 .collect::<Vec<_>>();
514 let mut rows = stmt.query(¶m_refs[..])?;
515
516 rows.next()?.map(mapper).transpose()
517}
518
519fn row_to_custom_db_row(
520 row: &rusqlite::Row<'_>,
521 column_names: Arc<Vec<String>>,
522 col_count: usize,
523) -> Result<CustomDbRow, SqlMiddlewareDbError> {
524 let mut row_values = Vec::with_capacity(col_count);
525 for idx in 0..col_count {
526 row_values.push(sqlite_extract_value_sync(row, idx)?);
527 }
528 Ok(CustomDbRow::new(column_names, row_values))
529}