11import { LockContext , QueryResult } from '@powersync/common' ;
2- import { Column , DriverValueDecoder , getTableName , SQL } from 'drizzle-orm' ;
2+ import { Column , DriverValueDecoder , SQL , getTableName } from 'drizzle-orm' ;
33import { entityKind , is } from 'drizzle-orm/entity' ;
44import type { Logger } from 'drizzle-orm/logger' ;
55import { fillPlaceholders , type Query } from 'drizzle-orm/sql/sql' ;
66import { SQLiteColumn } from 'drizzle-orm/sqlite-core' ;
77import type { SelectedFieldsOrdered } from 'drizzle-orm/sqlite-core/query-builders/select.types' ;
88import {
9+ SQLitePreparedQuery ,
910 type PreparedQueryConfig as PreparedQueryConfigBase ,
10- type SQLiteExecuteMethod ,
11- SQLitePreparedQuery
11+ type SQLiteExecuteMethod
1212} from 'drizzle-orm/sqlite-core/session' ;
1313
1414type PreparedQueryConfig = Omit < PreparedQueryConfigBase , 'statement' | 'run' > ;
1515
16+ /**
17+ * Callback which uses a LockContext for database operations.
18+ */
19+ export type LockCallback < T > = ( ctx : LockContext ) => Promise < T > ;
20+
21+ /**
22+ * Provider for specific database contexts.
23+ * Handlers are provided a context to the provided callback.
24+ * This does not necessarily need to acquire a database lock for each call.
25+ * Calls might use the same lock context for multiple operations.
26+ * The read/write context may relate to a single read OR write context.
27+ */
28+ export type ContextProvider = {
29+ useReadContext : < T > ( fn : LockCallback < T > ) => Promise < T > ;
30+ useWriteContext : < T > ( fn : LockCallback < T > ) => Promise < T > ;
31+ } ;
32+
1633export class PowerSyncSQLitePreparedQuery <
1734 T extends PreparedQueryConfig = PreparedQueryConfig
1835> extends SQLitePreparedQuery < {
@@ -26,7 +43,7 @@ export class PowerSyncSQLitePreparedQuery<
2643 static readonly [ entityKind ] : string = 'PowerSyncSQLitePreparedQuery' ;
2744
2845 constructor (
29- private db : LockContext ,
46+ private contextProvider : ContextProvider ,
3047 query : Query ,
3148 private logger : Logger ,
3249 private fields : SelectedFieldsOrdered | undefined ,
@@ -40,17 +57,23 @@ export class PowerSyncSQLitePreparedQuery<
4057 async run ( placeholderValues ?: Record < string , unknown > ) : Promise < QueryResult > {
4158 const params = fillPlaceholders ( this . query . params , placeholderValues ?? { } ) ;
4259 this . logger . logQuery ( this . query . sql , params ) ;
43- const rs = await this . db . execute ( this . query . sql , params ) ;
44- return rs ;
60+ /**
61+ * Run operations are teated as potential mutations, so they use the write context.
62+ */
63+ return this . contextProvider . useWriteContext ( async ( ctx ) => {
64+ const rs = await ctx . execute ( this . query . sql , params ) ;
65+ return rs ;
66+ } ) ;
4567 }
4668
4769 async all ( placeholderValues ?: Record < string , unknown > ) : Promise < T [ 'all' ] > {
4870 const { fields, query, logger, customResultMapper } = this ;
4971 if ( ! fields && ! customResultMapper ) {
5072 const params = fillPlaceholders ( query . params , placeholderValues ?? { } ) ;
5173 logger . logQuery ( query . sql , params ) ;
52- const rs = await this . db . execute ( this . query . sql , params ) ;
53- return rs . rows ?. _array ?? [ ] ;
74+ return await this . contextProvider . useReadContext ( async ( ctx ) => {
75+ return await ctx . getAll ( this . query . sql , params ) ;
76+ } ) ;
5477 }
5578
5679 const rows = ( await this . values ( placeholderValues ) ) as unknown [ ] [ ] ;
@@ -69,7 +92,9 @@ export class PowerSyncSQLitePreparedQuery<
6992 const { fields, customResultMapper } = this ;
7093 const joinsNotNullableMap = ( this as any ) . joinsNotNullableMap ;
7194 if ( ! fields && ! customResultMapper ) {
72- return this . db . get ( this . query . sql , params ) ;
95+ return this . contextProvider . useReadContext ( async ( ctx ) => {
96+ return await ctx . get ( this . query . sql , params ) ;
97+ } ) ;
7398 }
7499
75100 const rows = ( await this . values ( placeholderValues ) ) as unknown [ ] [ ] ;
@@ -90,7 +115,9 @@ export class PowerSyncSQLitePreparedQuery<
90115 const params = fillPlaceholders ( this . query . params , placeholderValues ?? { } ) ;
91116 this . logger . logQuery ( this . query . sql , params ) ;
92117
93- return await this . db . executeRaw ( this . query . sql , params ) ;
118+ return await this . contextProvider . useReadContext ( async ( ctx ) => {
119+ return await ctx . executeRaw ( this . query . sql , params ) ;
120+ } ) ;
94121 }
95122
96123 isResponseInArrayMode ( ) : boolean {
0 commit comments