Skip to content

Commit 4767ef2

Browse files
committed
Fix broken move to MRU
1 parent 26fb611 commit 4767ef2

4 files changed

Lines changed: 21 additions & 3 deletions

File tree

packages/web/src/db/adapters/options.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ export interface WebSpecificOpenOptions {
9292
/**
9393
* If set to a value greater than zero, the worker will cache prepared statements to avoid preparing them every time
9494
* a query runs.
95+
*
96+
* Defaults to 0 (disabling the cache).
9597
*/
9698
preparedStatementsCache?: number;
9799
}

packages/web/src/db/adapters/wa-sqlite/RawSqliteConnection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ export class RawSqliteConnection {
222222
}
223223
}
224224

225-
async *cachedStatements(api: SQLiteAPI, sql: string): AsyncIterable<number> {
225+
private async *cachedStatements(api: SQLiteAPI, sql: string): AsyncIterable<number> {
226226
{
227227
const existing = this.statementCache?.lookup(sql);
228228
if (existing != null) {
@@ -242,7 +242,7 @@ export class RawSqliteConnection {
242242
} finally {
243243
// We can only cache statements if the sql text corresponds to a single statement, otherwise it's not clear what
244244
// portion of the original sql text to use as a key.
245-
if (preparedStatements.length == 1 && this.statementCache) {
245+
if (preparedStatements.length === 1 && this.statementCache) {
246246
const stmt = preparedStatements[0];
247247
// Don't cache EXPLAIN statements, their result becomes invalid after schema changes.
248248
if (this.sqlite3_stmt_isexplain(stmt) == 0) {

packages/web/src/db/adapters/wa-sqlite/StatementCache.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export class PreparedStatementCache {
1414
lookup(sql: string): number | null {
1515
const foundStatement = this.#statements.get(sql);
1616
if (foundStatement != null) {
17-
// Insert again to mark it as used.
17+
// Delete and re-insert to move to the end (most-recently-used position).
18+
this.#statements.delete(sql);
1819
this.#statements.set(sql, foundStatement);
1920
return foundStatement;
2021
}

packages/web/tests/src/db/StatementCache.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ test('statement cache', () => {
1818
expect(cache.lookup('SELECT 1')).not.toBeNull();
1919
});
2020

21+
test('lookup promotes entry to most-recently-used', () => {
22+
const cache = new PreparedStatementCache(3);
23+
cache.addStatement('SELECT 0', 0);
24+
cache.addStatement('SELECT 1', 1);
25+
cache.addStatement('SELECT 2', 2);
26+
27+
// Access SELECT 0 so it becomes the most-recently-used entry.
28+
expect(cache.lookup('SELECT 0')).toStrictEqual(0);
29+
30+
// Adding a fourth entry must evict SELECT 1 (oldest).
31+
expect(cache.addStatement('SELECT 3', 3)).toStrictEqual(1);
32+
expect(cache.lookup('SELECT 0')).not.toBeNull();
33+
expect(cache.lookup('SELECT 1')).toBeNull();
34+
});
35+
2136
test('does not cache explain statements', async () => {
2237
const db = generateTestDb({
2338
schema: new Schema({}),

0 commit comments

Comments
 (0)