Skip to content

Commit 4915958

Browse files
committed
[SQLite] Add option to execute PRAGMA optimize; on close of a connection
1 parent 76ae286 commit 4915958

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub(crate) use handle::{ConnectionHandle, ConnectionHandleRaw};
1212
use crate::common::StatementCache;
1313
use crate::connection::{Connection, LogSettings};
1414
use crate::error::Error;
15+
use crate::executor::Executor;
1516
use crate::sqlite::connection::establish::EstablishParams;
1617
use crate::sqlite::connection::worker::ConnectionWorker;
1718
use crate::sqlite::statement::VirtualStatement;
@@ -39,6 +40,8 @@ mod worker;
3940
/// You can explicitly call [`.close()`][Self::close] to ensure the database is closed successfully
4041
/// or get an error otherwise.
4142
pub struct SqliteConnection {
43+
optimize_on_close: bool,
44+
analysis_limit: Option<u32>,
4245
pub(crate) worker: ConnectionWorker,
4346
pub(crate) row_channel_size: usize,
4447
}
@@ -70,6 +73,8 @@ impl SqliteConnection {
7073
let params = EstablishParams::from_options(options)?;
7174
let worker = ConnectionWorker::establish(params).await?;
7275
Ok(Self {
76+
optimize_on_close: options.optimize_on_close,
77+
analysis_limit: options.analysis_limit,
7378
worker,
7479
row_channel_size: options.row_channel_size,
7580
})
@@ -146,6 +151,14 @@ impl Connection for SqliteConnection {
146151

147152
fn close(mut self) -> BoxFuture<'static, Result<(), Error>> {
148153
Box::pin(async move {
154+
if self.optimize_on_close {
155+
let mut pragma_string = String::new();
156+
if let Some(limit) = self.analysis_limit {
157+
pragma_string.push_str(&format!("PRAGMA analysis_limit = {}; ", limit));
158+
}
159+
pragma_string.push_str("PRAGMA optimize;");
160+
self.execute(&*pragma_string).await?;
161+
}
149162
let shutdown = self.worker.shutdown();
150163
// Drop the statement worker, which should
151164
// cover all references to the connection handle outside of the worker thread

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

+35
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ pub struct SqliteConnectOptions {
7979

8080
pub(crate) serialized: bool,
8181
pub(crate) thread_name: Arc<DebugFn<dyn Fn(u64) -> String + Send + Sync + 'static>>,
82+
83+
pub(crate) optimize_on_close: bool,
84+
pub(crate) analysis_limit: Option<u32>,
8285
}
8386

8487
impl Default for SqliteConnectOptions {
@@ -185,6 +188,8 @@ impl SqliteConnectOptions {
185188
thread_name: Arc::new(DebugFn(|id| format!("sqlx-sqlite-worker-{}", id))),
186189
command_channel_size: 50,
187190
row_channel_size: 50,
191+
optimize_on_close: false,
192+
analysis_limit: None,
188193
}
189194
}
190195

@@ -458,4 +463,34 @@ impl SqliteConnectOptions {
458463
.insert(extension_name.into(), Some(entry_point.into()));
459464
self
460465
}
466+
/// Execute `PRAGMA optimize;` on the SQLite connection before closing.
467+
///
468+
/// The SQLite manual recommends using this for long-lived databases.
469+
///
470+
/// This will collect and store statistics about the layout of data in your tables to help the query planner make better decisions.
471+
/// Over the connection's lifetime, the query planner will make notes about which tables could use up-to-date statistics so this
472+
/// command doesn't have to scan the whole database every time. Thus, the best time to execute this is on connection close.
473+
///
474+
/// You may also wish to set the value for [`analyze_limit`][Self::analysis_limit] so database connections close quickly,
475+
/// even if your database is very large.
476+
///
477+
/// Not enabled by default.
478+
///
479+
/// See [the SQLite manual](https://www.sqlite.org/lang_analyze.html#automatically_running_analyze) for details.
480+
pub fn optimize_on_close(mut self, enabled: bool) -> Self {
481+
self.optimize_on_close = enabled;
482+
self
483+
}
484+
485+
/// Set a soft limit on the number of rows that `ANALYZE` touches per index.
486+
///
487+
/// This also affects `PRAGMA optimize` which is set by [Self::optimize_on_close].
488+
///
489+
/// The value recommended by SQLite is `400`. There is no default.
490+
///
491+
/// See [the SQLite manual](https://www.sqlite.org/lang_analyze.html#approx) for details.
492+
pub fn analysis_limit(mut self, limit: impl Into<Option<u32>>) -> Self {
493+
self.analysis_limit = limit.into();
494+
self
495+
}
461496
}

0 commit comments

Comments
 (0)