Add busy_timeout script-level option, override any busy_timeout pragma

This commit is contained in:
Tim Wojtulewicz 2025-06-03 15:03:40 -07:00
parent 0e5b3def84
commit be71196fa7
3 changed files with 16 additions and 9 deletions

View file

@ -20,14 +20,19 @@ export {
## different between the two. ## different between the two.
table_name: string; table_name: string;
## The timeout for the connection to the database. This is set
## per-connection. It is equivalent to setting a ``busy_timeout`` pragma
## value, but that value will be ignored in favor of this field.
busy_timeout: interval &default=5 secs;
## Key/value table for passing pragma commands when opening the database. ## Key/value table for passing pragma commands when opening the database.
## These must be pairs that can be passed to the ``pragma`` command in ## These must be pairs that can be passed to the ``pragma`` command in
## sqlite. The ``integrity_check`` pragma is run automatically and does ## sqlite. The ``integrity_check`` pragma is run automatically and does
## not need to be included here. For pragmas without a second argument, ## not need to be included here. For pragmas without a second argument,
## set the value to an empty string. ## set the value to an empty string. Setting the ``busy_timeout`` pragma
## here will be ignored.
pragma_commands: table[string] of string &ordered &default=table( pragma_commands: table[string] of string &ordered &default=table(
["integrity_check"] = "", ["integrity_check"] = "",
["busy_timeout"] = "5000",
["journal_mode"] = "WAL", ["journal_mode"] = "WAL",
["synchronous"] = "normal", ["synchronous"] = "normal",
["temp_store"] = "memory" ["temp_store"] = "memory"

View file

@ -84,6 +84,8 @@ OperationResult SQLite::DoOpen(OpenResultCallback* cb, RecordValPtr options) {
full_path = zeek::filesystem::path(path->ToStdString()).string(); full_path = zeek::filesystem::path(path->ToStdString()).string();
table_name = backend_options->GetField<StringVal>("table_name")->ToStdString(); table_name = backend_options->GetField<StringVal>("table_name")->ToStdString();
auto busy_timeout = backend_options->GetField<IntervalVal>("busy_timeout")->Get();
auto pragma_timeout_val = backend_options->GetField<IntervalVal>("pragma_timeout"); auto pragma_timeout_val = backend_options->GetField<IntervalVal>("pragma_timeout");
pragma_timeout = std::chrono::milliseconds(static_cast<int64_t>(pragma_timeout_val->Get() * 1000)); pragma_timeout = std::chrono::milliseconds(static_cast<int64_t>(pragma_timeout_val->Get() * 1000));
@ -99,25 +101,26 @@ OperationResult SQLite::DoOpen(OpenResultCallback* cb, RecordValPtr options) {
return open_res; return open_res;
} }
// TODO: Should we use sqlite3_busy_timeout here instead of using the pragma? That would sqlite3_busy_timeout(db, busy_timeout * 1000);
// at least let us skip over one. The busy timeout is per-connection as well, so it'll
// never fail to run like the other pragmas can.
// sqlite3_busy_timeout(db, 2000);
auto pragmas = backend_options->GetField<TableVal>("pragma_commands"); auto pragmas = backend_options->GetField<TableVal>("pragma_commands");
for ( const auto& iter : *(pragmas->Get()) ) { for ( const auto& iter : *(pragmas->Get()) ) {
auto k = iter.GetHashKey(); auto k = iter.GetHashKey();
auto v = iter.value;
auto vl = pragmas->GetTableHash()->RecoverVals(*k); auto vl = pragmas->GetTableHash()->RecoverVals(*k);
auto ks = vl->AsListVal()->Idx(0)->AsStringVal(); auto ks = vl->AsListVal()->Idx(0)->AsStringVal();
auto ks_sv = ks->ToStdStringView(); auto ks_sv = ks->ToStdStringView();
if ( ks_sv == "busy_timeout" )
continue;
auto vs = iter.value->GetVal()->AsStringVal(); auto vs = iter.value->GetVal()->AsStringVal();
auto vs_sv = vs->ToStdStringView(); auto vs_sv = vs->ToStdStringView();
auto pragma_res = RunPragma(ks_sv, vs_sv); auto pragma_res = RunPragma(ks_sv, vs_sv);
if ( pragma_res.code != ReturnCode::SUCCESS ) { if ( pragma_res.code != ReturnCode::SUCCESS ) {
Error(pragma_res.err_str.c_str()); Error(pragma_res.err_str.c_str());
Close(nullptr);
return pragma_res; return pragma_res;
} }
} }

View file

@ -1,7 +1,6 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
Storage::backend_opened, Storage::STORAGE_BACKEND_SQLITE, [serializer=Storage::STORAGE_SERIALIZER_JSON, sqlite=[database_path=test.sqlite, table_name=testing, pragma_commands={ Storage::backend_opened, Storage::STORAGE_BACKEND_SQLITE, [serializer=Storage::STORAGE_SERIALIZER_JSON, sqlite=[database_path=test.sqlite, table_name=testing, busy_timeout=5.0 secs, pragma_commands={
[integrity_check] = , [integrity_check] = ,
[busy_timeout] = 5000,
[journal_mode] = WAL, [journal_mode] = WAL,
[synchronous] = normal, [synchronous] = normal,
[temp_store] = memory [temp_store] = memory