Skip to content

Commit

Permalink
Merge pull request cloudflare#693 from cloudflare/kenton/fix-sql-curs…
Browse files Browse the repository at this point in the history
…or-lifetime

SQLite: Bugfix: Cursor from prepared statement should keep statement alive.
  • Loading branch information
kentonv authored May 23, 2023
2 parents c2a61cd + 8a5caae commit 0d2b68c
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/workerd/api/sql-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,22 @@ async function test(storage) {
});
assert.equal(getI(), 2);
}

await scheduler.wait(1);

// Test for bug where a cursor constructed from a prepared statement didn't have a strong ref
// to the statement object.
{
sql.exec("CREATE TABLE iteratorTest (i INTEGER)");
sql.exec("INSERT INTO iteratorTest VALUES (0), (1)");

let q = sql.prepare("SELECT * FROM iteratorTest")();
let i = 0;
for (let row of q) {
assert.equal(row.i, i++);
gc();
}
}
}

export class DurableObjectExample {
Expand Down
4 changes: 3 additions & 1 deletion src/workerd/api/sql-test.wd-test
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ const config :Workerd.Config = (
services = [
(name = "main", worker = .mainWorker),
(name = "TEST_TMPDIR", disk = (writable = true)),
]
],

v8Flags = [ "--expose-gc" ],
);

const mainWorker :Workerd.Worker = (
Expand Down
2 changes: 2 additions & 0 deletions src/workerd/api/sql.c++
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,12 @@ jsg::Ref<SqlStorage::Cursor> SqlStorage::Statement::run(jsg::Arguments<BindingVa
c->state = nullptr;
}
c->selfRef = nullptr;
c->statement = nullptr;
currentCursor = nullptr;
}

auto result = jsg::alloc<Cursor>(cachedColumnNames, statementRef, kj::mv(bindings));
result->statement = JSG_THIS;

result->selfRef = currentCursor;
currentCursor = *result;
Expand Down
7 changes: 7 additions & 0 deletions src/workerd/api/sql.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,16 @@ class SqlStorage::Cursor final: public jsg::Object {
// destruction. Used by Statement to invalidate past cursors when the statement is
// executed again.

kj::Maybe<jsg::Ref<Statement>> statement;
// If this cursor was created from a prepared statement, this keeps the statement object alive.

kj::Maybe<CachedColumnNames> ownCachedColumnNames;
CachedColumnNames& cachedColumnNames;

void visitForGc(jsg::GcVisitor& visitor) {
visitor.visit(statement);
}

static kj::Array<const SqliteDatabase::Query::ValuePtr> mapBindings(
kj::ArrayPtr<BindingValue> values);

Expand Down

0 comments on commit 0d2b68c

Please sign in to comment.