diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 39706fdd5..15ae191f7 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -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(()) } } diff --git a/core/lib.rs b/core/lib.rs index ae8fb31ab..79999a7bb 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -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) { + pub fn set_busy_timeout(&self, mut duration: Option) { duration = duration.filter(|duration| !duration.is_zero()); self.busy_timeout.set(duration); } + + pub fn get_busy_timeout(&self) -> Option { + self.busy_timeout.get() + } } #[derive(Debug, Default)] diff --git a/core/pragma.rs b/core/pragma.rs index edcfd21b9..c83509a69 100644 --- a/core/pragma.rs +++ b/core/pragma.rs @@ -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"], diff --git a/core/translate/pragma.rs b/core/translate/pragma.rs index 7fa74e9ca..fa4274ed3 100644 --- a/core/translate/pragma.rs +++ b/core/translate/pragma.rs @@ -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); diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 3c331107a..988bbab95 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -1312,6 +1312,8 @@ pub enum PragmaName { ApplicationId, /// set the autovacuum mode AutoVacuum, + /// set the busy_timeout + BusyTimeout, /// `cache_size` pragma CacheSize, /// encryption cipher algorithm name for encrypted databases