Skip to content

Commit dbd2fc6

Browse files
committed
Support custom initial options for sqlite
Apply suggestions from code review Co-authored-by: Austin Bonander <[email protected]> Apply suggestions from code review Co-authored-by: Austin Bonander <[email protected]> Use order-preserving map to set pragmas for an initial sqlite statement
1 parent e33e451 commit dbd2fc6

File tree

3 files changed

+54
-34
lines changed

3 files changed

+54
-34
lines changed

sqlx-core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,4 @@ stringprep = "0.1.2"
160160
bstr = { version = "0.2.14", default-features = false, features = ["std"], optional = true }
161161
git2 = { version = "0.13.12", default-features = false, optional = true }
162162
hashlink = "0.7.0"
163+
indexmap = "1.7.0"

sqlx-core/src/sqlite/options/connect.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,9 @@ impl ConnectOptions for SqliteConnectOptions {
1818
let mut conn = establish(self).await?;
1919

2020
// send an initial sql statement comprised of options
21-
//
22-
// page_size must be set before any other action on the database.
23-
//
24-
// Note that locking_mode should be set before journal_mode; see
25-
// https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory .
26-
let init = format!(
27-
"PRAGMA page_size = {}; PRAGMA locking_mode = {}; PRAGMA journal_mode = {}; PRAGMA foreign_keys = {}; PRAGMA synchronous = {}; PRAGMA auto_vacuum = {}",
28-
self.page_size,
29-
self.locking_mode.as_str(),
30-
self.journal_mode.as_str(),
31-
if self.foreign_keys { "ON" } else { "OFF" },
32-
self.synchronous.as_str(),
33-
self.auto_vacuum.as_str(),
34-
);
35-
36-
conn.execute(&*init).await?;
21+
for (key, value) in self.pragmas.iter() {
22+
conn.execute(&*format!("PRAGMA {} = {};", key, value)).await?;
23+
}
3724

3825
Ok(conn)
3926
})

sqlx-core/src/sqlite/options/mod.rs

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ pub use locking_mode::SqliteLockingMode;
1414
use std::{borrow::Cow, time::Duration};
1515
pub use synchronous::SqliteSynchronous;
1616

17+
use indexmap::IndexMap;
18+
1719
/// Options and flags which can be used to configure a SQLite connection.
1820
///
1921
/// A value of `SqliteConnectOptions` can be parsed from a connection URI,
@@ -53,16 +55,11 @@ pub struct SqliteConnectOptions {
5355
pub(crate) in_memory: bool,
5456
pub(crate) read_only: bool,
5557
pub(crate) create_if_missing: bool,
56-
pub(crate) journal_mode: SqliteJournalMode,
57-
pub(crate) locking_mode: SqliteLockingMode,
58-
pub(crate) foreign_keys: bool,
5958
pub(crate) shared_cache: bool,
6059
pub(crate) statement_cache_capacity: usize,
6160
pub(crate) busy_timeout: Duration,
6261
pub(crate) log_settings: LogSettings,
63-
pub(crate) synchronous: SqliteSynchronous,
64-
pub(crate) auto_vacuum: SqliteAutoVacuum,
65-
pub(crate) page_size: u32,
62+
pub(crate) pragmas: IndexMap<String, String>,
6663
}
6764

6865
impl Default for SqliteConnectOptions {
@@ -73,21 +70,43 @@ impl Default for SqliteConnectOptions {
7370

7471
impl SqliteConnectOptions {
7572
pub fn new() -> Self {
73+
// set default pragmas
74+
let mut pragmas = IndexMap::new();
75+
76+
let locking_mode: SqliteLockingMode = Default::default();
77+
let auto_vacuum: SqliteAutoVacuum = Default::default();
78+
79+
// page_size must be set before any other action on the database.
80+
pragmas.insert("page_size".into(), 4096.to_string());
81+
82+
// Note that locking_mode should be set before journal_mode; see
83+
// https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory .
84+
pragmas.insert("locking_mode".into(), locking_mode.as_str().into());
85+
86+
pragmas.insert(
87+
"journal_mode".into(),
88+
SqliteJournalMode::Wal.as_str().into(),
89+
);
90+
91+
pragmas.insert("foreign_keys".into(), "ON".into());
92+
93+
pragmas.insert(
94+
"synchronous".into(),
95+
SqliteSynchronous::Full.as_str().into(),
96+
);
97+
98+
pragmas.insert("auto_vacuum".into(), auto_vacuum.as_str().into());
99+
76100
Self {
77101
filename: Cow::Borrowed(Path::new(":memory:")),
78102
in_memory: false,
79103
read_only: false,
80104
create_if_missing: false,
81-
foreign_keys: true,
82105
shared_cache: false,
83106
statement_cache_capacity: 100,
84-
journal_mode: SqliteJournalMode::Wal,
85-
locking_mode: Default::default(),
86107
busy_timeout: Duration::from_secs(5),
87108
log_settings: Default::default(),
88-
synchronous: SqliteSynchronous::Full,
89-
auto_vacuum: Default::default(),
90-
page_size: 4096,
109+
pragmas,
91110
}
92111
}
93112

@@ -101,7 +120,10 @@ impl SqliteConnectOptions {
101120
///
102121
/// By default, this is enabled.
103122
pub fn foreign_keys(mut self, on: bool) -> Self {
104-
self.foreign_keys = on;
123+
self.pragmas.insert(
124+
"foreign_keys".into(),
125+
(if on { "ON" } else { "OFF" }).into(),
126+
);
105127
self
106128
}
107129

@@ -118,15 +140,17 @@ impl SqliteConnectOptions {
118140
/// The default journal mode is WAL. For most use cases this can be significantly faster but
119141
/// there are [disadvantages](https://www.sqlite.org/wal.html).
120142
pub fn journal_mode(mut self, mode: SqliteJournalMode) -> Self {
121-
self.journal_mode = mode;
143+
self.pragmas
144+
.insert("journal_mode".into(), mode.as_str().into());
122145
self
123146
}
124147

125148
/// Sets the [locking mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) for the database connection.
126149
///
127150
/// The default locking mode is NORMAL.
128151
pub fn locking_mode(mut self, mode: SqliteLockingMode) -> Self {
129-
self.locking_mode = mode;
152+
self.pragmas
153+
.insert("locking_mode".into(), mode.as_str().into());
130154
self
131155
}
132156

@@ -171,23 +195,31 @@ impl SqliteConnectOptions {
171195
/// The default synchronous settings is FULL. However, if durability is not a concern,
172196
/// then NORMAL is normally all one needs in WAL mode.
173197
pub fn synchronous(mut self, synchronous: SqliteSynchronous) -> Self {
174-
self.synchronous = synchronous;
198+
self.pragmas
199+
.insert("synchronous".into(), synchronous.as_str().into());
175200
self
176201
}
177202

178203
/// Sets the [auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) setting for the database connection.
179204
///
180205
/// The default auto_vacuum setting is NONE.
181206
pub fn auto_vacuum(mut self, auto_vacuum: SqliteAutoVacuum) -> Self {
182-
self.auto_vacuum = auto_vacuum;
207+
self.pragmas
208+
.insert("auto_vacuum".into(), auto_vacuum.as_str().into());
209+
self
210+
}
211+
212+
/// Sets custom initial pragmas for the database connection.
213+
pub fn pragma(mut self, key: &str, value: &str) -> Self {
214+
self.pragmas.insert(key.into(), value.into());
183215
self
184216
}
185217

186218
/// Sets the [page_size](https://www.sqlite.org/pragma.html#pragma_page_size) setting for the database connection.
187219
///
188220
/// The default page_size setting is 4096.
189221
pub fn page_size(mut self, page_size: u32) -> Self {
190-
self.page_size = page_size;
222+
self.pragmas.insert("page_size".into(), page_size.to_string());
191223
self
192224
}
193225
}

0 commit comments

Comments
 (0)