kern-orm 0.7.0 → 0.9.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.
- package/dist/{database-B7Kf5Q9X.mjs → database-t66EaIGE.mjs} +359 -90
- package/dist/{index-CLKi9gZL.d.mts → index-2z5iTzXf.d.mts} +412 -21
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +273 -2
- package/dist/testing.d.mts +2 -4
- package/dist/testing.mjs +181 -42
- package/dist/types.d.mts +1 -1
- package/package.json +1 -7
|
@@ -4222,6 +4222,131 @@ function bindSchema(schema, database, options = {}) {
|
|
|
4222
4222
|
const db = defineEntries(methods, schema.$tables, (key) => bindQuery(startQuery(schema.$tables[key], contexts[key]), db));
|
|
4223
4223
|
return db;
|
|
4224
4224
|
}
|
|
4225
|
+
// src/execution/driver-error.ts
|
|
4226
|
+
/** Marks an instance of `QueryError` of any copy of kern-orm, which `instanceof QueryError` of another copy recognizes. */
|
|
4227
|
+
const queryErrorBrand = /* @__PURE__ */ Symbol.for("kern-orm.QueryError");
|
|
4228
|
+
/** Marks an instance of `ConnectionError` of any copy of kern-orm. */
|
|
4229
|
+
const connectionErrorBrand = /* @__PURE__ */ Symbol.for("kern-orm.ConnectionError");
|
|
4230
|
+
/**
|
|
4231
|
+
* Tells whether `value` is an instance of `errorClass`: by the brand of any copy of kern-orm for `errorClass` itself, and by the prototype chain for its subclasses.
|
|
4232
|
+
*
|
|
4233
|
+
* An application can load several copies of kern-orm, such as one of a driver, and an error of one copy is then an instance of the class of another.
|
|
4234
|
+
*/
|
|
4235
|
+
function isInstance(errorClass, root, brand, value) {
|
|
4236
|
+
if (errorClass !== root) return Function.prototype[Symbol.hasInstance].call(errorClass, value);
|
|
4237
|
+
return typeof value === "object" && value !== null && value[brand] === true;
|
|
4238
|
+
}
|
|
4239
|
+
/** Sets the brand of `error`, which is not enumerable, so that it does not show among the fields of the error. */
|
|
4240
|
+
function setBrand(error, brand) {
|
|
4241
|
+
Object.defineProperty(error, brand, { value: true });
|
|
4242
|
+
}
|
|
4243
|
+
/**
|
|
4244
|
+
* Error of a statement that PostgreSQL rejected, such as for a violated constraint; the connection of the statement stays usable.
|
|
4245
|
+
*
|
|
4246
|
+
* A driver whose client gives the severity of an error only in the language of the server, such as node-postgres, tells such an error by its SQLSTATE when the server translates its messages.
|
|
4247
|
+
* An error that ends the session with a code that a statement also gets, such as `40001` of a conflict with recovery on a replica, then rejects with `QueryError`, and the next statement on the connection with `ConnectionError`.
|
|
4248
|
+
*/
|
|
4249
|
+
var QueryError = class QueryError extends Error {
|
|
4250
|
+
name = "QueryError";
|
|
4251
|
+
/** SQLSTATE of the error, such as `23505` for a violated unique constraint. */
|
|
4252
|
+
code;
|
|
4253
|
+
/** Name of the constraint that the statement violated, if any. */
|
|
4254
|
+
constraint;
|
|
4255
|
+
constructor(message, fields) {
|
|
4256
|
+
super(message, "cause" in fields ? { cause: fields.cause } : void 0);
|
|
4257
|
+
this.code = fields.code;
|
|
4258
|
+
this.constraint = fields.constraint;
|
|
4259
|
+
setBrand(this, queryErrorBrand);
|
|
4260
|
+
}
|
|
4261
|
+
/** Tells whether `value` is an instance of the class, including one of `QueryError` of another copy of kern-orm. */
|
|
4262
|
+
static [Symbol.hasInstance](value) {
|
|
4263
|
+
return isInstance(this, QueryError, queryErrorBrand, value);
|
|
4264
|
+
}
|
|
4265
|
+
};
|
|
4266
|
+
/**
|
|
4267
|
+
* Error of a statement or connection that failed for another reason than PostgreSQL rejecting a statement, such as a lost connection, a timeout of the client, or a closed driver.
|
|
4268
|
+
*
|
|
4269
|
+
* The statement may have run or not, and its connection may be lost or in an unknown state of its transaction.
|
|
4270
|
+
*/
|
|
4271
|
+
var ConnectionError = class ConnectionError extends Error {
|
|
4272
|
+
name = "ConnectionError";
|
|
4273
|
+
constructor(message, options) {
|
|
4274
|
+
super(message, options);
|
|
4275
|
+
setBrand(this, connectionErrorBrand);
|
|
4276
|
+
}
|
|
4277
|
+
/** Tells whether `value` is an instance of the class, including one of `ConnectionError` of another copy of kern-orm. */
|
|
4278
|
+
static [Symbol.hasInstance](value) {
|
|
4279
|
+
return isInstance(this, ConnectionError, connectionErrorBrand, value);
|
|
4280
|
+
}
|
|
4281
|
+
};
|
|
4282
|
+
/** SQLSTATE of five digits or uppercase letters; clients also give codes of their own, such as `ECONNRESET` or `CONNECTION_CLOSED`. */
|
|
4283
|
+
const sqlState = /^[0-9A-Z]{5}$/;
|
|
4284
|
+
/** SQLSTATE of an error that ends the session: of the classes of connection exceptions, authorization, operator intervention, and internal errors, and the timeouts of an idle transaction and of a transaction. */
|
|
4285
|
+
const sessionEndingCode = /^(?:08|28|57P|XX|25P03$|25P04$)/;
|
|
4286
|
+
/** Tells whether an error of the server of `severity` and SQLSTATE `code` ends its session. */
|
|
4287
|
+
function isSessionEnding(severity, code) {
|
|
4288
|
+
if (severity === "ERROR") return false;
|
|
4289
|
+
if (severity === "FATAL" || severity === "PANIC") return true;
|
|
4290
|
+
return sessionEndingCode.test(code);
|
|
4291
|
+
}
|
|
4292
|
+
/**
|
|
4293
|
+
* Classifies an error of a client as `QueryError` or `ConnectionError`, by the fields of the PostgreSQL error it carries, for a driver to reject with.
|
|
4294
|
+
*
|
|
4295
|
+
* An error that kern-orm has already classified returns as it is.
|
|
4296
|
+
* An error without a severity or a SQLSTATE, such as of a client that lost its connection, is a `ConnectionError`, and so is one of severity `FATAL` or `PANIC`, which ends the session.
|
|
4297
|
+
* An error of severity `ERROR` is a `QueryError`.
|
|
4298
|
+
* With a translated severity, the SQLSTATE tells an error that ends the session, so a few errors of other codes that end it give `QueryError`.
|
|
4299
|
+
*/
|
|
4300
|
+
function toDriverError(error, fields) {
|
|
4301
|
+
if (error instanceof QueryError || error instanceof ConnectionError) return error;
|
|
4302
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4303
|
+
const { severity, code, constraint } = fields ?? {};
|
|
4304
|
+
if (typeof severity !== "string" || typeof code !== "string" || !sqlState.test(code)) return new ConnectionError(message, { cause: error });
|
|
4305
|
+
if (isSessionEnding(severity, code)) return new ConnectionError(message, { cause: error });
|
|
4306
|
+
return new QueryError(message, {
|
|
4307
|
+
code,
|
|
4308
|
+
constraint: typeof constraint === "string" ? constraint : void 0,
|
|
4309
|
+
cause: error
|
|
4310
|
+
});
|
|
4311
|
+
}
|
|
4312
|
+
// src/execution/transaction/release.ts
|
|
4313
|
+
/**
|
|
4314
|
+
* Returns a connection to the driver and passes a failed release to `onReleaseError`, or to `console.error` without one.
|
|
4315
|
+
*
|
|
4316
|
+
* The result or error of the transaction is decided before its release, so a failed release must not change it: a committed transaction that rejected would be retried.
|
|
4317
|
+
* Reporting the failure cannot change it either.
|
|
4318
|
+
* The error of a handler that throws or rejects goes to `console.error` with the failure of the release, and a `console.error` that throws is ignored.
|
|
4319
|
+
*/
|
|
4320
|
+
async function releaseConnection(connection, onReleaseError) {
|
|
4321
|
+
try {
|
|
4322
|
+
await connection.release();
|
|
4323
|
+
} catch (error) {
|
|
4324
|
+
reportReleaseError(error, onReleaseError);
|
|
4325
|
+
}
|
|
4326
|
+
}
|
|
4327
|
+
/** Passes a failed release to `onReleaseError`, or to `console.error` without one, without throwing. */
|
|
4328
|
+
function reportReleaseError(error, onReleaseError) {
|
|
4329
|
+
if (!onReleaseError) {
|
|
4330
|
+
logReleaseError(error);
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
try {
|
|
4334
|
+
Promise.resolve(onReleaseError(error)).catch((handlerError) => logReleaseError(error, { error: handlerError }));
|
|
4335
|
+
} catch (handlerError) {
|
|
4336
|
+
logReleaseError(error, { error: handlerError });
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
/**
|
|
4340
|
+
* Writes a failed release to `console.error`, preceded by the error of `onReleaseError` when the handler failed.
|
|
4341
|
+
*
|
|
4342
|
+
* A console that throws, such as one redirected to a failing logger, leaves nowhere to report to, so its error is ignored.
|
|
4343
|
+
*/
|
|
4344
|
+
function logReleaseError(error, handlerFailure) {
|
|
4345
|
+
try {
|
|
4346
|
+
if (handlerFailure) console.error("kern-orm: onReleaseError failed", handlerFailure.error);
|
|
4347
|
+
console.error("kern-orm: releasing a connection failed", error);
|
|
4348
|
+
} catch {}
|
|
4349
|
+
}
|
|
4225
4350
|
// src/execution/transaction/abort.ts
|
|
4226
4351
|
/**
|
|
4227
4352
|
* Runs `start` and settles as its promise, or rejects with the reason of `signal` when it aborts first and `abort`, called on the abort, returns `true`.
|
|
@@ -4260,14 +4385,78 @@ function settleUnlessAborted(start, signal, abort, discard) {
|
|
|
4260
4385
|
/**
|
|
4261
4386
|
* Acquires a connection for a test transaction, rejecting with the reason of `signal` when it aborts first.
|
|
4262
4387
|
*
|
|
4263
|
-
* A connection acquired after the abort returns to the pool as best-effort cleanup: the test transaction has already rejected, so nothing awaits the release, and its failure
|
|
4388
|
+
* A connection acquired after the abort returns to the pool as best-effort cleanup: the test transaction has already rejected, so nothing awaits the release, and its failure goes to `onReleaseError`.
|
|
4264
4389
|
*/
|
|
4265
|
-
function acquireUnlessAborted(driver, signal) {
|
|
4390
|
+
function acquireUnlessAborted(driver, signal, onReleaseError) {
|
|
4266
4391
|
if (signal.aborted) return Promise.reject(signal.reason);
|
|
4267
|
-
return settleUnlessAborted(() => driver.acquire(), signal, () => true, (connection) =>
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4392
|
+
return settleUnlessAborted(() => driver.acquire(), signal, () => true, (connection) => void releaseConnection(connection, onReleaseError));
|
|
4393
|
+
}
|
|
4394
|
+
// src/execution/transaction/connection-loss.ts
|
|
4395
|
+
/** Marks an instance of `TransactionConnectionError` of any copy of kern-orm. */
|
|
4396
|
+
const transactionConnectionErrorBrand = /* @__PURE__ */ Symbol.for("kern-orm.TransactionConnectionError");
|
|
4397
|
+
/** Message of a transaction whose connection failed in each phase. */
|
|
4398
|
+
const phaseMessages = {
|
|
4399
|
+
begin: "Transaction did not start: its connection failed",
|
|
4400
|
+
transaction: "Transaction was rolled back: its connection failed",
|
|
4401
|
+
commit: "Transaction may have been committed: its connection failed during COMMIT"
|
|
4402
|
+
};
|
|
4403
|
+
/**
|
|
4404
|
+
* Error of a transaction whose connection failed, which tells whether the transaction may have been committed.
|
|
4405
|
+
*
|
|
4406
|
+
* Its `cause` is the error that the transaction would reject with otherwise, such as the error of the callback, or a `SuppressedError` of a failed rollback that keeps it.
|
|
4407
|
+
*/
|
|
4408
|
+
var TransactionConnectionError = class TransactionConnectionError extends ConnectionError {
|
|
4409
|
+
name = "TransactionConnectionError";
|
|
4410
|
+
/**
|
|
4411
|
+
* Phase of the transaction in which its connection failed:
|
|
4412
|
+
*
|
|
4413
|
+
* - `begin`: before the callback, such as getting the connection or `BEGIN`, so the transaction applied nothing;
|
|
4414
|
+
* - `transaction`: in the callback or its rollback, so the transaction was rolled back;
|
|
4415
|
+
* - `commit`: during `COMMIT`, so whether the transaction was committed is unknown.
|
|
4416
|
+
*/
|
|
4417
|
+
phase;
|
|
4418
|
+
constructor(phase, options) {
|
|
4419
|
+
super(phaseMessages[phase], options);
|
|
4420
|
+
this.phase = phase;
|
|
4421
|
+
setBrand(this, transactionConnectionErrorBrand);
|
|
4422
|
+
}
|
|
4423
|
+
/** Tells whether `value` is an instance of the class, including one of `TransactionConnectionError` of another copy of kern-orm. */
|
|
4424
|
+
static [Symbol.hasInstance](value) {
|
|
4425
|
+
return isInstance(this, TransactionConnectionError, transactionConnectionErrorBrand, value);
|
|
4426
|
+
}
|
|
4427
|
+
};
|
|
4428
|
+
/**
|
|
4429
|
+
* Reserved connection of a transaction of `transaction` that records the first `ConnectionError` of its statements and scripts, including those of its nested levels.
|
|
4430
|
+
*
|
|
4431
|
+
* A failure before `COMMIT` is sent makes the transaction roll back rather than commit, since the statement may not have run.
|
|
4432
|
+
* A transaction that rejects after a failure rejects with `TransactionConnectionError` of its phase, while one whose `COMMIT` succeeded resolves.
|
|
4433
|
+
*/
|
|
4434
|
+
var ConnectionWatch = class {
|
|
4435
|
+
/** Phase of the transaction, which its root advances to `transaction` before the callback and to `commit` before `COMMIT`. */
|
|
4436
|
+
phase = "begin";
|
|
4437
|
+
/** First `ConnectionError`; a later statement that succeeds changes nothing. */
|
|
4438
|
+
failure;
|
|
4439
|
+
#connection;
|
|
4440
|
+
#observe = (error) => {
|
|
4441
|
+
if (!this.failure && error instanceof ConnectionError) this.failure = {
|
|
4442
|
+
error,
|
|
4443
|
+
phase: this.phase
|
|
4444
|
+
};
|
|
4445
|
+
throw error;
|
|
4446
|
+
};
|
|
4447
|
+
constructor(connection) {
|
|
4448
|
+
this.#connection = connection;
|
|
4449
|
+
}
|
|
4450
|
+
execute(statement) {
|
|
4451
|
+
return this.#connection.execute(statement).catch(this.#observe);
|
|
4452
|
+
}
|
|
4453
|
+
executeScript(text) {
|
|
4454
|
+
return this.#connection.executeScript(text).catch(this.#observe);
|
|
4455
|
+
}
|
|
4456
|
+
release() {
|
|
4457
|
+
return this.#connection.release();
|
|
4458
|
+
}
|
|
4459
|
+
};
|
|
4271
4460
|
// src/execution/transaction/settings.ts
|
|
4272
4461
|
/** Settings of a level of `transaction` with `options`, or `undefined` when it has none. */
|
|
4273
4462
|
function getLevelSettings(options) {
|
|
@@ -4310,19 +4499,38 @@ function createSettingStatement(settings) {
|
|
|
4310
4499
|
return createStatement(text, parameters);
|
|
4311
4500
|
}
|
|
4312
4501
|
// src/execution/transaction/level.ts
|
|
4313
|
-
/**
|
|
4502
|
+
/** Options of a level started without options, shared so that such a start allocates none. */
|
|
4503
|
+
const noLevelOptions = {};
|
|
4314
4504
|
const beginStatement = /* @__PURE__ */ createStatement("BEGIN");
|
|
4505
|
+
const isolatedBeginStatements = {
|
|
4506
|
+
"read committed": /* @__PURE__ */ createStatement("BEGIN ISOLATION LEVEL READ COMMITTED"),
|
|
4507
|
+
"repeatable read": /* @__PURE__ */ createStatement("BEGIN ISOLATION LEVEL REPEATABLE READ"),
|
|
4508
|
+
serializable: /* @__PURE__ */ createStatement("BEGIN ISOLATION LEVEL SERIALIZABLE")
|
|
4509
|
+
};
|
|
4510
|
+
const readIsolationStatement = /* @__PURE__ */ createStatement("SELECT current_setting('transaction_isolation')");
|
|
4315
4511
|
const commitStatement = /* @__PURE__ */ createStatement("COMMIT");
|
|
4316
4512
|
const rollbackStatement = /* @__PURE__ */ createStatement("ROLLBACK");
|
|
4317
4513
|
/**
|
|
4514
|
+
* Statement that starts the transaction of a level without a parent, a transaction of `transaction`, a test transaction, or the first test fixture, at `isolation` if given.
|
|
4515
|
+
*
|
|
4516
|
+
* PostgreSQL takes the isolation level only before the first query of a transaction, so `BEGIN` sets it.
|
|
4517
|
+
*/
|
|
4518
|
+
function getBeginStatement(isolation) {
|
|
4519
|
+
return isolation ? isolatedBeginStatements[isolation] : beginStatement;
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4318
4522
|
* Creates the state of a `starting` level on `connection`, nested in `parent` if given.
|
|
4319
4523
|
*
|
|
4320
4524
|
* It sends no SQL and does not reserve the level as the `child` of `parent`; the caller does both.
|
|
4321
4525
|
* `transaction` tells whether the level is a transaction of `transaction` rather than a level of the test helpers.
|
|
4526
|
+
* A transaction of `transaction` without a parent watches its connection for a `ConnectionError`.
|
|
4527
|
+
* `isolation` is the isolation level that a level without a parent begins with.
|
|
4322
4528
|
*/
|
|
4323
|
-
function createLevel(connection, parent, transaction) {
|
|
4529
|
+
function createLevel(connection, parent, transaction, isolation) {
|
|
4530
|
+
const watch = transaction && !parent ? new ConnectionWatch(connection) : void 0;
|
|
4324
4531
|
return {
|
|
4325
|
-
connection,
|
|
4532
|
+
connection: watch ?? connection,
|
|
4533
|
+
watch,
|
|
4326
4534
|
parent,
|
|
4327
4535
|
depth: parent ? parent.depth + 1 : 0,
|
|
4328
4536
|
inTransaction: transaction || (parent?.inTransaction ?? false),
|
|
@@ -4331,19 +4539,32 @@ function createLevel(connection, parent, transaction) {
|
|
|
4331
4539
|
rollbackOnly: void 0,
|
|
4332
4540
|
cleanup: void 0,
|
|
4333
4541
|
endedBy: void 0,
|
|
4334
|
-
restore: void 0
|
|
4542
|
+
restore: void 0,
|
|
4543
|
+
isolation: parent ? parent.isolation : isolation
|
|
4335
4544
|
};
|
|
4336
4545
|
}
|
|
4337
4546
|
/**
|
|
4338
|
-
*
|
|
4547
|
+
* Starts a nested level of `parent` with the settings of `options`, at the isolation level of its transaction, rejecting when it cannot start.
|
|
4339
4548
|
*
|
|
4340
4549
|
* `transaction` tells whether the level is a transaction of `transaction` rather than a level of the test helpers.
|
|
4550
|
+
* A level whose `isolation` differs from that of its transaction rejects without `SAVEPOINT`, since PostgreSQL sets the isolation level only for a whole transaction.
|
|
4341
4551
|
* A level whose settings fail rolls back to its savepoint first.
|
|
4552
|
+
* Aborted by `signal` while it checks `isolation`, it rejects with the reason without `SAVEPOINT`.
|
|
4342
4553
|
* The failure suppresses the reason of `signal` when the signal aborted before it.
|
|
4343
4554
|
*/
|
|
4344
|
-
async function startNestedLevel(parent, transaction, signal, settings) {
|
|
4555
|
+
async function startNestedLevel(parent, transaction, { signal, settings, isolation } = noLevelOptions) {
|
|
4345
4556
|
const level = createLevel(parent.connection, parent, transaction);
|
|
4346
4557
|
parent.child = level;
|
|
4558
|
+
if (isolation) {
|
|
4559
|
+
level.state = "reserved";
|
|
4560
|
+
await checkIsolation(level, isolation, signal);
|
|
4561
|
+
if (level.cleanup) return level;
|
|
4562
|
+
if (signal?.aborted) {
|
|
4563
|
+
closeStarting(level);
|
|
4564
|
+
throw signal.reason;
|
|
4565
|
+
}
|
|
4566
|
+
level.state = "starting";
|
|
4567
|
+
}
|
|
4347
4568
|
try {
|
|
4348
4569
|
await level.connection.execute(createStatement(`SAVEPOINT ${getSavepointName(level)}`));
|
|
4349
4570
|
} catch (error) {
|
|
@@ -4361,6 +4582,30 @@ async function startNestedLevel(parent, transaction, signal, settings) {
|
|
|
4361
4582
|
return level;
|
|
4362
4583
|
}
|
|
4363
4584
|
/**
|
|
4585
|
+
* Checks that the transaction of a `reserved` nested `level` runs at `isolation`, and rejects otherwise, closing the level.
|
|
4586
|
+
*
|
|
4587
|
+
* A failure suppresses the reason of `signal` when the signal aborted before it.
|
|
4588
|
+
* A level that its enclosing level ended during the check returns with its cleanup started.
|
|
4589
|
+
*/
|
|
4590
|
+
async function checkIsolation(level, isolation, signal) {
|
|
4591
|
+
let actual = level.isolation;
|
|
4592
|
+
if (!actual) {
|
|
4593
|
+
try {
|
|
4594
|
+
actual = (await level.connection.execute(readIsolationStatement)).rows[0][0];
|
|
4595
|
+
} catch (error) {
|
|
4596
|
+
if (!level.cleanup) closeStarting(level);
|
|
4597
|
+
throw suppressAbortReason(error, signal);
|
|
4598
|
+
}
|
|
4599
|
+
level.parent.isolation = actual;
|
|
4600
|
+
level.isolation = actual;
|
|
4601
|
+
if (level.cleanup) return;
|
|
4602
|
+
}
|
|
4603
|
+
if (actual !== isolation) {
|
|
4604
|
+
closeStarting(level);
|
|
4605
|
+
throw suppressAbortReason(/* @__PURE__ */ new Error(`Cannot start a nested transaction at isolation level ${isolation}: its transaction runs at ${actual}, and PostgreSQL sets the isolation level of a whole transaction`), signal);
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
/**
|
|
4364
4609
|
* Runs `callback` in the context of a started `level` in `storage`, then ends the level.
|
|
4365
4610
|
*
|
|
4366
4611
|
* A level that `commits` commits only when the callback resolves with no nested level running and no nested level that failed to end.
|
|
@@ -4388,8 +4633,7 @@ async function runLevel(storage, level, callback, commits, signal) {
|
|
|
4388
4633
|
const cleanup = await endLevel(level, commits && !rejection);
|
|
4389
4634
|
return {
|
|
4390
4635
|
result,
|
|
4391
|
-
rejection: combineRejections(rejection, cleanup)
|
|
4392
|
-
failure: cleanup.failure
|
|
4636
|
+
rejection: combineRejections(rejection, cleanup)
|
|
4393
4637
|
};
|
|
4394
4638
|
}
|
|
4395
4639
|
/**
|
|
@@ -4400,6 +4644,11 @@ async function runLevel(storage, level, callback, commits, signal) {
|
|
|
4400
4644
|
function endLevel(level, commit, endedBy) {
|
|
4401
4645
|
if (level.cleanup) return level.cleanup;
|
|
4402
4646
|
level.endedBy = endedBy;
|
|
4647
|
+
if (level.state === "reserved") {
|
|
4648
|
+
closeStarting(level);
|
|
4649
|
+
level.cleanup = Promise.resolve({});
|
|
4650
|
+
return level.cleanup;
|
|
4651
|
+
}
|
|
4403
4652
|
level.state = "closing";
|
|
4404
4653
|
level.cleanup = cleanUpLevel(level, commit, level.child && endLevel(level.child, false, "enclosing level"));
|
|
4405
4654
|
return level.cleanup;
|
|
@@ -4407,28 +4656,33 @@ function endLevel(level, commit, endedBy) {
|
|
|
4407
4656
|
async function cleanUpLevel(level, commit, nested) {
|
|
4408
4657
|
const nestedCleanup = await nested;
|
|
4409
4658
|
const { parent } = level;
|
|
4410
|
-
const cleanup = parent ? await endSavepoint(level, commit && !level.rollbackOnly) : await endTransaction(level
|
|
4659
|
+
const cleanup = parent ? await endSavepoint(level, commit && !level.rollbackOnly) : await endTransaction(level, commit);
|
|
4411
4660
|
level.state = "closed";
|
|
4412
4661
|
if (parent) {
|
|
4413
4662
|
if (parent.child === level) parent.child = void 0;
|
|
4414
4663
|
parent.rollbackOnly ??= cleanup.rejection;
|
|
4415
4664
|
}
|
|
4416
|
-
return {
|
|
4417
|
-
rejection: combineRejections(nestedCleanup?.rejection, cleanup),
|
|
4418
|
-
failure: cleanup.failure
|
|
4419
|
-
};
|
|
4665
|
+
return { rejection: combineRejections(nestedCleanup?.rejection, cleanup) };
|
|
4420
4666
|
}
|
|
4421
|
-
/**
|
|
4422
|
-
|
|
4667
|
+
/**
|
|
4668
|
+
* Ends a transaction with `COMMIT` or `ROLLBACK`.
|
|
4669
|
+
*
|
|
4670
|
+
* A transaction whose watch recorded a `ConnectionError` rolls back instead of `COMMIT` and rejects with that error, as if its callback had rejected with it.
|
|
4671
|
+
*/
|
|
4672
|
+
async function endTransaction(level, commit) {
|
|
4673
|
+
const { connection, watch } = level;
|
|
4674
|
+
const lost = commit && watch?.failure ? { error: watch.failure.error } : void 0;
|
|
4423
4675
|
try {
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4676
|
+
if (commit && !lost) {
|
|
4677
|
+
if (watch) watch.phase = "commit";
|
|
4678
|
+
const { command } = await connection.execute(commitStatement);
|
|
4679
|
+
if (command !== "COMMIT") return { rejection: { error: /* @__PURE__ */ new Error("Transaction was rolled back: a statement in it failed") } };
|
|
4680
|
+
return {};
|
|
4681
|
+
}
|
|
4682
|
+
await connection.execute(rollbackStatement);
|
|
4683
|
+
return lost ? { rejection: lost } : {};
|
|
4427
4684
|
} catch (error) {
|
|
4428
|
-
return {
|
|
4429
|
-
rejection: { error },
|
|
4430
|
-
failure: { error }
|
|
4431
|
-
};
|
|
4685
|
+
return { rejection: suppress(error, lost, "Transaction rollback failed") };
|
|
4432
4686
|
}
|
|
4433
4687
|
}
|
|
4434
4688
|
/**
|
|
@@ -4451,7 +4705,7 @@ async function endSavepoint(level, commit) {
|
|
|
4451
4705
|
function getSavepointName(level) {
|
|
4452
4706
|
return `kern_${level.depth}`;
|
|
4453
4707
|
}
|
|
4454
|
-
/** Closes a nested level whose `SAVEPOINT` failed, freeing its parent for other statements. */
|
|
4708
|
+
/** Closes a nested level whose `SAVEPOINT` was not sent or failed, freeing its parent for other statements. */
|
|
4455
4709
|
function closeStarting(level) {
|
|
4456
4710
|
level.state = "closed";
|
|
4457
4711
|
if (level.parent?.child === level) level.parent.child = void 0;
|
|
@@ -4472,20 +4726,7 @@ function createClosedError(level, rejection) {
|
|
|
4472
4726
|
}
|
|
4473
4727
|
/** Outcome of a level that something other than its callback ended: a rejection with `error`, which a failed cleanup suppresses. */
|
|
4474
4728
|
async function getEndedOutcome(cleanup, error) {
|
|
4475
|
-
|
|
4476
|
-
return {
|
|
4477
|
-
rejection: combineRejections({ error }, ended),
|
|
4478
|
-
failure: ended.failure
|
|
4479
|
-
};
|
|
4480
|
-
}
|
|
4481
|
-
/** Returns the connection of a transaction to the driver, keeping a failed release as a rejection that suppresses `rejection`. */
|
|
4482
|
-
async function releaseConnection(connection, failure, rejection) {
|
|
4483
|
-
try {
|
|
4484
|
-
await connection.release(failure);
|
|
4485
|
-
return rejection;
|
|
4486
|
-
} catch (error) {
|
|
4487
|
-
return suppress(error, rejection, "Releasing the transaction connection failed");
|
|
4488
|
-
}
|
|
4729
|
+
return { rejection: combineRejections({ error }, await cleanup) };
|
|
4489
4730
|
}
|
|
4490
4731
|
/** Error of a failure to start a test transaction, which suppresses the reason of `signal` when the signal aborted before the failure. */
|
|
4491
4732
|
function suppressAbortReason(error, signal) {
|
|
@@ -4503,6 +4744,7 @@ function suppress(error, earlier, message) {
|
|
|
4503
4744
|
/** Open test fixtures of a transaction coordinator and the queue of the changes of their stack. */
|
|
4504
4745
|
var TestFixtureStack = class {
|
|
4505
4746
|
#driver;
|
|
4747
|
+
#onReleaseError;
|
|
4506
4748
|
/** Async context of the levels of the coordinator, which tells whether a call runs inside a level. */
|
|
4507
4749
|
#storage;
|
|
4508
4750
|
/** Open test fixtures, the innermost last. */
|
|
@@ -4522,16 +4764,17 @@ var TestFixtureStack = class {
|
|
|
4522
4764
|
* Openings that start after that closing is requested nest outside of the fixture once it closes, so a repeated closing of it, or a closing of a fixture nested in it, must not close them.
|
|
4523
4765
|
*/
|
|
4524
4766
|
#closing;
|
|
4525
|
-
constructor(driver, storage) {
|
|
4767
|
+
constructor(driver, storage, onReleaseError) {
|
|
4526
4768
|
this.#driver = driver;
|
|
4527
4769
|
this.#storage = storage;
|
|
4770
|
+
this.#onReleaseError = onReleaseError;
|
|
4528
4771
|
}
|
|
4529
4772
|
/**
|
|
4530
|
-
* Starts opening a test fixture
|
|
4773
|
+
* Starts opening a test fixture with `options`, see `startTestFixture` of the coordinator, or, given `refusal`, returns a fixture that rejects with it.
|
|
4531
4774
|
*
|
|
4532
4775
|
* The `close` of a refused fixture resolves once the earlier changes of the stack end.
|
|
4533
4776
|
*/
|
|
4534
|
-
start(seed, refusal) {
|
|
4777
|
+
start(seed, refusal, options) {
|
|
4535
4778
|
let level;
|
|
4536
4779
|
let closeRequested = false;
|
|
4537
4780
|
const closing = Promise.withResolvers();
|
|
@@ -4570,7 +4813,7 @@ var TestFixtureStack = class {
|
|
|
4570
4813
|
const open = async () => {
|
|
4571
4814
|
if (closeRequested) return;
|
|
4572
4815
|
const parent = this.#fixtures.at(-1);
|
|
4573
|
-
const started = parent ? await this.#startInFixture(parent) : await this.#beginFixture();
|
|
4816
|
+
const started = parent ? await this.#startInFixture(parent, options) : await this.#beginFixture(options?.isolation);
|
|
4574
4817
|
started.state = "open";
|
|
4575
4818
|
const outcome = closeRequested ? void 0 : await Promise.race([this.#seedFixture(started, seed), closing.promise]);
|
|
4576
4819
|
if (outcome && !outcome.rejection && !closeRequested) {
|
|
@@ -4614,13 +4857,14 @@ var TestFixtureStack = class {
|
|
|
4614
4857
|
* Aborted while it waits for its turn, it rejects at once and its change starts nothing, so that a test that has already ended never preempts the active level of the fixture.
|
|
4615
4858
|
* From its turn on, it settles with its change.
|
|
4616
4859
|
*/
|
|
4617
|
-
startTestLevel(
|
|
4860
|
+
startTestLevel(options) {
|
|
4861
|
+
const signal = options?.signal;
|
|
4618
4862
|
let waiting = true;
|
|
4619
4863
|
const start = () => this.#enqueue(() => {
|
|
4620
4864
|
if (signal?.aborted) return;
|
|
4621
4865
|
waiting = false;
|
|
4622
4866
|
const fixture = this.#fixtures.at(-1);
|
|
4623
|
-
return fixture && this.#startInFixture(fixture,
|
|
4867
|
+
return fixture && this.#startInFixture(fixture, options);
|
|
4624
4868
|
});
|
|
4625
4869
|
return signal ? settleUnlessAborted(start, signal, () => waiting) : start();
|
|
4626
4870
|
}
|
|
@@ -4674,8 +4918,9 @@ var TestFixtureStack = class {
|
|
|
4674
4918
|
}
|
|
4675
4919
|
/** Rolls back a fixture and releases the connection of the first one, returning the error to reject with. */
|
|
4676
4920
|
async #endFixture(fixture) {
|
|
4677
|
-
const
|
|
4678
|
-
|
|
4921
|
+
const { rejection } = await endLevel(fixture, false);
|
|
4922
|
+
if (!fixture.parent) await releaseConnection(fixture.connection, this.#onReleaseError);
|
|
4923
|
+
return rejection;
|
|
4679
4924
|
}
|
|
4680
4925
|
/** Runs a change of the fixture stack after the earlier ones. */
|
|
4681
4926
|
#enqueue(transition) {
|
|
@@ -4683,23 +4928,25 @@ var TestFixtureStack = class {
|
|
|
4683
4928
|
this.#transitions = result.catch(() => {});
|
|
4684
4929
|
return result;
|
|
4685
4930
|
}
|
|
4686
|
-
/** Starts the first test fixture: a transaction on a reserved connection. */
|
|
4687
|
-
async #beginFixture() {
|
|
4931
|
+
/** Starts the first test fixture: a transaction at `isolation` on a reserved connection. */
|
|
4932
|
+
async #beginFixture(isolation) {
|
|
4688
4933
|
const connection = await this.#driver.acquire();
|
|
4689
4934
|
try {
|
|
4690
|
-
await connection.execute(
|
|
4935
|
+
await connection.execute(getBeginStatement(isolation));
|
|
4691
4936
|
} catch (error) {
|
|
4692
|
-
|
|
4937
|
+
await releaseConnection(connection, this.#onReleaseError);
|
|
4938
|
+
throw error;
|
|
4693
4939
|
}
|
|
4694
|
-
return createLevel(connection, void 0, false);
|
|
4940
|
+
return createLevel(connection, void 0, false, isolation);
|
|
4695
4941
|
}
|
|
4696
4942
|
/**
|
|
4697
|
-
* Starts a nested level of a test fixture
|
|
4943
|
+
* Starts a nested level of a test fixture with `options`, preempting its active one.
|
|
4698
4944
|
*
|
|
4699
4945
|
* A fixture runs one nested level at a time, so a new one ends the previous one, such as a test that timed out.
|
|
4700
4946
|
* A level whose `signal` aborts while it preempts rejects with its reason instead of starting, and a failure to start after the abort suppresses the reason.
|
|
4701
4947
|
*/
|
|
4702
|
-
async #startInFixture(fixture,
|
|
4948
|
+
async #startInFixture(fixture, options) {
|
|
4949
|
+
const signal = options?.signal;
|
|
4703
4950
|
if (fixture.child) {
|
|
4704
4951
|
const cleanup = await endLevel(fixture.child, false, "preemption");
|
|
4705
4952
|
if (cleanup.rejection) throw suppressAbortReason(new Error("Cannot start a level of the test fixture: ending its active level failed", { cause: cleanup.rejection.error }), signal);
|
|
@@ -4707,7 +4954,7 @@ var TestFixtureStack = class {
|
|
|
4707
4954
|
const unavailable = createUnavailableError(fixture, "start a level of the test fixture");
|
|
4708
4955
|
if (unavailable) throw suppressAbortReason(unavailable, signal);
|
|
4709
4956
|
signal?.throwIfAborted();
|
|
4710
|
-
return startNestedLevel(fixture, false,
|
|
4957
|
+
return startNestedLevel(fixture, false, options);
|
|
4711
4958
|
}
|
|
4712
4959
|
};
|
|
4713
4960
|
// src/execution/transaction/coordinator.ts
|
|
@@ -4718,15 +4965,18 @@ var TestFixtureStack = class {
|
|
|
4718
4965
|
*/
|
|
4719
4966
|
var TransactionCoordinator = class {
|
|
4720
4967
|
driver;
|
|
4721
|
-
test;
|
|
4722
4968
|
#storage = new AsyncLocalStorage();
|
|
4723
4969
|
#fixtures;
|
|
4970
|
+
#onReleaseError;
|
|
4724
4971
|
/** Closing of the database, set by the first `close`; from then on, operations outside a transaction reject. */
|
|
4725
4972
|
#closed;
|
|
4726
|
-
|
|
4973
|
+
/** Rejects statements and transactions outside a test transaction or the seed of a test fixture instead of running them on the pool. */
|
|
4974
|
+
test;
|
|
4975
|
+
constructor(driver, { test = false, onReleaseError } = {}) {
|
|
4727
4976
|
this.driver = driver;
|
|
4728
4977
|
this.test = test;
|
|
4729
|
-
this.#
|
|
4978
|
+
this.#onReleaseError = onReleaseError;
|
|
4979
|
+
this.#fixtures = new TestFixtureStack(driver, this.#storage, onReleaseError);
|
|
4730
4980
|
}
|
|
4731
4981
|
execute(statement) {
|
|
4732
4982
|
const target = this.#route("execute a query");
|
|
@@ -4749,15 +4999,19 @@ var TransactionCoordinator = class {
|
|
|
4749
4999
|
/**
|
|
4750
5000
|
* Runs `callback` in a transaction that commits when it resolves and rolls back when it rejects, with the settings of `options`.
|
|
4751
5001
|
*
|
|
4752
|
-
* Inside a transaction, it runs `callback` in a savepoint nested in it, which restores the settings it changed when it ends.
|
|
5002
|
+
* Inside a transaction, it runs `callback` in a savepoint nested in it, which restores the settings it changed when it ends, and rejects without the savepoint when the isolation level of `options` differs from that of the transaction.
|
|
4753
5003
|
* A failed cleanup after an error rejects with a `SuppressedError` that keeps the original error in its `suppressed` chain.
|
|
5004
|
+
* A transaction that it starts rolls back instead of `COMMIT` after a `ConnectionError` on its connection, and when it rejects after such an error, also of `COMMIT`, it rejects with `TransactionConnectionError` of the phase of the failure, whose `cause` is the error it would reject with otherwise.
|
|
4754
5005
|
*/
|
|
4755
5006
|
transaction(callback, options) {
|
|
4756
|
-
const
|
|
5007
|
+
const levelOptions = options && {
|
|
5008
|
+
settings: getLevelSettings(options),
|
|
5009
|
+
isolation: options.isolation
|
|
5010
|
+
};
|
|
4757
5011
|
const parent = this.#storage.getStore();
|
|
4758
|
-
if (parent) return this.#runNested(parent, callback, true,
|
|
5012
|
+
if (parent) return this.#runNested(parent, callback, true, levelOptions);
|
|
4759
5013
|
if (this.#closed) return Promise.reject(createDatabaseClosedError("start a transaction"));
|
|
4760
|
-
return this.test ? Promise.reject(new Error(describeOutsideTest("start a transaction"))) : this.#runRoot(callback, true,
|
|
5014
|
+
return this.test ? Promise.reject(new Error(describeOutsideTest("start a transaction"))) : this.#runRoot(callback, true, levelOptions);
|
|
4761
5015
|
}
|
|
4762
5016
|
/**
|
|
4763
5017
|
* Runs `callback` in the current transaction, or in a new transaction outside of one.
|
|
@@ -4789,13 +5043,14 @@ var TransactionCoordinator = class {
|
|
|
4789
5043
|
* A failure to start or end the level after the abort suppresses the reason in a `SuppressedError`.
|
|
4790
5044
|
* Aborted while it waits for its turn in the fixture stack or for a connection, it rejects at once; after the abort, it never calls `callback`.
|
|
4791
5045
|
*/
|
|
4792
|
-
testTransaction(callback,
|
|
5046
|
+
testTransaction(callback, options) {
|
|
5047
|
+
const signal = options?.signal;
|
|
4793
5048
|
if (!this.test) return Promise.reject(/* @__PURE__ */ new Error("testTransaction requires a database created with test: true"));
|
|
4794
5049
|
if (signal?.aborted) return Promise.reject(signal.reason);
|
|
4795
5050
|
const parent = this.#storage.getStore();
|
|
4796
|
-
if (parent) return this.#runNested(parent, callback, false,
|
|
5051
|
+
if (parent) return this.#runNested(parent, callback, false, options);
|
|
4797
5052
|
if (this.#closed) return Promise.reject(createDatabaseClosedError("start a test transaction"));
|
|
4798
|
-
return this.#fixtures.startTestLevel(
|
|
5053
|
+
return this.#fixtures.startTestLevel(options).then((level) => level ? this.#runStarted(level, callback, false, signal) : this.#runRoot(callback, false, options));
|
|
4799
5054
|
}
|
|
4800
5055
|
/**
|
|
4801
5056
|
* Opens a test fixture: a transaction on a reserved connection, or a savepoint in the innermost open fixture, and runs `seed` in it.
|
|
@@ -4803,8 +5058,8 @@ var TransactionCoordinator = class {
|
|
|
4803
5058
|
* Test transactions started outside any transaction run in the innermost fixture.
|
|
4804
5059
|
* A fixture whose `seed` rejects rolls back and closes.
|
|
4805
5060
|
*/
|
|
4806
|
-
createTestFixture(seed) {
|
|
4807
|
-
return this.startTestFixture(seed).fixture;
|
|
5061
|
+
createTestFixture(seed, options) {
|
|
5062
|
+
return this.startTestFixture(seed, options).fixture;
|
|
4808
5063
|
}
|
|
4809
5064
|
/**
|
|
4810
5065
|
* Starts opening a test fixture, see `createTestFixture`, and returns it with a `close` that can be called before it opens.
|
|
@@ -4812,8 +5067,8 @@ var TransactionCoordinator = class {
|
|
|
4812
5067
|
* Closing before the fixture opens rejects the opening without waiting for `seed` and rolls the fixture back, so a fixture or test transaction started after `close` never nests in it, even when its `seed` never settles.
|
|
4813
5068
|
* Closing an open fixture also closes the fixtures opening in it.
|
|
4814
5069
|
*/
|
|
4815
|
-
startTestFixture(seed) {
|
|
4816
|
-
return this.#fixtures.start(seed, this.#getFixtureRefusal());
|
|
5070
|
+
startTestFixture(seed, options) {
|
|
5071
|
+
return this.#fixtures.start(seed, this.#getFixtureRefusal(), options);
|
|
4817
5072
|
}
|
|
4818
5073
|
/** Returns the error that rejects a test fixture created now, or `undefined` when it can open. */
|
|
4819
5074
|
#getFixtureRefusal() {
|
|
@@ -4848,34 +5103,48 @@ var TransactionCoordinator = class {
|
|
|
4848
5103
|
}
|
|
4849
5104
|
if (rejection) throw rejection.error;
|
|
4850
5105
|
}
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
5106
|
+
/**
|
|
5107
|
+
* Runs `callback` in a level without a parent on a connection of its own: a transaction of `transaction` when it `commits`, and a test transaction otherwise.
|
|
5108
|
+
*
|
|
5109
|
+
* A transaction of `transaction` whose connection fails rejects with `TransactionConnectionError`.
|
|
5110
|
+
*/
|
|
5111
|
+
async #runRoot(callback, commits, { signal, settings, isolation } = noLevelOptions) {
|
|
5112
|
+
let connection;
|
|
5113
|
+
try {
|
|
5114
|
+
connection = await (signal ? acquireUnlessAborted(this.driver, signal, this.#onReleaseError) : this.driver.acquire());
|
|
5115
|
+
} catch (error) {
|
|
5116
|
+
throw commits && error instanceof ConnectionError ? new TransactionConnectionError("begin", { cause: error }) : error;
|
|
5117
|
+
}
|
|
5118
|
+
if (signal?.aborted) {
|
|
5119
|
+
await releaseConnection(connection, this.#onReleaseError);
|
|
5120
|
+
throw signal.reason;
|
|
5121
|
+
}
|
|
5122
|
+
const level = createLevel(connection, void 0, commits, isolation);
|
|
5123
|
+
const { watch } = level;
|
|
4855
5124
|
let outcome;
|
|
4856
5125
|
try {
|
|
4857
|
-
await connection.execute(
|
|
5126
|
+
await level.connection.execute(getBeginStatement(isolation));
|
|
4858
5127
|
} catch (error) {
|
|
4859
5128
|
level.state = "closed";
|
|
4860
|
-
outcome = {
|
|
4861
|
-
rejection: { error: suppressAbortReason(error, signal) },
|
|
4862
|
-
failure: { error }
|
|
4863
|
-
};
|
|
5129
|
+
outcome = { rejection: { error: suppressAbortReason(error, signal) } };
|
|
4864
5130
|
}
|
|
4865
5131
|
if (!outcome && settings) try {
|
|
4866
5132
|
await applySettings(level, settings);
|
|
4867
5133
|
} catch (error) {
|
|
4868
5134
|
outcome = await getEndedOutcome(endLevel(level, false), error);
|
|
4869
5135
|
}
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
5136
|
+
if (!outcome) {
|
|
5137
|
+
if (watch) watch.phase = "transaction";
|
|
5138
|
+
outcome = await runLevel(this.#storage, level, callback, commits, signal);
|
|
5139
|
+
}
|
|
5140
|
+
await releaseConnection(connection, this.#onReleaseError);
|
|
5141
|
+
if (outcome.rejection) throw watch?.failure ? new TransactionConnectionError(watch.failure.phase, { cause: outcome.rejection.error }) : outcome.rejection.error;
|
|
4873
5142
|
return outcome.result;
|
|
4874
5143
|
}
|
|
4875
|
-
async #runNested(parent, callback, commits,
|
|
5144
|
+
async #runNested(parent, callback, commits, options) {
|
|
4876
5145
|
const unavailable = createUnavailableError(parent, "start a nested transaction");
|
|
4877
5146
|
if (unavailable) throw unavailable;
|
|
4878
|
-
return this.#runStarted(await startNestedLevel(parent, commits,
|
|
5147
|
+
return this.#runStarted(await startNestedLevel(parent, commits, options), callback, commits, options?.signal);
|
|
4879
5148
|
}
|
|
4880
5149
|
/** Runs `callback` in a started level, returning its result or throwing its rejection. */
|
|
4881
5150
|
async #runStarted(level, callback, commits, signal) {
|
|
@@ -4894,8 +5163,8 @@ function createDatabaseClosedError(operation) {
|
|
|
4894
5163
|
}
|
|
4895
5164
|
// src/execution/database.ts
|
|
4896
5165
|
/** Creates a database over a driver; its transactions are shared by every schema bound to it. */
|
|
4897
|
-
function createDatabase({ driver,
|
|
4898
|
-
const coordinator = new TransactionCoordinator(driver,
|
|
5166
|
+
function createDatabase({ driver, ...options }) {
|
|
5167
|
+
const coordinator = new TransactionCoordinator(driver, options);
|
|
4899
5168
|
let tablelessDb;
|
|
4900
5169
|
const getTablelessDb = () => tablelessDb ??= bindSchema(defineSchema(), database);
|
|
4901
5170
|
const database = {
|
|
@@ -4920,4 +5189,4 @@ function createDatabase({ driver, test }) {
|
|
|
4920
5189
|
function createLockStatement(key) {
|
|
4921
5190
|
return createStatement("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [key]);
|
|
4922
5191
|
}
|
|
4923
|
-
export {
|
|
5192
|
+
export { toAggregateType as A, NotFoundError as C, countType as D, countProjection as E, or as F, combineNodes as I, and as M, isColumnValues as N, createAggregateCall as O, not as P, defineTable as S, ResultDecodeError as T, matchColumn as _, toDriverError as a, createStatement as b, sql as c, from as d, requireDerived as f, orderBy as g, desc as h, QueryError as i, literal as j, createCountCall as k, defineSchema as l, asc as m, TransactionConnectionError as n, identifier as o, addTerms as p, ConnectionError as r, param as s, createDatabase as t, SelectQuery as u, many as v, RequiredRelationError as w, createTableFactory as x, one as y };
|