@dbsp/nql 1.8.0 → 1.8.1

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.js CHANGED
@@ -1176,6 +1176,7 @@ function assignMutationValue(target, column, value, ctx) {
1176
1176
  function compileMutationPipeline(pipeline, ctx, fns, bindings) {
1177
1177
  ctx.currentFromTable = pipeline.mutation.table;
1178
1178
  const mutation = compileMutation(pipeline.mutation, ctx, fns, bindings);
1179
+ ctx.currentFromTable = pipeline.mutation.table;
1179
1180
  let returning;
1180
1181
  let returningItems;
1181
1182
  for (const clause of pipeline.clauses) {
@@ -1186,8 +1187,18 @@ function compileMutationPipeline(pipeline, ctx, fns, bindings) {
1186
1187
  }
1187
1188
  ctx.lastMutationReturningItems = returningItems;
1188
1189
  if (returning) {
1190
+ const aliasAwareReturningItems = returningItems !== void 0 && returningItems !== "star" && returningItems.some((item) => item.aliased) ? returningItems.map((item) => ({
1191
+ source: item.source,
1192
+ output: item.output
1193
+ })) : void 0;
1189
1194
  return {
1190
- mutation: { ...mutation, returning }
1195
+ mutation: {
1196
+ ...mutation,
1197
+ returning,
1198
+ ...aliasAwareReturningItems !== void 0 && {
1199
+ returningItems: aliasAwareReturningItems
1200
+ }
1201
+ }
1191
1202
  };
1192
1203
  }
1193
1204
  return { mutation };
@@ -1374,19 +1385,42 @@ function compileUpsertFrom(upsertFrom, ctx, fns, bindings) {
1374
1385
  }
1375
1386
  function extractReturningItems(clause, ctx) {
1376
1387
  const items = [];
1388
+ const outputs = /* @__PURE__ */ new Set();
1377
1389
  for (const item of clause.items) {
1378
1390
  if (item.type === "star") {
1391
+ if (clause.items.length > 1) {
1392
+ throw new NqlSemanticException(
1393
+ NqlErrorCodes.SEM_INVALID_SYNTAX,
1394
+ "Mutation RETURNING cannot mix `select *` with explicit projection items."
1395
+ );
1396
+ }
1379
1397
  return "star";
1380
1398
  }
1381
1399
  if (item.type === "expression") {
1382
1400
  const field = expressionToField(item.expression);
1383
1401
  if (field) {
1402
+ const aliased = item.alias !== void 0;
1403
+ if (aliased && field.includes(".")) {
1404
+ throw new NqlSemanticException(
1405
+ NqlErrorCodes.SEM_INVALID_SYNTAX,
1406
+ `Mutation RETURNING alias cannot use dotted source '${field}'.`
1407
+ );
1408
+ }
1384
1409
  if (ctx.currentFromTable && !field.includes(".")) {
1385
1410
  ctx.validator?.validateColumn(ctx.currentFromTable, field);
1386
1411
  }
1412
+ const output = item.alias ?? field;
1413
+ if (outputs.has(output)) {
1414
+ throw new NqlSemanticException(
1415
+ NqlErrorCodes.SEM_INVALID_SYNTAX,
1416
+ `Mutation RETURNING has duplicate output name '${output}'.`
1417
+ );
1418
+ }
1419
+ outputs.add(output);
1387
1420
  items.push({
1388
- output: item.alias ?? field,
1389
- aliased: item.alias !== void 0
1421
+ source: field,
1422
+ output,
1423
+ aliased
1390
1424
  });
1391
1425
  }
1392
1426
  }
@@ -4243,6 +4277,9 @@ function programSequenceStepFromResult(result, bindName, final, bindingDependenc
4243
4277
  function stringArraysEqual(left, right) {
4244
4278
  return left.length === right.length && left.every((value, index) => value === right[index]);
4245
4279
  }
4280
+ function mutationReturningItemsMatchReturning(returning, returningItems) {
4281
+ return returningItems.length === returning.length && returningItems.every((item, index) => item.output === returning[index]);
4282
+ }
4246
4283
  function isNqlAstRecord(value) {
4247
4284
  return typeof value === "object" && value !== null;
4248
4285
  }
@@ -4733,7 +4770,50 @@ var NqlCompiler = class {
4733
4770
  mutation
4734
4771
  );
4735
4772
  const returning = mutation.returning;
4736
- if (returning === void 0 || returning.length === 0 || returning.includes("*") || outputSchema === void 0 || stringArraysEqual(returning, outputSchema.columns)) {
4773
+ const returningItems = mutation.returningItems;
4774
+ if (returning === void 0 || returning.length === 0 || returning.includes("*") || outputSchema === void 0) {
4775
+ return { mutation, outputSchema };
4776
+ }
4777
+ const seenOutputs = /* @__PURE__ */ new Set();
4778
+ for (const column of outputSchema.columns) {
4779
+ if (seenOutputs.has(column)) {
4780
+ throw new NqlSemanticException(
4781
+ NqlErrorCodes.SEM_INVALID_SYNTAX,
4782
+ `Mutation RETURNING resolves to duplicate output name '${column}' after column canonicalization for binding '${bindName}'.`
4783
+ );
4784
+ }
4785
+ seenOutputs.add(column);
4786
+ }
4787
+ if (returningItems !== void 0) {
4788
+ const internalItems = this.ctx.lastMutationReturningItems !== void 0 && this.ctx.lastMutationReturningItems !== "star" ? this.ctx.lastMutationReturningItems : void 0;
4789
+ const canonicalItems = returningItems.map((item, index) => {
4790
+ const source = this.ctx.validator?.resolveColumnName(mutation.table, item.source) ?? item.source;
4791
+ const internalItem = internalItems?.[index];
4792
+ const output = internalItem?.aliased ? item.output : source;
4793
+ return source === item.source && output === item.output ? item : { source, output };
4794
+ });
4795
+ if (!mutationReturningItemsMatchReturning(
4796
+ outputSchema.columns,
4797
+ canonicalItems
4798
+ )) {
4799
+ throw new NqlSemanticException(
4800
+ NqlErrorCodes.SEM_INVALID_SYNTAX,
4801
+ `Mutation RETURNING item outputs drifted during canonicalization for binding '${bindName}'.`
4802
+ );
4803
+ }
4804
+ if (stringArraysEqual(returning, outputSchema.columns) && canonicalItems.every((item, index) => item === returningItems[index])) {
4805
+ return { mutation, outputSchema };
4806
+ }
4807
+ return {
4808
+ mutation: {
4809
+ ...mutation,
4810
+ returning: outputSchema.columns,
4811
+ returningItems: canonicalItems
4812
+ },
4813
+ outputSchema
4814
+ };
4815
+ }
4816
+ if (stringArraysEqual(returning, outputSchema.columns)) {
4737
4817
  return { mutation, outputSchema };
4738
4818
  }
4739
4819
  return {
@@ -4764,6 +4844,18 @@ var NqlCompiler = class {
4764
4844
  const columns = returning.map(
4765
4845
  (column) => this.ctx.validator?.resolveColumnName(mutation.table, column) ?? column
4766
4846
  );
4847
+ const returningItems = mutation.returningItems;
4848
+ if (returningItems !== void 0) {
4849
+ const internalItems = this.ctx.lastMutationReturningItems !== void 0 && this.ctx.lastMutationReturningItems !== "star" ? this.ctx.lastMutationReturningItems : void 0;
4850
+ const columns2 = returningItems.map((item, index) => {
4851
+ const source = this.ctx.validator?.resolveColumnName(mutation.table, item.source) ?? item.source;
4852
+ return internalItems?.[index]?.aliased ? item.output : source;
4853
+ });
4854
+ return {
4855
+ columns: columns2,
4856
+ ...this.buildMutationReturningColumnTypes(mutation.table, columns2)
4857
+ };
4858
+ }
4767
4859
  return {
4768
4860
  columns,
4769
4861
  ...this.buildMutationReturningColumnTypes(mutation.table, columns)