Merge 'Pragma busy timeout' from Nikita Sivukhin

Expose busy_timeout added in #3067 as a `PRAGMA busy_timeout=<ms
duration>`
https://www.sqlite.org/pragma.html#pragma_busy_timeout

Reviewed-by: Avinash Sajjanshetty (@avinassh)
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>

Closes #3224
This commit is contained in:
Preston Thorpe
2025-09-20 14:36:29 -04:00
committed by GitHub
5 changed files with 38 additions and 3 deletions

View File

@@ -413,7 +413,7 @@ impl Connection {
.inner
.lock()
.map_err(|e| Error::MutexError(e.to_string()))?;
conn.busy_timeout(duration);
conn.set_busy_timeout(duration);
Ok(())
}
}

View File

@@ -2174,10 +2174,14 @@ impl Connection {
/// 5. Step through query -> returns Busy -> return Busy to user
///
/// This slight api change demonstrated a better throughtput in `perf/throughput/turso` benchmark
pub fn busy_timeout(&self, mut duration: Option<std::time::Duration>) {
pub fn set_busy_timeout(&self, mut duration: Option<std::time::Duration>) {
duration = duration.filter(|duration| !duration.is_zero());
self.busy_timeout.set(duration);
}
pub fn get_busy_timeout(&self) -> Option<std::time::Duration> {
self.busy_timeout.get()
}
}
#[derive(Debug, Default)]

View File

@@ -102,6 +102,10 @@ pub fn pragma_for(pragma: &PragmaName) -> Pragma {
PragmaFlags::NoColumns1 | PragmaFlags::Result0,
&["auto_vacuum"],
),
BusyTimeout => Pragma::new(
PragmaFlags::NoColumns1 | PragmaFlags::Result0,
&["busy_timeout"],
),
IntegrityCheck => Pragma::new(
PragmaFlags::NeedSchema | PragmaFlags::ReadOnly | PragmaFlags::Result0,
&["message"],

View File

@@ -99,7 +99,7 @@ fn update_pragma(
let app_id_value = match data {
Value::Integer(i) => i as i32,
Value::Float(f) => f as i32,
_ => unreachable!(),
_ => bail_parse_error!("expected integer, got {:?}", data),
};
program.emit_insn(Insn::SetCookie {
@@ -110,6 +110,19 @@ fn update_pragma(
});
Ok((program, TransactionMode::Write))
}
PragmaName::BusyTimeout => {
let data = parse_signed_number(&value)?;
let busy_timeout_ms = match data {
Value::Integer(i) => i as i32,
Value::Float(f) => f as i32,
_ => bail_parse_error!("expected integer, got {:?}", data),
};
let busy_timeout_ms = busy_timeout_ms.max(0);
connection.set_busy_timeout(Some(std::time::Duration::from_millis(
busy_timeout_ms as u64,
)));
Ok((program, TransactionMode::Write))
}
PragmaName::CacheSize => {
let cache_size = match parse_signed_number(&value)? {
Value::Integer(size) => size,
@@ -388,6 +401,18 @@ fn query_pragma(
program.emit_result_row(register, 1);
Ok((program, TransactionMode::Read))
}
PragmaName::BusyTimeout => {
program.emit_int(
connection
.get_busy_timeout()
.map(|t| t.as_millis() as i64)
.unwrap_or_default(),
register,
);
program.emit_result_row(register, 1);
program.add_pragma_result_column(pragma.to_string());
Ok((program, TransactionMode::None))
}
PragmaName::CacheSize => {
program.emit_int(connection.get_cache_size() as i64, register);
program.emit_result_row(register, 1);

View File

@@ -1312,6 +1312,8 @@ pub enum PragmaName {
ApplicationId,
/// set the autovacuum mode
AutoVacuum,
/// set the busy_timeout (see https://www.sqlite.org/pragma.html#pragma_busy_timeout)
BusyTimeout,
/// `cache_size` pragma
CacheSize,
/// encryption cipher algorithm name for encrypted databases