@dbsp/core 1.2.0 → 1.4.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/index.d.ts +4 -2
- package/dist/index.js +622 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -5524,7 +5524,7 @@ async function runMutationWithHooksInner(opts, store) {
|
|
|
5524
5524
|
opts.onHookError
|
|
5525
5525
|
);
|
|
5526
5526
|
if (prepared.returnAfterMutationResult) {
|
|
5527
|
-
return transformed;
|
|
5527
|
+
return prepared.mapAfterMutationResult?.(result, transformed) ?? transformed;
|
|
5528
5528
|
}
|
|
5529
5529
|
}
|
|
5530
5530
|
return result;
|
|
@@ -6163,20 +6163,77 @@ import {
|
|
|
6163
6163
|
NqlLexer,
|
|
6164
6164
|
compile as nqlCompile
|
|
6165
6165
|
} from "@dbsp/nql";
|
|
6166
|
-
import {
|
|
6166
|
+
import {
|
|
6167
|
+
getTrustedNqlRelationFilterFields,
|
|
6168
|
+
NQL_INTERNAL_COMPILER_OPTIONS
|
|
6169
|
+
} from "@dbsp/types/internal";
|
|
6167
6170
|
var NQL_RAW_FRAGMENT = /* @__PURE__ */ Symbol("NqlRawFragment");
|
|
6168
6171
|
function hasNqlBindings(bundle) {
|
|
6169
6172
|
return (bundle.bindings?.size ?? 0) > 0;
|
|
6170
6173
|
}
|
|
6171
|
-
function
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6174
|
+
function isBindingFinalQuery(bundle) {
|
|
6175
|
+
return bundle.query !== void 0 && (bundle.bindings?.has(bundle.query.from) ?? false);
|
|
6176
|
+
}
|
|
6177
|
+
function formatBindingRelationPath(path) {
|
|
6178
|
+
return typeof path === "string" ? path : path.join(".");
|
|
6179
|
+
}
|
|
6180
|
+
function findBindingFinalRelationFilter(where) {
|
|
6181
|
+
switch (where.kind) {
|
|
6182
|
+
case "and":
|
|
6183
|
+
case "or":
|
|
6184
|
+
for (const condition of where.conditions) {
|
|
6185
|
+
const found = findBindingFinalRelationFilter(condition);
|
|
6186
|
+
if (found !== void 0) return found;
|
|
6187
|
+
}
|
|
6188
|
+
return void 0;
|
|
6189
|
+
case "not":
|
|
6190
|
+
return findBindingFinalRelationFilter(where.condition);
|
|
6191
|
+
case "relationFilter":
|
|
6192
|
+
if (getTrustedNqlRelationFilterFields(where) !== void 0) {
|
|
6193
|
+
return void 0;
|
|
6194
|
+
}
|
|
6195
|
+
return formatBindingRelationPath(where.relation);
|
|
6196
|
+
case "exists":
|
|
6197
|
+
case "notExists":
|
|
6198
|
+
return where.relation;
|
|
6199
|
+
case "rawExists":
|
|
6200
|
+
case "rawNotExists":
|
|
6201
|
+
return "raw EXISTS";
|
|
6202
|
+
default:
|
|
6203
|
+
return void 0;
|
|
6175
6204
|
}
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6205
|
+
}
|
|
6206
|
+
function assertBindingFinalQueryCanUseSyntheticPlan(intent) {
|
|
6207
|
+
const relationColumns = intent.select?.type === "expressions" ? intent.select.columns.flatMap((column) => {
|
|
6208
|
+
if (column.kind !== "relationColumn") return [];
|
|
6209
|
+
const trusted = getTrustedNqlRelationFilterFields(column);
|
|
6210
|
+
if (trusted?.selectedColumn !== void 0 && trusted.cardinality === "one") {
|
|
6211
|
+
return [];
|
|
6212
|
+
}
|
|
6213
|
+
return [column.relation];
|
|
6214
|
+
}) : [];
|
|
6215
|
+
const relationFilter = intent.where ? findBindingFinalRelationFilter(intent.where) : void 0;
|
|
6216
|
+
const havingRelationFilter = intent.having ? findBindingFinalRelationFilter(intent.having) : void 0;
|
|
6217
|
+
if ((intent.include?.length ?? 0) > 0 || relationColumns.length > 0 || (intent.joins?.length ?? 0) > 0 || relationFilter !== void 0 || havingRelationFilter !== void 0) {
|
|
6218
|
+
throw new Error(
|
|
6219
|
+
`NQL binding-final query '${intent.from}' cannot select relation columns, use includes, joins, or relation filters. Relation planning requires a physical model table, not a CTE binding.`
|
|
6220
|
+
);
|
|
6221
|
+
}
|
|
6222
|
+
}
|
|
6223
|
+
function createBindingFinalPlan(intent) {
|
|
6224
|
+
assertBindingFinalQueryCanUseSyntheticPlan(intent);
|
|
6225
|
+
return {
|
|
6226
|
+
rootTable: intent.from,
|
|
6227
|
+
decisions: [],
|
|
6228
|
+
warnings: [],
|
|
6229
|
+
ctes: [],
|
|
6230
|
+
intent,
|
|
6231
|
+
metadata: {
|
|
6232
|
+
planningTimeMs: 0,
|
|
6233
|
+
relationsAnalyzed: 0,
|
|
6234
|
+
isAmbiguous: false
|
|
6235
|
+
}
|
|
6236
|
+
};
|
|
6180
6237
|
}
|
|
6181
6238
|
function nqlRaw(fragment) {
|
|
6182
6239
|
if (typeof fragment !== "string") {
|
|
@@ -6289,7 +6346,250 @@ function assembleNqlTemplate(strings, values) {
|
|
|
6289
6346
|
sourceError: findInternalParamSourceError(query, generatedRanges)
|
|
6290
6347
|
};
|
|
6291
6348
|
}
|
|
6292
|
-
function
|
|
6349
|
+
function hasMutationBindingBodies(bundle) {
|
|
6350
|
+
return (bundle.mutationBindings?.size ?? 0) > 0;
|
|
6351
|
+
}
|
|
6352
|
+
function requireMutationBindingColumns(bundle, bindName) {
|
|
6353
|
+
const columns = bundle.bindingOutputSchemas?.get(bindName)?.columns;
|
|
6354
|
+
if (columns === void 0 || columns.length === 0) {
|
|
6355
|
+
throw new Error(
|
|
6356
|
+
`NQL mutation binding '${bindName}' cannot be materialized because its projected column schema is unavailable.`
|
|
6357
|
+
);
|
|
6358
|
+
}
|
|
6359
|
+
return columns;
|
|
6360
|
+
}
|
|
6361
|
+
function toSnakeCaseIdentifier(identifier) {
|
|
6362
|
+
if (!identifier) return identifier;
|
|
6363
|
+
const leadingUnderscores = identifier.match(/^_+/)?.[0] ?? "";
|
|
6364
|
+
const rest = identifier.slice(leadingUnderscores.length);
|
|
6365
|
+
if (!rest) return identifier;
|
|
6366
|
+
const snakeCase = rest.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
6367
|
+
return leadingUnderscores + snakeCase;
|
|
6368
|
+
}
|
|
6369
|
+
function toDatabaseColumnName(column, dbCasing) {
|
|
6370
|
+
return dbCasing === "snake_case" ? toSnakeCaseIdentifier(column) : column;
|
|
6371
|
+
}
|
|
6372
|
+
function toRuntimeBindingRow(bindName, row, columns, dbCasing) {
|
|
6373
|
+
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
6374
|
+
throw new Error(
|
|
6375
|
+
`NQL mutation binding '${bindName}' returned a non-object row; runtime VALUES materialization requires object rows keyed by projected column name.`
|
|
6376
|
+
);
|
|
6377
|
+
}
|
|
6378
|
+
const source = row;
|
|
6379
|
+
const materialized = {};
|
|
6380
|
+
for (const column of columns) {
|
|
6381
|
+
const dbColumn = toDatabaseColumnName(column, dbCasing);
|
|
6382
|
+
const sourceColumn = Object.hasOwn(source, column) ? column : dbColumn !== column && Object.hasOwn(source, dbColumn) ? dbColumn : void 0;
|
|
6383
|
+
if (sourceColumn === void 0) {
|
|
6384
|
+
throw new Error(
|
|
6385
|
+
`NQL mutation binding '${bindName}' returned a row without projected column '${column}'.`
|
|
6386
|
+
);
|
|
6387
|
+
}
|
|
6388
|
+
materialized[column] = source[sourceColumn];
|
|
6389
|
+
}
|
|
6390
|
+
return materialized;
|
|
6391
|
+
}
|
|
6392
|
+
function createRuntimeBinding(bundle, bindName, rows, dbCasing) {
|
|
6393
|
+
const columns = requireMutationBindingColumns(bundle, bindName);
|
|
6394
|
+
return {
|
|
6395
|
+
columns,
|
|
6396
|
+
rows: rows.map(
|
|
6397
|
+
(row) => toRuntimeBindingRow(bindName, row, columns, dbCasing)
|
|
6398
|
+
)
|
|
6399
|
+
};
|
|
6400
|
+
}
|
|
6401
|
+
function bindingEntryIsFinal(compiledIntent, bindName, boundQuery, sourceBundle) {
|
|
6402
|
+
if (compiledIntent.kind === "query") {
|
|
6403
|
+
return boundQuery === compiledIntent.intent;
|
|
6404
|
+
}
|
|
6405
|
+
return sourceBundle.mutationBindings?.get(bindName) === compiledIntent.intent;
|
|
6406
|
+
}
|
|
6407
|
+
function orderedSequenceStepToProgramStep(step) {
|
|
6408
|
+
const dependencyStep = step;
|
|
6409
|
+
if (step.kind === "query") {
|
|
6410
|
+
return {
|
|
6411
|
+
kind: "query",
|
|
6412
|
+
intent: step.query,
|
|
6413
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6414
|
+
final: step.final,
|
|
6415
|
+
...dependencyStep.bindingDependencies !== void 0 && {
|
|
6416
|
+
bindingDependencies: dependencyStep.bindingDependencies
|
|
6417
|
+
}
|
|
6418
|
+
};
|
|
6419
|
+
}
|
|
6420
|
+
return {
|
|
6421
|
+
kind: "mutation",
|
|
6422
|
+
intent: step.mutation,
|
|
6423
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6424
|
+
final: step.final,
|
|
6425
|
+
...dependencyStep.bindingDependencies !== void 0 && {
|
|
6426
|
+
bindingDependencies: dependencyStep.bindingDependencies
|
|
6427
|
+
}
|
|
6428
|
+
};
|
|
6429
|
+
}
|
|
6430
|
+
function snapshotMutationRows(rows) {
|
|
6431
|
+
return rows.map((row) => {
|
|
6432
|
+
if (Array.isArray(row)) {
|
|
6433
|
+
return [...row];
|
|
6434
|
+
}
|
|
6435
|
+
if (row !== null && typeof row === "object") {
|
|
6436
|
+
return { ...row };
|
|
6437
|
+
}
|
|
6438
|
+
return row;
|
|
6439
|
+
});
|
|
6440
|
+
}
|
|
6441
|
+
function assertNqlProgramSteps(compiledIntent, steps) {
|
|
6442
|
+
if (steps.length === 0) {
|
|
6443
|
+
throw new Error("NQL program sequence did not contain any statements.");
|
|
6444
|
+
}
|
|
6445
|
+
const finalIndexes = steps.map((step, index) => step.final ? index : -1).filter((index) => index !== -1);
|
|
6446
|
+
if (finalIndexes.length !== 1 || finalIndexes[0] !== steps.length - 1) {
|
|
6447
|
+
throw new Error(
|
|
6448
|
+
"NQL program sequence must contain exactly one final statement at the end."
|
|
6449
|
+
);
|
|
6450
|
+
}
|
|
6451
|
+
const finalStep = steps.at(-1);
|
|
6452
|
+
if (finalStep === void 0) {
|
|
6453
|
+
throw new Error("NQL program sequence did not contain a final statement.");
|
|
6454
|
+
}
|
|
6455
|
+
if (finalStep.kind !== compiledIntent.kind || finalStep.intent !== compiledIntent.intent) {
|
|
6456
|
+
throw new Error(
|
|
6457
|
+
"NQL program sequence final statement does not match the compiled NQL result."
|
|
6458
|
+
);
|
|
6459
|
+
}
|
|
6460
|
+
const seenBindNames = /* @__PURE__ */ new Set();
|
|
6461
|
+
for (const step of steps) {
|
|
6462
|
+
if (step.bindName === void 0) continue;
|
|
6463
|
+
if (seenBindNames.has(step.bindName)) {
|
|
6464
|
+
throw new Error(
|
|
6465
|
+
`NQL program sequence contains duplicate binding '${step.bindName}'.`
|
|
6466
|
+
);
|
|
6467
|
+
}
|
|
6468
|
+
seenBindNames.add(step.bindName);
|
|
6469
|
+
if (!(compiledIntent.bundle.bindings?.has(step.bindName) ?? false)) {
|
|
6470
|
+
throw new Error(
|
|
6471
|
+
`NQL program sequence references unknown binding '${step.bindName}'.`
|
|
6472
|
+
);
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
}
|
|
6476
|
+
function createNqlProgramSteps(compiledIntent) {
|
|
6477
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6478
|
+
if (sourceBundle.nqlProgramSequence !== void 0) {
|
|
6479
|
+
const steps2 = sourceBundle.nqlProgramSequence.map(
|
|
6480
|
+
orderedSequenceStepToProgramStep
|
|
6481
|
+
);
|
|
6482
|
+
assertNqlProgramSteps(compiledIntent, steps2);
|
|
6483
|
+
return steps2;
|
|
6484
|
+
}
|
|
6485
|
+
const bindingEntries = [...sourceBundle.bindings ?? /* @__PURE__ */ new Map()];
|
|
6486
|
+
const steps = bindingEntries.map(
|
|
6487
|
+
([bindName, boundQuery]) => {
|
|
6488
|
+
const boundMutation = sourceBundle.mutationBindings?.get(bindName);
|
|
6489
|
+
if (boundMutation !== void 0) {
|
|
6490
|
+
return {
|
|
6491
|
+
kind: "mutation",
|
|
6492
|
+
intent: boundMutation,
|
|
6493
|
+
bindName,
|
|
6494
|
+
final: false
|
|
6495
|
+
};
|
|
6496
|
+
}
|
|
6497
|
+
return {
|
|
6498
|
+
kind: "query",
|
|
6499
|
+
intent: boundQuery,
|
|
6500
|
+
bindName,
|
|
6501
|
+
final: false
|
|
6502
|
+
};
|
|
6503
|
+
}
|
|
6504
|
+
);
|
|
6505
|
+
const lastBindingEntry = bindingEntries.at(-1);
|
|
6506
|
+
const finalIsBound = lastBindingEntry !== void 0 && bindingEntryIsFinal(
|
|
6507
|
+
compiledIntent,
|
|
6508
|
+
lastBindingEntry[0],
|
|
6509
|
+
lastBindingEntry[1],
|
|
6510
|
+
sourceBundle
|
|
6511
|
+
);
|
|
6512
|
+
if (finalIsBound) {
|
|
6513
|
+
const lastStep = steps.at(-1);
|
|
6514
|
+
if (lastStep === void 0) return steps;
|
|
6515
|
+
steps[steps.length - 1] = { ...lastStep, final: true };
|
|
6516
|
+
return steps;
|
|
6517
|
+
}
|
|
6518
|
+
if (compiledIntent.kind === "query") {
|
|
6519
|
+
steps.push({
|
|
6520
|
+
kind: "query",
|
|
6521
|
+
intent: compiledIntent.intent,
|
|
6522
|
+
final: true
|
|
6523
|
+
});
|
|
6524
|
+
} else {
|
|
6525
|
+
steps.push({
|
|
6526
|
+
kind: "mutation",
|
|
6527
|
+
intent: compiledIntent.intent,
|
|
6528
|
+
final: true
|
|
6529
|
+
});
|
|
6530
|
+
}
|
|
6531
|
+
assertNqlProgramSteps(compiledIntent, steps);
|
|
6532
|
+
return steps;
|
|
6533
|
+
}
|
|
6534
|
+
function renumberDumpSqlParams(sql2, offset) {
|
|
6535
|
+
if (offset === 0) return sql2;
|
|
6536
|
+
return sql2.replace(/\$(\d+)/g, (_match, num) => {
|
|
6537
|
+
return `$${Number.parseInt(num, 10) + offset}`;
|
|
6538
|
+
});
|
|
6539
|
+
}
|
|
6540
|
+
function joinDumpSequenceSql(sequence) {
|
|
6541
|
+
let parameterOffset = 0;
|
|
6542
|
+
return sequence.map((step) => {
|
|
6543
|
+
const sql2 = renumberDumpSqlParams(step.sql, parameterOffset);
|
|
6544
|
+
parameterOffset += step.params.length;
|
|
6545
|
+
return sql2;
|
|
6546
|
+
}).join(";\n");
|
|
6547
|
+
}
|
|
6548
|
+
function flattenDumpSequenceParams(sequence) {
|
|
6549
|
+
return sequence.flatMap((step) => [...step.params]);
|
|
6550
|
+
}
|
|
6551
|
+
function filterMapByBindingDependencies(source, bindingDependencies) {
|
|
6552
|
+
if (source === void 0) return /* @__PURE__ */ new Map();
|
|
6553
|
+
if (bindingDependencies === void 0) return new Map(source);
|
|
6554
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6555
|
+
for (const bindName of bindingDependencies) {
|
|
6556
|
+
const value = source.get(bindName);
|
|
6557
|
+
if (value !== void 0) {
|
|
6558
|
+
filtered.set(bindName, value);
|
|
6559
|
+
}
|
|
6560
|
+
}
|
|
6561
|
+
return filtered;
|
|
6562
|
+
}
|
|
6563
|
+
function filterOptionalMapByBindingDependencies(source, bindingDependencies) {
|
|
6564
|
+
const filtered = filterMapByBindingDependencies(source, bindingDependencies);
|
|
6565
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
6566
|
+
}
|
|
6567
|
+
function filterMapByRuntimeBindingDependencies(source, runtimeSourceBindings, bindingDependencies) {
|
|
6568
|
+
if (source === void 0) return /* @__PURE__ */ new Map();
|
|
6569
|
+
if (bindingDependencies === void 0 || runtimeSourceBindings === void 0 || runtimeSourceBindings.size === 0) {
|
|
6570
|
+
return new Map(source);
|
|
6571
|
+
}
|
|
6572
|
+
const dependencies = new Set(bindingDependencies);
|
|
6573
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6574
|
+
for (const [bindName, value] of source) {
|
|
6575
|
+
if (!runtimeSourceBindings.has(bindName) || dependencies.has(bindName)) {
|
|
6576
|
+
filtered.set(bindName, value);
|
|
6577
|
+
}
|
|
6578
|
+
}
|
|
6579
|
+
return filtered;
|
|
6580
|
+
}
|
|
6581
|
+
function filterOptionalMapByNames(source, names) {
|
|
6582
|
+
if (source === void 0) return void 0;
|
|
6583
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6584
|
+
for (const name of names) {
|
|
6585
|
+
const value = source.get(name);
|
|
6586
|
+
if (value !== void 0) {
|
|
6587
|
+
filtered.set(name, value);
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
6591
|
+
}
|
|
6592
|
+
function createNqlTag(_schemaDefinition, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6293
6593
|
return function nql(strings, ...values) {
|
|
6294
6594
|
const assembled = assembleNqlTemplate(strings, values);
|
|
6295
6595
|
return new NqlBuilderImpl(
|
|
@@ -6297,7 +6597,6 @@ function createNqlTag(schemaDefinition, model, adapter, schemaName, hookStore, o
|
|
|
6297
6597
|
assembled.params,
|
|
6298
6598
|
assembled.hasBoundParams,
|
|
6299
6599
|
assembled.sourceError,
|
|
6300
|
-
schemaDefinition,
|
|
6301
6600
|
model,
|
|
6302
6601
|
adapter,
|
|
6303
6602
|
schemaName,
|
|
@@ -6313,19 +6612,17 @@ var NqlBuilderImpl = class {
|
|
|
6313
6612
|
params;
|
|
6314
6613
|
hasBoundParams;
|
|
6315
6614
|
sourceError;
|
|
6316
|
-
schemaDefinition;
|
|
6317
6615
|
model;
|
|
6318
6616
|
_schemaName;
|
|
6319
6617
|
adapter;
|
|
6320
6618
|
hookStore;
|
|
6321
6619
|
onHookError;
|
|
6322
6620
|
inTransaction;
|
|
6323
|
-
constructor(query, params, hasBoundParams, sourceError,
|
|
6621
|
+
constructor(query, params, hasBoundParams, sourceError, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6324
6622
|
this.query = query;
|
|
6325
6623
|
this.params = params;
|
|
6326
6624
|
this.hasBoundParams = hasBoundParams;
|
|
6327
6625
|
this.sourceError = sourceError;
|
|
6328
|
-
this.schemaDefinition = schemaDefinition;
|
|
6329
6626
|
this.model = model;
|
|
6330
6627
|
this.adapter = adapter;
|
|
6331
6628
|
this._schemaName = schemaName;
|
|
@@ -6347,7 +6644,7 @@ var NqlBuilderImpl = class {
|
|
|
6347
6644
|
};
|
|
6348
6645
|
const result = nqlCompile(
|
|
6349
6646
|
this.query,
|
|
6350
|
-
this.
|
|
6647
|
+
this.model,
|
|
6351
6648
|
void 0,
|
|
6352
6649
|
compilerOptions
|
|
6353
6650
|
);
|
|
@@ -6360,7 +6657,6 @@ var NqlBuilderImpl = class {
|
|
|
6360
6657
|
if (!bundle) {
|
|
6361
6658
|
throw new Error("NQL compilation failed: no query AST produced");
|
|
6362
6659
|
}
|
|
6363
|
-
assertNoMutationBindingBodies(bundle);
|
|
6364
6660
|
if (bundle.query) {
|
|
6365
6661
|
this._compiled = {
|
|
6366
6662
|
kind: "query",
|
|
@@ -6392,18 +6688,28 @@ var NqlBuilderImpl = class {
|
|
|
6392
6688
|
return plan(compiled.intent, this.model);
|
|
6393
6689
|
}
|
|
6394
6690
|
plan() {
|
|
6395
|
-
|
|
6691
|
+
const compiled = this.compile();
|
|
6692
|
+
if (compiled.kind === "mutation") {
|
|
6693
|
+
throw new Error(
|
|
6694
|
+
"NQL mutations do not have execution plans; use dump() for SQL and parameters."
|
|
6695
|
+
);
|
|
6696
|
+
}
|
|
6697
|
+
return isBindingFinalQuery(compiled.bundle) ? createBindingFinalPlan(compiled.intent) : this.planInternal();
|
|
6396
6698
|
}
|
|
6397
6699
|
dump(meta) {
|
|
6398
6700
|
const compiledIntent = this.compile();
|
|
6701
|
+
if (hasMutationBindingBodies(compiledIntent.bundle)) {
|
|
6702
|
+
return this.dumpNqlProgramSequence(compiledIntent, meta);
|
|
6703
|
+
}
|
|
6399
6704
|
if (compiledIntent.kind === "mutation") {
|
|
6400
6705
|
return this.dumpMutation(
|
|
6401
|
-
compiledIntent
|
|
6706
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
6402
6707
|
compiledIntent.intent,
|
|
6403
6708
|
meta
|
|
6404
6709
|
);
|
|
6405
6710
|
}
|
|
6406
|
-
const
|
|
6711
|
+
const bindingFinalQuery = isBindingFinalQuery(compiledIntent.bundle);
|
|
6712
|
+
const planReport = bindingFinalQuery ? createBindingFinalPlan(compiledIntent.intent) : this.planInternal();
|
|
6407
6713
|
if (!this.adapter) {
|
|
6408
6714
|
return {
|
|
6409
6715
|
plan: planReport,
|
|
@@ -6412,10 +6718,8 @@ var NqlBuilderImpl = class {
|
|
|
6412
6718
|
...meta !== void 0 && { meta }
|
|
6413
6719
|
};
|
|
6414
6720
|
}
|
|
6415
|
-
const
|
|
6416
|
-
|
|
6417
|
-
this.nqlBundleCompileOptions()
|
|
6418
|
-
) : this.adapter.compile(planReport);
|
|
6721
|
+
const finalBundle = this.createFinalNqlStatementBundle(compiledIntent);
|
|
6722
|
+
const compiled = bindingFinalQuery || hasNqlBindings(finalBundle) ? this.adapter.compile(finalBundle, this.nqlBundleCompileOptions()) : this.adapter.compile(planReport);
|
|
6419
6723
|
try {
|
|
6420
6724
|
return this.adapter.createDump(planReport, compiled, meta);
|
|
6421
6725
|
} catch (err) {
|
|
@@ -6466,6 +6770,268 @@ var NqlBuilderImpl = class {
|
|
|
6466
6770
|
...this._schemaName !== void 0 && { schemaName: this._schemaName }
|
|
6467
6771
|
};
|
|
6468
6772
|
}
|
|
6773
|
+
createNqlStatementBundle(statement, bindings, runtimeBindings, sourceBundle, bindingDependencies) {
|
|
6774
|
+
const statementBindings = filterMapByRuntimeBindingDependencies(
|
|
6775
|
+
bindings,
|
|
6776
|
+
sourceBundle.mutationBindings,
|
|
6777
|
+
bindingDependencies
|
|
6778
|
+
);
|
|
6779
|
+
const statementRuntimeBindings = filterMapByBindingDependencies(
|
|
6780
|
+
runtimeBindings,
|
|
6781
|
+
bindingDependencies
|
|
6782
|
+
);
|
|
6783
|
+
const emittedBindingNames = /* @__PURE__ */ new Set([
|
|
6784
|
+
...statementBindings.keys(),
|
|
6785
|
+
...statementRuntimeBindings.keys()
|
|
6786
|
+
]);
|
|
6787
|
+
const statementBindingOutputSchemas = filterOptionalMapByNames(
|
|
6788
|
+
sourceBundle.bindingOutputSchemas,
|
|
6789
|
+
emittedBindingNames
|
|
6790
|
+
);
|
|
6791
|
+
const statementMutationBindings = filterOptionalMapByBindingDependencies(
|
|
6792
|
+
sourceBundle.mutationBindings,
|
|
6793
|
+
bindingDependencies
|
|
6794
|
+
);
|
|
6795
|
+
return {
|
|
6796
|
+
...statement,
|
|
6797
|
+
...statementBindings.size > 0 && { bindings: statementBindings },
|
|
6798
|
+
...statementBindingOutputSchemas !== void 0 && {
|
|
6799
|
+
bindingOutputSchemas: statementBindingOutputSchemas
|
|
6800
|
+
},
|
|
6801
|
+
...statementMutationBindings !== void 0 && {
|
|
6802
|
+
mutationBindings: statementMutationBindings
|
|
6803
|
+
},
|
|
6804
|
+
...statementRuntimeBindings.size > 0 && {
|
|
6805
|
+
runtimeBindings: statementRuntimeBindings
|
|
6806
|
+
}
|
|
6807
|
+
};
|
|
6808
|
+
}
|
|
6809
|
+
createFinalNqlStatementBundle(compiledIntent) {
|
|
6810
|
+
const finalStep = createNqlProgramSteps(compiledIntent).at(-1);
|
|
6811
|
+
if (compiledIntent.kind === "query") {
|
|
6812
|
+
return this.createNqlStatementBundle(
|
|
6813
|
+
{ query: compiledIntent.intent },
|
|
6814
|
+
compiledIntent.bundle.bindings ?? /* @__PURE__ */ new Map(),
|
|
6815
|
+
compiledIntent.bundle.runtimeBindings ?? /* @__PURE__ */ new Map(),
|
|
6816
|
+
compiledIntent.bundle,
|
|
6817
|
+
finalStep?.bindingDependencies
|
|
6818
|
+
);
|
|
6819
|
+
}
|
|
6820
|
+
return this.createNqlStatementBundle(
|
|
6821
|
+
{ mutation: compiledIntent.intent },
|
|
6822
|
+
compiledIntent.bundle.bindings ?? /* @__PURE__ */ new Map(),
|
|
6823
|
+
compiledIntent.bundle.runtimeBindings ?? /* @__PURE__ */ new Map(),
|
|
6824
|
+
compiledIntent.bundle,
|
|
6825
|
+
finalStep?.bindingDependencies
|
|
6826
|
+
);
|
|
6827
|
+
}
|
|
6828
|
+
runMutationStatement(adapter, bundle, intent, inTransaction) {
|
|
6829
|
+
const hasReturning = (intent.returning?.length ?? 0) > 0;
|
|
6830
|
+
return runMutationWithHooks({
|
|
6831
|
+
table: intent.table,
|
|
6832
|
+
intent,
|
|
6833
|
+
hookStore: this.hookStore,
|
|
6834
|
+
onHookError: this.onHookError,
|
|
6835
|
+
schemaName: this._schemaName,
|
|
6836
|
+
inTransaction,
|
|
6837
|
+
prepare: () => {
|
|
6838
|
+
const compiled = adapter.compile(
|
|
6839
|
+
bundle,
|
|
6840
|
+
this.mutationCompileOptions()
|
|
6841
|
+
);
|
|
6842
|
+
return {
|
|
6843
|
+
sql: compiled.sql,
|
|
6844
|
+
parameters: compiled.parameters,
|
|
6845
|
+
execute: async () => {
|
|
6846
|
+
const hookRows = await adapter.execute(compiled);
|
|
6847
|
+
const rawRows = snapshotMutationRows(hookRows);
|
|
6848
|
+
return {
|
|
6849
|
+
rawRows,
|
|
6850
|
+
hookRows,
|
|
6851
|
+
transformedRows: hookRows
|
|
6852
|
+
};
|
|
6853
|
+
},
|
|
6854
|
+
getAfterMutationResult: (result) => hasReturning ? result.hookRows : [],
|
|
6855
|
+
mapAfterMutationResult: (result, transformedRows) => ({
|
|
6856
|
+
rawRows: result.rawRows,
|
|
6857
|
+
hookRows: result.hookRows,
|
|
6858
|
+
transformedRows: [...transformedRows]
|
|
6859
|
+
}),
|
|
6860
|
+
returnAfterMutationResult: hasReturning
|
|
6861
|
+
};
|
|
6862
|
+
}
|
|
6863
|
+
});
|
|
6864
|
+
}
|
|
6865
|
+
async executeNqlProgramSequence(compiledIntent, adapter) {
|
|
6866
|
+
if (!supportsTransactions(adapter)) {
|
|
6867
|
+
throw new ExecutionError({
|
|
6868
|
+
operation: "nql",
|
|
6869
|
+
reason: "NQL programs with mutation bindings require adapter transaction support",
|
|
6870
|
+
fix: "Use an adapter that implements transaction(fn), such as the PostgreSQL adapter."
|
|
6871
|
+
});
|
|
6872
|
+
}
|
|
6873
|
+
return adapter.transaction(async (txAdapter) => {
|
|
6874
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6875
|
+
const priorBindings = /* @__PURE__ */ new Map();
|
|
6876
|
+
const runtimeBindings = /* @__PURE__ */ new Map();
|
|
6877
|
+
const steps = createNqlProgramSteps(compiledIntent);
|
|
6878
|
+
let finalRows = [];
|
|
6879
|
+
for (const step of steps) {
|
|
6880
|
+
if (step.kind === "mutation") {
|
|
6881
|
+
if ((step.intent.returning?.length ?? 0) === 0 && step.bindName) {
|
|
6882
|
+
throw new Error(
|
|
6883
|
+
`NQL mutation binding '${step.bindName}' cannot execute without a RETURNING projection.`
|
|
6884
|
+
);
|
|
6885
|
+
}
|
|
6886
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6887
|
+
{ mutation: step.intent },
|
|
6888
|
+
priorBindings,
|
|
6889
|
+
runtimeBindings,
|
|
6890
|
+
sourceBundle,
|
|
6891
|
+
step.bindingDependencies
|
|
6892
|
+
);
|
|
6893
|
+
const rows = await this.runMutationStatement(
|
|
6894
|
+
txAdapter,
|
|
6895
|
+
statementBundle,
|
|
6896
|
+
step.intent,
|
|
6897
|
+
true
|
|
6898
|
+
);
|
|
6899
|
+
if (step.bindName) {
|
|
6900
|
+
runtimeBindings.set(
|
|
6901
|
+
step.bindName,
|
|
6902
|
+
createRuntimeBinding(
|
|
6903
|
+
sourceBundle,
|
|
6904
|
+
step.bindName,
|
|
6905
|
+
rows.rawRows,
|
|
6906
|
+
txAdapter.dbCasing
|
|
6907
|
+
)
|
|
6908
|
+
);
|
|
6909
|
+
}
|
|
6910
|
+
if (step.final) {
|
|
6911
|
+
finalRows = rows.transformedRows;
|
|
6912
|
+
}
|
|
6913
|
+
} else if (step.final) {
|
|
6914
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6915
|
+
{ query: step.intent },
|
|
6916
|
+
priorBindings,
|
|
6917
|
+
runtimeBindings,
|
|
6918
|
+
sourceBundle,
|
|
6919
|
+
step.bindingDependencies
|
|
6920
|
+
);
|
|
6921
|
+
const compiled = txAdapter.compile(
|
|
6922
|
+
statementBundle,
|
|
6923
|
+
this.nqlBundleCompileOptions()
|
|
6924
|
+
);
|
|
6925
|
+
finalRows = await txAdapter.execute(compiled);
|
|
6926
|
+
}
|
|
6927
|
+
if (step.bindName) {
|
|
6928
|
+
const boundQuery = sourceBundle.bindings?.get(step.bindName);
|
|
6929
|
+
if (boundQuery !== void 0) {
|
|
6930
|
+
priorBindings.set(step.bindName, boundQuery);
|
|
6931
|
+
}
|
|
6932
|
+
}
|
|
6933
|
+
}
|
|
6934
|
+
return finalRows;
|
|
6935
|
+
});
|
|
6936
|
+
}
|
|
6937
|
+
dumpNqlProgramSequence(compiledIntent, meta) {
|
|
6938
|
+
const adapter = this.requireAdapter("dump");
|
|
6939
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6940
|
+
const priorBindings = /* @__PURE__ */ new Map();
|
|
6941
|
+
const runtimeBindings = /* @__PURE__ */ new Map();
|
|
6942
|
+
const sequence = [];
|
|
6943
|
+
const steps = createNqlProgramSteps(compiledIntent);
|
|
6944
|
+
for (const step of steps) {
|
|
6945
|
+
if (step.kind === "mutation") {
|
|
6946
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6947
|
+
{ mutation: step.intent },
|
|
6948
|
+
priorBindings,
|
|
6949
|
+
runtimeBindings,
|
|
6950
|
+
sourceBundle,
|
|
6951
|
+
step.bindingDependencies
|
|
6952
|
+
);
|
|
6953
|
+
const compiled = adapter.compile(
|
|
6954
|
+
statementBundle,
|
|
6955
|
+
this.mutationCompileOptions()
|
|
6956
|
+
);
|
|
6957
|
+
sequence.push({
|
|
6958
|
+
kind: "mutation",
|
|
6959
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6960
|
+
sql: compiled.sql,
|
|
6961
|
+
params: compiled.parameters
|
|
6962
|
+
});
|
|
6963
|
+
if (step.bindName !== void 0) {
|
|
6964
|
+
runtimeBindings.set(step.bindName, {
|
|
6965
|
+
columns: requireMutationBindingColumns(sourceBundle, step.bindName),
|
|
6966
|
+
rows: []
|
|
6967
|
+
});
|
|
6968
|
+
}
|
|
6969
|
+
} else {
|
|
6970
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6971
|
+
{ query: step.intent },
|
|
6972
|
+
priorBindings,
|
|
6973
|
+
runtimeBindings,
|
|
6974
|
+
sourceBundle,
|
|
6975
|
+
step.bindingDependencies
|
|
6976
|
+
);
|
|
6977
|
+
const compiled = adapter.compile(
|
|
6978
|
+
statementBundle,
|
|
6979
|
+
this.nqlBundleCompileOptions()
|
|
6980
|
+
);
|
|
6981
|
+
sequence.push({
|
|
6982
|
+
kind: "query",
|
|
6983
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6984
|
+
sql: compiled.sql,
|
|
6985
|
+
params: compiled.parameters
|
|
6986
|
+
});
|
|
6987
|
+
}
|
|
6988
|
+
if (step.bindName !== void 0) {
|
|
6989
|
+
const boundQuery = sourceBundle.bindings?.get(step.bindName);
|
|
6990
|
+
if (boundQuery !== void 0) {
|
|
6991
|
+
priorBindings.set(step.bindName, boundQuery);
|
|
6992
|
+
}
|
|
6993
|
+
}
|
|
6994
|
+
}
|
|
6995
|
+
const finalStep = steps.at(-1);
|
|
6996
|
+
if (finalStep?.kind === "query") {
|
|
6997
|
+
const planReport = isBindingFinalQuery(compiledIntent.bundle) ? createBindingFinalPlan(finalStep.intent) : this.planInternal();
|
|
6998
|
+
const dumpMeta2 = {
|
|
6999
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
7000
|
+
...this._schemaName !== void 0 && { schema: this._schemaName },
|
|
7001
|
+
...meta?.queryName !== void 0 && { queryName: meta.queryName },
|
|
7002
|
+
...meta?.correlationId !== void 0 && {
|
|
7003
|
+
correlationId: meta.correlationId
|
|
7004
|
+
}
|
|
7005
|
+
};
|
|
7006
|
+
return {
|
|
7007
|
+
plan: planReport,
|
|
7008
|
+
sql: joinDumpSequenceSql(sequence),
|
|
7009
|
+
params: flattenDumpSequenceParams(sequence),
|
|
7010
|
+
meta: dumpMeta2,
|
|
7011
|
+
sequence
|
|
7012
|
+
};
|
|
7013
|
+
}
|
|
7014
|
+
if (finalStep?.kind !== "mutation") {
|
|
7015
|
+
throw new Error(
|
|
7016
|
+
"NQL program sequence did not contain a final statement."
|
|
7017
|
+
);
|
|
7018
|
+
}
|
|
7019
|
+
const dumpMeta = {
|
|
7020
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
7021
|
+
...this._schemaName !== void 0 && { schema: this._schemaName },
|
|
7022
|
+
...meta?.queryName !== void 0 && { queryName: meta.queryName },
|
|
7023
|
+
...meta?.correlationId !== void 0 && {
|
|
7024
|
+
correlationId: meta.correlationId
|
|
7025
|
+
}
|
|
7026
|
+
};
|
|
7027
|
+
return {
|
|
7028
|
+
sql: joinDumpSequenceSql(sequence),
|
|
7029
|
+
parameters: flattenDumpSequenceParams(sequence),
|
|
7030
|
+
intent: finalStep.intent,
|
|
7031
|
+
meta: dumpMeta,
|
|
7032
|
+
sequence
|
|
7033
|
+
};
|
|
7034
|
+
}
|
|
6469
7035
|
dumpMutation(bundle, intent, meta) {
|
|
6470
7036
|
const adapter = this.requireAdapter("dump");
|
|
6471
7037
|
const compiled = adapter.compile(bundle, this.mutationCompileOptions(meta));
|
|
@@ -6492,35 +7058,27 @@ var NqlBuilderImpl = class {
|
|
|
6492
7058
|
);
|
|
6493
7059
|
}
|
|
6494
7060
|
const compiledIntent = this.compile();
|
|
7061
|
+
if (hasMutationBindingBodies(compiledIntent.bundle)) {
|
|
7062
|
+
return this.executeNqlProgramSequence(compiledIntent, adapter);
|
|
7063
|
+
}
|
|
6495
7064
|
if (compiledIntent.kind === "mutation") {
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
return {
|
|
6510
|
-
sql: compiled2.sql,
|
|
6511
|
-
parameters: compiled2.parameters,
|
|
6512
|
-
execute: () => adapter.execute(compiled2),
|
|
6513
|
-
getAfterMutationResult: (result) => hasReturning ? result : [],
|
|
6514
|
-
returnAfterMutationResult: hasReturning
|
|
6515
|
-
};
|
|
6516
|
-
}
|
|
6517
|
-
});
|
|
7065
|
+
return (await this.runMutationStatement(
|
|
7066
|
+
adapter,
|
|
7067
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
7068
|
+
compiledIntent.intent,
|
|
7069
|
+
this.inTransaction
|
|
7070
|
+
)).transformedRows;
|
|
7071
|
+
}
|
|
7072
|
+
if (isBindingFinalQuery(compiledIntent.bundle)) {
|
|
7073
|
+
const compiled2 = adapter.compile(
|
|
7074
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
7075
|
+
this.nqlBundleCompileOptions()
|
|
7076
|
+
);
|
|
7077
|
+
return adapter.execute(compiled2);
|
|
6518
7078
|
}
|
|
6519
7079
|
const planReport = this.planInternal();
|
|
6520
|
-
const
|
|
6521
|
-
|
|
6522
|
-
this.nqlBundleCompileOptions()
|
|
6523
|
-
) : adapter.compile(planReport);
|
|
7080
|
+
const finalBundle = this.createFinalNqlStatementBundle(compiledIntent);
|
|
7081
|
+
const compiled = hasNqlBindings(finalBundle) ? adapter.compile(finalBundle, this.nqlBundleCompileOptions()) : adapter.compile(planReport);
|
|
6524
7082
|
return adapter.execute(compiled);
|
|
6525
7083
|
}
|
|
6526
7084
|
async run() {
|
|
@@ -10422,6 +10980,8 @@ var POSTGRESQL_CAPABILITIES = {
|
|
|
10422
10980
|
supportsJsonType: true,
|
|
10423
10981
|
supportsJsonOperators: true,
|
|
10424
10982
|
// PG: ->, ->>, @>, <@, ?, #>, #>>
|
|
10983
|
+
supportsRowLevelLocks: true,
|
|
10984
|
+
supportsLockWaitPolicies: true,
|
|
10425
10985
|
supportsSchemas: true,
|
|
10426
10986
|
// Include Strategy Capabilities (CORE-006)
|
|
10427
10987
|
supportsLateralJoin: true,
|
|
@@ -10466,6 +11026,9 @@ var MYSQL_CAPABILITIES = {
|
|
|
10466
11026
|
supportsJsonType: true,
|
|
10467
11027
|
supportsJsonOperators: false,
|
|
10468
11028
|
// MySQL uses JSON_EXTRACT() functions, not operators
|
|
11029
|
+
// Coarse PostgreSQL-shaped lock flags; revisit MySQL with per-strength caps.
|
|
11030
|
+
supportsRowLevelLocks: false,
|
|
11031
|
+
supportsLockWaitPolicies: false,
|
|
10469
11032
|
supportsSchemas: true,
|
|
10470
11033
|
// MySQL uses database as schema
|
|
10471
11034
|
// Include Strategy Capabilities (CORE-006)
|
|
@@ -10496,6 +11059,8 @@ var SQLITE_CAPABILITIES = {
|
|
|
10496
11059
|
// SQLite 3.38+ (JSON1 extension)
|
|
10497
11060
|
supportsJsonOperators: false,
|
|
10498
11061
|
// SQLite uses json_extract() functions
|
|
11062
|
+
supportsRowLevelLocks: false,
|
|
11063
|
+
supportsLockWaitPolicies: false,
|
|
10499
11064
|
supportsSchemas: false,
|
|
10500
11065
|
// SQLite uses ATTACH for multiple databases
|
|
10501
11066
|
// Include Strategy Capabilities (CORE-006)
|
|
@@ -10524,6 +11089,8 @@ var DUCKDB_CAPABILITIES = {
|
|
|
10524
11089
|
supportsJsonType: true,
|
|
10525
11090
|
supportsJsonOperators: false,
|
|
10526
11091
|
// DuckDB uses json_extract() style
|
|
11092
|
+
supportsRowLevelLocks: false,
|
|
11093
|
+
supportsLockWaitPolicies: false,
|
|
10527
11094
|
supportsSchemas: true,
|
|
10528
11095
|
// Include Strategy Capabilities (CORE-006)
|
|
10529
11096
|
supportsLateralJoin: true,
|
|
@@ -10553,6 +11120,9 @@ var MSSQL_CAPABILITIES = {
|
|
|
10553
11120
|
// SQL Server 2016+
|
|
10554
11121
|
supportsJsonOperators: false,
|
|
10555
11122
|
// MSSQL uses JSON_VALUE/JSON_QUERY functions
|
|
11123
|
+
// Coarse PostgreSQL-shaped lock flags; revisit MSSQL hints with per-strength caps.
|
|
11124
|
+
supportsRowLevelLocks: false,
|
|
11125
|
+
supportsLockWaitPolicies: false,
|
|
10556
11126
|
supportsSchemas: true,
|
|
10557
11127
|
// Include Strategy Capabilities (CORE-006)
|
|
10558
11128
|
supportsLateralJoin: true,
|
|
@@ -10610,6 +11180,8 @@ function createDialectCapabilities(overrides, options) {
|
|
|
10610
11180
|
supportsRangeTypes: false,
|
|
10611
11181
|
supportsJsonType: false,
|
|
10612
11182
|
supportsJsonOperators: false,
|
|
11183
|
+
supportsRowLevelLocks: false,
|
|
11184
|
+
supportsLockWaitPolicies: false,
|
|
10613
11185
|
supportsSchemas: false,
|
|
10614
11186
|
supportsLateralJoin: false,
|
|
10615
11187
|
supportsJsonAgg: false,
|