@dbsp/adapter-pgsql 1.3.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.js CHANGED
@@ -949,6 +949,42 @@ var init_ast_helpers = __esm({
949
949
  }
950
950
  });
951
951
 
952
+ // src/binding-registry.ts
953
+ function emittedBindName(name, naming) {
954
+ return naming.toDatabase(name);
955
+ }
956
+ function hasBindingName(bindingNames, name, naming) {
957
+ return bindingNames?.has(emittedBindName(name, naming)) ?? false;
958
+ }
959
+ function schemaForFromName(schemaName, fromName, bindingNames, naming) {
960
+ return hasBindingName(bindingNames, fromName, naming) ? void 0 : schemaName;
961
+ }
962
+ function withBindingName(bindingNames, name, naming) {
963
+ const next = new Set(bindingNames ?? []);
964
+ next.add(emittedBindName(name, naming));
965
+ return next;
966
+ }
967
+ var init_binding_registry = __esm({
968
+ "src/binding-registry.ts"() {
969
+ "use strict";
970
+ }
971
+ });
972
+
973
+ // src/dialect-capabilities.ts
974
+ function supportsDialectCapability(capabilities, flag) {
975
+ return capabilities?.[flag] !== false;
976
+ }
977
+ function assertDialectCapability(capabilities, flag, feature) {
978
+ if (!supportsDialectCapability(capabilities, flag)) {
979
+ throw new Error(`${feature} not supported by this adapter`);
980
+ }
981
+ }
982
+ var init_dialect_capabilities = __esm({
983
+ "src/dialect-capabilities.ts"() {
984
+ "use strict";
985
+ }
986
+ });
987
+
952
988
  // src/param-ref.ts
953
989
  function validateParamRef(paramRef) {
954
990
  const errors = [];
@@ -2813,6 +2849,7 @@ var init_param_intent = __esm({
2813
2849
  });
2814
2850
 
2815
2851
  // src/handlers/where/utils.ts
2852
+ import { validateTypeName as validateTypeName3 } from "@dbsp/core";
2816
2853
  import { isFieldRef, isParamIntent as isParamIntent3 } from "@dbsp/types";
2817
2854
  function buildColumnRef(column, ctx) {
2818
2855
  if (column.includes(".")) {
@@ -2874,7 +2911,11 @@ function resolveColumnPgType(columnName, ctx) {
2874
2911
  if (!table) return void 0;
2875
2912
  const column = table.columns.find((c) => c.name === columnName);
2876
2913
  if (!column) return void 0;
2877
- if (column.originalDbType) return validateDbTypeName(column.originalDbType);
2914
+ if (column.originalDbType) {
2915
+ const typeName = column.originalDbType.trim();
2916
+ validateTypeName3(typeName);
2917
+ return typeName;
2918
+ }
2878
2919
  return void 0;
2879
2920
  }
2880
2921
  var init_utils = __esm({
@@ -2883,7 +2924,6 @@ var init_utils = __esm({
2883
2924
  init_ast_helpers();
2884
2925
  init_param_intent();
2885
2926
  init_param_ref();
2886
- init_validate();
2887
2927
  init_types();
2888
2928
  init_param_intent();
2889
2929
  }
@@ -2915,6 +2955,7 @@ var init_any = __esm({
2915
2955
  "src/handlers/where/any.ts"() {
2916
2956
  "use strict";
2917
2957
  init_compiler_utils();
2958
+ init_dialect_capabilities();
2918
2959
  init_param_intent();
2919
2960
  init_param_ref();
2920
2961
  init_types();
@@ -2922,6 +2963,11 @@ var init_any = __esm({
2922
2963
  anyHandler = {
2923
2964
  operators: [COLLECTION_OPERATORS.ANY],
2924
2965
  compile(decision, ctx, state) {
2966
+ assertDialectCapability(
2967
+ ctx.dialectCapabilities,
2968
+ "supportsArrayType",
2969
+ "ANY array operator is"
2970
+ );
2925
2971
  const column = decision.column;
2926
2972
  if (!column) {
2927
2973
  throw new Error("ANY handler requires a column");
@@ -3117,6 +3163,9 @@ function buildCorrelation(sourceAlias, sourceColumn, targetAlias, targetColumn,
3117
3163
  const right = columnRef(targetColumn, targetAlias, void 0, ctx.naming);
3118
3164
  return eqExpr(left, right);
3119
3165
  }
3166
+ function schemaForExistsFromName(ctx, fromName) {
3167
+ return schemaForFromName(ctx.schema, fromName, ctx.bindingNames, ctx.naming);
3168
+ }
3120
3169
  function buildExistsSubquery(decision, ctx, state, dispatch) {
3121
3170
  const relation = decision.relation;
3122
3171
  const targetTable = decision.targetTable ?? relation;
@@ -3160,7 +3209,7 @@ function buildExistsSubquery(decision, ctx, state, dispatch) {
3160
3209
  let fromNode = rangeVar(
3161
3210
  targetTable,
3162
3211
  targetAlias,
3163
- ctx.schema,
3212
+ schemaForExistsFromName(ctx, targetTable),
3164
3213
  ctx.naming
3165
3214
  );
3166
3215
  const includeDecisions = decision.include;
@@ -3219,7 +3268,7 @@ function buildExistsSubquery(decision, ctx, state, dispatch) {
3219
3268
  const joinRangeVar = rangeVar(
3220
3269
  joinTargetTable,
3221
3270
  joinAlias,
3222
- ctx.schema,
3271
+ schemaForExistsFromName(ctx, joinTargetTable),
3223
3272
  ctx.naming
3224
3273
  );
3225
3274
  fromNode = joinExpr(joinType, fromNode, joinRangeVar, joinQuals);
@@ -3245,6 +3294,7 @@ var init_exists = __esm({
3245
3294
  "use strict";
3246
3295
  init_assert_field();
3247
3296
  init_ast_helpers();
3297
+ init_binding_registry();
3248
3298
  existsHandler = {
3249
3299
  operators: ["exists", "some"],
3250
3300
  compile(decision, ctx, state, dispatch) {
@@ -3315,6 +3365,21 @@ function createNotInExpr(columnNode, state, values, columnType) {
3315
3365
  }
3316
3366
  };
3317
3367
  }
3368
+ function createLiteralInListExpr(columnNode, state, values, negated) {
3369
+ const paramRefs = values.map((value) => {
3370
+ state.paramIndex++;
3371
+ state.parameters.push(value);
3372
+ return createParamRef(state.paramIndex);
3373
+ });
3374
+ return {
3375
+ A_Expr: {
3376
+ kind: "AEXPR_IN",
3377
+ name: [{ String: { sval: negated ? "<>" : "=" } }],
3378
+ lexpr: columnNode,
3379
+ rexpr: { List: { items: paramRefs } }
3380
+ }
3381
+ };
3382
+ }
3318
3383
  function isWholeArrayParamList(value) {
3319
3384
  return value.length === 1 && isParamIntent4(value[0]) && Array.isArray(value[0].value);
3320
3385
  }
@@ -3330,6 +3395,7 @@ var init_in = __esm({
3330
3395
  "src/handlers/where/in.ts"() {
3331
3396
  "use strict";
3332
3397
  init_ast_helpers();
3398
+ init_dialect_capabilities();
3333
3399
  init_param_intent();
3334
3400
  init_param_ref();
3335
3401
  init_types();
@@ -3358,7 +3424,11 @@ var init_in = __esm({
3358
3424
  }
3359
3425
  const columnNode = buildColumnRef(column, ctx);
3360
3426
  const columnType = resolveColumnPgType(column, ctx);
3361
- if (operator === COLLECTION_OPERATORS.NOT_IN || operator === "notIn") {
3427
+ const isNotIn = operator === COLLECTION_OPERATORS.NOT_IN || operator === "notIn";
3428
+ if (!supportsDialectCapability(ctx.dialectCapabilities, "supportsArrayType")) {
3429
+ return createLiteralInListExpr(columnNode, state, values, isNotIn);
3430
+ }
3431
+ if (isNotIn) {
3362
3432
  return createNotInExpr(columnNode, state, values, columnType);
3363
3433
  }
3364
3434
  return createInExpr(columnNode, state, values, columnType);
@@ -3372,10 +3442,16 @@ var jsonContainsHandler, jsonExistsHandler, jsonComparisonHandler;
3372
3442
  var init_json = __esm({
3373
3443
  "src/handlers/where/json.ts"() {
3374
3444
  "use strict";
3445
+ init_dialect_capabilities();
3375
3446
  init_utils();
3376
3447
  jsonContainsHandler = {
3377
3448
  operators: ["jsonContains", "jsonContainedBy"],
3378
3449
  compile(decision, ctx, state) {
3450
+ assertDialectCapability(
3451
+ ctx.dialectCapabilities,
3452
+ "supportsJsonOperators",
3453
+ "JSON operators are"
3454
+ );
3379
3455
  const column = decision.column;
3380
3456
  if (!column) {
3381
3457
  throw new Error("JSON contains handler requires a column");
@@ -3396,6 +3472,11 @@ var init_json = __esm({
3396
3472
  jsonExistsHandler = {
3397
3473
  operators: ["jsonExists"],
3398
3474
  compile(decision, ctx, state) {
3475
+ assertDialectCapability(
3476
+ ctx.dialectCapabilities,
3477
+ "supportsJsonOperators",
3478
+ "JSON operators are"
3479
+ );
3399
3480
  const column = decision.column;
3400
3481
  if (!column) {
3401
3482
  throw new Error("JSON exists handler requires a column");
@@ -3415,6 +3496,11 @@ var init_json = __esm({
3415
3496
  jsonComparisonHandler = {
3416
3497
  operators: ["jsonComparison"],
3417
3498
  compile(decision, ctx, state) {
3499
+ assertDialectCapability(
3500
+ ctx.dialectCapabilities,
3501
+ "supportsJsonOperators",
3502
+ "JSON operators are"
3503
+ );
3418
3504
  const column = decision.column;
3419
3505
  if (!column) {
3420
3506
  throw new Error("JSON comparison handler requires a column");
@@ -3592,6 +3678,7 @@ var RANGE_OP_MAP, rangeHandler;
3592
3678
  var init_range = __esm({
3593
3679
  "src/handlers/where/range.ts"() {
3594
3680
  "use strict";
3681
+ init_dialect_capabilities();
3595
3682
  init_param_intent();
3596
3683
  init_param_ref();
3597
3684
  init_types();
@@ -3604,6 +3691,11 @@ var init_range = __esm({
3604
3691
  rangeHandler = {
3605
3692
  operators: ["contains", "containedBy", "overlaps"],
3606
3693
  compile(decision, ctx, state) {
3694
+ assertDialectCapability(
3695
+ ctx.dialectCapabilities,
3696
+ "supportsRangeTypes",
3697
+ "Range operators are"
3698
+ );
3607
3699
  const column = decision.column;
3608
3700
  if (!column) {
3609
3701
  throw new Error("Range handler requires a column");
@@ -3651,27 +3743,6 @@ var init_range = __esm({
3651
3743
  }
3652
3744
  });
3653
3745
 
3654
- // src/binding-registry.ts
3655
- function emittedBindName(name, naming) {
3656
- return naming.toDatabase(name);
3657
- }
3658
- function hasBindingName(bindingNames, name, naming) {
3659
- return bindingNames?.has(emittedBindName(name, naming)) ?? false;
3660
- }
3661
- function schemaForFromName(schemaName, fromName, bindingNames, naming) {
3662
- return hasBindingName(bindingNames, fromName, naming) ? void 0 : schemaName;
3663
- }
3664
- function withBindingName(bindingNames, name, naming) {
3665
- const next = new Set(bindingNames ?? []);
3666
- next.add(emittedBindName(name, naming));
3667
- return next;
3668
- }
3669
- var init_binding_registry = __esm({
3670
- "src/binding-registry.ts"() {
3671
- "use strict";
3672
- }
3673
- });
3674
-
3675
3746
  // src/compile-where.ts
3676
3747
  function toHandlerContext(ctx) {
3677
3748
  return {
@@ -3680,12 +3751,15 @@ function toHandlerContext(ctx) {
3680
3751
  currentAlias: ctx.currentAlias ?? ctx.rootTable,
3681
3752
  maxRecursiveDepth: 100,
3682
3753
  ...ctx.schemaName !== void 0 && { schema: ctx.schemaName },
3754
+ ...ctx.dialectCapabilities !== void 0 && {
3755
+ dialectCapabilities: ctx.dialectCapabilities
3756
+ },
3683
3757
  ...ctx.bindingNames !== void 0 && { bindingNames: ctx.bindingNames },
3684
3758
  ...ctx.model !== void 0 && { model: ctx.model },
3685
3759
  ...ctx.outerTable !== void 0 && { outerAlias: ctx.outerTable }
3686
3760
  };
3687
3761
  }
3688
- function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, schemaName, use = "rawExists", bindingNames) {
3762
+ function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, schemaName, use = "rawExists", bindingNames, dialectCapabilities) {
3689
3763
  assertNoUnsupportedSubqueryModifiers(intent, use);
3690
3764
  if (intent.where && containsOuterRef(intent.where)) {
3691
3765
  throw new Error(
@@ -3751,6 +3825,8 @@ function buildSubqueryFromIntent(intent, paramOffset, naming = identityNaming, s
3751
3825
  aliases: /* @__PURE__ */ new Map(),
3752
3826
  paramState: innerState,
3753
3827
  naming,
3828
+ ...schemaName !== void 0 && { schemaName },
3829
+ ...dialectCapabilities !== void 0 && { dialectCapabilities },
3754
3830
  ...bindingNames !== void 0 && { bindingNames },
3755
3831
  compileSubquery: (_nestedIntent, _nestedOffset) => {
3756
3832
  throw new Error(
@@ -4175,7 +4251,8 @@ var init_raw_exists = __esm({
4175
4251
  ctx.naming,
4176
4252
  ctx.schema,
4177
4253
  "rawExists",
4178
- ctx.bindingNames
4254
+ ctx.bindingNames,
4255
+ ctx.dialectCapabilities
4179
4256
  );
4180
4257
  if (innerParams) {
4181
4258
  for (const p of innerParams) {
@@ -5984,11 +6061,17 @@ var init_json2 = __esm({
5984
6061
  "src/handlers/expression/json.ts"() {
5985
6062
  "use strict";
5986
6063
  init_ast_helpers();
6064
+ init_dialect_capabilities();
5987
6065
  init_param_intent();
5988
6066
  init_utils();
5989
6067
  jsonExtractHandler = {
5990
6068
  types: ["jsonExtract"],
5991
6069
  compile(decision, ctx, state) {
6070
+ assertDialectCapability(
6071
+ ctx.dialectCapabilities,
6072
+ "supportsJsonOperators",
6073
+ "JSON operators are"
6074
+ );
5992
6075
  const column = decision.column;
5993
6076
  if (!column) {
5994
6077
  throw new Error("JSON extract handler requires a column");
@@ -6016,6 +6099,11 @@ var init_json2 = __esm({
6016
6099
  jsonPathExtractHandler = {
6017
6100
  types: ["jsonPathExtract"],
6018
6101
  compile(decision, ctx, state) {
6102
+ assertDialectCapability(
6103
+ ctx.dialectCapabilities,
6104
+ "supportsJsonOperators",
6105
+ "JSON operators are"
6106
+ );
6019
6107
  const column = decision.column;
6020
6108
  if (!column) {
6021
6109
  throw new Error("JSON path extract handler requires a column");
@@ -7087,6 +7175,7 @@ init_ast_helpers();
7087
7175
  // src/compiler.ts
7088
7176
  init_assert_field();
7089
7177
  init_ast_helpers();
7178
+ init_binding_registry();
7090
7179
  import { InvalidOperationError as InvalidOperationError2 } from "@dbsp/core";
7091
7180
  import {
7092
7181
  isParamIntent as isParamIntent6,
@@ -8148,6 +8237,7 @@ function deparseQuoted(ast) {
8148
8237
  }
8149
8238
 
8150
8239
  // src/compiler.ts
8240
+ init_dialect_capabilities();
8151
8241
  init_case_value();
8152
8242
  init_custom();
8153
8243
  init_expression();
@@ -8380,6 +8470,7 @@ var PlanCompiler = class _PlanCompiler {
8380
8470
  defaultPk;
8381
8471
  deriveFk;
8382
8472
  model;
8473
+ dialectCapabilities;
8383
8474
  bindingNames;
8384
8475
  /** Mutable state shared with extracted condition/value compilation functions */
8385
8476
  state = {
@@ -8415,8 +8506,25 @@ var PlanCompiler = class _PlanCompiler {
8415
8506
  this.defaultPk = options.defaultPkColumnName ?? DEFAULT_PK_COLUMN;
8416
8507
  this.deriveFk = options.deriveFkColumnName ?? defaultFkDerivation;
8417
8508
  this.model = options.model ?? void 0;
8509
+ this.dialectCapabilities = options.dialectCapabilities;
8418
8510
  this.bindingNames = options.bindingNames;
8419
8511
  }
8512
+ childCompilerOptions(overrides = {}) {
8513
+ return {
8514
+ naming: this.naming,
8515
+ ...this.schema !== void 0 && { schema: this.schema },
8516
+ defaultPkColumnName: this.defaultPk,
8517
+ deriveFkColumnName: this.deriveFk,
8518
+ ...this.model !== void 0 && { model: this.model },
8519
+ ...this.dialectCapabilities !== void 0 && {
8520
+ dialectCapabilities: this.dialectCapabilities
8521
+ },
8522
+ ...this.bindingNames !== void 0 && {
8523
+ bindingNames: this.bindingNames
8524
+ },
8525
+ ...overrides
8526
+ };
8527
+ }
8420
8528
  /** Build immutable context for handler-based WHERE compilation */
8421
8529
  handlerCtx() {
8422
8530
  return {
@@ -8427,6 +8535,9 @@ var PlanCompiler = class _PlanCompiler {
8427
8535
  defaultPkColumnName: this.defaultPk,
8428
8536
  deriveFkColumnName: this.deriveFk,
8429
8537
  ...this.schema != null && { schema: this.schema },
8538
+ ...this.dialectCapabilities != null && {
8539
+ dialectCapabilities: this.dialectCapabilities
8540
+ },
8430
8541
  ...this.bindingNames != null && { bindingNames: this.bindingNames },
8431
8542
  ...this.model != null && { model: this.model }
8432
8543
  };
@@ -8737,6 +8848,9 @@ var PlanCompiler = class _PlanCompiler {
8737
8848
  defaultPkColumnName: this.defaultPk,
8738
8849
  deriveFkColumnName: this.deriveFk,
8739
8850
  ...plan.schema ?? this.schema ? { schema: plan.schema ?? this.schema } : {},
8851
+ ...this.dialectCapabilities != null && {
8852
+ dialectCapabilities: this.dialectCapabilities
8853
+ },
8740
8854
  ...this.bindingNames != null && { bindingNames: this.bindingNames },
8741
8855
  ...this.model != null && { model: this.model },
8742
8856
  compileSubquery: (query, paramOffset) => this.compileExpressionSubquery(query, paramOffset),
@@ -8753,18 +8867,16 @@ var PlanCompiler = class _PlanCompiler {
8753
8867
  joins: []
8754
8868
  };
8755
8869
  }
8870
+ schemaForRangeVar(plan, table) {
8871
+ return schemaForFromName(
8872
+ plan.schema ?? this.schema,
8873
+ table,
8874
+ this.bindingNames,
8875
+ this.naming
8876
+ );
8877
+ }
8756
8878
  compileExpressionSubquery(query, paramOffset) {
8757
- const innerCompiler = new _PlanCompiler({
8758
- naming: this.naming,
8759
- ...this.schema !== void 0 && {
8760
- schema: this.schema
8761
- },
8762
- defaultPkColumnName: this.defaultPk,
8763
- deriveFkColumnName: this.deriveFk,
8764
- ...this.bindingNames !== void 0 && {
8765
- bindingNames: this.bindingNames
8766
- }
8767
- });
8879
+ const innerCompiler = new _PlanCompiler(this.childCompilerOptions());
8768
8880
  const innerPlan = {
8769
8881
  rootTable: query.from,
8770
8882
  decisions: intentToDecisions(query, query.from)
@@ -9104,24 +9216,7 @@ var PlanCompiler = class _PlanCompiler {
9104
9216
  const ctx = {
9105
9217
  ...this.createHandlerContext(plan, plan.rootTable),
9106
9218
  compileSubquery(query, paramOffset) {
9107
- const innerCompiler = new _PlanCompiler({
9108
- naming: outerThis.naming,
9109
- ...outerThis.schema !== void 0 && {
9110
- schema: outerThis.schema
9111
- },
9112
- defaultPkColumnName: outerThis.defaultPk,
9113
- deriveFkColumnName: outerThis.deriveFk
9114
- });
9115
- const innerPlan = {
9116
- rootTable: query.from,
9117
- decisions: intentToDecisions(query, query.from)
9118
- };
9119
- const innerResult = innerCompiler.compile(innerPlan);
9120
- const renumbered = renumberParamRefsInAst(
9121
- innerResult.ast,
9122
- paramOffset
9123
- );
9124
- return { ast: renumbered, parameters: innerResult.parameters };
9219
+ return outerThis.compileExpressionSubquery(query, paramOffset);
9125
9220
  }
9126
9221
  };
9127
9222
  const state = this.createHandlerState();
@@ -9307,13 +9402,13 @@ var PlanCompiler = class _PlanCompiler {
9307
9402
  const targetRV = rangeVar(
9308
9403
  pj.table,
9309
9404
  pj.alias,
9310
- plan.schema ?? this.schema,
9405
+ this.schemaForRangeVar(plan, pj.table),
9311
9406
  this.naming
9312
9407
  );
9313
9408
  const base = from.length > 0 ? from[0] : rangeVar(
9314
9409
  plan.rootTable,
9315
9410
  void 0,
9316
- plan.schema ?? this.schema,
9411
+ this.schemaForRangeVar(plan, plan.rootTable),
9317
9412
  this.naming
9318
9413
  );
9319
9414
  from[0] = pj.type === "LEFT JOIN" ? leftJoin(base, targetRV, pj.on) : innerJoin(base, targetRV, pj.on);
@@ -9322,7 +9417,7 @@ var PlanCompiler = class _PlanCompiler {
9322
9417
  const base = from.length > 0 ? from[0] : rangeVar(
9323
9418
  plan.rootTable,
9324
9419
  void 0,
9325
- plan.schema ?? this.schema,
9420
+ this.schemaForRangeVar(plan, plan.rootTable),
9326
9421
  this.naming
9327
9422
  );
9328
9423
  const joinExpr2 = rawJoin;
@@ -9347,7 +9442,7 @@ var PlanCompiler = class _PlanCompiler {
9347
9442
  plan.batchValuesFromNode ? plan.batchValuesFromNode : rangeVar(
9348
9443
  plan.rootTable,
9349
9444
  void 0,
9350
- plan.schema ?? this.schema,
9445
+ this.schemaForRangeVar(plan, plan.rootTable),
9351
9446
  this.naming
9352
9447
  )
9353
9448
  ];
@@ -9494,6 +9589,18 @@ var PlanCompiler = class _PlanCompiler {
9494
9589
  options.withClause = { ctes: this.pendingCtes, recursive: false };
9495
9590
  }
9496
9591
  if (plan.lock) {
9592
+ assertDialectCapability(
9593
+ this.dialectCapabilities,
9594
+ "supportsRowLevelLocks",
9595
+ "Row-level locks are"
9596
+ );
9597
+ if (plan.lock.waitPolicy !== "block") {
9598
+ assertDialectCapability(
9599
+ this.dialectCapabilities,
9600
+ "supportsLockWaitPolicies",
9601
+ "Lock wait policies are"
9602
+ );
9603
+ }
9497
9604
  const mapped = mapLockToAst(plan.lock);
9498
9605
  const hasJoins = this.rawJoins.length > 0;
9499
9606
  options.lockingClause = {
@@ -9503,7 +9610,7 @@ var PlanCompiler = class _PlanCompiler {
9503
9610
  rangeVar(
9504
9611
  plan.rootTable,
9505
9612
  void 0,
9506
- plan.schema ?? this.schema,
9613
+ this.schemaForRangeVar(plan, plan.rootTable),
9507
9614
  this.naming
9508
9615
  )
9509
9616
  ]
@@ -9883,13 +9990,13 @@ var PlanCompiler = class _PlanCompiler {
9883
9990
  const baseTable = larg ?? rangeVar(
9884
9991
  plan.rootTable,
9885
9992
  void 0,
9886
- plan.schema ?? this.schema,
9993
+ this.schemaForRangeVar(plan, plan.rootTable),
9887
9994
  this.naming
9888
9995
  );
9889
9996
  const targetTable = rangeVar(
9890
9997
  decision.targetTable ?? "",
9891
9998
  decision.alias,
9892
- plan.schema ?? this.schema,
9999
+ this.schemaForRangeVar(plan, decision.targetTable ?? ""),
9893
10000
  this.naming
9894
10001
  );
9895
10002
  const onCondition = eqExpr(
@@ -13939,7 +14046,11 @@ init_naming_plugin();
13939
14046
  init_param_ref();
13940
14047
 
13941
14048
  // src/pgsql-adapter.ts
13942
- import { POSTGRESQL_CAPABILITIES as POSTGRESQL_CAPABILITIES2, plan as planFn2 } from "@dbsp/core";
14049
+ import {
14050
+ POSTGRESQL_CAPABILITIES as POSTGRESQL_CAPABILITIES2,
14051
+ plan as planFn2,
14052
+ validateTypeName as validateTypeName4
14053
+ } from "@dbsp/core";
13943
14054
  import { getNqlBindingRefName as getNqlBindingRefName2, isNqlBindingRef as isNqlBindingRef2 } from "@dbsp/types/internal";
13944
14055
 
13945
14056
  // src/adapter-compiler-includes.ts
@@ -14136,6 +14247,7 @@ import {
14136
14247
  // src/adapter-compiler-select.ts
14137
14248
  init_assert_field();
14138
14249
  init_ast_helpers();
14250
+ init_binding_registry();
14139
14251
  init_compile_where();
14140
14252
  import { countDistinctRelationPathsByName } from "@dbsp/core";
14141
14253
  init_compiler_utils();
@@ -15174,7 +15286,13 @@ function compileJoinIntents(joins, rootTable, schemaName, deps) {
15174
15286
  naming,
15175
15287
  outerTable: alias,
15176
15288
  ...schemaName !== void 0 && { schemaName },
15289
+ ...deps.bindingNames !== void 0 && {
15290
+ bindingNames: deps.bindingNames
15291
+ },
15177
15292
  ...model !== void 0 && { model },
15293
+ ...deps.dialectCapabilities !== void 0 && {
15294
+ dialectCapabilities: deps.dialectCapabilities
15295
+ },
15178
15296
  compileSubquery: () => {
15179
15297
  throw new Error(
15180
15298
  "Subquery in BatchValues JOIN ON condition is not supported."
@@ -15214,7 +15332,13 @@ function compileJoinIntents(joins, rootTable, schemaName, deps) {
15214
15332
  // joined alias (e.g. 'e2' in self-join ON conditions).
15215
15333
  outerTable: tableAlias,
15216
15334
  ...schemaName !== void 0 && { schemaName },
15335
+ ...deps.bindingNames !== void 0 && {
15336
+ bindingNames: deps.bindingNames
15337
+ },
15217
15338
  ...model !== void 0 && { model },
15339
+ ...deps.dialectCapabilities !== void 0 && {
15340
+ dialectCapabilities: deps.dialectCapabilities
15341
+ },
15218
15342
  compileSubquery: () => {
15219
15343
  throw new Error("Subquery in JOIN ON condition is not supported.");
15220
15344
  }
@@ -15223,7 +15347,7 @@ function compileJoinIntents(joins, rootTable, schemaName, deps) {
15223
15347
  const joinedRangeVar = rangeVar(
15224
15348
  intent.table,
15225
15349
  tableAlias,
15226
- schemaName,
15350
+ schemaForFromName(schemaName, intent.table, deps.bindingNames, naming),
15227
15351
  naming
15228
15352
  );
15229
15353
  results.push({
@@ -15386,6 +15510,9 @@ function compileSelect(plan, options, deps) {
15386
15510
  ...deps.bindingNames !== void 0 && {
15387
15511
  bindingNames: deps.bindingNames
15388
15512
  },
15513
+ ...deps.dialectCapabilities !== void 0 && {
15514
+ dialectCapabilities: deps.dialectCapabilities
15515
+ },
15389
15516
  ...resolvedModelForCompiler != null && {
15390
15517
  model: resolvedModelForCompiler
15391
15518
  }
@@ -15545,7 +15672,7 @@ function compileSourceQueryCte(operation, sourceName, sourceQuery, options, deps
15545
15672
  );
15546
15673
  }
15547
15674
  const sourcePlan = planFn(sourceQuery, model, {
15548
- dialectCapabilities: POSTGRESQL_CAPABILITIES
15675
+ dialectCapabilities: deps.dialectCapabilities ?? POSTGRESQL_CAPABILITIES
15549
15676
  });
15550
15677
  return compileSelect(sourcePlan, options, deps);
15551
15678
  }
@@ -15560,20 +15687,31 @@ function prependSourceCte(sql, parameters, sourceName, sourceCte, naming) {
15560
15687
  parameters: [...sourceCte.parameters, ...parameters]
15561
15688
  };
15562
15689
  }
15690
+ function resolveMutationExistsForeignKey(foreignKey, relationName) {
15691
+ if (typeof foreignKey === "string") return foreignKey;
15692
+ if (!Array.isArray(foreignKey)) return void 0;
15693
+ if (foreignKey.length > 1) {
15694
+ throw new Error(
15695
+ `Mutation exists()/notExists() guards do not support composite foreignKey relations yet: relation '${relationName}' has foreignKey ${JSON.stringify(foreignKey)}. Composite FK correlation is tracked by #179.`
15696
+ );
15697
+ }
15698
+ return foreignKey[0];
15699
+ }
15563
15700
  function resolveExistsRelation(sourceTable, relation, model) {
15564
15701
  if (!model) return { targetTable: relation };
15565
- const rel = model.getRelation(`${sourceTable}.${relation}`);
15702
+ const relationName = `${sourceTable}.${relation}`;
15703
+ const rel = model.getRelation(relationName);
15566
15704
  if (!rel) return { targetTable: relation };
15567
15705
  const targetTable = rel.target;
15568
15706
  if (rel.type === "belongsTo") {
15569
- const fk2 = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
15707
+ const fk2 = resolveMutationExistsForeignKey(rel.foreignKey, relationName);
15570
15708
  return {
15571
15709
  targetTable,
15572
15710
  ...fk2 !== void 0 && { sourceColumn: fk2 },
15573
15711
  targetColumn: "id"
15574
15712
  };
15575
15713
  }
15576
- const fk = typeof rel.foreignKey === "string" ? rel.foreignKey : rel.foreignKey?.[0];
15714
+ const fk = resolveMutationExistsForeignKey(rel.foreignKey, relationName);
15577
15715
  return {
15578
15716
  targetTable,
15579
15717
  sourceColumn: rel.sourceKey ?? "id",
@@ -15601,7 +15739,11 @@ function resolveExistsIntent(where, sourceTable, deps) {
15601
15739
  if (kind !== "exists" && kind !== "notExists") return where;
15602
15740
  const relation = w.relation;
15603
15741
  const resolved = resolveExistsRelation(sourceTable, relation, deps.model);
15604
- if (resolved.targetTable === relation && !resolved.sourceColumn) return where;
15742
+ const nestedWhere = w.where;
15743
+ const enrichedNestedWhere = nestedWhere !== void 0 ? resolveExistsIntent(nestedWhere, resolved.targetTable, deps) : void 0;
15744
+ if (resolved.targetTable === relation && !resolved.sourceColumn && !resolved.targetColumn && enrichedNestedWhere === nestedWhere) {
15745
+ return where;
15746
+ }
15605
15747
  return {
15606
15748
  ...w,
15607
15749
  targetTable: resolved.targetTable,
@@ -15610,7 +15752,8 @@ function resolveExistsIntent(where, sourceTable, deps) {
15610
15752
  },
15611
15753
  ...resolved.targetColumn !== void 0 && {
15612
15754
  targetColumn: resolved.targetColumn
15613
- }
15755
+ },
15756
+ ...enrichedNestedWhere !== void 0 && { where: enrichedNestedWhere }
15614
15757
  };
15615
15758
  }
15616
15759
  function getColumnTypes(tableName, columns, deps) {
@@ -15636,13 +15779,17 @@ function compileUpsertActionWhere(where, table, state, deps, schemaName) {
15636
15779
  ...schemaName !== void 0 && { schemaName },
15637
15780
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
15638
15781
  ...deps.model !== void 0 && { model: deps.model },
15782
+ ...deps.dialectCapabilities !== void 0 && {
15783
+ dialectCapabilities: deps.dialectCapabilities
15784
+ },
15639
15785
  compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
15640
15786
  sqIntent,
15641
15787
  paramOffset,
15642
15788
  deps.naming,
15643
15789
  schemaName,
15644
15790
  "rawExists",
15645
- deps.bindingNames
15791
+ deps.bindingNames,
15792
+ deps.dialectCapabilities
15646
15793
  )
15647
15794
  };
15648
15795
  return compileWhereIntent(where, whereCtx);
@@ -15653,6 +15800,9 @@ function compileInsert2(intent, options, deps) {
15653
15800
  naming: deps.naming,
15654
15801
  rootTable: intent.table,
15655
15802
  ...schemaName !== void 0 && { schema: schemaName },
15803
+ ...deps.dialectCapabilities !== void 0 && {
15804
+ dialectCapabilities: deps.dialectCapabilities
15805
+ },
15656
15806
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
15657
15807
  maxRecursiveDepth: 100
15658
15808
  };
@@ -15699,15 +15849,19 @@ function compileInsertFrom2(intent, options, deps) {
15699
15849
  naming: deps.naming,
15700
15850
  rootTable: intent.source,
15701
15851
  ...schemaName !== void 0 && { schema: schemaName },
15852
+ ...deps.dialectCapabilities !== void 0 && {
15853
+ dialectCapabilities: deps.dialectCapabilities
15854
+ },
15702
15855
  ...bindingNames !== void 0 && { bindingNames },
15703
15856
  maxRecursiveDepth: 100
15704
15857
  };
15705
15858
  const state = createCompilerState();
15859
+ const resolvedWhere = intent.where ? resolveExistsIntent(intent.where, intent.source, deps) : void 0;
15706
15860
  const config = {
15707
15861
  targetTable: intent.table,
15708
15862
  sourceTable: intent.source,
15709
15863
  ...intent.columns && { columns: [...intent.columns] },
15710
- ...intent.where && { where: [whereIntentAsDecision(intent.where)] },
15864
+ ...resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] },
15711
15865
  ...intent.limit !== void 0 && { limit: intent.limit },
15712
15866
  ...intent.returning && { returning: [...intent.returning] }
15713
15867
  };
@@ -15730,6 +15884,9 @@ function compileUpdate2(intent, options, deps) {
15730
15884
  ...schemaName !== void 0 && { schema: schemaName },
15731
15885
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
15732
15886
  ...resolvedModel !== void 0 && { model: resolvedModel },
15887
+ ...deps.dialectCapabilities !== void 0 && {
15888
+ dialectCapabilities: deps.dialectCapabilities
15889
+ },
15733
15890
  maxRecursiveDepth: 100
15734
15891
  };
15735
15892
  const state = createCompilerState();
@@ -15759,6 +15916,9 @@ function compileBatchUpdate(intent, _options, deps) {
15759
15916
  naming: deps.naming,
15760
15917
  rootTable: intent.table,
15761
15918
  ...schemaName !== void 0 && { schema: schemaName },
15919
+ ...deps.dialectCapabilities !== void 0 && {
15920
+ dialectCapabilities: deps.dialectCapabilities
15921
+ },
15762
15922
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
15763
15923
  maxRecursiveDepth: 100
15764
15924
  };
@@ -15789,6 +15949,7 @@ function compileBatchUpdate(intent, _options, deps) {
15789
15949
  })) : void 0;
15790
15950
  let whereGuard;
15791
15951
  if (intent.where) {
15952
+ const resolvedWhere = resolveExistsIntent(intent.where, intent.table, deps);
15792
15953
  const whereCtx = {
15793
15954
  rootTable: intent.table,
15794
15955
  aliases: /* @__PURE__ */ new Map(),
@@ -15799,16 +15960,20 @@ function compileBatchUpdate(intent, _options, deps) {
15799
15960
  bindingNames: deps.bindingNames
15800
15961
  },
15801
15962
  ...deps.model !== void 0 && { model: deps.model },
15963
+ ...deps.dialectCapabilities !== void 0 && {
15964
+ dialectCapabilities: deps.dialectCapabilities
15965
+ },
15802
15966
  compileSubquery: (sqIntent, paramOffset) => buildSubqueryFromIntent(
15803
15967
  sqIntent,
15804
15968
  paramOffset,
15805
15969
  deps.naming,
15806
15970
  schemaName,
15807
15971
  "rawExists",
15808
- deps.bindingNames
15972
+ deps.bindingNames,
15973
+ deps.dialectCapabilities
15809
15974
  )
15810
15975
  };
15811
- whereGuard = compileWhereIntent(intent.where, whereCtx);
15976
+ whereGuard = compileWhereIntent(resolvedWhere, whereCtx);
15812
15977
  }
15813
15978
  const config = {
15814
15979
  table: intent.table,
@@ -15835,6 +16000,9 @@ function compileDelete2(intent, options, deps) {
15835
16000
  rootTable: intent.table,
15836
16001
  ...schemaName !== void 0 && { schema: schemaName },
15837
16002
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
16003
+ ...deps.dialectCapabilities !== void 0 && {
16004
+ dialectCapabilities: deps.dialectCapabilities
16005
+ },
15838
16006
  maxRecursiveDepth: 100,
15839
16007
  ...resolvedModel !== void 0 && { model: resolvedModel }
15840
16008
  };
@@ -15860,6 +16028,9 @@ function compileUpsert2(intent, options, deps) {
15860
16028
  ...schemaName !== void 0 && { schema: schemaName },
15861
16029
  ...deps.bindingNames !== void 0 && { bindingNames: deps.bindingNames },
15862
16030
  ...deps.model !== void 0 && { model: deps.model },
16031
+ ...deps.dialectCapabilities !== void 0 && {
16032
+ dialectCapabilities: deps.dialectCapabilities
16033
+ },
15863
16034
  maxRecursiveDepth: 100
15864
16035
  };
15865
16036
  const state = createCompilerState();
@@ -15953,10 +16124,14 @@ function compileUpsertFrom2(intent, options, deps) {
15953
16124
  naming: deps.naming,
15954
16125
  rootTable: intent.source,
15955
16126
  ...schemaName !== void 0 && { schema: schemaName },
16127
+ ...deps.dialectCapabilities !== void 0 && {
16128
+ dialectCapabilities: deps.dialectCapabilities
16129
+ },
15956
16130
  ...bindingNames !== void 0 && { bindingNames },
15957
16131
  maxRecursiveDepth: 100
15958
16132
  };
15959
16133
  const state = createCompilerState();
16134
+ const resolvedWhere = intent.where ? resolveExistsIntent(intent.where, intent.source, deps) : void 0;
15960
16135
  let columns;
15961
16136
  if (intent.columns) {
15962
16137
  columns = [...intent.columns];
@@ -15971,7 +16146,7 @@ function compileUpsertFrom2(intent, options, deps) {
15971
16146
  sourceTable: intent.source,
15972
16147
  conflictColumns: [...intent.conflictColumns],
15973
16148
  ...columns && { columns },
15974
- ...intent.where && { where: [whereIntentAsDecision(intent.where)] },
16149
+ ...resolvedWhere && { where: [whereIntentAsDecision(resolvedWhere)] },
15975
16150
  ...intent.limit !== void 0 && { limit: intent.limit },
15976
16151
  ...intent.returning && { returning: [...intent.returning] }
15977
16152
  };
@@ -17363,6 +17538,7 @@ function mapFetchDirection(direction) {
17363
17538
 
17364
17539
  // src/pgsql-adapter.ts
17365
17540
  init_validate();
17541
+ var MAX_NQL_RUNTIME_BINDING_VALUES_PARAMETERS = 32e3;
17366
17542
  function renumberSqlParams2(sql, offset) {
17367
17543
  if (offset === 0) return sql;
17368
17544
  return sql.replace(/\$(\d+)/g, (_match, num) => {
@@ -17370,7 +17546,7 @@ function renumberSqlParams2(sql, offset) {
17370
17546
  });
17371
17547
  }
17372
17548
  function isCompiledNqlQuery(input) {
17373
- return !("intent" in input) && ("query" in input || "cteQuery" in input || "mutation" in input || "setOperation" in input || "bindings" in input || "mutationBindings" in input);
17549
+ return !("intent" in input) && ("query" in input || "cteQuery" in input || "mutation" in input || "setOperation" in input || "bindings" in input || "mutationBindings" in input || "runtimeBindings" in input);
17374
17550
  }
17375
17551
  function formatGuardPathSegment(key) {
17376
17552
  return /^[A-Za-z_$][\w$]*$/.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
@@ -17445,6 +17621,175 @@ function findDuplicateEmittedNqlBindingName(bindingNames, naming) {
17445
17621
  }
17446
17622
  return void 0;
17447
17623
  }
17624
+ function orderedNqlBindingNames(bundle) {
17625
+ const names = [];
17626
+ const seen = /* @__PURE__ */ new Set();
17627
+ for (const name of bundle.bindings?.keys() ?? []) {
17628
+ names.push(name);
17629
+ seen.add(name);
17630
+ }
17631
+ for (const name of bundle.runtimeBindings?.keys() ?? []) {
17632
+ if (!seen.has(name)) {
17633
+ names.push(name);
17634
+ seen.add(name);
17635
+ }
17636
+ }
17637
+ return names;
17638
+ }
17639
+ function mapRuntimeBindingColumnType(type) {
17640
+ switch (type) {
17641
+ case "string":
17642
+ return "text";
17643
+ case "text":
17644
+ return "text";
17645
+ case "number":
17646
+ case "integer":
17647
+ return "integer";
17648
+ case "bigint":
17649
+ return "bigint";
17650
+ case "decimal":
17651
+ return "numeric";
17652
+ case "boolean":
17653
+ return "boolean";
17654
+ case "date":
17655
+ return "date";
17656
+ case "time":
17657
+ return "time";
17658
+ case "datetime":
17659
+ case "timestamp":
17660
+ return "timestamptz";
17661
+ case "json":
17662
+ case "jsonb":
17663
+ return "jsonb";
17664
+ case "uuid":
17665
+ return "uuid";
17666
+ case "daterange":
17667
+ return "daterange";
17668
+ case "tsrange":
17669
+ return "tsrange";
17670
+ case "tstzrange":
17671
+ return "tstzrange";
17672
+ case "int4range":
17673
+ return "int4range";
17674
+ case "int8range":
17675
+ return "int8range";
17676
+ case "numrange":
17677
+ return "numrange";
17678
+ default:
17679
+ return void 0;
17680
+ }
17681
+ }
17682
+ function findRuntimeBindingSourceTable(model, sourceTable) {
17683
+ return model.getTable(sourceTable) ?? [...model.tables.values()].find((table) => table.name === sourceTable);
17684
+ }
17685
+ function resolveRuntimeBindingColumnType(bindingName, sourceTable, columnName) {
17686
+ const column = sourceTable.columns.find(
17687
+ (candidate) => candidate.name === columnName
17688
+ );
17689
+ if (column === void 0) {
17690
+ throw new Error(
17691
+ `NQL runtime binding '${bindingName}' cannot resolve projected column '${columnName}' on source mutation table '${sourceTable.name}'.`
17692
+ );
17693
+ }
17694
+ const dbType = column.originalDbType?.trim() || mapRuntimeBindingColumnType(column.type);
17695
+ if (dbType === void 0 || dbType.trim() === "") {
17696
+ throw new Error(
17697
+ `NQL runtime binding '${bindingName}' cannot resolve a PostgreSQL type for projected column '${columnName}' on source mutation table '${sourceTable.name}'.`
17698
+ );
17699
+ }
17700
+ const typeName = dbType.trim();
17701
+ try {
17702
+ validateTypeName4(typeName);
17703
+ } catch (error) {
17704
+ const reason = error instanceof Error ? error.message : String(error);
17705
+ throw new Error(
17706
+ `NQL runtime binding '${bindingName}' cannot use PostgreSQL cast type for projected column '${columnName}': ${reason}`
17707
+ );
17708
+ }
17709
+ return typeName;
17710
+ }
17711
+ function resolveRuntimeBindingColumnTypes(name, binding, model, sourceTableName) {
17712
+ if (model === void 0) {
17713
+ throw new Error(
17714
+ `NQL runtime binding '${name}' cannot materialize non-empty rows because no model is available for source-table column type resolution.`
17715
+ );
17716
+ }
17717
+ const sourceTable = findRuntimeBindingSourceTable(model, sourceTableName);
17718
+ if (sourceTable === void 0) {
17719
+ throw new Error(
17720
+ `NQL runtime binding '${name}' cannot resolve source mutation table '${sourceTableName}' in the model.`
17721
+ );
17722
+ }
17723
+ return binding.columns.map(
17724
+ (column) => resolveRuntimeBindingColumnType(name, sourceTable, column)
17725
+ );
17726
+ }
17727
+ function assertRuntimeBindingValuesParameterCount(name, binding, parameterOffset) {
17728
+ const valueParameterCount = binding.rows.length * binding.columns.length;
17729
+ if (valueParameterCount <= MAX_NQL_RUNTIME_BINDING_VALUES_PARAMETERS && parameterOffset + valueParameterCount <= MAX_NQL_RUNTIME_BINDING_VALUES_PARAMETERS) {
17730
+ return;
17731
+ }
17732
+ const totalParameterCount = parameterOffset + valueParameterCount;
17733
+ throw new Error(
17734
+ `NQL runtime binding '${name}' would materialize ${valueParameterCount} VALUES parameters; limit is ${MAX_NQL_RUNTIME_BINDING_VALUES_PARAMETERS}. Current parameter offset is ${parameterOffset}, which would make ${totalParameterCount} total parameters before compiling the final statement.`
17735
+ );
17736
+ }
17737
+ function compileNqlRuntimeBindingCte(name, binding, naming, parameterOffset, sourceTable, schemaName, model) {
17738
+ if (binding.columns.length === 0) {
17739
+ throw new Error(
17740
+ `NQL runtime binding '${name}' cannot be materialized without projected columns.`
17741
+ );
17742
+ }
17743
+ const cteName = quoteIdent2(emittedBindName(name, naming), "alias");
17744
+ const columnSql = binding.columns.map((column) => quoteIdent2(naming.toDatabase(column), "column")).join(", ");
17745
+ if (sourceTable === void 0) {
17746
+ throw new Error(
17747
+ `NQL runtime binding '${name}' cannot materialize a typed relation because its source mutation table is unavailable.`
17748
+ );
17749
+ }
17750
+ const projectedColumns = binding.columns.map((column) => quoteIdent2(naming.toDatabase(column), "column")).join(", ");
17751
+ const sourceAnchorSql = `SELECT ${projectedColumns} FROM ${qualifyTableIdent(sourceTable, schemaName, naming)} WHERE false`;
17752
+ if (binding.rows.length === 0) {
17753
+ return {
17754
+ cte: `${cteName} (${columnSql}) as (${sourceAnchorSql})`,
17755
+ parameters: []
17756
+ };
17757
+ }
17758
+ assertRuntimeBindingValuesParameterCount(name, binding, parameterOffset);
17759
+ const columnTypes = resolveRuntimeBindingColumnTypes(
17760
+ name,
17761
+ binding,
17762
+ model,
17763
+ sourceTable
17764
+ );
17765
+ const parameters = [];
17766
+ let nextParam = parameterOffset + 1;
17767
+ const valuesSql = binding.rows.map((row) => {
17768
+ const placeholders = binding.columns.map((column, columnIndex) => {
17769
+ parameters.push(row[column]);
17770
+ return `$${nextParam++}::${columnTypes[columnIndex]}`;
17771
+ });
17772
+ return `(${placeholders.join(", ")})`;
17773
+ }).join(", ");
17774
+ return {
17775
+ cte: `${cteName} (${columnSql}) as (${sourceAnchorSql} UNION ALL VALUES ${valuesSql})`,
17776
+ parameters
17777
+ };
17778
+ }
17779
+ function createNqlBindingSelectPlan(query) {
17780
+ return {
17781
+ rootTable: query.from,
17782
+ decisions: [],
17783
+ warnings: [],
17784
+ ctes: [],
17785
+ intent: query,
17786
+ metadata: {
17787
+ planningTimeMs: 0,
17788
+ relationsAnalyzed: 0,
17789
+ isAmbiguous: false
17790
+ }
17791
+ };
17792
+ }
17448
17793
  var PgsqlAdapter = class _PgsqlAdapter {
17449
17794
  pool;
17450
17795
  client;
@@ -17521,6 +17866,7 @@ var PgsqlAdapter = class _PgsqlAdapter {
17521
17866
  // `||` (not `??`): empty string is treated as "no override" and falls back to this.schemaName (which may be a configured schema or undefined)
17522
17867
  schemaName: options?.schemaName || this.schemaName,
17523
17868
  model: options?.model ?? this.model,
17869
+ dialectCapabilities: options?.dialectCapabilities ?? this.dialectCapabilities,
17524
17870
  defaultPk: this.defaultPk,
17525
17871
  deriveFk: this.deriveFk,
17526
17872
  ...bindingNames !== void 0 && { bindingNames }
@@ -17601,22 +17947,17 @@ var PgsqlAdapter = class _PgsqlAdapter {
17601
17947
  }
17602
17948
  compileNqlBundleLeaf(bundle, options, bindingNames) {
17603
17949
  if (bundle.query !== void 0) {
17604
- const naming = this.buildCompileDeps(options, bindingNames).naming;
17605
- if (hasBindingName(bindingNames, bundle.query.from, naming)) {
17606
- throw new Error(
17607
- `NQL binding '${bundle.query.from}' cannot be used as the final FROM source yet. Use the binding from a mutation source or WHERE IN predicate, or select from a real table.`
17608
- );
17609
- }
17610
- const model = this.requireNqlCompileModel(options);
17611
- const planReport = planFn2(bundle.query, model, {
17612
- dialectCapabilities: this.dialectCapabilities
17950
+ const deps = this.buildCompileDeps(options, bindingNames);
17951
+ const queryFromBinding = hasBindingName(
17952
+ bindingNames,
17953
+ bundle.query.from,
17954
+ deps.naming
17955
+ );
17956
+ const planReport = queryFromBinding ? createNqlBindingSelectPlan(bundle.query) : planFn2(bundle.query, this.requireNqlCompileModel(options), {
17957
+ dialectCapabilities: options?.dialectCapabilities ?? this.dialectCapabilities
17613
17958
  });
17614
17959
  return guardCompiledQuery(
17615
- compileSelect(
17616
- planReport,
17617
- options,
17618
- this.buildCompileDeps(options, bindingNames)
17619
- ),
17960
+ compileSelect(planReport, options, deps),
17620
17961
  "NQL query"
17621
17962
  );
17622
17963
  }
@@ -17657,20 +17998,41 @@ var PgsqlAdapter = class _PgsqlAdapter {
17657
17998
  compileNqlBundle(bundle, options) {
17658
17999
  const ctes = [];
17659
18000
  const parameters = [];
17660
- const naming = this.buildCompileDeps(options).naming;
17661
- const duplicateEmittedBinding = bundle.bindings !== void 0 ? findDuplicateEmittedNqlBindingName(bundle.bindings.keys(), naming) : void 0;
18001
+ const deps = this.buildCompileDeps(options);
18002
+ const { naming } = deps;
18003
+ const bindingNamesInOrder = orderedNqlBindingNames(bundle);
18004
+ const duplicateEmittedBinding = bindingNamesInOrder.length > 0 ? findDuplicateEmittedNqlBindingName(bindingNamesInOrder, naming) : void 0;
17662
18005
  if (duplicateEmittedBinding !== void 0) {
17663
18006
  throw new Error(
17664
18007
  `NQL bindings '${duplicateEmittedBinding.originalName}' and '${duplicateEmittedBinding.duplicateName}' emit to duplicate CTE name '${duplicateEmittedBinding.emittedName}'. NQL binding names must be unique after database naming.`
17665
18008
  );
17666
18009
  }
17667
- const bindingNames = bundle.bindings !== void 0 ? new Set(
17668
- [...bundle.bindings.keys()].map(
17669
- (name) => emittedBindName(name, naming)
17670
- )
18010
+ const bindingNames = bindingNamesInOrder.length > 0 ? new Set(
18011
+ bindingNamesInOrder.map((name) => emittedBindName(name, naming))
17671
18012
  ) : void 0;
17672
18013
  this.assertNqlBindingNamesDisjointFromTables(bindingNames, options);
17673
- for (const [name, queryIntent] of bundle.bindings ?? []) {
18014
+ for (const name of bindingNamesInOrder) {
18015
+ const runtimeBinding = bundle.runtimeBindings?.get(name);
18016
+ if (runtimeBinding !== void 0) {
18017
+ const compiledRuntimeBinding = compileNqlRuntimeBindingCte(
18018
+ name,
18019
+ runtimeBinding,
18020
+ naming,
18021
+ parameters.length,
18022
+ bundle.mutationBindings?.get(name)?.table,
18023
+ deps.schemaName,
18024
+ deps.model
18025
+ );
18026
+ ctes.push(compiledRuntimeBinding.cte);
18027
+ parameters.push(...compiledRuntimeBinding.parameters);
18028
+ continue;
18029
+ }
18030
+ const queryIntent = bundle.bindings?.get(name);
18031
+ if (queryIntent === void 0) {
18032
+ throw new Error(
18033
+ `NQL binding '${name}' has no query intent or runtime rows to materialize.`
18034
+ );
18035
+ }
17674
18036
  const cteName = quoteIdent2(emittedBindName(name, naming), "alias");
17675
18037
  const bindingBundle = bundle.mutationBindings?.has(name) ? { mutation: bundle.mutationBindings.get(name) } : { query: queryIntent };
17676
18038
  const compiled2 = this.compileNqlBundleLeaf(
@@ -17745,6 +18107,11 @@ var PgsqlAdapter = class _PgsqlAdapter {
17745
18107
  // =========================================================================
17746
18108
  /**
17747
18109
  * Compile a plan to executable SQL.
18110
+ *
18111
+ * When passed a direct `CompiledNqlQuery`, the adapter trusts that the bundle
18112
+ * has already been semantically validated by the NQL compiler. This method
18113
+ * still performs adapter-owned SQL safety checks for emitted binding names
18114
+ * before CTE emission.
17748
18115
  */
17749
18116
  compile(plan, options) {
17750
18117
  if (isCompiledNqlQuery(plan)) {
@@ -17796,10 +18163,12 @@ var PgsqlAdapter = class _PgsqlAdapter {
17796
18163
  compileSelectExpression(expr) {
17797
18164
  const naming = this.naming;
17798
18165
  const schemaName = this.schemaName;
18166
+ const dialectCapabilities = this.dialectCapabilities;
17799
18167
  const state = createCompilerState();
17800
18168
  const ctx = {
17801
18169
  naming,
17802
18170
  ...schemaName !== void 0 && { schema: schemaName },
18171
+ dialectCapabilities,
17803
18172
  rootTable: "",
17804
18173
  maxRecursiveDepth: 100,
17805
18174
  // Wire compileSubquery so that SubqueryExpressionIntent nested inside
@@ -17809,7 +18178,8 @@ var PgsqlAdapter = class _PgsqlAdapter {
17809
18178
  compileSubquery(query, paramOffset) {
17810
18179
  const innerCompiler = new PlanCompiler({
17811
18180
  naming,
17812
- ...schemaName !== void 0 && { schema: schemaName }
18181
+ ...schemaName !== void 0 && { schema: schemaName },
18182
+ dialectCapabilities
17813
18183
  });
17814
18184
  const innerPlan = {
17815
18185
  rootTable: query.from,
@@ -17943,19 +18313,22 @@ var PgsqlAdapter = class _PgsqlAdapter {
17943
18313
  );
17944
18314
  }
17945
18315
  compileSetOperationWithBindings(intent, model, options, bindingNames) {
17946
- const compileFn = createLeafCompileFn(
17947
- {
17948
- dialectCapabilities: this.dialectCapabilities,
17949
- compile: (planReport, leafOptions) => compileSelect(
17950
- planReport,
17951
- leafOptions,
17952
- this.buildCompileDeps(leafOptions, bindingNames)
17953
- )
17954
- },
17955
- model,
17956
- planFn2,
17957
- options
17958
- );
18316
+ const compileFn = (query) => {
18317
+ const leafOptions = {
18318
+ ...options,
18319
+ model
18320
+ };
18321
+ const deps = this.buildCompileDeps(leafOptions, bindingNames);
18322
+ const queryFromBinding = hasBindingName(
18323
+ bindingNames,
18324
+ query.from,
18325
+ deps.naming
18326
+ );
18327
+ const planReport = queryFromBinding ? createNqlBindingSelectPlan(query) : planFn2(query, model, {
18328
+ dialectCapabilities: options?.dialectCapabilities ?? this.dialectCapabilities
18329
+ });
18330
+ return compileSelect(planReport, leafOptions, deps);
18331
+ };
17959
18332
  const result = compileSetOperation(intent, compileFn);
17960
18333
  return guardCompiledQuery(
17961
18334
  {