Skip to content

Commit 6564053

Browse files
committed
Replace run methods’ Regulator option with QueryOptions struct
I’m going to want to pass an additional option to the various run methods. The Regulator is already optional, so I might as well prepare the code to take all of the options as a bundle.
1 parent 80a340a commit 6564053

File tree

6 files changed

+67
-46
lines changed

6 files changed

+67
-46
lines changed

src/workerd/api/actor-state.c++

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,8 @@ jsg::JsRef<jsg::JsValue> DurableObjectStorage::transactionSync(
712712
// depth to each savepoint name like I originally thought. We should refactor this -- and use
713713
// prepared statements.
714714

715-
sqlite.run(SqliteDatabase::TRUSTED, kj::str("SAVEPOINT _cf_sync_savepoint_", depth));
715+
sqlite.run(
716+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("SAVEPOINT _cf_sync_savepoint_", depth));
716717
return js.tryCatch([&]() {
717718
auto result = callback(js);
718719

@@ -721,14 +722,17 @@ jsg::JsRef<jsg::JsValue> DurableObjectStorage::transactionSync(
721722
JSG_REQUIRE(!sqlite.observedCriticalError(), Error,
722723
"Cannot commit transaction due to an earlier SQL critical error");
723724

724-
sqlite.run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_sync_savepoint_", depth));
725+
sqlite.run(
726+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("RELEASE _cf_sync_savepoint_", depth));
725727
return kj::mv(result);
726728
}, [&](jsg::Value exception) -> jsg::JsRef<jsg::JsValue> {
727729
// If a critical error forced an automatic rollback, we skip the rollback and release
728730
// attempt, because savepoints should already be released.
729731
if (!sqlite.observedCriticalError()) {
730-
sqlite.run(SqliteDatabase::TRUSTED, kj::str("ROLLBACK TO _cf_sync_savepoint_", depth));
731-
sqlite.run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_sync_savepoint_", depth));
732+
sqlite.run({.regulator = SqliteDatabase::TRUSTED},
733+
kj::str("ROLLBACK TO _cf_sync_savepoint_", depth));
734+
sqlite.run(
735+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("RELEASE _cf_sync_savepoint_", depth));
732736
}
733737
js.throwException(kj::mv(exception));
734738
});

src/workerd/api/sql.c++

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ SqlStorage::IngestResult SqlStorage::ingest(jsg::Lock& js, kj::String querySql)
8383

8484
void SqlStorage::setMaxPageCountForTest(jsg::Lock& js, int count) {
8585
auto& db = getDb(js);
86-
db.run(SqliteDatabase::TRUSTED, kj::str("PRAGMA max_page_count = ", count));
86+
db.run({.regulator = SqliteDatabase::TRUSTED}, kj::str("PRAGMA max_page_count = ", count));
8787
}
8888

8989
jsg::Ref<SqlStorage::Statement> SqlStorage::prepare(jsg::Lock& js, jsg::JsString query) {
@@ -156,7 +156,7 @@ SqlStorage::Cursor::State::State(SqliteDatabase& db,
156156
kj::StringPtr sqlCode,
157157
kj::Array<BindingValue> bindingsParam)
158158
: bindings(kj::mv(bindingsParam)),
159-
query(db.run(regulator, sqlCode, mapBindings(bindings).asPtr())) {}
159+
query(db.run({.regulator = regulator}, sqlCode, mapBindings(bindings).asPtr())) {}
160160

161161
SqlStorage::Cursor::State::State(
162162
kj::Rc<CachedStatement> cachedStatementParam, kj::Array<BindingValue> bindingsParam)

src/workerd/io/actor-sqlite.c++

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ ActorSqlite::ExplicitTxn::ExplicitTxn(ActorSqlite& actorSqlite): actorSqlite(act
115115
// Unfortunately this means we cannot prepare the statement, unless we prepare a series of
116116
// statements for each depth. (Actually, it could be reasonable to prepare statements for
117117
// depth 0 specifically, but I'm not going to try it for now.)
118-
actorSqlite.db->run(SqliteDatabase::TRUSTED, kj::str("SAVEPOINT _cf_savepoint_", depth));
118+
actorSqlite.db->run(
119+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("SAVEPOINT _cf_savepoint_", depth));
119120
}
120121
ActorSqlite::ExplicitTxn::~ExplicitTxn() noexcept(false) {
121122
[&]() noexcept {
@@ -158,7 +159,8 @@ kj::Maybe<kj::Promise<void>> ActorSqlite::ExplicitTxn::commit() {
158159
precommitAlarmState = actorSqlite.startPrecommitAlarmScheduling();
159160
}
160161

161-
actorSqlite.db->run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_savepoint_", depth));
162+
actorSqlite.db->run(
163+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("RELEASE _cf_savepoint_", depth));
162164
committed = true;
163165

164166
KJ_IF_SOME(p, parent) {
@@ -192,8 +194,10 @@ kj::Promise<void> ActorSqlite::ExplicitTxn::rollback() {
192194
}
193195

194196
void ActorSqlite::ExplicitTxn::rollbackImpl() noexcept(false) {
195-
actorSqlite.db->run(SqliteDatabase::TRUSTED, kj::str("ROLLBACK TO _cf_savepoint_", depth));
196-
actorSqlite.db->run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_savepoint_", depth));
197+
actorSqlite.db->run(
198+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("ROLLBACK TO _cf_savepoint_", depth));
199+
actorSqlite.db->run(
200+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("RELEASE _cf_savepoint_", depth));
197201
KJ_IF_SOME(p, parent) {
198202
alarmDirty = p->alarmDirty;
199203
} else {
@@ -483,19 +487,23 @@ kj::Maybe<kj::Promise<void>> ActorSqlite::put(kj::Array<KeyValuePair> pairs, Wri
483487
txn->commit();
484488
} else {
485489
// If we are in a transaction, let's just set a SAVEPOINT that we can rollback to if needed.
486-
db->run(SqliteDatabase::TRUSTED, kj::str("SAVEPOINT _cf_put_multiple_savepoint"));
490+
db->run(
491+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("SAVEPOINT _cf_put_multiple_savepoint"));
487492
for (const auto& pair: pairs) {
488493
try {
489494
kv.put(pair.key, pair.value);
490495
} catch (kj::Exception& e) {
491496
// We need to rollback to the putMultiple SAVEPOINT. Do it, and then release the SAVEPOINT.
492-
db->run(SqliteDatabase::TRUSTED, kj::str("ROLLBACK TO _cf_put_multiple_savepoint"));
493-
db->run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_put_multiple_savepoint"));
497+
db->run({.regulator = SqliteDatabase::TRUSTED},
498+
kj::str("ROLLBACK TO _cf_put_multiple_savepoint"));
499+
db->run({.regulator = SqliteDatabase::TRUSTED},
500+
kj::str("RELEASE _cf_put_multiple_savepoint"));
494501
kj::throwFatalException(kj::mv(e));
495502
}
496503
}
497504
// We're done here. RELEASE the savepoint.
498-
db->run(SqliteDatabase::TRUSTED, kj::str("RELEASE _cf_put_multiple_savepoint"));
505+
db->run(
506+
{.regulator = SqliteDatabase::TRUSTED}, kj::str("RELEASE _cf_put_multiple_savepoint"));
499507
}
500508
} else {
501509
for (auto& pair: pairs) {

src/workerd/util/sqlite-test.c++

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ RowCounts countRowsTouched(SqliteDatabase& db,
482482
uint64_t rowsFound = 0;
483483

484484
// Runs a query; retrieves and discards all the data.
485-
auto query = db.run(regulator, sqlCode, bindParams...);
485+
auto query = db.run({.regulator = regulator}, sqlCode, bindParams...);
486486
while (!query.isDone()) {
487487
rowsFound++;
488488
query.nextRow();
@@ -749,10 +749,10 @@ KJ_TEST("SQLite row counters with triggers") {
749749

750750
// A deletion incurs two writes: one for the row and one for the log.
751751
{
752-
db.run(regulator, "DELETE FROM things");
753-
db.run(regulator, "INSERT INTO things (id) VALUES (1)");
754-
db.run(regulator, "INSERT INTO things (id) VALUES (2)");
755-
db.run(regulator, "INSERT INTO things (id) VALUES (3)");
752+
db.run({.regulator = regulator}, "DELETE FROM things");
753+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (1)");
754+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (2)");
755+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (3)");
756756

757757
RowCounts stats = countRowsTouched(db, regulator, "DELETE FROM things");
758758
KJ_EXPECT(stats.written == 6);
@@ -859,9 +859,9 @@ KJ_TEST("SQLite observer addQueryStats") {
859859
int rowsWrittenBefore = sqliteObserver.rowsWritten;
860860
constexpr int dbRowCount = 3;
861861
{
862-
db.run(regulator, "INSERT INTO things (id) VALUES (10)");
863-
db.run(regulator, "INSERT INTO things (id) VALUES (11)");
864-
db.run(regulator, "INSERT INTO things (id) VALUES (12)");
862+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (10)");
863+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (11)");
864+
db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (12)");
865865
}
866866
KJ_EXPECT(sqliteObserver.rowsRead - rowsReadBefore == dbRowCount);
867867
KJ_EXPECT(sqliteObserver.rowsWritten - rowsWrittenBefore == dbRowCount);
@@ -906,7 +906,7 @@ KJ_TEST("SQLite observer addQueryStats") {
906906
rowsReadBefore = sqliteObserver.rowsRead;
907907
rowsWrittenBefore = sqliteObserver.rowsWritten;
908908
{
909-
auto query = db.run(regulator, "INSERT INTO things (id) VALUES (100)");
909+
auto query = db.run({.regulator = regulator}, "INSERT INTO things (id) VALUES (100)");
910910
db.reset();
911911
}
912912
KJ_EXPECT(sqliteObserver.rowsRead - rowsReadBefore == 1);
@@ -1552,7 +1552,7 @@ KJ_TEST("I/O exceptions pass through SQLite") {
15521552
SqliteDatabase::Vfs vfs(*dir);
15531553
SqliteDatabase db(vfs, kj::Path({"db"}), kj::WriteMode::CREATE | kj::WriteMode::MODIFY);
15541554

1555-
db.run(SqliteDatabase::TRUSTED, kj::str(R"(
1555+
db.run({.regulator = SqliteDatabase::TRUSTED}, kj::str(R"(
15561556
CREATE TABLE IF NOT EXISTS things (
15571557
id INTEGER PRIMARY KEY AUTOINCREMENT,
15581558
value INTEGER
@@ -1564,7 +1564,8 @@ KJ_TEST("I/O exceptions pass through SQLite") {
15641564
KJ_ASSERT_NONNULL(dir->dbFile)->error = KJ_EXCEPTION(FAILED, "test-vfs-error");
15651565

15661566
// It should pass through.
1567-
KJ_EXPECT_THROW_MESSAGE("test-vfs-error", db.run(SqliteDatabase::TRUSTED, kj::str(R"(
1567+
KJ_EXPECT_THROW_MESSAGE(
1568+
"test-vfs-error", db.run({.regulator = SqliteDatabase::TRUSTED}, kj::str(R"(
15681569
INSERT INTO things(value) VALUES (456);
15691570
)")));
15701571
}
@@ -1613,9 +1614,9 @@ KJ_TEST("SQLite critical error handling for SQLITE_IOERR") {
16131614
});
16141615

16151616
// Use a small cache size to force flushing to disk on even a small write
1616-
db.run(SqliteDatabase::TRUSTED, "PRAGMA cache_size = 1"); // 1 page cache
1617+
db.run({.regulator = SqliteDatabase::TRUSTED}, "PRAGMA cache_size = 1"); // 1 page cache
16171618

1618-
db.run(SqliteDatabase::TRUSTED, kj::str(R"(
1619+
db.run({.regulator = SqliteDatabase::TRUSTED}, kj::str(R"(
16191620
CREATE TABLE IF NOT EXISTS things (
16201621
id INTEGER PRIMARY KEY AUTOINCREMENT,
16211622
value INTEGER
@@ -1629,7 +1630,8 @@ KJ_TEST("SQLite critical error handling for SQLITE_IOERR") {
16291630
KJ_ASSERT_NONNULL(dir->dbFile)->error = KJ_EXCEPTION(FAILED, "test-vfs-error");
16301631

16311632
KJ_EXPECT(!db.observedCriticalError());
1632-
KJ_EXPECT_THROW_MESSAGE("test-vfs-error", db.run(SqliteDatabase::TRUSTED, kj::str(R"(
1633+
KJ_EXPECT_THROW_MESSAGE(
1634+
"test-vfs-error", db.run({.regulator = SqliteDatabase::TRUSTED}, kj::str(R"(
16331635
INSERT INTO things(value) VALUES (456);
16341636
)")));
16351637

@@ -1655,7 +1657,8 @@ KJ_TEST("SQLite critical error handling for SQLITE_FULL") {
16551657
auto largeData = kj::heapArray<byte>(100000, 'X'); // 100KB
16561658

16571659
// This should eventually trigger SQLITE_FULL
1658-
db.run(SqliteDatabase::TRUSTED, "INSERT INTO test_full VALUES (?, ?)", 1, largeData.asPtr());
1660+
db.run({.regulator = SqliteDatabase::TRUSTED}, "INSERT INTO test_full VALUES (?, ?)", 1,
1661+
largeData.asPtr());
16591662
});
16601663
}
16611664

@@ -1676,7 +1679,8 @@ KJ_TEST("SQLite critical error handling for SQLITE_NOMEM") {
16761679
// Create data that will exceed the memory limit
16771680
auto largeData = kj::heapArray<byte>(50000, 'X'); // 50KB
16781681

1679-
db.run(SqliteDatabase::TRUSTED, "INSERT INTO test_nomem VALUES (?, ?)", 2, largeData.asPtr());
1682+
db.run({.regulator = SqliteDatabase::TRUSTED}, "INSERT INTO test_nomem VALUES (?, ?)", 2,
1683+
largeData.asPtr());
16801684
});
16811685
}
16821686

src/workerd/util/sqlite.c++

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ SqliteDatabase::IngestResult SqliteDatabase::ingestSql(
847847
// Slice off the next valid statement SQL
848848
auto nextStatement = kj::str(sqlCode.first(statementLength));
849849
// Create a Query object, which will prepare & execute it
850-
auto q = Query(*this, regulator, nextStatement);
850+
auto q = Query(*this, QueryOptions{.regulator = regulator}, nextStatement);
851851

852852
rowsRead += q.getRowsRead();
853853
rowsWritten += q.getRowsWritten();
@@ -1340,11 +1340,11 @@ void SqliteDatabase::Statement::beforeSqliteReset() {
13401340
}
13411341

13421342
SqliteDatabase::Query::Query(SqliteDatabase& db,
1343-
const Regulator& regulator,
1343+
QueryOptions options,
13441344
Statement& statement,
13451345
kj::ArrayPtr<const ValuePtr> bindings)
13461346
: ResetListener(db),
1347-
regulator(regulator),
1347+
regulator(options.regulator),
13481348
maybeStatement(statement.prepareForExecution()),
13491349
queryEvent(this->db.sqliteObserver) {
13501350
// If we throw from the constructor, the destructor won't run. Need to call destroy() explicitly.
@@ -1353,11 +1353,11 @@ SqliteDatabase::Query::Query(SqliteDatabase& db,
13531353
}
13541354

13551355
SqliteDatabase::Query::Query(SqliteDatabase& db,
1356-
const Regulator& regulator,
1356+
QueryOptions options,
13571357
kj::StringPtr sqlCode,
13581358
kj::ArrayPtr<const ValuePtr> bindings)
13591359
: ResetListener(db),
1360-
regulator(regulator),
1360+
regulator(options.regulator),
13611361
ownStatement(db.prepareSql(regulator, sqlCode, 0, MULTI)),
13621362
maybeStatement(ownStatement),
13631363
queryEvent(this->db.sqliteObserver) {

src/workerd/util/sqlite.h

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class SqliteDatabase {
7272
class Lock;
7373
class LockManager;
7474
struct VfsOptions;
75+
class Regulator;
76+
77+
struct QueryOptions {
78+
const Regulator& regulator;
79+
};
7580

7681
struct IngestResult {
7782
kj::StringPtr remainder;
@@ -180,7 +185,7 @@ class SqliteDatabase {
180185
// `Query` object are both associated with the last statement. This is particularly convenient
181186
// for doing database initialization such as creating several tables at once.
182187
template <typename... Params>
183-
Query run(const Regulator& regulator, kj::StringPtr sqlCode, Params&&... bindings);
188+
Query run(QueryOptions options, kj::StringPtr sqlCode, Params&&... bindings);
184189

185190
template <size_t size>
186191
Statement prepare(const char (&sqlCode)[size]);
@@ -630,17 +635,17 @@ class SqliteDatabase::Query final: private ResetListener {
630635
friend class SqliteDatabase;
631636

632637
Query(SqliteDatabase& db,
633-
const Regulator& regulator,
638+
QueryOptions options,
634639
Statement& statement,
635640
kj::ArrayPtr<const ValuePtr> bindings);
636641
Query(SqliteDatabase& db,
637-
const Regulator& regulator,
642+
QueryOptions options,
638643
kj::StringPtr sqlCode,
639644
kj::ArrayPtr<const ValuePtr> bindings);
640645
template <typename... Params>
641-
Query(SqliteDatabase& db, const Regulator& regulator, Statement& statement, Params&&... bindings)
646+
Query(SqliteDatabase& db, QueryOptions options, Statement& statement, Params&&... bindings)
642647
: ResetListener(db),
643-
regulator(regulator),
648+
regulator(options.regulator),
644649
maybeStatement(statement.prepareForExecution()),
645650
queryEvent(this->db.sqliteObserver) {
646651
// If we throw from the constructor, the destructor won't run. Need to call destroy()
@@ -649,9 +654,9 @@ class SqliteDatabase::Query final: private ResetListener {
649654
bindAll(std::index_sequence_for<Params...>(), kj::fwd<Params>(bindings)...);
650655
}
651656
template <typename... Params>
652-
Query(SqliteDatabase& db, const Regulator& regulator, kj::StringPtr sqlCode, Params&&... bindings)
657+
Query(SqliteDatabase& db, QueryOptions options, kj::StringPtr sqlCode, Params&&... bindings)
653658
: ResetListener(db),
654-
regulator(regulator),
659+
regulator(options.regulator),
655660
ownStatement(db.prepareSql(regulator, sqlCode, 0, MULTI)),
656661
maybeStatement(ownStatement),
657662
queryEvent(this->db.sqliteObserver) {
@@ -952,18 +957,18 @@ class SqliteDatabase::Lock {
952957

953958
template <typename... Params>
954959
SqliteDatabase::Query SqliteDatabase::run(
955-
const Regulator& regulator, kj::StringPtr sqlCode, Params&&... params) {
956-
return Query(*this, regulator, sqlCode, kj::fwd<Params>(params)...);
960+
QueryOptions options, kj::StringPtr sqlCode, Params&&... params) {
961+
return Query(*this, options, sqlCode, kj::fwd<Params>(params)...);
957962
}
958963

959964
template <typename... Params>
960965
SqliteDatabase::Query SqliteDatabase::Statement::run(Params&&... params) {
961-
return Query(db, regulator, *this, kj::fwd<Params>(params)...);
966+
return Query(db, QueryOptions{.regulator = regulator}, *this, kj::fwd<Params>(params)...);
962967
}
963968

964969
template <size_t size, typename... Params>
965970
SqliteDatabase::Query SqliteDatabase::run(const char (&sqlCode)[size], Params&&... params) {
966-
return Query(*this, TRUSTED, sqlCode, kj::fwd<Params>(params)...);
971+
return Query(*this, QueryOptions{.regulator = TRUSTED}, sqlCode, kj::fwd<Params>(params)...);
967972
}
968973

969974
template <size_t size>

0 commit comments

Comments
 (0)