Skip to main content

vantage_sql/
sqlite.rs

1#[macro_use]
2mod macros;
3pub mod impls;
4pub mod operation;
5pub(crate) mod row;
6pub mod statements;
7pub mod types;
8
9#[cfg(feature = "vista")]
10pub mod vista;
11
12use std::sync::Arc;
13
14use sqlx::sqlite::SqlitePool;
15use vantage_vista::{Transaction, TxKey};
16
17use crate::sql_tx::SqlTx;
18
19pub use types::{AnySqliteType, SqliteType};
20
21crate::define_typed_ident!(
22    SqliteIdent,
23    sqlite_ident,
24    AnySqliteType,
25    crate::condition::SqliteCondition
26);
27
28/// SQLite provider. Wraps a connection pool, or one transaction on it.
29#[derive(Clone)]
30pub struct SqliteDB {
31    pool: SqlitePool,
32    /// Identity shared by every clone: one transaction per datasource.
33    key: Arc<()>,
34    tx: Option<Arc<SqlTx<sqlx::Sqlite>>>,
35}
36
37impl SqliteDB {
38    /// Create from an existing sqlx connection pool.
39    pub fn new(pool: SqlitePool) -> Self {
40        Self {
41            pool,
42            key: Arc::new(()),
43            tx: None,
44        }
45    }
46
47    pub async fn connect(url: &str) -> Result<Self, sqlx::Error> {
48        Ok(Self::new(SqlitePool::connect(url).await?))
49    }
50
51    pub fn pool(&self) -> &SqlitePool {
52        &self.pool
53    }
54
55    /// This datasource running its statements on `tx`. `BEGIN IMMEDIATE`
56    /// takes the write lock up front, so two writers queue instead of
57    /// failing to upgrade a read lock.
58    pub fn in_transaction(&self, tx: &Transaction) -> vantage_core::Result<Self> {
59        tx.check_open()?;
60        let joined = tx.participant(self.tx_key(), || {
61            SqlTx::new(self.pool.clone(), "BEGIN IMMEDIATE", tx)
62        })?;
63        Ok(Self {
64            tx: Some(joined),
65            ..self.clone()
66        })
67    }
68
69    pub fn tx_key(&self) -> TxKey {
70        TxKey::of(&self.key)
71    }
72
73    /// Execute an aggregate query (COUNT, SUM, MAX, MIN etc.) and return the scalar result.
74    pub async fn aggregate(
75        &self,
76        select: &statements::SqliteSelect,
77        func: &str,
78        column: impl vantage_expressions::Expressive<AnySqliteType>,
79    ) -> vantage_core::Result<AnySqliteType> {
80        use vantage_expressions::ExprDataSource;
81        let expr = select.as_aggregate(func, column);
82        let result = self.execute(&expr).await?;
83        Ok(result.unwrap_scalar())
84    }
85}