@prisma/orm-family-sql 8.0.0-rc.17-dev.26 → 8.0.0-rc.17-dev.28
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/{index-ZHk0SsBA.d.mts → index-qr6LA3dl.d.mts} +4 -4
- package/dist/{index-ZHk0SsBA.d.mts.map → index-qr6LA3dl.d.mts.map} +1 -1
- package/dist/middleware-DOKGNt72.d.mts +1 -0
- package/dist/{middleware-mLwvcOLS-wIYSKgog.d.mts → middleware-YsFLC19Y-xhimGDiS.d.mts} +4 -4
- package/dist/{middleware-mLwvcOLS-wIYSKgog.d.mts.map → middleware-YsFLC19Y-xhimGDiS.d.mts.map} +1 -1
- package/dist/orm-client.d.mts +2 -2
- package/dist/orm-client.mjs +8 -1
- package/dist/orm-client.mjs.map +1 -1
- package/dist/{prepared-statement-YtgdlN7e-DqHHwo30.d.mts → prepared-statement-Bs9TKj5u-CInk8vXF.d.mts} +60 -76
- package/dist/prepared-statement-Bs9TKj5u-CInk8vXF.d.mts.map +1 -0
- package/dist/relational-core.d.mts +1 -1
- package/dist/relational-core__middleware.d.mts +2 -2
- package/dist/runtime.d.mts +3 -3
- package/dist/runtime.mjs +217 -137
- package/dist/runtime.mjs.map +1 -1
- package/dist/runtime__internal__prepared-query.d.mts +2 -2
- package/dist/runtime__internal__prepared-query.mjs +2 -2
- package/dist/transaction-state-BfXhs7D7-3k10jZ8I.mjs +45 -0
- package/dist/transaction-state-BfXhs7D7-3k10jZ8I.mjs.map +1 -0
- package/package.json +18 -18
- package/dist/middleware-FHkIPvYR.d.mts +0 -1
- package/dist/prepared-query-BJr50wPm-ChoqfJbX.mjs +0 -22
- package/dist/prepared-query-BJr50wPm-ChoqfJbX.mjs.map +0 -1
- package/dist/prepared-statement-YtgdlN7e-DqHHwo30.d.mts.map +0 -1
package/dist/runtime.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { t as collectOrderedParamRefs } from "./util-BBgcP3gI-XJBkxo1K.mjs";
|
|
|
4
4
|
import { t as createSqlParamRefMutator } from "./middleware-yBAfiVWn-CzNCthJT.mjs";
|
|
5
5
|
import { t as buildSqlAggregateDescriptorRegistry } from "./aggregate-descriptor-registry-DrJ1vHEo.mjs";
|
|
6
6
|
import { t as buildCodecDescriptorRegistry } from "./codec-descriptor-registry-CYK0Wzja.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { a as runPreparedQuery, c as transactionStart, i as runPreparedExecute, l as wasRefusedBeforeBegin, n as preparedStatementExecute, o as settlementOf, r as preparedStatementQuery, s as transactionSettlement, t as createTransactionStart } from "./transaction-state-BfXhs7D7-3k10jZ8I.mjs";
|
|
8
8
|
import { isStructuredError, structuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
9
9
|
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
@@ -13,11 +13,11 @@ import { blindCast } from "@prisma/orm-framework/utils/casts";
|
|
|
13
13
|
import { assertNever, isInternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
14
14
|
import { canonicalStringify } from "@prisma/orm-framework/utils/canonical-stringify";
|
|
15
15
|
import { checkContractComponentRequirements, mergeCapabilityMatrices } from "@prisma/orm-framework/components/components";
|
|
16
|
-
import { AsyncIterableResult, RuntimeCore, applyMutationDefaults, assertMutationDefaultGeneratorsAvailable, checkAborted, checkMiddlewareCompatibility, collectMutationDefaultGenerators,
|
|
16
|
+
import { AsyncIterableResult, RuntimeCore, applyMutationDefaults, assertMutationDefaultGeneratorsAvailable, checkAborted, checkMiddlewareCompatibility, collectMutationDefaultGenerators, createStateStore, executeStatement, raceAgainstAbort, runtimeError as runtimeError$1, startTransactionActivity, streamStatement } from "@prisma/orm-framework/components/runtime";
|
|
17
17
|
import { canonicalizeJson } from "@prisma/orm-framework/components/utils";
|
|
18
18
|
import { createExecutionStack } from "@prisma/orm-framework/components/execution";
|
|
19
19
|
import { hashContent } from "@prisma/orm-framework/utils/hash-content";
|
|
20
|
-
//#region ../../../2-sql/5-runtime/dist/exports-
|
|
20
|
+
//#region ../../../2-sql/5-runtime/dist/exports-BxFmkVE5.mjs
|
|
21
21
|
/**
|
|
22
22
|
* Build an {@link AstCodecResolver} bound to a descriptor registry and a per-call instance-context factory.
|
|
23
23
|
*
|
|
@@ -216,6 +216,7 @@ function emitBudgetViolation(error, shouldBlock, ctx) {
|
|
|
216
216
|
details: error.details
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
|
+
const observedRows = Symbol("budgets.observedRows");
|
|
219
220
|
function budgets(options) {
|
|
220
221
|
const maxRows = options?.maxRows ?? 1e4;
|
|
221
222
|
const defaultTableRows = options?.defaultTableRows ?? 1e4;
|
|
@@ -223,39 +224,38 @@ function budgets(options) {
|
|
|
223
224
|
const maxLatencyMs = options?.maxLatencyMs ?? 1e3;
|
|
224
225
|
const rowSeverity = options?.severities?.rowCount ?? "error";
|
|
225
226
|
const latencySeverity = options?.severities?.latency ?? "warn";
|
|
226
|
-
const observedRowsByPlan = /* @__PURE__ */ new WeakMap();
|
|
227
|
-
const beforeOperation = async (plan, ctx) => {
|
|
228
|
-
observedRowsByPlan.set(plan, { count: 0 });
|
|
229
|
-
if (isQueryAst(plan.ast) && plan.ast.kind === "select") evaluateSelectAst(plan.ast, ctx);
|
|
230
|
-
};
|
|
231
|
-
const afterOperation = async (_plan, result, ctx) => {
|
|
232
|
-
const latencyMs = result.latencyMs;
|
|
233
|
-
if (latencyMs > maxLatencyMs) {
|
|
234
|
-
const shouldBlock = latencySeverity === "error" || ctx.mode === "strict";
|
|
235
|
-
emitBudgetViolation(runtimeError$1("BUDGET.TIME_EXCEEDED", "Query latency exceeds budget", {
|
|
236
|
-
latencyMs,
|
|
237
|
-
maxLatencyMs
|
|
238
|
-
}), shouldBlock, ctx);
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
227
|
return Object.freeze({
|
|
242
228
|
name: "budgets",
|
|
243
229
|
familyId: "sql",
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
230
|
+
async beforeEncode(plan, ctx) {
|
|
231
|
+
if (isQueryAst(plan.ast) && plan.ast.kind === "select") evaluateSelectAst(plan.ast, ctx);
|
|
232
|
+
},
|
|
233
|
+
async onRow(_row, _plan, ctx) {
|
|
234
|
+
const observed = ctx.state(observedRows);
|
|
235
|
+
const count = (typeof observed["count"] === "number" ? observed["count"] : 0) + 1;
|
|
236
|
+
observed["count"] = count;
|
|
237
|
+
if (count <= maxRows || observed["warned"] === true) return;
|
|
238
|
+
const shouldBlock = rowSeverity === "error" || ctx.mode === "strict";
|
|
239
|
+
if (!shouldBlock) observed["warned"] = true;
|
|
240
|
+
emitBudgetViolation(runtimeError$1("BUDGET.ROWS_EXCEEDED", "Observed row count exceeds budget", {
|
|
251
241
|
source: "observed",
|
|
252
|
-
observedRows:
|
|
242
|
+
observedRows: count,
|
|
253
243
|
maxRows
|
|
254
|
-
});
|
|
244
|
+
}), shouldBlock, ctx);
|
|
255
245
|
},
|
|
256
|
-
|
|
257
|
-
|
|
246
|
+
async activityEnded(_activity, result, ctx) {
|
|
247
|
+
if (result.kind === "statement") checkLatency(result.latencyMs, ctx);
|
|
248
|
+
}
|
|
258
249
|
});
|
|
250
|
+
function checkLatency(latencyMs, ctx) {
|
|
251
|
+
if (latencyMs > maxLatencyMs) {
|
|
252
|
+
const shouldBlock = latencySeverity === "error" || ctx.mode === "strict";
|
|
253
|
+
emitBudgetViolation(runtimeError$1("BUDGET.TIME_EXCEEDED", "Query latency exceeds budget", {
|
|
254
|
+
latencyMs,
|
|
255
|
+
maxLatencyMs
|
|
256
|
+
}), shouldBlock, ctx);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
259
|
function evaluateSelectAst(ast, ctx) {
|
|
260
260
|
const hasAggNoGroup = hasAggregateWithoutGroupBy(ast);
|
|
261
261
|
const estimated = estimateRowsFromAst(ast, tableRows, defaultTableRows, hasAggNoGroup);
|
|
@@ -455,8 +455,7 @@ function lints(options) {
|
|
|
455
455
|
return Object.freeze({
|
|
456
456
|
name: "lints",
|
|
457
457
|
familyId: "sql",
|
|
458
|
-
|
|
459
|
-
beforeExecute: beforeOperation
|
|
458
|
+
beforeEncode: beforeOperation
|
|
460
459
|
});
|
|
461
460
|
}
|
|
462
461
|
var PreparedStatementImpl = class {
|
|
@@ -1227,6 +1226,7 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1227
1226
|
#refusing = false;
|
|
1228
1227
|
#heldQueryables = /* @__PURE__ */ new WeakSet();
|
|
1229
1228
|
#preparedStatementHandles = /* @__PURE__ */ new WeakMap();
|
|
1229
|
+
#holdFinishedChildren;
|
|
1230
1230
|
#openTransactions = /* @__PURE__ */ new WeakMap();
|
|
1231
1231
|
codecRegistryValidated;
|
|
1232
1232
|
_telemetry;
|
|
@@ -1239,13 +1239,13 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1239
1239
|
now: () => Date.now(),
|
|
1240
1240
|
log: log ?? noopLog,
|
|
1241
1241
|
contentHash: (exec) => computeSqlContentHash(blindCast(exec)),
|
|
1242
|
-
scope: "runtime"
|
|
1243
|
-
planExecutionId: ""
|
|
1242
|
+
scope: "runtime"
|
|
1244
1243
|
};
|
|
1245
1244
|
super({
|
|
1246
1245
|
middleware: middleware ?? [],
|
|
1247
1246
|
ctx: sqlCtx
|
|
1248
1247
|
});
|
|
1248
|
+
this.#holdFinishedChildren = this.middleware.some((mw) => mw.activityFinalized !== void 0);
|
|
1249
1249
|
this.contract = context.contract;
|
|
1250
1250
|
this.adapter = adapter;
|
|
1251
1251
|
this.driver = driver;
|
|
@@ -1267,9 +1267,8 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1267
1267
|
* Implementation note: SQL splits lower-then-encode across
|
|
1268
1268
|
* {@link lowerToDraft} + {@link encodeDraftParams} so the selected
|
|
1269
1269
|
* operation's middleware chain can run between them:
|
|
1270
|
-
* {@link
|
|
1271
|
-
*
|
|
1272
|
-
* `execute()` (cipherstash bulk-encrypt, for example, mutates pre-encode
|
|
1270
|
+
* {@link prepareOperation} runs the statement's `beforeEncode` chain
|
|
1271
|
+
* between them (cipherstash bulk-encrypt, for example, mutates pre-encode
|
|
1273
1272
|
* `ParamRef.value` slots). This protected hook composes the two back into
|
|
1274
1273
|
* the cross-family `lower()` shape `RuntimeCore` expects. The production
|
|
1275
1274
|
* operation methods use the matching split form before driver execution.
|
|
@@ -1320,12 +1319,8 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1320
1319
|
});
|
|
1321
1320
|
}
|
|
1322
1321
|
/**
|
|
1323
|
-
*
|
|
1324
|
-
* AST directly.
|
|
1322
|
+
* Runs the registered middleware `beforeCompile` chain over the plan's draft (AST + meta). Returns the original plan unchanged when no middleware rewrote the AST; otherwise returns a new plan carrying the rewritten AST and meta. The lowering adapter and the encoder both walk the rewritten AST directly.
|
|
1325
1323
|
*/
|
|
1326
|
-
runBeforeCompile(plan) {
|
|
1327
|
-
return this.compilePlan(plan, this.sqlCtx);
|
|
1328
|
-
}
|
|
1329
1324
|
async compilePlan(plan, middlewareCtx) {
|
|
1330
1325
|
const rewrittenDraft = await runBeforeCompileChain(this.middleware, {
|
|
1331
1326
|
ast: plan.ast,
|
|
@@ -1374,25 +1369,19 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1374
1369
|
if (queryable === this.driver && this.#refusing) throw runtimeClosedError();
|
|
1375
1370
|
return this.#inFlight.begin();
|
|
1376
1371
|
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
if (runStage === void 0) return void 0;
|
|
1380
|
-
const rememberOnTransaction = this.#openTransactions.get(queryable);
|
|
1381
|
-
return rememberOnTransaction === void 0 ? onQueryEndOutsideTransaction(runStage) : rememberOnTransaction(runStage);
|
|
1372
|
+
parentOf(queryable) {
|
|
1373
|
+
return this.#openTransactions.get(queryable);
|
|
1382
1374
|
}
|
|
1383
1375
|
getListDecoder() {
|
|
1384
1376
|
return sqlNativeArrayListDecoder;
|
|
1385
1377
|
}
|
|
1386
|
-
|
|
1387
|
-
return reportQueryEnding(this.scheduleAfterTransaction(queryable, exec, execMiddlewareCtx), () => this.streamDecodedRows(exec, createDecodeContext, driverCall, codecCtx, execMiddlewareCtx, queryable, onDriverAnswered));
|
|
1388
|
-
}
|
|
1389
|
-
async *streamDecodedRows(exec, createDecodeContext, driverCall, codecCtx, execMiddlewareCtx, queryable, onDriverAnswered) {
|
|
1378
|
+
async *streamDecodedRows(run, exec, createDecodeContext, driverCall, codecCtx, queryable, onDriverAnswered) {
|
|
1390
1379
|
const rowDecodeContext = createDecodeContext();
|
|
1391
1380
|
await this.setupDriverExecution(exec, queryable);
|
|
1392
1381
|
const startedAt = Date.now();
|
|
1393
1382
|
let telemetryOutcome = null;
|
|
1394
1383
|
try {
|
|
1395
|
-
const iterator =
|
|
1384
|
+
const iterator = run.runQuery(exec, driverCall)[Symbol.asyncIterator]();
|
|
1396
1385
|
let answered = false;
|
|
1397
1386
|
try {
|
|
1398
1387
|
while (true) {
|
|
@@ -1418,25 +1407,18 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1418
1407
|
const scope = options?.scope ?? "runtime";
|
|
1419
1408
|
return {
|
|
1420
1409
|
codecCtx: signal === void 0 ? {} : { signal },
|
|
1421
|
-
|
|
1410
|
+
contextFields: {
|
|
1422
1411
|
...this.sqlCtx,
|
|
1423
1412
|
...ifDefined("signal", signal),
|
|
1424
|
-
...scope !== "runtime" ? { scope } : {}
|
|
1425
|
-
planExecutionId: crypto.randomUUID()
|
|
1413
|
+
...scope !== "runtime" ? { scope } : {}
|
|
1426
1414
|
}
|
|
1427
1415
|
};
|
|
1428
1416
|
}
|
|
1429
|
-
|
|
1430
|
-
return this.prepareOperation(plan, codecCtx, middlewareCtx, runBeforeQueryChain);
|
|
1431
|
-
}
|
|
1432
|
-
prepareExecuteExecution(plan, codecCtx, middlewareCtx) {
|
|
1433
|
-
return this.prepareOperation(plan, codecCtx, middlewareCtx, runBeforeExecuteChain);
|
|
1434
|
-
}
|
|
1435
|
-
async prepareOperation(plan, codecCtx, middlewareCtx, runBefore) {
|
|
1417
|
+
async prepareOperation(plan, codecCtx, run) {
|
|
1436
1418
|
checkAborted(codecCtx, "stream");
|
|
1437
1419
|
if (isExecutionPlan(plan)) {
|
|
1438
1420
|
const mutator = createSqlParamRefMutator(plan);
|
|
1439
|
-
await
|
|
1421
|
+
await run.beforeEncode(plan, mutator);
|
|
1440
1422
|
return Object.freeze({
|
|
1441
1423
|
...plan,
|
|
1442
1424
|
params: await encodeParams({
|
|
@@ -1445,10 +1427,10 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1445
1427
|
}, codecCtx, this.contractCodecs)
|
|
1446
1428
|
});
|
|
1447
1429
|
}
|
|
1448
|
-
const compiled = await this.compilePlan(plan,
|
|
1430
|
+
const compiled = await this.compilePlan(plan, run.ctx);
|
|
1449
1431
|
const draft = this.lowerToDraft(compiled);
|
|
1450
1432
|
const mutator = createSqlParamRefMutator(draft);
|
|
1451
|
-
await
|
|
1433
|
+
await run.beforeEncode(draft, mutator);
|
|
1452
1434
|
const draftWithMutations = Object.freeze({
|
|
1453
1435
|
...draft,
|
|
1454
1436
|
params: mutator.currentParams()
|
|
@@ -1459,15 +1441,22 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1459
1441
|
queryAgainstQueryable(plan, queryable, options) {
|
|
1460
1442
|
this.ensureCodecRegistryValidated();
|
|
1461
1443
|
const self = this;
|
|
1462
|
-
const { codecCtx,
|
|
1444
|
+
const { codecCtx, contextFields } = this.createQueryContexts(options);
|
|
1463
1445
|
const generator = async function* () {
|
|
1464
1446
|
const endOperation = self.beginOperation(queryable);
|
|
1465
1447
|
try {
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1448
|
+
yield* streamStatement({
|
|
1449
|
+
middleware: self.middleware,
|
|
1450
|
+
plan,
|
|
1451
|
+
context: contextFields,
|
|
1452
|
+
parent: self.parentOf(queryable)
|
|
1453
|
+
}, async function* (run) {
|
|
1454
|
+
const exec = await self.prepareOperation(plan, codecCtx, run);
|
|
1455
|
+
yield* self.streamDecodedRows(run, exec, () => buildDecodeContext(exec.ast, self.contractCodecs), () => queryable.query({
|
|
1456
|
+
sql: exec.sql,
|
|
1457
|
+
params: exec.params
|
|
1458
|
+
}), codecCtx, queryable, endOperation);
|
|
1459
|
+
});
|
|
1471
1460
|
} finally {
|
|
1472
1461
|
endOperation();
|
|
1473
1462
|
}
|
|
@@ -1485,33 +1474,41 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1485
1474
|
}
|
|
1486
1475
|
async executeStatisticsInFlight(plan, queryable, options) {
|
|
1487
1476
|
this.ensureCodecRegistryValidated();
|
|
1488
|
-
const { codecCtx,
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
executeEncodedPlan(exec, queryable, codecCtx, middlewareCtx, driverCall) {
|
|
1496
|
-
return reportExecuteEnding(this.scheduleAfterTransaction(queryable, exec, middlewareCtx), async () => {
|
|
1497
|
-
await this.setupDriverExecution(exec, queryable);
|
|
1498
|
-
checkAborted(codecCtx, "stream");
|
|
1499
|
-
const startedAt = Date.now();
|
|
1500
|
-
let telemetryOutcome = "success";
|
|
1501
|
-
try {
|
|
1502
|
-
return await runExecuteWithMiddleware(exec, this.middleware, middlewareCtx, driverCall);
|
|
1503
|
-
} catch (error) {
|
|
1504
|
-
telemetryOutcome = "runtime-error";
|
|
1505
|
-
throw error;
|
|
1506
|
-
} finally {
|
|
1507
|
-
this.recordTelemetry(exec, telemetryOutcome, Date.now() - startedAt);
|
|
1508
|
-
}
|
|
1477
|
+
const { codecCtx, contextFields } = this.createQueryContexts(options);
|
|
1478
|
+
return this.executeOn(queryable, plan, contextFields, async (run) => {
|
|
1479
|
+
const exec = await this.prepareOperation(plan, codecCtx, run);
|
|
1480
|
+
return this.executeEncodedPlan(run, exec, queryable, codecCtx, () => queryable.execute({
|
|
1481
|
+
sql: exec.sql,
|
|
1482
|
+
params: exec.params
|
|
1483
|
+
}));
|
|
1509
1484
|
});
|
|
1510
1485
|
}
|
|
1486
|
+
executeOn(queryable, plan, context, body) {
|
|
1487
|
+
return executeStatement({
|
|
1488
|
+
middleware: this.middleware,
|
|
1489
|
+
plan,
|
|
1490
|
+
context,
|
|
1491
|
+
parent: this.parentOf(queryable)
|
|
1492
|
+
}, body);
|
|
1493
|
+
}
|
|
1494
|
+
async executeEncodedPlan(run, exec, queryable, codecCtx, driverCall) {
|
|
1495
|
+
await this.setupDriverExecution(exec, queryable);
|
|
1496
|
+
checkAborted(codecCtx, "stream");
|
|
1497
|
+
const startedAt = Date.now();
|
|
1498
|
+
let telemetryOutcome = "success";
|
|
1499
|
+
try {
|
|
1500
|
+
return await run.runExecute(exec, driverCall);
|
|
1501
|
+
} catch (error) {
|
|
1502
|
+
telemetryOutcome = "runtime-error";
|
|
1503
|
+
throw error;
|
|
1504
|
+
} finally {
|
|
1505
|
+
this.recordTelemetry(exec, telemetryOutcome, Date.now() - startedAt);
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1511
1508
|
async prepare(declaration, callback) {
|
|
1512
1509
|
this.ensureCodecRegistryValidated();
|
|
1513
1510
|
const userPlan = callback(buildBindSiteParams(declaration));
|
|
1514
|
-
const finalPlan = await this.
|
|
1511
|
+
const finalPlan = await this.compilePlan(userPlan, standaloneContext(this.sqlCtx));
|
|
1515
1512
|
const orderedRefs = collectOrderedParamRefs(finalPlan.ast);
|
|
1516
1513
|
const referencedNames = /* @__PURE__ */ new Set();
|
|
1517
1514
|
for (const ref of orderedRefs) if (ref.kind === "prepared-param-ref") referencedNames.add(ref.name);
|
|
@@ -1537,18 +1534,23 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1537
1534
|
runPreparedQueryAgainstQueryable(ps, userParams, queryable, options) {
|
|
1538
1535
|
this.ensureCodecRegistryValidated();
|
|
1539
1536
|
const self = this;
|
|
1540
|
-
const { codecCtx,
|
|
1537
|
+
const { codecCtx, contextFields } = this.createQueryContexts(options);
|
|
1541
1538
|
const generator = async function* () {
|
|
1542
1539
|
const endOperation = self.beginOperation(queryable);
|
|
1543
1540
|
try {
|
|
1544
|
-
yield*
|
|
1541
|
+
yield* streamStatement({
|
|
1542
|
+
middleware: self.middleware,
|
|
1543
|
+
plan: ps,
|
|
1544
|
+
context: contextFields,
|
|
1545
|
+
parent: self.parentOf(queryable)
|
|
1546
|
+
}, (run) => self.streamPreparedRows(run, ps, userParams, queryable, codecCtx, endOperation));
|
|
1545
1547
|
} finally {
|
|
1546
1548
|
endOperation();
|
|
1547
1549
|
}
|
|
1548
1550
|
};
|
|
1549
1551
|
return new AsyncIterableResult(generator());
|
|
1550
1552
|
}
|
|
1551
|
-
async *streamPreparedRows(ps, userParams, queryable, codecCtx,
|
|
1553
|
+
async *streamPreparedRows(run, ps, userParams, queryable, codecCtx, onDriverAnswered) {
|
|
1552
1554
|
checkAborted(codecCtx, "stream");
|
|
1553
1555
|
const preEncodeValues = resolvePreparedSlotValues(ps, userParams);
|
|
1554
1556
|
const preEncodeExec = {
|
|
@@ -1558,7 +1560,7 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1558
1560
|
meta: ps.meta
|
|
1559
1561
|
};
|
|
1560
1562
|
const mutator = createSqlParamRefMutator(preEncodeExec);
|
|
1561
|
-
await
|
|
1563
|
+
await run.beforeEncode(preEncodeExec, mutator);
|
|
1562
1564
|
const encodedParams = await encodeParamsWithMetadata(mutator.currentParams(), ps.paramMetadata, codecCtx, this.contractCodecs);
|
|
1563
1565
|
const exec = {
|
|
1564
1566
|
sql: ps.sql,
|
|
@@ -1577,7 +1579,7 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1577
1579
|
}
|
|
1578
1580
|
}
|
|
1579
1581
|
};
|
|
1580
|
-
yield* this.
|
|
1582
|
+
yield* this.streamDecodedRows(run, exec, () => ps.decodeContext, () => queryable.query(request), codecCtx, queryable, onDriverAnswered);
|
|
1581
1583
|
}
|
|
1582
1584
|
/** Execute a prepared statement's statistics against a caller-supplied queryable through the full pipeline. */
|
|
1583
1585
|
async runPreparedExecuteAgainstQueryable(ps, userParams, queryable, options) {
|
|
@@ -1590,7 +1592,10 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1590
1592
|
}
|
|
1591
1593
|
async runPreparedExecuteInFlight(ps, userParams, queryable, options) {
|
|
1592
1594
|
this.ensureCodecRegistryValidated();
|
|
1593
|
-
const { codecCtx,
|
|
1595
|
+
const { codecCtx, contextFields } = this.createQueryContexts(options);
|
|
1596
|
+
return this.executeOn(queryable, ps, contextFields, (run) => this.executePrepared(run, ps, userParams, queryable, codecCtx));
|
|
1597
|
+
}
|
|
1598
|
+
async executePrepared(run, ps, userParams, queryable, codecCtx) {
|
|
1594
1599
|
checkAborted(codecCtx, "stream");
|
|
1595
1600
|
const preEncodeValues = resolvePreparedSlotValues(ps, userParams);
|
|
1596
1601
|
const preEncodeExec = {
|
|
@@ -1600,7 +1605,7 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1600
1605
|
meta: ps.meta
|
|
1601
1606
|
};
|
|
1602
1607
|
const mutator = createSqlParamRefMutator(preEncodeExec);
|
|
1603
|
-
await
|
|
1608
|
+
await run.beforeEncode(preEncodeExec, mutator);
|
|
1604
1609
|
const exec = {
|
|
1605
1610
|
sql: ps.sql,
|
|
1606
1611
|
params: await encodeParamsWithMetadata(mutator.currentParams(), ps.paramMetadata, codecCtx, this.contractCodecs),
|
|
@@ -1618,7 +1623,7 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1618
1623
|
}
|
|
1619
1624
|
}
|
|
1620
1625
|
};
|
|
1621
|
-
return this.executeEncodedPlan(exec, queryable, codecCtx,
|
|
1626
|
+
return this.executeEncodedPlan(run, exec, queryable, codecCtx, () => queryable.execute(request));
|
|
1622
1627
|
}
|
|
1623
1628
|
async connection() {
|
|
1624
1629
|
const endOperation = this.beginOperation(this.driver);
|
|
@@ -1630,11 +1635,10 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1630
1635
|
}
|
|
1631
1636
|
this.#heldQueryables.add(driverConn);
|
|
1632
1637
|
const self = this;
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
self
|
|
1637
|
-
return self.wrapTransaction(driverTx, driverConn);
|
|
1638
|
+
const wrappedConnection = {
|
|
1639
|
+
[transactionStart]: createTransactionStart(),
|
|
1640
|
+
transaction() {
|
|
1641
|
+
return self.beginTransactionOn(driverConn, wrappedConnection);
|
|
1638
1642
|
},
|
|
1639
1643
|
async release() {
|
|
1640
1644
|
await self.#inFlight.track(() => driverConn.release());
|
|
@@ -1667,33 +1671,106 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1667
1671
|
});
|
|
1668
1672
|
}
|
|
1669
1673
|
};
|
|
1674
|
+
return wrappedConnection;
|
|
1670
1675
|
}
|
|
1671
1676
|
/**
|
|
1672
|
-
*
|
|
1677
|
+
* Begins a transaction on `connection`, which `owner` wraps, as a transaction activity. When the transaction's `activityStarted` hooks refuse the start, no `BEGIN` is sent, `owner` is recorded as clean, and `withTransaction` releases it; after any other start failure it destroys it. The transaction's `activityStarted` hooks run before `BEGIN`. Every statement sent on the transaction, or on `connection`, from the end of `BEGIN` until `commit()` or `rollback()` is called is the transaction's child, and is finalized when the transaction ends, with its outcome. `commit()` and `rollback()` resolve after every finalization hook has run. A subclass that holds its own connection begins its transactions here.
|
|
1673
1678
|
*/
|
|
1674
|
-
|
|
1675
|
-
|
|
1679
|
+
async beginTransactionOn(connection, owner) {
|
|
1680
|
+
owner[transactionStart].refusedBeforeBegin = false;
|
|
1681
|
+
let activity;
|
|
1682
|
+
try {
|
|
1683
|
+
activity = await startTransactionActivity({
|
|
1684
|
+
middleware: this.middleware,
|
|
1685
|
+
context: {
|
|
1686
|
+
...this.sqlCtx,
|
|
1687
|
+
scope: "transaction"
|
|
1688
|
+
},
|
|
1689
|
+
holdFinishedChildren: this.#holdFinishedChildren
|
|
1690
|
+
});
|
|
1691
|
+
} catch (error) {
|
|
1692
|
+
owner[transactionStart].refusedBeforeBegin = true;
|
|
1693
|
+
throw error;
|
|
1694
|
+
}
|
|
1695
|
+
let driverTx;
|
|
1696
|
+
try {
|
|
1697
|
+
driverTx = await this.#inFlight.track(() => connection.beginTransaction());
|
|
1698
|
+
} catch (error) {
|
|
1699
|
+
await activity.end({
|
|
1700
|
+
by: "rollback",
|
|
1701
|
+
outcome: "failed",
|
|
1702
|
+
commitAttempted: false
|
|
1703
|
+
});
|
|
1704
|
+
throw error;
|
|
1705
|
+
}
|
|
1706
|
+
if (this.#heldQueryables.has(connection)) this.#heldQueryables.add(driverTx);
|
|
1707
|
+
return this.wrapTransaction(driverTx, connection, activity);
|
|
1708
|
+
}
|
|
1709
|
+
wrapTransaction(driverTx, connection, activity) {
|
|
1710
|
+
this.#openTransactions.set(driverTx, activity);
|
|
1711
|
+
this.#openTransactions.set(connection, activity);
|
|
1712
|
+
const stopAdopting = () => {
|
|
1713
|
+
for (const queryable of [driverTx, connection]) if (this.#openTransactions.get(queryable) === activity) this.#openTransactions.delete(queryable);
|
|
1714
|
+
};
|
|
1676
1715
|
let commitAttempted = false;
|
|
1716
|
+
const settlement = {
|
|
1717
|
+
committed: false,
|
|
1718
|
+
rolledBack: false,
|
|
1719
|
+
logDroppedError(error) {
|
|
1720
|
+
try {
|
|
1721
|
+
activity.ctx.log.error({
|
|
1722
|
+
event: "middleware.activityEnded.error",
|
|
1723
|
+
error
|
|
1724
|
+
});
|
|
1725
|
+
} catch {}
|
|
1726
|
+
}
|
|
1727
|
+
};
|
|
1728
|
+
let commitEnding;
|
|
1677
1729
|
const self = this;
|
|
1678
1730
|
return {
|
|
1731
|
+
[transactionSettlement]: settlement,
|
|
1679
1732
|
async commit() {
|
|
1680
1733
|
commitAttempted = true;
|
|
1681
|
-
|
|
1734
|
+
stopAdopting();
|
|
1682
1735
|
try {
|
|
1683
1736
|
await self.#inFlight.track(() => driverTx.commit());
|
|
1684
1737
|
} catch (error) {
|
|
1685
|
-
await
|
|
1738
|
+
await activity.end({
|
|
1739
|
+
by: "commit",
|
|
1740
|
+
outcome: "failed"
|
|
1741
|
+
});
|
|
1686
1742
|
throw error;
|
|
1687
1743
|
}
|
|
1688
|
-
|
|
1744
|
+
settlement.committed = true;
|
|
1745
|
+
commitEnding = activity.end({
|
|
1746
|
+
by: "commit",
|
|
1747
|
+
outcome: "succeeded"
|
|
1748
|
+
});
|
|
1749
|
+
await commitEnding;
|
|
1689
1750
|
},
|
|
1690
1751
|
async rollback() {
|
|
1691
|
-
|
|
1752
|
+
stopAdopting();
|
|
1753
|
+
if (settlement.committed) {
|
|
1754
|
+
await commitEnding?.catch(() => void 0);
|
|
1755
|
+
return;
|
|
1756
|
+
}
|
|
1757
|
+
if (settlement.rolledBack) return;
|
|
1692
1758
|
try {
|
|
1693
1759
|
await self.#inFlight.track(() => driverTx.rollback());
|
|
1694
|
-
}
|
|
1695
|
-
await
|
|
1760
|
+
} catch (error) {
|
|
1761
|
+
await activity.end({
|
|
1762
|
+
by: "rollback",
|
|
1763
|
+
outcome: "failed",
|
|
1764
|
+
commitAttempted
|
|
1765
|
+
});
|
|
1766
|
+
throw error;
|
|
1696
1767
|
}
|
|
1768
|
+
settlement.rolledBack = true;
|
|
1769
|
+
await activity.end({
|
|
1770
|
+
by: "rollback",
|
|
1771
|
+
outcome: "succeeded",
|
|
1772
|
+
commitAttempted
|
|
1773
|
+
});
|
|
1697
1774
|
},
|
|
1698
1775
|
query(plan, options) {
|
|
1699
1776
|
return self.queryAgainstQueryable(plan, driverTx, {
|
|
@@ -1721,26 +1798,6 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1721
1798
|
}
|
|
1722
1799
|
};
|
|
1723
1800
|
}
|
|
1724
|
-
rememberQueriesUntilEnd(queryables) {
|
|
1725
|
-
const awaitingTransactionEnd = [];
|
|
1726
|
-
let aQueryFailed = false;
|
|
1727
|
-
const remember = (runStage) => {
|
|
1728
|
-
awaitingTransactionEnd.push(runStage);
|
|
1729
|
-
return async (ending) => {
|
|
1730
|
-
if (ending === "failed") aQueryFailed = true;
|
|
1731
|
-
};
|
|
1732
|
-
};
|
|
1733
|
-
for (const queryable of queryables) this.#openTransactions.set(queryable, remember);
|
|
1734
|
-
return {
|
|
1735
|
-
stopRemembering: () => {
|
|
1736
|
-
for (const queryable of queryables) if (this.#openTransactions.get(queryable) === remember) this.#openTransactions.delete(queryable);
|
|
1737
|
-
},
|
|
1738
|
-
end: async (outcome) => {
|
|
1739
|
-
const reported = outcome === "committed" && aQueryFailed ? "unknown" : outcome;
|
|
1740
|
-
for (const runStage of awaitingTransactionEnd.splice(0)) await runStage({ outcome: reported });
|
|
1741
|
-
}
|
|
1742
|
-
};
|
|
1743
|
-
}
|
|
1744
1801
|
telemetry() {
|
|
1745
1802
|
return this._telemetry;
|
|
1746
1803
|
}
|
|
@@ -1811,12 +1868,27 @@ var SqlRuntimeBase = class extends RuntimeCore {
|
|
|
1811
1868
|
});
|
|
1812
1869
|
}
|
|
1813
1870
|
};
|
|
1871
|
+
function standaloneContext(fields) {
|
|
1872
|
+
return {
|
|
1873
|
+
...fields,
|
|
1874
|
+
parent: void 0,
|
|
1875
|
+
state: createStateStore().state,
|
|
1876
|
+
inTransaction: () => false
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1814
1879
|
function transactionClosedError() {
|
|
1815
1880
|
return runtimeError$1("RUNTIME.TRANSACTION_CLOSED", "Cannot use a transaction operation after the transaction has ended. Consume query results and await execute calls inside the transaction callback.", {});
|
|
1816
1881
|
}
|
|
1817
1882
|
async function withTransaction(runtime, fn) {
|
|
1818
1883
|
const connection = await runtime.connection();
|
|
1819
|
-
|
|
1884
|
+
let transaction;
|
|
1885
|
+
try {
|
|
1886
|
+
transaction = await connection.transaction();
|
|
1887
|
+
} catch (error) {
|
|
1888
|
+
if (wasRefusedBeforeBegin(connection)) await connection.release().catch(() => void 0);
|
|
1889
|
+
else await connection.destroy(error).catch(() => void 0);
|
|
1890
|
+
throw error;
|
|
1891
|
+
}
|
|
1820
1892
|
let invalidated = false;
|
|
1821
1893
|
async function* guardedStream(inner) {
|
|
1822
1894
|
if (invalidated) throw transactionClosedError();
|
|
@@ -1860,6 +1932,11 @@ async function withTransaction(runtime, fn) {
|
|
|
1860
1932
|
try {
|
|
1861
1933
|
await transaction.rollback();
|
|
1862
1934
|
} catch (rollbackError) {
|
|
1935
|
+
const settlement = settlementOf(transaction);
|
|
1936
|
+
if (settlement?.rolledBack === true) {
|
|
1937
|
+
settlement.logDroppedError(rollbackError);
|
|
1938
|
+
throw error;
|
|
1939
|
+
}
|
|
1863
1940
|
await destroyConnection(rollbackError);
|
|
1864
1941
|
const wrapped = runtimeError$1("RUNTIME.TRANSACTION_ROLLBACK_FAILED", "Transaction rollback failed after callback error", { rollbackError });
|
|
1865
1942
|
wrapped.cause = error;
|
|
@@ -1872,10 +1949,13 @@ async function withTransaction(runtime, fn) {
|
|
|
1872
1949
|
try {
|
|
1873
1950
|
await transaction.commit();
|
|
1874
1951
|
} catch (commitError) {
|
|
1952
|
+
if (settlementOf(transaction)?.committed === true) throw commitError;
|
|
1875
1953
|
try {
|
|
1876
1954
|
await transaction.rollback();
|
|
1877
|
-
} catch {
|
|
1878
|
-
|
|
1955
|
+
} catch (rollbackError) {
|
|
1956
|
+
const settlement = settlementOf(transaction);
|
|
1957
|
+
if (settlement?.rolledBack === true) settlement.logDroppedError(rollbackError);
|
|
1958
|
+
else await destroyConnection(commitError);
|
|
1879
1959
|
}
|
|
1880
1960
|
const wrapped = runtimeError$1("RUNTIME.TRANSACTION_COMMIT_FAILED", "Transaction commit failed", { commitError });
|
|
1881
1961
|
wrapped.cause = commitError;
|