rsdbc_sqlite/options/
mod.rs

1// From SQLx - https://github.com/launchbadge/sqlx/blob/master/sqlx-core/src/sqlite/options/mod.rs
2
3mod auto_vacuum;
4mod journal_mode;
5mod locking_mode;
6mod synchronous;
7mod parse;
8mod mode;
9
10// TODO: add log settings
11// use crate::connection::LogSettings;
12pub use auto_vacuum::SqliteAutoVacuum;
13pub use journal_mode::SqliteJournalMode;
14pub use locking_mode::SqliteLockingMode;
15pub use synchronous::SqliteSynchronous;
16
17use std::{borrow::Cow, time::Duration};
18use std::future::Future;
19use std::path::Path;
20use std::pin::Pin;
21use crate::{SqliteConnection, to_rsdbc_err};
22use crate::Result;
23use futures::future::BoxFuture;
24use rusqlite::{Connection, OpenFlags};
25use std::sync::{Arc, Mutex};
26use rusqlite::params;
27use std::rc::Rc;
28use rsdbc_core::connection::{ConnectionFactory, ConnectionFactoryMetadata, ConnectionFactoryOptions};
29use rsdbc_core::error::RsdbcErrors;
30
31// // TODO:
32// // - ^ the trait `From<rusqlite::Error>` is not implemented for `rsdbc::Error`
33// impl From<RusqliteError> for Error {
34//     fn from(err: rusqlite::Error) -> Self {
35//         Error::General(err.to_string())
36//     }
37// }
38
39
40// TODO: rename to SqliteConnectionConfiguration?
41#[derive(Clone, Debug)]
42pub struct SqliteConnectOptions {
43    pub(crate) filename: Cow<'static, Path>,
44    pub(crate) in_memory: bool,
45    pub(crate) read_only: bool,
46    pub(crate) create_if_missing: bool,
47    pub(crate) journal_mode: SqliteJournalMode,
48    pub(crate) locking_mode: SqliteLockingMode,
49    pub(crate) foreign_keys: bool,
50    pub(crate) shared_cache: bool,
51    pub(crate) statement_cache_capacity: usize,
52    pub(crate) busy_timeout: Duration,
53    // pub(crate) log_settings: LogSettings,
54    pub(crate) synchronous: SqliteSynchronous,
55    pub(crate) auto_vacuum: SqliteAutoVacuum,
56}
57
58// TODO: document...see new
59impl Default for SqliteConnectOptions {
60    fn default() -> Self {
61        Self::new()
62    }
63}
64
65impl SqliteConnectOptions {
66
67    // TODO: document these options
68    pub fn new() -> Self {
69        Self {
70            filename: Cow::Borrowed(Path::new(":memory:")),
71            in_memory: false,
72            read_only: false,
73            create_if_missing: false,
74            foreign_keys: true,
75            shared_cache: false,
76            statement_cache_capacity: 100,
77            journal_mode: Default::default(),
78            locking_mode: Default::default(),
79            busy_timeout: Duration::from_secs(5),
80            // log_settings: Default::default(),
81            synchronous: Default::default(),
82            auto_vacuum: Default::default(),
83        }
84    }
85
86    /// Sets the name of the database file.
87    pub fn filename(mut self, filename: impl AsRef<Path>) -> Self {
88        self.filename = Cow::Owned(filename.as_ref().to_owned());
89        self
90    }
91
92    /// Set the enforcement of [foreign key constraints](https://www.sqlite.org/pragma.html#pragma_foreign_keys).
93    ///
94    /// By default, this is enabled.
95    pub fn foreign_keys(mut self, on: bool) -> Self {
96        self.foreign_keys = on;
97        self
98    }
99
100    /// Sets the [journal mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) for the database connection.
101    ///
102    /// The default journal mode is WAL. For most use cases this can be significantly faster but
103    /// there are [disadvantages](https://www.sqlite.org/wal.html).
104    pub fn journal_mode(mut self, mode: SqliteJournalMode) -> Self {
105        self.journal_mode = mode;
106        self
107    }
108
109    /// Sets the [locking mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) for the database connection.
110    ///
111    /// The default locking mode is NORMAL.
112    pub fn locking_mode(mut self, mode: SqliteLockingMode) -> Self {
113        self.locking_mode = mode;
114        self
115    }
116
117    /// Sets the [access mode](https://www.sqlite.org/c3ref/open.html) to open the database
118    /// for read-only access.
119    pub fn read_only(mut self, read_only: bool) -> Self {
120        self.read_only = read_only;
121        self
122    }
123
124    /// Sets the [access mode](https://www.sqlite.org/c3ref/open.html) to create the database file
125    /// if the file does not exist.
126    ///
127    /// By default, a new file **will not be** created if one is not found.
128    pub fn create_if_missing(mut self, create: bool) -> Self {
129        self.create_if_missing = create;
130        self
131    }
132
133    /// Sets the capacity of the connection's statement cache in a number of stored
134    /// distinct statements. Caching is handled using LRU, meaning when the
135    /// amount of queries hits the defined limit, the oldest statement will get
136    /// dropped.
137    ///
138    /// The default cache capacity is 100 statements.
139    pub fn statement_cache_capacity(mut self, capacity: usize) -> Self {
140        self.statement_cache_capacity = capacity;
141        self
142    }
143
144    /// Sets a timeout value to wait when the database is locked, before
145    /// returning a busy timeout error.
146    ///
147    /// The default busy timeout is 5 seconds.
148    pub fn busy_timeout(mut self, timeout: Duration) -> Self {
149        self.busy_timeout = timeout;
150        self
151    }
152
153    /// Sets the [synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) setting for
154    /// the database connection.
155    ///
156    /// The default synchronous settings is FULL. However, if durability is not a concern,
157    /// then NORMAL is normally all one needs in WAL mode.
158    pub fn synchronous(mut self, synchronous: SqliteSynchronous) -> Self {
159        self.synchronous = synchronous;
160        self
161    }
162
163    /// Sets the [auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) setting for
164    /// the database connection.
165    ///
166    /// The default auto_vacuum setting is NONE.
167    pub fn auto_vacuum(mut self, auto_vacuum: SqliteAutoVacuum) -> Self {
168        self.auto_vacuum = auto_vacuum;
169        self
170    }
171
172    /// Set the [`SQLITE_OPEN_SHAREDCACHE` flag](https://sqlite.org/sharedcache.html).
173    ///
174    /// By default, this is disabled.
175    pub fn shared_cache(mut self, on: bool) -> Self {
176        self.shared_cache = on;
177        self
178    }
179}
180
181impl ConnectionFactory for SqliteConnectOptions {
182    // fn connect(&self) -> BoxFuture<'_, Result<Box<SqliteConnection>>>
183    fn connect(&self) -> Pin<Box<dyn Future<Output = Result<Box<(dyn rsdbc_core::connection::Connection + 'static)>>> + Send>>
184    {
185        todo!()
186        // Box::pin(async move {
187        //     let mut flags = OpenFlags::SQLITE_OPEN_NO_MUTEX;
188        //
189        //     flags |= if self.read_only {
190        //         OpenFlags::SQLITE_OPEN_READ_ONLY
191        //     } else if self.create_if_missing {
192        //         OpenFlags::SQLITE_OPEN_CREATE | OpenFlags::SQLITE_OPEN_READ_WRITE
193        //     } else {
194        //         OpenFlags::SQLITE_OPEN_READ_WRITE
195        //     };
196        //
197        //     if self.in_memory {
198        //         flags |= OpenFlags::SQLITE_OPEN_MEMORY;
199        //     }
200        //
201        //     flags |= if self.shared_cache {
202        //         OpenFlags::SQLITE_OPEN_SHARED_CACHE
203        //     } else {
204        //         OpenFlags::SQLITE_OPEN_PRIVATE_CACHE
205        //     };
206        //
207        //     let conn =
208        //         rusqlite::Connection::open_with_flags(self.filename.to_path_buf(), flags)
209        //             .map_err(to_rsdbc_err)?;
210        //
211        //     conn.busy_timeout(self.busy_timeout);
212        //
213        //     // execute pragma
214        //     let init = format!(
215        //         "PRAGMA locking_mode = {}; PRAGMA journal_mode = {}; PRAGMA foreign_keys = {}; PRAGMA synchronous = {}; PRAGMA auto_vacuum = {}",
216        //         self.locking_mode.as_str(),
217        //         self.journal_mode.as_str(),
218        //         if self.foreign_keys { "ON" } else { "OFF" },
219        //         self.synchronous.as_str(),
220        //         self.auto_vacuum.as_str(),
221        //     );
222        //     conn.execute(init.as_str(), params![]).map_err(to_rsdbc_err)?;
223        //
224        //     // // TODO: make this better
225        //     // Ok(Box::new(SqliteConnection {
226        //     //     // conn: Mutex::new(Some(&conn)),
227        //     //     conn: Some(Arc::new(Mutex::new(conn))),
228        //     // }) as Box<(dyn rsdbc_core::connection::Connection + 'static)>)
229        //
230        //     todo!()
231        //
232        //
233        //     // let mut conn = establish(self).await?;
234        //     //
235        //     // // send an initial sql statement comprised of options
236        //     // //
237        //     // // Note that locking_mode should be set before journal_mode; see
238        //     // // https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory .
239        //     // let init = format!(
240        //     //     "PRAGMA locking_mode = {}; PRAGMA journal_mode = {}; PRAGMA foreign_keys = {}; PRAGMA synchronous = {}; PRAGMA auto_vacuum = {}",
241        //     //     self.locking_mode.as_str(),
242        //     //     self.journal_mode.as_str(),
243        //     //     if self.foreign_keys { "ON" } else { "OFF" },
244        //     //     self.synchronous.as_str(),
245        //     //     self.auto_vacuum.as_str(),
246        //     // );
247        //     //
248        //     // conn.execute(&*init).await?;
249        //     //
250        //     // Ok(conn)
251        // })
252    }
253
254    // TODO: use SQLite Connection Factory Metadata?
255    fn get_metadata(&self) -> Box<dyn ConnectionFactoryMetadata> {
256        todo!()
257    }
258}