Skip to content

Commit dd31ff5

Browse files
test: findMany use read lock
1 parent 580531e commit dd31ff5

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

packages/drizzle-driver/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,3 @@ For more information on how to use Drizzle queries in PowerSync, see [here](http
155155
## Known limitations
156156

157157
- The integration does not currently support nested transactions (also known as `savepoints`).
158-
- `findMany` queries execute with a write connection if not wrapped in an explicit `read only` transaction.

packages/drizzle-driver/src/sqlite/PowerSyncSQLiteDatabase.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ import {
1111
createTableRelationsHelpers,
1212
extractTablesRelationalConfig,
1313
ExtractTablesWithRelations,
14+
TableRelationalConfig,
1415
type RelationalSchemaConfig,
1516
type TablesRelationalConfig
1617
} from 'drizzle-orm/relations';
17-
import { SQLiteTransaction } from 'drizzle-orm/sqlite-core';
18+
import { SQLiteSession, SQLiteTable, SQLiteTransaction } from 'drizzle-orm/sqlite-core';
1819
import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core/db';
1920
import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core/dialect';
21+
import { RelationalQueryBuilder } from 'drizzle-orm/sqlite-core/query-builders/query';
2022
import type { DrizzleConfig } from 'drizzle-orm/utils';
2123
import { toCompilableQuery } from './../utils/compilableQuery.js';
22-
import { PowerSyncSQLiteTransactionConfig } from './PowerSyncSQLiteBaseSession.js';
24+
import { PowerSyncSQLiteBaseSession, PowerSyncSQLiteTransactionConfig } from './PowerSyncSQLiteBaseSession.js';
2325
import { PowerSyncSQLiteSession } from './PowerSyncSQLiteSession.js';
2426

2527
export type DrizzleQuery<T> = { toSQL(): Query; execute(): Promise<T | T[]> };
@@ -54,6 +56,37 @@ export class PowerSyncSQLiteDatabase<
5456

5557
super('async', dialect, session as any, schema as any);
5658
this.db = db;
59+
60+
/**
61+
* A hack in order to use read locks for `db.query.users.findMany()` etc queries.
62+
* We don't currently get queryMetadata for these queries, so we can't use the regular session.
63+
* This session always uses read locks.
64+
*/
65+
const querySession = new PowerSyncSQLiteBaseSession(
66+
{
67+
useReadContext: (callback) => db.readLock(callback),
68+
useWriteContext: (callback) => db.readLock(callback)
69+
},
70+
dialect,
71+
schema,
72+
{
73+
logger
74+
}
75+
);
76+
if (this._.schema) {
77+
for (const [tableName, columns] of Object.entries(this._.schema)) {
78+
this.query[tableName as keyof typeof this.query] = new RelationalQueryBuilder(
79+
'async',
80+
schema!.fullSchema,
81+
this._.schema,
82+
this._.tableNamesMap,
83+
schema!.fullSchema[tableName] as SQLiteTable,
84+
columns as TableRelationalConfig,
85+
dialect,
86+
querySession as SQLiteSession<any, any, any, any> as any
87+
) as any;
88+
}
89+
}
5790
}
5891

5992
transaction<T>(

packages/drizzle-driver/tests/sqlite/lock-usage.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ describe('Lock Usage Tests', () => {
8181
expect(readLockSpy).toHaveBeenCalled();
8282
expect(writeLockSpy).not.toHaveBeenCalled();
8383
});
84+
85+
lockUsageTest('should use readLock for query.findMany()', async ({ db, readLockSpy, writeLockSpy }) => {
86+
await db.query.users.findMany();
87+
88+
expect(readLockSpy).toHaveBeenCalled();
89+
expect(writeLockSpy).not.toHaveBeenCalled();
90+
});
8491
});
8592

8693
describe('INSERT queries', () => {

0 commit comments

Comments
 (0)