@quereus/quereus 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@ export declare class Database {
28
28
  private isAutocommit;
29
29
  private inTransaction;
30
30
  private activeConnections;
31
- private inImplicitTransaction;
31
+ private inImplicit;
32
32
  readonly optimizer: Optimizer;
33
33
  readonly options: DatabaseOptionsManager;
34
34
  private instructionTracer;
@@ -38,6 +38,12 @@ export declare class Database {
38
38
  private changeLogLayers;
39
39
  /** Deferred constraint evaluation queue */
40
40
  private readonly deferredConstraints;
41
+ /**
42
+ * Mutex for serializing statement execution.
43
+ * This prevents concurrent statements from interfering with each other's
44
+ * transaction state, matching SQLite's behavior of serializing writes.
45
+ */
46
+ private execMutex;
41
47
  constructor();
42
48
  /**
43
49
  * Prepares an SQL statement for execution.
@@ -65,12 +71,34 @@ export declare class Database {
65
71
  prepare(sql: string, paramsOrTypes?: SqlParameters | SqlValue[] | Map<string | number, ScalarType>): Statement;
66
72
  /**
67
73
  * Executes a query and returns the first result row as an object.
74
+ * The execution is serialized through the mutex and wrapped in an implicit
75
+ * transaction when in autocommit mode.
76
+ *
68
77
  * @param sql The SQL query string to execute.
69
78
  * @param params Optional parameters to bind.
70
79
  * @returns A Promise resolving to the first result row as an object, or undefined if no rows.
71
80
  * @throws QuereusError on failure.
72
81
  */
73
82
  get(sql: string, params?: SqlParameters | SqlValue[]): Promise<Record<string, SqlValue> | undefined>;
83
+ /**
84
+ * Parses SQL into a statement batch.
85
+ */
86
+ private _parseSql;
87
+ /**
88
+ * Determines if a statement batch contains explicit transaction control.
89
+ */
90
+ private _hasExplicitTransactionControl;
91
+ /**
92
+ * Executes one or more SQL statements directly.
93
+ * Statements are serialized through the execution mutex and wrapped in an
94
+ * implicit transaction when in autocommit mode (unless they contain explicit
95
+ * transaction control statements).
96
+ *
97
+ * @param sql The SQL string(s) to execute.
98
+ * @param params Optional parameters to bind.
99
+ * @returns A Promise resolving when execution completes.
100
+ * @throws QuereusError on failure.
101
+ */
74
102
  exec(sql: string, params?: SqlParameters): Promise<void>;
75
103
  /**
76
104
  * Registers a virtual table module.
@@ -266,6 +294,10 @@ export declare class Database {
266
294
  * The underlying statement is automatically finalized when iteration completes
267
295
  * or if an error occurs.
268
296
  *
297
+ * The execution is serialized through the mutex and wrapped in an implicit
298
+ * transaction when in autocommit mode. The mutex is held for the entire
299
+ * iteration to ensure transactional consistency.
300
+ *
269
301
  * @param sql The SQL query string to execute.
270
302
  * @param params Optional parameters to bind (array for positional, object for named).
271
303
  * @yields Each result row as an object (`Record<string, SqlValue>`).
@@ -1 +1 @@
1
- {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/core/database.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/core/database.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,7 @@ import { DeclaredSchemaManager } from '../schema/declared-schema-manager.js';
30
30
  import { analyzeRowSpecific } from '../planner/analysis/constraint-extractor.js';
31
31
  import { DeferredConstraintQueue } from '../runtime/deferred-constraint-queue.js';
32
32
  import { getParameterTypes } from './param.js';
33
+ import { rowToObject } from './utils.js';
33
34
  const log = createLogger('core:database');
34
35
  const warnLog = log.extend('warn');
35
36
  const errorLog = log.extend('error');
@@ -46,7 +47,7 @@ export class Database {
46
47
  isAutocommit = true; // Manages transaction state
47
48
  inTransaction = false;
48
49
  activeConnections = new Map();
49
- inImplicitTransaction = false; // Track if we're in an implicit transaction
50
+ inImplicit = false; // Track if we're in an implicit transaction
50
51
  optimizer;
51
52
  options;
52
53
  instructionTracer;
@@ -56,6 +57,12 @@ export class Database {
56
57
  changeLogLayers = [];
57
58
  /** Deferred constraint evaluation queue */
58
59
  deferredConstraints = new DeferredConstraintQueue(this);
60
+ /**
61
+ * Mutex for serializing statement execution.
62
+ * This prevents concurrent statements from interfering with each other's
63
+ * transaction state, matching SQLite's behavior of serializing writes.
64
+ */
65
+ execMutex = Promise.resolve();
59
66
  constructor() {
60
67
  this.schemaManager = new SchemaManager(this);
61
68
  this.declaredSchemaManager = new DeclaredSchemaManager();
@@ -205,14 +212,23 @@ export class Database {
205
212
  }
206
213
  /**
207
214
  * Executes a query and returns the first result row as an object.
215
+ * The execution is serialized through the mutex and wrapped in an implicit
216
+ * transaction when in autocommit mode.
217
+ *
208
218
  * @param sql The SQL query string to execute.
209
219
  * @param params Optional parameters to bind.
210
220
  * @returns A Promise resolving to the first result row as an object, or undefined if no rows.
211
221
  * @throws QuereusError on failure.
212
222
  */
213
- get(sql, params) {
223
+ async get(sql, params) {
224
+ this.checkOpen();
214
225
  const stmt = this.prepare(sql, params);
215
- return stmt.get(params);
226
+ try {
227
+ return await stmt.get(params);
228
+ }
229
+ finally {
230
+ await stmt.finalize();
231
+ }
216
232
  }
217
233
  /**
218
234
  * Executes one or more SQL statements directly.
@@ -221,12 +237,78 @@ export class Database {
221
237
  * @returns A Promise resolving when execution completes.
222
238
  * @throws QuereusError on failure.
223
239
  */
240
+ // ============================================================================
241
+ // Statement Execution - Core Infrastructure
242
+ // ============================================================================
243
+ /**
244
+ * Acquires the execution mutex and returns a release function.
245
+ * All statement execution is serialized through this mutex to prevent
246
+ * concurrent transactions from interfering with each other.
247
+ * This matches SQLite's behavior of serializing database access.
248
+ * @internal
249
+ */
250
+ async _acquireExecMutex() {
251
+ const previousMutex = this.execMutex;
252
+ let releaseMutex;
253
+ this.execMutex = new Promise(resolve => {
254
+ releaseMutex = resolve;
255
+ });
256
+ await previousMutex;
257
+ return releaseMutex;
258
+ }
259
+ /**
260
+ * Unified execution wrapper that handles mutex acquisition and implicit transactions.
261
+ * All public execution methods should use this to ensure consistent behavior.
262
+ * @internal
263
+ */
264
+ async _executeWithProtection(options, executor) {
265
+ let releaseMutex;
266
+ try {
267
+ // Acquire mutex if requested
268
+ if (options.acquireMutex) {
269
+ releaseMutex = await this._acquireExecMutex();
270
+ }
271
+ // Determine if we need an implicit transaction
272
+ const needsImplicit = options.manageTransaction && this.isAutocommit;
273
+ let executionError = null;
274
+ let result;
275
+ try {
276
+ if (needsImplicit) {
277
+ await this._beginImplicit();
278
+ }
279
+ try {
280
+ result = await executor();
281
+ }
282
+ catch (err) {
283
+ const error = err instanceof Error ? err : new Error(String(err));
284
+ executionError = error instanceof QuereusError ? error : new QuereusError(error.message, StatusCode.ERROR, error);
285
+ throw executionError;
286
+ }
287
+ }
288
+ finally {
289
+ if (needsImplicit) {
290
+ if (executionError) {
291
+ await this._rollbackImplicit();
292
+ }
293
+ else {
294
+ await this._commitImplicit();
295
+ }
296
+ }
297
+ }
298
+ return result;
299
+ }
300
+ finally {
301
+ if (releaseMutex) {
302
+ releaseMutex();
303
+ }
304
+ }
305
+ }
224
306
  /**
225
307
  * @internal
226
- * Executes a single AST statement without transaction management.
227
- * Used by both exec() and eval() to avoid code duplication.
308
+ * Executes a single AST statement. Does not manage mutex or transactions.
309
+ * Used as the innermost execution primitive.
228
310
  */
229
- async _executeStatement(statementAst, params) {
311
+ async _executeSingleStatement(statementAst, params) {
230
312
  const plan = this._buildPlan([statementAst], params);
231
313
  if (plan.statements.length === 0)
232
314
  return; // No-op for this AST
@@ -245,54 +327,81 @@ export class Database {
245
327
  };
246
328
  await scheduler.run(runtimeCtx);
247
329
  }
248
- async exec(sql, params) {
249
- this.checkOpen();
250
- log('Executing SQL block (new runtime): %s', sql);
330
+ /**
331
+ * @internal
332
+ * Executes a batch of AST statements sequentially.
333
+ * Does not manage mutex or transactions - caller must handle that.
334
+ */
335
+ async _executeStatementBatch(batch, params) {
336
+ for (const statementAst of batch) {
337
+ await this._executeSingleStatement(statementAst, params);
338
+ }
339
+ }
340
+ /**
341
+ * Parses SQL into a statement batch.
342
+ */
343
+ _parseSql(sql) {
251
344
  const parser = new Parser();
252
- let batch;
253
345
  try {
254
- batch = parser.parseAll(sql);
346
+ return parser.parseAll(sql);
255
347
  }
256
348
  catch (e) {
257
349
  if (e instanceof ParseError)
258
350
  throw new QuereusError(`Parse error: ${e.message}`, StatusCode.ERROR, e);
259
351
  throw e;
260
352
  }
353
+ }
354
+ /**
355
+ * Determines if a statement batch contains explicit transaction control.
356
+ */
357
+ _hasExplicitTransactionControl(batch) {
358
+ return batch.some(ast => ast.type === 'begin' || ast.type === 'commit' || ast.type === 'rollback' || ast.type === 'savepoint' || ast.type === 'release');
359
+ }
360
+ // ============================================================================
361
+ // Statement Execution - Public API
362
+ // ============================================================================
363
+ /**
364
+ * Executes one or more SQL statements directly.
365
+ * Statements are serialized through the execution mutex and wrapped in an
366
+ * implicit transaction when in autocommit mode (unless they contain explicit
367
+ * transaction control statements).
368
+ *
369
+ * @param sql The SQL string(s) to execute.
370
+ * @param params Optional parameters to bind.
371
+ * @returns A Promise resolving when execution completes.
372
+ * @throws QuereusError on failure.
373
+ */
374
+ async exec(sql, params) {
375
+ this.checkOpen();
376
+ log('Executing SQL block: %s', sql);
377
+ const batch = this._parseSql(sql);
261
378
  if (batch.length === 0)
262
379
  return;
263
- const needsImplicitTransaction = batch.length >= 1
264
- && this.isAutocommit
265
- // has explicit transaction
266
- && !batch.some(ast => ast.type === 'begin' || ast.type === 'commit' || ast.type === 'rollback' || ast.type === 'savepoint' || ast.type === 'release');
267
- let executionError = null;
268
- try {
269
- if (needsImplicitTransaction) {
270
- await this._beginImplicitTransaction();
271
- }
272
- for (let i = 0; i < batch.length; i++) {
273
- try {
274
- await this._executeStatement(batch[i], params);
275
- }
276
- catch (err) {
277
- const error = err instanceof Error ? err : new Error(String(err));
278
- executionError = error instanceof QuereusError ? error : new QuereusError(error.message, StatusCode.ERROR, error);
279
- break; // Stop processing further statements on error
280
- }
281
- }
282
- }
283
- finally {
284
- if (needsImplicitTransaction) {
285
- if (executionError) {
286
- await this._rollbackImplicitTransaction();
287
- }
288
- else {
289
- await this._commitImplicitTransaction();
290
- }
291
- }
292
- }
293
- if (executionError) {
294
- throw executionError;
295
- }
380
+ // Don't wrap in implicit transaction if batch has explicit transaction control
381
+ const hasExplicitTxn = this._hasExplicitTransactionControl(batch);
382
+ await this._executeWithProtection({ acquireMutex: true, manageTransaction: !hasExplicitTxn }, () => this._executeStatementBatch(batch, params));
383
+ }
384
+ /**
385
+ * Execute SQL without acquiring the mutex.
386
+ * Used by runtime code (e.g., APPLY SCHEMA) that needs to execute
387
+ * nested SQL statements while already holding the mutex.
388
+ * @internal
389
+ */
390
+ async _execWithinTransaction(sql, params) {
391
+ log('Executing nested SQL: %s', sql);
392
+ const batch = this._parseSql(sql);
393
+ if (batch.length === 0)
394
+ return;
395
+ // No mutex, no implicit transaction - we're already inside one
396
+ await this._executeWithProtection({ acquireMutex: false, manageTransaction: false }, () => this._executeStatementBatch(batch, params));
397
+ }
398
+ /**
399
+ * Execute a function with mutex and optional implicit transaction management.
400
+ * This is exposed for Statement to use, avoiding code duplication.
401
+ * @internal
402
+ */
403
+ async _runWithProtection(acquireMutex, manageTransaction, executor) {
404
+ return this._executeWithProtection({ acquireMutex, manageTransaction }, executor);
296
405
  }
297
406
  /**
298
407
  * Registers a virtual table module.
@@ -717,6 +826,10 @@ export class Database {
717
826
  * The underlying statement is automatically finalized when iteration completes
718
827
  * or if an error occurs.
719
828
  *
829
+ * The execution is serialized through the mutex and wrapped in an implicit
830
+ * transaction when in autocommit mode. The mutex is held for the entire
831
+ * iteration to ensure transactional consistency.
832
+ *
720
833
  * @param sql The SQL query string to execute.
721
834
  * @param params Optional parameters to bind (array for positional, object for named).
722
835
  * @yields Each result row as an object (`Record<string, SqlValue>`).
@@ -737,8 +850,17 @@ export class Database {
737
850
  */
738
851
  async *eval(sql, params) {
739
852
  this.checkOpen();
853
+ // Acquire mutex for the entire iteration
854
+ const releaseMutex = await this._acquireExecMutex();
855
+ // Determine if we need implicit transaction
856
+ const needsImplicit = this.isAutocommit;
857
+ let transactionStarted = false;
740
858
  let stmt = null;
741
859
  try {
860
+ if (needsImplicit) {
861
+ await this._beginImplicit();
862
+ transactionStarted = true;
863
+ }
742
864
  stmt = this.prepare(sql);
743
865
  if (stmt.astBatch.length === 0) {
744
866
  // No statements, yield nothing.
@@ -747,17 +869,19 @@ export class Database {
747
869
  if (stmt.astBatch.length > 1) {
748
870
  // Multi-statement batch: execute all but the last statement,
749
871
  // then yield results from the last statement
750
- const parser = new Parser();
751
- const batch = parser.parseAll(sql);
872
+ const batch = this._parseSql(sql);
752
873
  // Execute all statements except the last one
753
874
  for (let i = 0; i < batch.length - 1; i++) {
754
- await this._executeStatement(batch[i], params);
875
+ await this._executeSingleStatement(batch[i], params);
755
876
  }
756
877
  // Now prepare and execute the last statement to yield its results
757
878
  const lastStmt = new Statement(this, [batch[batch.length - 1]]);
758
879
  this.statements.add(lastStmt);
759
880
  try {
760
- yield* lastStmt.all(params);
881
+ const names = lastStmt.getColumnNames();
882
+ for await (const row of lastStmt.iterateRows(params)) {
883
+ yield rowToObject(row, names);
884
+ }
761
885
  }
762
886
  finally {
763
887
  await lastStmt.finalize();
@@ -765,13 +889,34 @@ export class Database {
765
889
  }
766
890
  else {
767
891
  // Single statement: execute and yield results
768
- yield* stmt.all(params);
892
+ const names = stmt.getColumnNames();
893
+ for await (const row of stmt.iterateRows(params)) {
894
+ yield rowToObject(row, names);
895
+ }
896
+ }
897
+ // Commit implicit transaction on successful completion
898
+ if (transactionStarted) {
899
+ await this._commitImplicit();
900
+ transactionStarted = false;
769
901
  }
770
902
  }
903
+ catch (err) {
904
+ // Rollback on error
905
+ if (transactionStarted) {
906
+ await this._rollbackImplicit();
907
+ transactionStarted = false;
908
+ }
909
+ throw err;
910
+ }
771
911
  finally {
772
912
  if (stmt) {
773
913
  await stmt.finalize();
774
914
  }
915
+ // If we somehow exit without committing/rolling back, rollback
916
+ if (transactionStarted) {
917
+ await this._rollbackImplicit();
918
+ }
919
+ releaseMutex();
775
920
  }
776
921
  }
777
922
  getPlan(sqlOrAst) {
@@ -909,7 +1054,7 @@ export class Database {
909
1054
  const connection = this.activeConnections.get(connectionId);
910
1055
  if (connection) {
911
1056
  // Don't disconnect during implicit transactions - let the transaction coordinate
912
- if (this.inImplicitTransaction) {
1057
+ if (this.inImplicit) {
913
1058
  debugLog(`Deferring disconnect of connection ${connectionId} until implicit transaction completes`);
914
1059
  return;
915
1060
  }
@@ -972,9 +1117,9 @@ export class Database {
972
1117
  * Begin an implicit transaction and coordinate with virtual table connections
973
1118
  */
974
1119
  /** @internal Begin an implicit transaction */
975
- async _beginImplicitTransaction() {
1120
+ async _beginImplicit() {
976
1121
  debugLog("Database: Starting implicit transaction for multi-statement block.");
977
- this.inImplicitTransaction = true;
1122
+ this.inImplicit = true;
978
1123
  // Begin transaction on all active connections first
979
1124
  const connections = this.getAllConnections();
980
1125
  for (const connection of connections) {
@@ -994,7 +1139,7 @@ export class Database {
994
1139
  * Commit an implicit transaction and coordinate with virtual table connections
995
1140
  * @internal
996
1141
  */
997
- async _commitImplicitTransaction() {
1142
+ async _commitImplicit() {
998
1143
  debugLog("Database: Committing implicit transaction.");
999
1144
  try {
1000
1145
  const connectionsToCommit = this.getAllConnections();
@@ -1029,7 +1174,7 @@ export class Database {
1029
1174
  finally {
1030
1175
  this.inTransaction = false;
1031
1176
  this.isAutocommit = true;
1032
- this.inImplicitTransaction = false;
1177
+ this.inImplicit = false;
1033
1178
  this._clearChangeLog();
1034
1179
  }
1035
1180
  }
@@ -1109,9 +1254,10 @@ export class Database {
1109
1254
  }
1110
1255
  }
1111
1256
  async executeViolationOnce(assertionName, sql) {
1112
- const stmt = await this.prepare(sql);
1257
+ const stmt = this.prepare(sql);
1113
1258
  try {
1114
- for await (const _ of stmt.all()) {
1259
+ // Use raw iterateRows() to avoid mutex acquisition - we're already inside the mutex
1260
+ for await (const _ of stmt.iterateRows()) {
1115
1261
  throw new QuereusError(`Integrity assertion failed: ${assertionName}`, StatusCode.CONSTRAINT);
1116
1262
  }
1117
1263
  }
@@ -1251,7 +1397,7 @@ export class Database {
1251
1397
  * Rollback an implicit transaction and coordinate with virtual table connections
1252
1398
  */
1253
1399
  /** @internal Rollback an implicit transaction */
1254
- async _rollbackImplicitTransaction() {
1400
+ async _rollbackImplicit() {
1255
1401
  debugLog("Database: Rolling back implicit transaction.");
1256
1402
  // Rollback all active connections
1257
1403
  const connections = this.getAllConnections();
@@ -1268,7 +1414,7 @@ export class Database {
1268
1414
  // Reset database state
1269
1415
  this.inTransaction = false;
1270
1416
  this.isAutocommit = true;
1271
- this.inImplicitTransaction = false;
1417
+ this.inImplicit = false;
1272
1418
  }
1273
1419
  createBlockWithNewStatements(block, statements) {
1274
1420
  return new BlockNode(block.scope, statements, block.parameters);