@dbsp/core 1.2.0 → 1.3.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 +608 -49
- 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;
|
|
@@ -6168,15 +6168,59 @@ var NQL_RAW_FRAGMENT = /* @__PURE__ */ Symbol("NqlRawFragment");
|
|
|
6168
6168
|
function hasNqlBindings(bundle) {
|
|
6169
6169
|
return (bundle.bindings?.size ?? 0) > 0;
|
|
6170
6170
|
}
|
|
6171
|
-
function
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6171
|
+
function isBindingFinalQuery(bundle) {
|
|
6172
|
+
return bundle.query !== void 0 && (bundle.bindings?.has(bundle.query.from) ?? false);
|
|
6173
|
+
}
|
|
6174
|
+
function formatBindingRelationPath(path) {
|
|
6175
|
+
return typeof path === "string" ? path : path.join(".");
|
|
6176
|
+
}
|
|
6177
|
+
function findBindingFinalRelationFilter(where) {
|
|
6178
|
+
switch (where.kind) {
|
|
6179
|
+
case "and":
|
|
6180
|
+
case "or":
|
|
6181
|
+
for (const condition of where.conditions) {
|
|
6182
|
+
const found = findBindingFinalRelationFilter(condition);
|
|
6183
|
+
if (found !== void 0) return found;
|
|
6184
|
+
}
|
|
6185
|
+
return void 0;
|
|
6186
|
+
case "not":
|
|
6187
|
+
return findBindingFinalRelationFilter(where.condition);
|
|
6188
|
+
case "relationFilter":
|
|
6189
|
+
return formatBindingRelationPath(where.relation);
|
|
6190
|
+
case "exists":
|
|
6191
|
+
case "notExists":
|
|
6192
|
+
return where.relation;
|
|
6193
|
+
case "rawExists":
|
|
6194
|
+
case "rawNotExists":
|
|
6195
|
+
return "raw EXISTS";
|
|
6196
|
+
default:
|
|
6197
|
+
return void 0;
|
|
6198
|
+
}
|
|
6199
|
+
}
|
|
6200
|
+
function assertBindingFinalQueryCanUseSyntheticPlan(intent) {
|
|
6201
|
+
const relationColumns = intent.select?.type === "expressions" ? intent.select.columns.filter((column) => column.kind === "relationColumn").map((column) => column.relation) : [];
|
|
6202
|
+
const relationFilter = intent.where ? findBindingFinalRelationFilter(intent.where) : void 0;
|
|
6203
|
+
const havingRelationFilter = intent.having ? findBindingFinalRelationFilter(intent.having) : void 0;
|
|
6204
|
+
if ((intent.include?.length ?? 0) > 0 || relationColumns.length > 0 || (intent.joins?.length ?? 0) > 0 || relationFilter !== void 0 || havingRelationFilter !== void 0) {
|
|
6205
|
+
throw new Error(
|
|
6206
|
+
`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.`
|
|
6207
|
+
);
|
|
6175
6208
|
}
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6209
|
+
}
|
|
6210
|
+
function createBindingFinalPlan(intent) {
|
|
6211
|
+
assertBindingFinalQueryCanUseSyntheticPlan(intent);
|
|
6212
|
+
return {
|
|
6213
|
+
rootTable: intent.from,
|
|
6214
|
+
decisions: [],
|
|
6215
|
+
warnings: [],
|
|
6216
|
+
ctes: [],
|
|
6217
|
+
intent,
|
|
6218
|
+
metadata: {
|
|
6219
|
+
planningTimeMs: 0,
|
|
6220
|
+
relationsAnalyzed: 0,
|
|
6221
|
+
isAmbiguous: false
|
|
6222
|
+
}
|
|
6223
|
+
};
|
|
6180
6224
|
}
|
|
6181
6225
|
function nqlRaw(fragment) {
|
|
6182
6226
|
if (typeof fragment !== "string") {
|
|
@@ -6289,7 +6333,250 @@ function assembleNqlTemplate(strings, values) {
|
|
|
6289
6333
|
sourceError: findInternalParamSourceError(query, generatedRanges)
|
|
6290
6334
|
};
|
|
6291
6335
|
}
|
|
6292
|
-
function
|
|
6336
|
+
function hasMutationBindingBodies(bundle) {
|
|
6337
|
+
return (bundle.mutationBindings?.size ?? 0) > 0;
|
|
6338
|
+
}
|
|
6339
|
+
function requireMutationBindingColumns(bundle, bindName) {
|
|
6340
|
+
const columns = bundle.bindingOutputSchemas?.get(bindName)?.columns;
|
|
6341
|
+
if (columns === void 0 || columns.length === 0) {
|
|
6342
|
+
throw new Error(
|
|
6343
|
+
`NQL mutation binding '${bindName}' cannot be materialized because its projected column schema is unavailable.`
|
|
6344
|
+
);
|
|
6345
|
+
}
|
|
6346
|
+
return columns;
|
|
6347
|
+
}
|
|
6348
|
+
function toSnakeCaseIdentifier(identifier) {
|
|
6349
|
+
if (!identifier) return identifier;
|
|
6350
|
+
const leadingUnderscores = identifier.match(/^_+/)?.[0] ?? "";
|
|
6351
|
+
const rest = identifier.slice(leadingUnderscores.length);
|
|
6352
|
+
if (!rest) return identifier;
|
|
6353
|
+
const snakeCase = rest.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2").toLowerCase();
|
|
6354
|
+
return leadingUnderscores + snakeCase;
|
|
6355
|
+
}
|
|
6356
|
+
function toDatabaseColumnName(column, dbCasing) {
|
|
6357
|
+
return dbCasing === "snake_case" ? toSnakeCaseIdentifier(column) : column;
|
|
6358
|
+
}
|
|
6359
|
+
function toRuntimeBindingRow(bindName, row, columns, dbCasing) {
|
|
6360
|
+
if (typeof row !== "object" || row === null || Array.isArray(row)) {
|
|
6361
|
+
throw new Error(
|
|
6362
|
+
`NQL mutation binding '${bindName}' returned a non-object row; runtime VALUES materialization requires object rows keyed by projected column name.`
|
|
6363
|
+
);
|
|
6364
|
+
}
|
|
6365
|
+
const source = row;
|
|
6366
|
+
const materialized = {};
|
|
6367
|
+
for (const column of columns) {
|
|
6368
|
+
const dbColumn = toDatabaseColumnName(column, dbCasing);
|
|
6369
|
+
const sourceColumn = Object.hasOwn(source, column) ? column : dbColumn !== column && Object.hasOwn(source, dbColumn) ? dbColumn : void 0;
|
|
6370
|
+
if (sourceColumn === void 0) {
|
|
6371
|
+
throw new Error(
|
|
6372
|
+
`NQL mutation binding '${bindName}' returned a row without projected column '${column}'.`
|
|
6373
|
+
);
|
|
6374
|
+
}
|
|
6375
|
+
materialized[column] = source[sourceColumn];
|
|
6376
|
+
}
|
|
6377
|
+
return materialized;
|
|
6378
|
+
}
|
|
6379
|
+
function createRuntimeBinding(bundle, bindName, rows, dbCasing) {
|
|
6380
|
+
const columns = requireMutationBindingColumns(bundle, bindName);
|
|
6381
|
+
return {
|
|
6382
|
+
columns,
|
|
6383
|
+
rows: rows.map(
|
|
6384
|
+
(row) => toRuntimeBindingRow(bindName, row, columns, dbCasing)
|
|
6385
|
+
)
|
|
6386
|
+
};
|
|
6387
|
+
}
|
|
6388
|
+
function bindingEntryIsFinal(compiledIntent, bindName, boundQuery, sourceBundle) {
|
|
6389
|
+
if (compiledIntent.kind === "query") {
|
|
6390
|
+
return boundQuery === compiledIntent.intent;
|
|
6391
|
+
}
|
|
6392
|
+
return sourceBundle.mutationBindings?.get(bindName) === compiledIntent.intent;
|
|
6393
|
+
}
|
|
6394
|
+
function orderedSequenceStepToProgramStep(step) {
|
|
6395
|
+
const dependencyStep = step;
|
|
6396
|
+
if (step.kind === "query") {
|
|
6397
|
+
return {
|
|
6398
|
+
kind: "query",
|
|
6399
|
+
intent: step.query,
|
|
6400
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6401
|
+
final: step.final,
|
|
6402
|
+
...dependencyStep.bindingDependencies !== void 0 && {
|
|
6403
|
+
bindingDependencies: dependencyStep.bindingDependencies
|
|
6404
|
+
}
|
|
6405
|
+
};
|
|
6406
|
+
}
|
|
6407
|
+
return {
|
|
6408
|
+
kind: "mutation",
|
|
6409
|
+
intent: step.mutation,
|
|
6410
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6411
|
+
final: step.final,
|
|
6412
|
+
...dependencyStep.bindingDependencies !== void 0 && {
|
|
6413
|
+
bindingDependencies: dependencyStep.bindingDependencies
|
|
6414
|
+
}
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
6417
|
+
function snapshotMutationRows(rows) {
|
|
6418
|
+
return rows.map((row) => {
|
|
6419
|
+
if (Array.isArray(row)) {
|
|
6420
|
+
return [...row];
|
|
6421
|
+
}
|
|
6422
|
+
if (row !== null && typeof row === "object") {
|
|
6423
|
+
return { ...row };
|
|
6424
|
+
}
|
|
6425
|
+
return row;
|
|
6426
|
+
});
|
|
6427
|
+
}
|
|
6428
|
+
function assertNqlProgramSteps(compiledIntent, steps) {
|
|
6429
|
+
if (steps.length === 0) {
|
|
6430
|
+
throw new Error("NQL program sequence did not contain any statements.");
|
|
6431
|
+
}
|
|
6432
|
+
const finalIndexes = steps.map((step, index) => step.final ? index : -1).filter((index) => index !== -1);
|
|
6433
|
+
if (finalIndexes.length !== 1 || finalIndexes[0] !== steps.length - 1) {
|
|
6434
|
+
throw new Error(
|
|
6435
|
+
"NQL program sequence must contain exactly one final statement at the end."
|
|
6436
|
+
);
|
|
6437
|
+
}
|
|
6438
|
+
const finalStep = steps.at(-1);
|
|
6439
|
+
if (finalStep === void 0) {
|
|
6440
|
+
throw new Error("NQL program sequence did not contain a final statement.");
|
|
6441
|
+
}
|
|
6442
|
+
if (finalStep.kind !== compiledIntent.kind || finalStep.intent !== compiledIntent.intent) {
|
|
6443
|
+
throw new Error(
|
|
6444
|
+
"NQL program sequence final statement does not match the compiled NQL result."
|
|
6445
|
+
);
|
|
6446
|
+
}
|
|
6447
|
+
const seenBindNames = /* @__PURE__ */ new Set();
|
|
6448
|
+
for (const step of steps) {
|
|
6449
|
+
if (step.bindName === void 0) continue;
|
|
6450
|
+
if (seenBindNames.has(step.bindName)) {
|
|
6451
|
+
throw new Error(
|
|
6452
|
+
`NQL program sequence contains duplicate binding '${step.bindName}'.`
|
|
6453
|
+
);
|
|
6454
|
+
}
|
|
6455
|
+
seenBindNames.add(step.bindName);
|
|
6456
|
+
if (!(compiledIntent.bundle.bindings?.has(step.bindName) ?? false)) {
|
|
6457
|
+
throw new Error(
|
|
6458
|
+
`NQL program sequence references unknown binding '${step.bindName}'.`
|
|
6459
|
+
);
|
|
6460
|
+
}
|
|
6461
|
+
}
|
|
6462
|
+
}
|
|
6463
|
+
function createNqlProgramSteps(compiledIntent) {
|
|
6464
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6465
|
+
if (sourceBundle.nqlProgramSequence !== void 0) {
|
|
6466
|
+
const steps2 = sourceBundle.nqlProgramSequence.map(
|
|
6467
|
+
orderedSequenceStepToProgramStep
|
|
6468
|
+
);
|
|
6469
|
+
assertNqlProgramSteps(compiledIntent, steps2);
|
|
6470
|
+
return steps2;
|
|
6471
|
+
}
|
|
6472
|
+
const bindingEntries = [...sourceBundle.bindings ?? /* @__PURE__ */ new Map()];
|
|
6473
|
+
const steps = bindingEntries.map(
|
|
6474
|
+
([bindName, boundQuery]) => {
|
|
6475
|
+
const boundMutation = sourceBundle.mutationBindings?.get(bindName);
|
|
6476
|
+
if (boundMutation !== void 0) {
|
|
6477
|
+
return {
|
|
6478
|
+
kind: "mutation",
|
|
6479
|
+
intent: boundMutation,
|
|
6480
|
+
bindName,
|
|
6481
|
+
final: false
|
|
6482
|
+
};
|
|
6483
|
+
}
|
|
6484
|
+
return {
|
|
6485
|
+
kind: "query",
|
|
6486
|
+
intent: boundQuery,
|
|
6487
|
+
bindName,
|
|
6488
|
+
final: false
|
|
6489
|
+
};
|
|
6490
|
+
}
|
|
6491
|
+
);
|
|
6492
|
+
const lastBindingEntry = bindingEntries.at(-1);
|
|
6493
|
+
const finalIsBound = lastBindingEntry !== void 0 && bindingEntryIsFinal(
|
|
6494
|
+
compiledIntent,
|
|
6495
|
+
lastBindingEntry[0],
|
|
6496
|
+
lastBindingEntry[1],
|
|
6497
|
+
sourceBundle
|
|
6498
|
+
);
|
|
6499
|
+
if (finalIsBound) {
|
|
6500
|
+
const lastStep = steps.at(-1);
|
|
6501
|
+
if (lastStep === void 0) return steps;
|
|
6502
|
+
steps[steps.length - 1] = { ...lastStep, final: true };
|
|
6503
|
+
return steps;
|
|
6504
|
+
}
|
|
6505
|
+
if (compiledIntent.kind === "query") {
|
|
6506
|
+
steps.push({
|
|
6507
|
+
kind: "query",
|
|
6508
|
+
intent: compiledIntent.intent,
|
|
6509
|
+
final: true
|
|
6510
|
+
});
|
|
6511
|
+
} else {
|
|
6512
|
+
steps.push({
|
|
6513
|
+
kind: "mutation",
|
|
6514
|
+
intent: compiledIntent.intent,
|
|
6515
|
+
final: true
|
|
6516
|
+
});
|
|
6517
|
+
}
|
|
6518
|
+
assertNqlProgramSteps(compiledIntent, steps);
|
|
6519
|
+
return steps;
|
|
6520
|
+
}
|
|
6521
|
+
function renumberDumpSqlParams(sql2, offset) {
|
|
6522
|
+
if (offset === 0) return sql2;
|
|
6523
|
+
return sql2.replace(/\$(\d+)/g, (_match, num) => {
|
|
6524
|
+
return `$${Number.parseInt(num, 10) + offset}`;
|
|
6525
|
+
});
|
|
6526
|
+
}
|
|
6527
|
+
function joinDumpSequenceSql(sequence) {
|
|
6528
|
+
let parameterOffset = 0;
|
|
6529
|
+
return sequence.map((step) => {
|
|
6530
|
+
const sql2 = renumberDumpSqlParams(step.sql, parameterOffset);
|
|
6531
|
+
parameterOffset += step.params.length;
|
|
6532
|
+
return sql2;
|
|
6533
|
+
}).join(";\n");
|
|
6534
|
+
}
|
|
6535
|
+
function flattenDumpSequenceParams(sequence) {
|
|
6536
|
+
return sequence.flatMap((step) => [...step.params]);
|
|
6537
|
+
}
|
|
6538
|
+
function filterMapByBindingDependencies(source, bindingDependencies) {
|
|
6539
|
+
if (source === void 0) return /* @__PURE__ */ new Map();
|
|
6540
|
+
if (bindingDependencies === void 0) return new Map(source);
|
|
6541
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6542
|
+
for (const bindName of bindingDependencies) {
|
|
6543
|
+
const value = source.get(bindName);
|
|
6544
|
+
if (value !== void 0) {
|
|
6545
|
+
filtered.set(bindName, value);
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
return filtered;
|
|
6549
|
+
}
|
|
6550
|
+
function filterOptionalMapByBindingDependencies(source, bindingDependencies) {
|
|
6551
|
+
const filtered = filterMapByBindingDependencies(source, bindingDependencies);
|
|
6552
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
6553
|
+
}
|
|
6554
|
+
function filterMapByRuntimeBindingDependencies(source, runtimeSourceBindings, bindingDependencies) {
|
|
6555
|
+
if (source === void 0) return /* @__PURE__ */ new Map();
|
|
6556
|
+
if (bindingDependencies === void 0 || runtimeSourceBindings === void 0 || runtimeSourceBindings.size === 0) {
|
|
6557
|
+
return new Map(source);
|
|
6558
|
+
}
|
|
6559
|
+
const dependencies = new Set(bindingDependencies);
|
|
6560
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6561
|
+
for (const [bindName, value] of source) {
|
|
6562
|
+
if (!runtimeSourceBindings.has(bindName) || dependencies.has(bindName)) {
|
|
6563
|
+
filtered.set(bindName, value);
|
|
6564
|
+
}
|
|
6565
|
+
}
|
|
6566
|
+
return filtered;
|
|
6567
|
+
}
|
|
6568
|
+
function filterOptionalMapByNames(source, names) {
|
|
6569
|
+
if (source === void 0) return void 0;
|
|
6570
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
6571
|
+
for (const name of names) {
|
|
6572
|
+
const value = source.get(name);
|
|
6573
|
+
if (value !== void 0) {
|
|
6574
|
+
filtered.set(name, value);
|
|
6575
|
+
}
|
|
6576
|
+
}
|
|
6577
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
6578
|
+
}
|
|
6579
|
+
function createNqlTag(_schemaDefinition, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6293
6580
|
return function nql(strings, ...values) {
|
|
6294
6581
|
const assembled = assembleNqlTemplate(strings, values);
|
|
6295
6582
|
return new NqlBuilderImpl(
|
|
@@ -6297,7 +6584,6 @@ function createNqlTag(schemaDefinition, model, adapter, schemaName, hookStore, o
|
|
|
6297
6584
|
assembled.params,
|
|
6298
6585
|
assembled.hasBoundParams,
|
|
6299
6586
|
assembled.sourceError,
|
|
6300
|
-
schemaDefinition,
|
|
6301
6587
|
model,
|
|
6302
6588
|
adapter,
|
|
6303
6589
|
schemaName,
|
|
@@ -6313,19 +6599,17 @@ var NqlBuilderImpl = class {
|
|
|
6313
6599
|
params;
|
|
6314
6600
|
hasBoundParams;
|
|
6315
6601
|
sourceError;
|
|
6316
|
-
schemaDefinition;
|
|
6317
6602
|
model;
|
|
6318
6603
|
_schemaName;
|
|
6319
6604
|
adapter;
|
|
6320
6605
|
hookStore;
|
|
6321
6606
|
onHookError;
|
|
6322
6607
|
inTransaction;
|
|
6323
|
-
constructor(query, params, hasBoundParams, sourceError,
|
|
6608
|
+
constructor(query, params, hasBoundParams, sourceError, model, adapter, schemaName, hookStore, onHookError, inTransaction) {
|
|
6324
6609
|
this.query = query;
|
|
6325
6610
|
this.params = params;
|
|
6326
6611
|
this.hasBoundParams = hasBoundParams;
|
|
6327
6612
|
this.sourceError = sourceError;
|
|
6328
|
-
this.schemaDefinition = schemaDefinition;
|
|
6329
6613
|
this.model = model;
|
|
6330
6614
|
this.adapter = adapter;
|
|
6331
6615
|
this._schemaName = schemaName;
|
|
@@ -6347,7 +6631,7 @@ var NqlBuilderImpl = class {
|
|
|
6347
6631
|
};
|
|
6348
6632
|
const result = nqlCompile(
|
|
6349
6633
|
this.query,
|
|
6350
|
-
this.
|
|
6634
|
+
this.model,
|
|
6351
6635
|
void 0,
|
|
6352
6636
|
compilerOptions
|
|
6353
6637
|
);
|
|
@@ -6360,7 +6644,6 @@ var NqlBuilderImpl = class {
|
|
|
6360
6644
|
if (!bundle) {
|
|
6361
6645
|
throw new Error("NQL compilation failed: no query AST produced");
|
|
6362
6646
|
}
|
|
6363
|
-
assertNoMutationBindingBodies(bundle);
|
|
6364
6647
|
if (bundle.query) {
|
|
6365
6648
|
this._compiled = {
|
|
6366
6649
|
kind: "query",
|
|
@@ -6392,18 +6675,28 @@ var NqlBuilderImpl = class {
|
|
|
6392
6675
|
return plan(compiled.intent, this.model);
|
|
6393
6676
|
}
|
|
6394
6677
|
plan() {
|
|
6395
|
-
|
|
6678
|
+
const compiled = this.compile();
|
|
6679
|
+
if (compiled.kind === "mutation") {
|
|
6680
|
+
throw new Error(
|
|
6681
|
+
"NQL mutations do not have execution plans; use dump() for SQL and parameters."
|
|
6682
|
+
);
|
|
6683
|
+
}
|
|
6684
|
+
return isBindingFinalQuery(compiled.bundle) ? createBindingFinalPlan(compiled.intent) : this.planInternal();
|
|
6396
6685
|
}
|
|
6397
6686
|
dump(meta) {
|
|
6398
6687
|
const compiledIntent = this.compile();
|
|
6688
|
+
if (hasMutationBindingBodies(compiledIntent.bundle)) {
|
|
6689
|
+
return this.dumpNqlProgramSequence(compiledIntent, meta);
|
|
6690
|
+
}
|
|
6399
6691
|
if (compiledIntent.kind === "mutation") {
|
|
6400
6692
|
return this.dumpMutation(
|
|
6401
|
-
compiledIntent
|
|
6693
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
6402
6694
|
compiledIntent.intent,
|
|
6403
6695
|
meta
|
|
6404
6696
|
);
|
|
6405
6697
|
}
|
|
6406
|
-
const
|
|
6698
|
+
const bindingFinalQuery = isBindingFinalQuery(compiledIntent.bundle);
|
|
6699
|
+
const planReport = bindingFinalQuery ? createBindingFinalPlan(compiledIntent.intent) : this.planInternal();
|
|
6407
6700
|
if (!this.adapter) {
|
|
6408
6701
|
return {
|
|
6409
6702
|
plan: planReport,
|
|
@@ -6412,10 +6705,8 @@ var NqlBuilderImpl = class {
|
|
|
6412
6705
|
...meta !== void 0 && { meta }
|
|
6413
6706
|
};
|
|
6414
6707
|
}
|
|
6415
|
-
const
|
|
6416
|
-
|
|
6417
|
-
this.nqlBundleCompileOptions()
|
|
6418
|
-
) : this.adapter.compile(planReport);
|
|
6708
|
+
const finalBundle = this.createFinalNqlStatementBundle(compiledIntent);
|
|
6709
|
+
const compiled = bindingFinalQuery || hasNqlBindings(finalBundle) ? this.adapter.compile(finalBundle, this.nqlBundleCompileOptions()) : this.adapter.compile(planReport);
|
|
6419
6710
|
try {
|
|
6420
6711
|
return this.adapter.createDump(planReport, compiled, meta);
|
|
6421
6712
|
} catch (err) {
|
|
@@ -6466,6 +6757,268 @@ var NqlBuilderImpl = class {
|
|
|
6466
6757
|
...this._schemaName !== void 0 && { schemaName: this._schemaName }
|
|
6467
6758
|
};
|
|
6468
6759
|
}
|
|
6760
|
+
createNqlStatementBundle(statement, bindings, runtimeBindings, sourceBundle, bindingDependencies) {
|
|
6761
|
+
const statementBindings = filterMapByRuntimeBindingDependencies(
|
|
6762
|
+
bindings,
|
|
6763
|
+
sourceBundle.mutationBindings,
|
|
6764
|
+
bindingDependencies
|
|
6765
|
+
);
|
|
6766
|
+
const statementRuntimeBindings = filterMapByBindingDependencies(
|
|
6767
|
+
runtimeBindings,
|
|
6768
|
+
bindingDependencies
|
|
6769
|
+
);
|
|
6770
|
+
const emittedBindingNames = /* @__PURE__ */ new Set([
|
|
6771
|
+
...statementBindings.keys(),
|
|
6772
|
+
...statementRuntimeBindings.keys()
|
|
6773
|
+
]);
|
|
6774
|
+
const statementBindingOutputSchemas = filterOptionalMapByNames(
|
|
6775
|
+
sourceBundle.bindingOutputSchemas,
|
|
6776
|
+
emittedBindingNames
|
|
6777
|
+
);
|
|
6778
|
+
const statementMutationBindings = filterOptionalMapByBindingDependencies(
|
|
6779
|
+
sourceBundle.mutationBindings,
|
|
6780
|
+
bindingDependencies
|
|
6781
|
+
);
|
|
6782
|
+
return {
|
|
6783
|
+
...statement,
|
|
6784
|
+
...statementBindings.size > 0 && { bindings: statementBindings },
|
|
6785
|
+
...statementBindingOutputSchemas !== void 0 && {
|
|
6786
|
+
bindingOutputSchemas: statementBindingOutputSchemas
|
|
6787
|
+
},
|
|
6788
|
+
...statementMutationBindings !== void 0 && {
|
|
6789
|
+
mutationBindings: statementMutationBindings
|
|
6790
|
+
},
|
|
6791
|
+
...statementRuntimeBindings.size > 0 && {
|
|
6792
|
+
runtimeBindings: statementRuntimeBindings
|
|
6793
|
+
}
|
|
6794
|
+
};
|
|
6795
|
+
}
|
|
6796
|
+
createFinalNqlStatementBundle(compiledIntent) {
|
|
6797
|
+
const finalStep = createNqlProgramSteps(compiledIntent).at(-1);
|
|
6798
|
+
if (compiledIntent.kind === "query") {
|
|
6799
|
+
return this.createNqlStatementBundle(
|
|
6800
|
+
{ query: compiledIntent.intent },
|
|
6801
|
+
compiledIntent.bundle.bindings ?? /* @__PURE__ */ new Map(),
|
|
6802
|
+
compiledIntent.bundle.runtimeBindings ?? /* @__PURE__ */ new Map(),
|
|
6803
|
+
compiledIntent.bundle,
|
|
6804
|
+
finalStep?.bindingDependencies
|
|
6805
|
+
);
|
|
6806
|
+
}
|
|
6807
|
+
return this.createNqlStatementBundle(
|
|
6808
|
+
{ mutation: compiledIntent.intent },
|
|
6809
|
+
compiledIntent.bundle.bindings ?? /* @__PURE__ */ new Map(),
|
|
6810
|
+
compiledIntent.bundle.runtimeBindings ?? /* @__PURE__ */ new Map(),
|
|
6811
|
+
compiledIntent.bundle,
|
|
6812
|
+
finalStep?.bindingDependencies
|
|
6813
|
+
);
|
|
6814
|
+
}
|
|
6815
|
+
runMutationStatement(adapter, bundle, intent, inTransaction) {
|
|
6816
|
+
const hasReturning = (intent.returning?.length ?? 0) > 0;
|
|
6817
|
+
return runMutationWithHooks({
|
|
6818
|
+
table: intent.table,
|
|
6819
|
+
intent,
|
|
6820
|
+
hookStore: this.hookStore,
|
|
6821
|
+
onHookError: this.onHookError,
|
|
6822
|
+
schemaName: this._schemaName,
|
|
6823
|
+
inTransaction,
|
|
6824
|
+
prepare: () => {
|
|
6825
|
+
const compiled = adapter.compile(
|
|
6826
|
+
bundle,
|
|
6827
|
+
this.mutationCompileOptions()
|
|
6828
|
+
);
|
|
6829
|
+
return {
|
|
6830
|
+
sql: compiled.sql,
|
|
6831
|
+
parameters: compiled.parameters,
|
|
6832
|
+
execute: async () => {
|
|
6833
|
+
const hookRows = await adapter.execute(compiled);
|
|
6834
|
+
const rawRows = snapshotMutationRows(hookRows);
|
|
6835
|
+
return {
|
|
6836
|
+
rawRows,
|
|
6837
|
+
hookRows,
|
|
6838
|
+
transformedRows: hookRows
|
|
6839
|
+
};
|
|
6840
|
+
},
|
|
6841
|
+
getAfterMutationResult: (result) => hasReturning ? result.hookRows : [],
|
|
6842
|
+
mapAfterMutationResult: (result, transformedRows) => ({
|
|
6843
|
+
rawRows: result.rawRows,
|
|
6844
|
+
hookRows: result.hookRows,
|
|
6845
|
+
transformedRows: [...transformedRows]
|
|
6846
|
+
}),
|
|
6847
|
+
returnAfterMutationResult: hasReturning
|
|
6848
|
+
};
|
|
6849
|
+
}
|
|
6850
|
+
});
|
|
6851
|
+
}
|
|
6852
|
+
async executeNqlProgramSequence(compiledIntent, adapter) {
|
|
6853
|
+
if (!supportsTransactions(adapter)) {
|
|
6854
|
+
throw new ExecutionError({
|
|
6855
|
+
operation: "nql",
|
|
6856
|
+
reason: "NQL programs with mutation bindings require adapter transaction support",
|
|
6857
|
+
fix: "Use an adapter that implements transaction(fn), such as the PostgreSQL adapter."
|
|
6858
|
+
});
|
|
6859
|
+
}
|
|
6860
|
+
return adapter.transaction(async (txAdapter) => {
|
|
6861
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6862
|
+
const priorBindings = /* @__PURE__ */ new Map();
|
|
6863
|
+
const runtimeBindings = /* @__PURE__ */ new Map();
|
|
6864
|
+
const steps = createNqlProgramSteps(compiledIntent);
|
|
6865
|
+
let finalRows = [];
|
|
6866
|
+
for (const step of steps) {
|
|
6867
|
+
if (step.kind === "mutation") {
|
|
6868
|
+
if ((step.intent.returning?.length ?? 0) === 0 && step.bindName) {
|
|
6869
|
+
throw new Error(
|
|
6870
|
+
`NQL mutation binding '${step.bindName}' cannot execute without a RETURNING projection.`
|
|
6871
|
+
);
|
|
6872
|
+
}
|
|
6873
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6874
|
+
{ mutation: step.intent },
|
|
6875
|
+
priorBindings,
|
|
6876
|
+
runtimeBindings,
|
|
6877
|
+
sourceBundle,
|
|
6878
|
+
step.bindingDependencies
|
|
6879
|
+
);
|
|
6880
|
+
const rows = await this.runMutationStatement(
|
|
6881
|
+
txAdapter,
|
|
6882
|
+
statementBundle,
|
|
6883
|
+
step.intent,
|
|
6884
|
+
true
|
|
6885
|
+
);
|
|
6886
|
+
if (step.bindName) {
|
|
6887
|
+
runtimeBindings.set(
|
|
6888
|
+
step.bindName,
|
|
6889
|
+
createRuntimeBinding(
|
|
6890
|
+
sourceBundle,
|
|
6891
|
+
step.bindName,
|
|
6892
|
+
rows.rawRows,
|
|
6893
|
+
txAdapter.dbCasing
|
|
6894
|
+
)
|
|
6895
|
+
);
|
|
6896
|
+
}
|
|
6897
|
+
if (step.final) {
|
|
6898
|
+
finalRows = rows.transformedRows;
|
|
6899
|
+
}
|
|
6900
|
+
} else if (step.final) {
|
|
6901
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6902
|
+
{ query: step.intent },
|
|
6903
|
+
priorBindings,
|
|
6904
|
+
runtimeBindings,
|
|
6905
|
+
sourceBundle,
|
|
6906
|
+
step.bindingDependencies
|
|
6907
|
+
);
|
|
6908
|
+
const compiled = txAdapter.compile(
|
|
6909
|
+
statementBundle,
|
|
6910
|
+
this.nqlBundleCompileOptions()
|
|
6911
|
+
);
|
|
6912
|
+
finalRows = await txAdapter.execute(compiled);
|
|
6913
|
+
}
|
|
6914
|
+
if (step.bindName) {
|
|
6915
|
+
const boundQuery = sourceBundle.bindings?.get(step.bindName);
|
|
6916
|
+
if (boundQuery !== void 0) {
|
|
6917
|
+
priorBindings.set(step.bindName, boundQuery);
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6920
|
+
}
|
|
6921
|
+
return finalRows;
|
|
6922
|
+
});
|
|
6923
|
+
}
|
|
6924
|
+
dumpNqlProgramSequence(compiledIntent, meta) {
|
|
6925
|
+
const adapter = this.requireAdapter("dump");
|
|
6926
|
+
const sourceBundle = compiledIntent.bundle;
|
|
6927
|
+
const priorBindings = /* @__PURE__ */ new Map();
|
|
6928
|
+
const runtimeBindings = /* @__PURE__ */ new Map();
|
|
6929
|
+
const sequence = [];
|
|
6930
|
+
const steps = createNqlProgramSteps(compiledIntent);
|
|
6931
|
+
for (const step of steps) {
|
|
6932
|
+
if (step.kind === "mutation") {
|
|
6933
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6934
|
+
{ mutation: step.intent },
|
|
6935
|
+
priorBindings,
|
|
6936
|
+
runtimeBindings,
|
|
6937
|
+
sourceBundle,
|
|
6938
|
+
step.bindingDependencies
|
|
6939
|
+
);
|
|
6940
|
+
const compiled = adapter.compile(
|
|
6941
|
+
statementBundle,
|
|
6942
|
+
this.mutationCompileOptions()
|
|
6943
|
+
);
|
|
6944
|
+
sequence.push({
|
|
6945
|
+
kind: "mutation",
|
|
6946
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6947
|
+
sql: compiled.sql,
|
|
6948
|
+
params: compiled.parameters
|
|
6949
|
+
});
|
|
6950
|
+
if (step.bindName !== void 0) {
|
|
6951
|
+
runtimeBindings.set(step.bindName, {
|
|
6952
|
+
columns: requireMutationBindingColumns(sourceBundle, step.bindName),
|
|
6953
|
+
rows: []
|
|
6954
|
+
});
|
|
6955
|
+
}
|
|
6956
|
+
} else {
|
|
6957
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
6958
|
+
{ query: step.intent },
|
|
6959
|
+
priorBindings,
|
|
6960
|
+
runtimeBindings,
|
|
6961
|
+
sourceBundle,
|
|
6962
|
+
step.bindingDependencies
|
|
6963
|
+
);
|
|
6964
|
+
const compiled = adapter.compile(
|
|
6965
|
+
statementBundle,
|
|
6966
|
+
this.nqlBundleCompileOptions()
|
|
6967
|
+
);
|
|
6968
|
+
sequence.push({
|
|
6969
|
+
kind: "query",
|
|
6970
|
+
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6971
|
+
sql: compiled.sql,
|
|
6972
|
+
params: compiled.parameters
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6975
|
+
if (step.bindName !== void 0) {
|
|
6976
|
+
const boundQuery = sourceBundle.bindings?.get(step.bindName);
|
|
6977
|
+
if (boundQuery !== void 0) {
|
|
6978
|
+
priorBindings.set(step.bindName, boundQuery);
|
|
6979
|
+
}
|
|
6980
|
+
}
|
|
6981
|
+
}
|
|
6982
|
+
const finalStep = steps.at(-1);
|
|
6983
|
+
if (finalStep?.kind === "query") {
|
|
6984
|
+
const planReport = isBindingFinalQuery(compiledIntent.bundle) ? createBindingFinalPlan(finalStep.intent) : this.planInternal();
|
|
6985
|
+
const dumpMeta2 = {
|
|
6986
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
6987
|
+
...this._schemaName !== void 0 && { schema: this._schemaName },
|
|
6988
|
+
...meta?.queryName !== void 0 && { queryName: meta.queryName },
|
|
6989
|
+
...meta?.correlationId !== void 0 && {
|
|
6990
|
+
correlationId: meta.correlationId
|
|
6991
|
+
}
|
|
6992
|
+
};
|
|
6993
|
+
return {
|
|
6994
|
+
plan: planReport,
|
|
6995
|
+
sql: joinDumpSequenceSql(sequence),
|
|
6996
|
+
params: flattenDumpSequenceParams(sequence),
|
|
6997
|
+
meta: dumpMeta2,
|
|
6998
|
+
sequence
|
|
6999
|
+
};
|
|
7000
|
+
}
|
|
7001
|
+
if (finalStep?.kind !== "mutation") {
|
|
7002
|
+
throw new Error(
|
|
7003
|
+
"NQL program sequence did not contain a final statement."
|
|
7004
|
+
);
|
|
7005
|
+
}
|
|
7006
|
+
const dumpMeta = {
|
|
7007
|
+
compiledAt: /* @__PURE__ */ new Date(),
|
|
7008
|
+
...this._schemaName !== void 0 && { schema: this._schemaName },
|
|
7009
|
+
...meta?.queryName !== void 0 && { queryName: meta.queryName },
|
|
7010
|
+
...meta?.correlationId !== void 0 && {
|
|
7011
|
+
correlationId: meta.correlationId
|
|
7012
|
+
}
|
|
7013
|
+
};
|
|
7014
|
+
return {
|
|
7015
|
+
sql: joinDumpSequenceSql(sequence),
|
|
7016
|
+
parameters: flattenDumpSequenceParams(sequence),
|
|
7017
|
+
intent: finalStep.intent,
|
|
7018
|
+
meta: dumpMeta,
|
|
7019
|
+
sequence
|
|
7020
|
+
};
|
|
7021
|
+
}
|
|
6469
7022
|
dumpMutation(bundle, intent, meta) {
|
|
6470
7023
|
const adapter = this.requireAdapter("dump");
|
|
6471
7024
|
const compiled = adapter.compile(bundle, this.mutationCompileOptions(meta));
|
|
@@ -6492,35 +7045,27 @@ var NqlBuilderImpl = class {
|
|
|
6492
7045
|
);
|
|
6493
7046
|
}
|
|
6494
7047
|
const compiledIntent = this.compile();
|
|
7048
|
+
if (hasMutationBindingBodies(compiledIntent.bundle)) {
|
|
7049
|
+
return this.executeNqlProgramSequence(compiledIntent, adapter);
|
|
7050
|
+
}
|
|
6495
7051
|
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
|
-
});
|
|
7052
|
+
return (await this.runMutationStatement(
|
|
7053
|
+
adapter,
|
|
7054
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
7055
|
+
compiledIntent.intent,
|
|
7056
|
+
this.inTransaction
|
|
7057
|
+
)).transformedRows;
|
|
7058
|
+
}
|
|
7059
|
+
if (isBindingFinalQuery(compiledIntent.bundle)) {
|
|
7060
|
+
const compiled2 = adapter.compile(
|
|
7061
|
+
this.createFinalNqlStatementBundle(compiledIntent),
|
|
7062
|
+
this.nqlBundleCompileOptions()
|
|
7063
|
+
);
|
|
7064
|
+
return adapter.execute(compiled2);
|
|
6518
7065
|
}
|
|
6519
7066
|
const planReport = this.planInternal();
|
|
6520
|
-
const
|
|
6521
|
-
|
|
6522
|
-
this.nqlBundleCompileOptions()
|
|
6523
|
-
) : adapter.compile(planReport);
|
|
7067
|
+
const finalBundle = this.createFinalNqlStatementBundle(compiledIntent);
|
|
7068
|
+
const compiled = hasNqlBindings(finalBundle) ? adapter.compile(finalBundle, this.nqlBundleCompileOptions()) : adapter.compile(planReport);
|
|
6524
7069
|
return adapter.execute(compiled);
|
|
6525
7070
|
}
|
|
6526
7071
|
async run() {
|
|
@@ -10422,6 +10967,8 @@ var POSTGRESQL_CAPABILITIES = {
|
|
|
10422
10967
|
supportsJsonType: true,
|
|
10423
10968
|
supportsJsonOperators: true,
|
|
10424
10969
|
// PG: ->, ->>, @>, <@, ?, #>, #>>
|
|
10970
|
+
supportsRowLevelLocks: true,
|
|
10971
|
+
supportsLockWaitPolicies: true,
|
|
10425
10972
|
supportsSchemas: true,
|
|
10426
10973
|
// Include Strategy Capabilities (CORE-006)
|
|
10427
10974
|
supportsLateralJoin: true,
|
|
@@ -10466,6 +11013,9 @@ var MYSQL_CAPABILITIES = {
|
|
|
10466
11013
|
supportsJsonType: true,
|
|
10467
11014
|
supportsJsonOperators: false,
|
|
10468
11015
|
// MySQL uses JSON_EXTRACT() functions, not operators
|
|
11016
|
+
// Coarse PostgreSQL-shaped lock flags; revisit MySQL with per-strength caps.
|
|
11017
|
+
supportsRowLevelLocks: false,
|
|
11018
|
+
supportsLockWaitPolicies: false,
|
|
10469
11019
|
supportsSchemas: true,
|
|
10470
11020
|
// MySQL uses database as schema
|
|
10471
11021
|
// Include Strategy Capabilities (CORE-006)
|
|
@@ -10496,6 +11046,8 @@ var SQLITE_CAPABILITIES = {
|
|
|
10496
11046
|
// SQLite 3.38+ (JSON1 extension)
|
|
10497
11047
|
supportsJsonOperators: false,
|
|
10498
11048
|
// SQLite uses json_extract() functions
|
|
11049
|
+
supportsRowLevelLocks: false,
|
|
11050
|
+
supportsLockWaitPolicies: false,
|
|
10499
11051
|
supportsSchemas: false,
|
|
10500
11052
|
// SQLite uses ATTACH for multiple databases
|
|
10501
11053
|
// Include Strategy Capabilities (CORE-006)
|
|
@@ -10524,6 +11076,8 @@ var DUCKDB_CAPABILITIES = {
|
|
|
10524
11076
|
supportsJsonType: true,
|
|
10525
11077
|
supportsJsonOperators: false,
|
|
10526
11078
|
// DuckDB uses json_extract() style
|
|
11079
|
+
supportsRowLevelLocks: false,
|
|
11080
|
+
supportsLockWaitPolicies: false,
|
|
10527
11081
|
supportsSchemas: true,
|
|
10528
11082
|
// Include Strategy Capabilities (CORE-006)
|
|
10529
11083
|
supportsLateralJoin: true,
|
|
@@ -10553,6 +11107,9 @@ var MSSQL_CAPABILITIES = {
|
|
|
10553
11107
|
// SQL Server 2016+
|
|
10554
11108
|
supportsJsonOperators: false,
|
|
10555
11109
|
// MSSQL uses JSON_VALUE/JSON_QUERY functions
|
|
11110
|
+
// Coarse PostgreSQL-shaped lock flags; revisit MSSQL hints with per-strength caps.
|
|
11111
|
+
supportsRowLevelLocks: false,
|
|
11112
|
+
supportsLockWaitPolicies: false,
|
|
10556
11113
|
supportsSchemas: true,
|
|
10557
11114
|
// Include Strategy Capabilities (CORE-006)
|
|
10558
11115
|
supportsLateralJoin: true,
|
|
@@ -10610,6 +11167,8 @@ function createDialectCapabilities(overrides, options) {
|
|
|
10610
11167
|
supportsRangeTypes: false,
|
|
10611
11168
|
supportsJsonType: false,
|
|
10612
11169
|
supportsJsonOperators: false,
|
|
11170
|
+
supportsRowLevelLocks: false,
|
|
11171
|
+
supportsLockWaitPolicies: false,
|
|
10613
11172
|
supportsSchemas: false,
|
|
10614
11173
|
supportsLateralJoin: false,
|
|
10615
11174
|
supportsJsonAgg: false,
|