Skip to content

Commit 6b29092

Browse files
committed
Use order-preserving map to set pragmas for an initial sqlite statement
1 parent e69b0f1 commit 6b29092

File tree

3 files changed

+50
-46
lines changed

3 files changed

+50
-46
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: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,10 @@ 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-
let page_size_opt = format!("PRAGMA page_size = {};", self.page_size);
24-
conn.execute(&*page_size_opt).await?;
25-
26-
// apply custom initial_options
27-
if let Some(stmt) = self.initial_options {
28-
conn.execute(&*stmt).await?;
21+
for (key, value) in self.pragmas.iter() {
22+
conn.execute(&*format!("PRAGMA {} = {};", key, value)).await?;
2923
}
3024

31-
// Note that locking_mode should be set before journal_mode; see
32-
// https://www.sqlite.org/wal.html#use_of_wal_without_shared_memory .
33-
let init = format!(
34-
"PRAGMA locking_mode = {}; PRAGMA journal_mode = {}; PRAGMA foreign_keys = {}; PRAGMA synchronous = {}; PRAGMA auto_vacuum = {}",
35-
self.locking_mode.as_str(),
36-
self.journal_mode.as_str(),
37-
if self.foreign_keys { "ON" } else { "OFF" },
38-
self.synchronous.as_str(),
39-
self.auto_vacuum.as_str(),
40-
);
41-
42-
conn.execute(&*init).await?;
43-
4425
Ok(conn)
4526
})
4627
}

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

Lines changed: 47 additions & 25 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,17 +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) initial_options: Option<&'static str>,
66-
pub(crate) page_size: u32,
62+
pub(crate) pragmas: IndexMap<String, String>,
6763
}
6864

6965
impl Default for SqliteConnectOptions {
@@ -74,22 +70,43 @@ impl Default for SqliteConnectOptions {
7470

7571
impl SqliteConnectOptions {
7672
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+
77100
Self {
78101
filename: Cow::Borrowed(Path::new(":memory:")),
79102
in_memory: false,
80103
read_only: false,
81104
create_if_missing: false,
82-
foreign_keys: true,
83105
shared_cache: false,
84106
statement_cache_capacity: 100,
85-
journal_mode: SqliteJournalMode::Wal,
86-
locking_mode: Default::default(),
87107
busy_timeout: Duration::from_secs(5),
88108
log_settings: Default::default(),
89-
synchronous: SqliteSynchronous::Full,
90-
auto_vacuum: Default::default(),
91-
initial_options: None,
92-
page_size: 4096,
109+
pragmas,
93110
}
94111
}
95112

@@ -103,7 +120,10 @@ impl SqliteConnectOptions {
103120
///
104121
/// By default, this is enabled.
105122
pub fn foreign_keys(mut self, on: bool) -> Self {
106-
self.foreign_keys = on;
123+
self.pragmas.insert(
124+
"foreign_keys".into(),
125+
(if on { "ON" } else { "OFF" }).into(),
126+
);
107127
self
108128
}
109129

@@ -120,15 +140,17 @@ impl SqliteConnectOptions {
120140
/// The default journal mode is WAL. For most use cases this can be significantly faster but
121141
/// there are [disadvantages](https://www.sqlite.org/wal.html).
122142
pub fn journal_mode(mut self, mode: SqliteJournalMode) -> Self {
123-
self.journal_mode = mode;
143+
self.pragmas
144+
.insert("journal_mode".into(), mode.as_str().into());
124145
self
125146
}
126147

127148
/// Sets the [locking mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) for the database connection.
128149
///
129150
/// The default locking mode is NORMAL.
130151
pub fn locking_mode(mut self, mode: SqliteLockingMode) -> Self {
131-
self.locking_mode = mode;
152+
self.pragmas
153+
.insert("locking_mode".into(), mode.as_str().into());
132154
self
133155
}
134156

@@ -173,31 +195,31 @@ impl SqliteConnectOptions {
173195
/// The default synchronous settings is FULL. However, if durability is not a concern,
174196
/// then NORMAL is normally all one needs in WAL mode.
175197
pub fn synchronous(mut self, synchronous: SqliteSynchronous) -> Self {
176-
self.synchronous = synchronous;
198+
self.pragmas
199+
.insert("synchronous".into(), synchronous.as_str().into());
177200
self
178201
}
179202

180203
/// Sets the [auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) setting for the database connection.
181204
///
182205
/// The default auto_vacuum setting is NONE.
183206
pub fn auto_vacuum(mut self, auto_vacuum: SqliteAutoVacuum) -> Self {
184-
self.auto_vacuum = auto_vacuum;
207+
self.pragmas
208+
.insert("auto_vacuum".into(), auto_vacuum.as_str().into());
185209
self
186210
}
187211

188-
/// Sets custom initial settings for the database connection.
189-
///
190-
/// The default initial_options is NONE.
191-
pub fn initial_options(mut self, initial_options: &'static str) -> Self {
192-
self.initial_options = Some(initial_options);
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());
193215
self
194216
}
195217

196218
/// Sets the [page_size](https://www.sqlite.org/pragma.html#pragma_page_size) setting for the database connection.
197219
///
198220
/// The default page_size setting is 4096.
199221
pub fn page_size(mut self, page_size: u32) -> Self {
200-
self.page_size = page_size;
222+
self.pragmas.insert("page_size".into(), page_size.to_string());
201223
self
202224
}
203225
}

0 commit comments

Comments
 (0)