effect-qb 0.15.0 → 0.17.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.
Files changed (88) hide show
  1. package/dist/mysql.js +1957 -595
  2. package/dist/postgres/metadata.js +2507 -182
  3. package/dist/postgres.js +9587 -8201
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +7 -2
  6. package/src/internal/column-state.ts +7 -0
  7. package/src/internal/column.ts +22 -0
  8. package/src/internal/derived-table.ts +29 -3
  9. package/src/internal/dialect.ts +14 -1
  10. package/src/internal/dsl-mutation-runtime.ts +173 -4
  11. package/src/internal/dsl-plan-runtime.ts +165 -20
  12. package/src/internal/dsl-query-runtime.ts +60 -6
  13. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  14. package/src/internal/executor.ts +62 -13
  15. package/src/internal/expression-ast.ts +3 -2
  16. package/src/internal/grouping-key.ts +141 -1
  17. package/src/internal/implication-runtime.ts +2 -1
  18. package/src/internal/json/types.ts +155 -40
  19. package/src/internal/predicate/analysis.ts +103 -1
  20. package/src/internal/predicate/atom.ts +7 -0
  21. package/src/internal/predicate/context.ts +170 -17
  22. package/src/internal/predicate/key.ts +64 -2
  23. package/src/internal/predicate/normalize.ts +115 -34
  24. package/src/internal/predicate/runtime.ts +144 -13
  25. package/src/internal/query.ts +563 -103
  26. package/src/internal/renderer.ts +39 -2
  27. package/src/internal/runtime/driver-value-mapping.ts +244 -0
  28. package/src/internal/runtime/normalize.ts +62 -38
  29. package/src/internal/runtime/schema.ts +5 -3
  30. package/src/internal/runtime/value.ts +153 -30
  31. package/src/internal/scalar.ts +11 -0
  32. package/src/internal/table-options.ts +108 -1
  33. package/src/internal/table.ts +87 -29
  34. package/src/mysql/column.ts +19 -2
  35. package/src/mysql/datatypes/index.ts +21 -0
  36. package/src/mysql/errors/catalog.ts +5 -5
  37. package/src/mysql/errors/normalize.ts +2 -2
  38. package/src/mysql/executor.ts +20 -5
  39. package/src/mysql/internal/dialect.ts +12 -6
  40. package/src/mysql/internal/dsl.ts +995 -263
  41. package/src/mysql/internal/renderer.ts +13 -3
  42. package/src/mysql/internal/sql-expression-renderer.ts +530 -128
  43. package/src/mysql/query.ts +9 -2
  44. package/src/mysql/renderer.ts +7 -2
  45. package/src/mysql/table.ts +38 -12
  46. package/src/postgres/cast.ts +22 -7
  47. package/src/postgres/column.ts +5 -2
  48. package/src/postgres/errors/normalize.ts +2 -2
  49. package/src/postgres/executor.ts +68 -10
  50. package/src/postgres/function/core.ts +19 -1
  51. package/src/postgres/internal/dialect.ts +12 -6
  52. package/src/postgres/internal/dsl.ts +958 -288
  53. package/src/postgres/internal/renderer.ts +13 -3
  54. package/src/postgres/internal/schema-ddl.ts +2 -1
  55. package/src/postgres/internal/schema-model.ts +6 -3
  56. package/src/postgres/internal/sql-expression-renderer.ts +477 -96
  57. package/src/postgres/json.ts +57 -17
  58. package/src/postgres/query.ts +9 -2
  59. package/src/postgres/renderer.ts +7 -2
  60. package/src/postgres/schema-management.ts +91 -4
  61. package/src/postgres/schema.ts +1 -1
  62. package/src/postgres/table.ts +189 -53
  63. package/src/postgres/type.ts +4 -0
  64. package/src/sqlite/column.ts +128 -0
  65. package/src/sqlite/datatypes/index.ts +79 -0
  66. package/src/sqlite/datatypes/spec.ts +98 -0
  67. package/src/sqlite/errors/catalog.ts +103 -0
  68. package/src/sqlite/errors/fields.ts +19 -0
  69. package/src/sqlite/errors/index.ts +19 -0
  70. package/src/sqlite/errors/normalize.ts +229 -0
  71. package/src/sqlite/errors/requirements.ts +71 -0
  72. package/src/sqlite/errors/types.ts +29 -0
  73. package/src/sqlite/executor.ts +227 -0
  74. package/src/sqlite/function/aggregate.ts +2 -0
  75. package/src/sqlite/function/core.ts +2 -0
  76. package/src/sqlite/function/index.ts +19 -0
  77. package/src/sqlite/function/string.ts +2 -0
  78. package/src/sqlite/function/temporal.ts +100 -0
  79. package/src/sqlite/function/window.ts +2 -0
  80. package/src/sqlite/internal/dialect.ts +37 -0
  81. package/src/sqlite/internal/dsl.ts +6926 -0
  82. package/src/sqlite/internal/renderer.ts +47 -0
  83. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  84. package/src/sqlite/json.ts +2 -0
  85. package/src/sqlite/query.ts +196 -0
  86. package/src/sqlite/renderer.ts +24 -0
  87. package/src/sqlite/table.ts +183 -0
  88. package/src/sqlite.ts +22 -0
@@ -74,6 +74,7 @@ var makeColumnDefinition = (schema, metadata) => {
74
74
  runtime: undefined,
75
75
  dbType: metadata.dbType,
76
76
  runtimeSchema: schema,
77
+ driverValueMapping: metadata.driverValueMapping,
77
78
  nullability: metadata.nullable ? "maybe" : "never",
78
79
  dialect: metadata.dbType.dialect,
79
80
  kind: "scalar",
@@ -93,6 +94,7 @@ var makeColumnDefinition = (schema, metadata) => {
93
94
  defaultValue: metadata.defaultValue,
94
95
  generatedValue: metadata.generatedValue,
95
96
  ddlType: metadata.ddlType,
97
+ driverValueMapping: metadata.driverValueMapping,
96
98
  identity: metadata.identity,
97
99
  enum: metadata.enum
98
100
  };
@@ -109,6 +111,7 @@ var remapColumnDefinition = (column, options = {}) => {
109
111
  runtime: undefined,
110
112
  dbType: metadata.dbType,
111
113
  runtimeSchema: schema,
114
+ driverValueMapping: metadata.driverValueMapping,
112
115
  nullability: metadata.nullable ? "maybe" : "never",
113
116
  dialect: metadata.dbType.dialect
114
117
  };
@@ -127,6 +130,7 @@ var remapColumnDefinition = (column, options = {}) => {
127
130
  defaultValue: metadata.defaultValue,
128
131
  generatedValue: metadata.generatedValue,
129
132
  ddlType: metadata.ddlType,
133
+ driverValueMapping: metadata.driverValueMapping,
130
134
  identity: metadata.identity,
131
135
  enum: metadata.enum
132
136
  };
@@ -148,6 +152,7 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
148
152
  runtime: undefined,
149
153
  dbType: column.metadata.dbType,
150
154
  runtimeSchema: schema,
155
+ driverValueMapping: column.metadata.driverValueMapping,
151
156
  nullability: column.metadata.nullable ? "maybe" : "never",
152
157
  dialect: column.metadata.dbType.dialect,
153
158
  kind: "scalar",
@@ -171,6 +176,27 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
171
176
  };
172
177
 
173
178
  // src/internal/table-options.ts
179
+ var referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault";
180
+ var renderReferentialAction = (action) => {
181
+ switch (action) {
182
+ case "noAction":
183
+ return "no action";
184
+ case "restrict":
185
+ return "restrict";
186
+ case "cascade":
187
+ return "cascade";
188
+ case "setNull":
189
+ return "set null";
190
+ case "setDefault":
191
+ return "set default";
192
+ }
193
+ throw new Error(referentialActionError);
194
+ };
195
+ var validateReferentialAction = (action) => {
196
+ if (action !== undefined) {
197
+ renderReferentialAction(action);
198
+ }
199
+ };
174
200
  var normalizeColumnList = (columns) => {
175
201
  const normalized = Array.isArray(columns) ? [...columns] : [columns];
176
202
  if (normalized.length === 0) {
@@ -198,6 +224,8 @@ var collectInlineOptions = (fields) => {
198
224
  });
199
225
  }
200
226
  if (column.metadata.references) {
227
+ validateReferentialAction(column.metadata.references.onUpdate);
228
+ validateReferentialAction(column.metadata.references.onDelete);
201
229
  const local = [columnName];
202
230
  options.push({
203
231
  kind: "foreignKey",
@@ -274,6 +302,8 @@ var validateOptions = (tableName, fields, options) => {
274
302
  }
275
303
  }
276
304
  if (option.kind === "foreignKey") {
305
+ validateReferentialAction(option.onUpdate);
306
+ validateReferentialAction(option.onDelete);
277
307
  const reference = option.references();
278
308
  if (reference.columns.length !== columns.length) {
279
309
  throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
@@ -298,7 +328,7 @@ var validateOptions = (tableName, fields, options) => {
298
328
  throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
299
329
  }
300
330
  }
301
- if (option.columns === undefined && (option.keys === undefined || option.keys.length === 0)) {
331
+ if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
302
332
  throw new Error(`Index on table '${tableName}' requires at least one column or key`);
303
333
  }
304
334
  }
@@ -512,10 +542,13 @@ function make2(name, fields, schemaName) {
512
542
  const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
513
543
  return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
514
544
  }
515
- var schema = (schemaName) => ({
516
- schemaName,
517
- table: (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2)
518
- });
545
+ var schema = (schemaName) => {
546
+ const table = (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2);
547
+ return {
548
+ schemaName,
549
+ table
550
+ };
551
+ };
519
552
  var alias = (table, aliasName) => {
520
553
  const state = table[TypeId4];
521
554
  const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
@@ -691,6 +724,9 @@ var normalize = (expression) => (() => {
691
724
  }
692
725
  })();
693
726
 
727
+ // src/postgres/internal/sql-expression-renderer.ts
728
+ import * as Schema5 from "effect/Schema";
729
+
694
730
  // src/internal/query.ts
695
731
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
696
732
 
@@ -711,6 +747,7 @@ var emptyContext = () => ({
711
747
  nullKeys: new Set,
712
748
  eqLiterals: new Map,
713
749
  neqLiterals: new Map,
750
+ literalSets: new Map,
714
751
  sourceNames: new Set,
715
752
  contradiction: false,
716
753
  unknown: false
@@ -720,12 +757,24 @@ var cloneContext = (context) => ({
720
757
  nullKeys: new Set(context.nullKeys),
721
758
  eqLiterals: new Map(context.eqLiterals),
722
759
  neqLiterals: new Map(Array.from(context.neqLiterals.entries(), ([key, values]) => [key, new Set(values)])),
760
+ literalSets: new Map(Array.from(context.literalSets.entries(), ([key, values]) => [key, new Set(values)])),
723
761
  sourceNames: new Set(context.sourceNames),
724
762
  contradiction: context.contradiction,
725
763
  unknown: context.unknown
726
764
  });
727
765
  var freezeContext = (context) => context;
728
- var sourceNameOfKey = (key) => key.split(".", 1)[0] ?? key;
766
+ var columnPredicateKey = (tableName, columnName) => JSON.stringify([tableName, columnName]);
767
+ var columnPredicateKeyParts = (key) => {
768
+ const jsonSeparator = key.indexOf("#json:");
769
+ const columnKey = jsonSeparator === -1 ? key : key.slice(0, jsonSeparator);
770
+ try {
771
+ const parsed = JSON.parse(columnKey);
772
+ return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : undefined;
773
+ } catch {
774
+ return;
775
+ }
776
+ };
777
+ var sourceNameOfKey = (key) => columnPredicateKeyParts(key)?.[0] ?? key.split(".", 1)[0] ?? key;
729
778
  var addSourceName = (context, key) => {
730
779
  context.sourceNames.add(sourceNameOfKey(key));
731
780
  };
@@ -753,7 +802,12 @@ var addEqLiteral = (context, key, value) => {
753
802
  if (neqValues?.has(value)) {
754
803
  context.contradiction = true;
755
804
  }
805
+ const existingSet = context.literalSets.get(key);
806
+ if (existingSet !== undefined && !existingSet.has(value)) {
807
+ context.contradiction = true;
808
+ }
756
809
  context.eqLiterals.set(key, value);
810
+ context.literalSets.set(key, new Set([value]));
757
811
  };
758
812
  var addNeqLiteral = (context, key, value) => {
759
813
  addNonNull(context, key);
@@ -764,6 +818,18 @@ var addNeqLiteral = (context, key, value) => {
764
818
  values.add(value);
765
819
  context.neqLiterals.set(key, values);
766
820
  };
821
+ var addLiteralSet = (context, key, values) => {
822
+ addNonNull(context, key);
823
+ const existingEq = context.eqLiterals.get(key);
824
+ if (existingEq !== undefined && !values.has(existingEq)) {
825
+ context.contradiction = true;
826
+ }
827
+ const existing = context.literalSets.get(key);
828
+ context.literalSets.set(key, existing === undefined ? new Set(values) : new Set(Array.from(existing).filter((value) => values.has(value))));
829
+ if (context.literalSets.get(key)?.size === 0) {
830
+ context.contradiction = true;
831
+ }
832
+ };
767
833
  var applyEqColumn = (context, left, right) => {
768
834
  const leftValue = context.eqLiterals.get(left);
769
835
  const rightValue = context.eqLiterals.get(right);
@@ -803,6 +869,9 @@ var applyAtom = (context, atom) => {
803
869
  case "neq-literal":
804
870
  addNeqLiteral(context, atom.key, atom.value);
805
871
  return;
872
+ case "literal-set":
873
+ addLiteralSet(context, atom.key, new Set(atom.values));
874
+ return;
806
875
  case "eq-column":
807
876
  applyEqColumn(context, atom.left, atom.right);
808
877
  return;
@@ -825,6 +894,9 @@ var applyNegativeAtom = (context, atom) => {
825
894
  case "neq-literal":
826
895
  addEqLiteral(context, atom.key, atom.value);
827
896
  return;
897
+ case "literal-set":
898
+ addNonNull(context, atom.key);
899
+ return;
828
900
  case "eq-column":
829
901
  addNonNull(context, atom.left);
830
902
  addNonNull(context, atom.right);
@@ -857,6 +929,17 @@ var intersectNeqLiterals = (left, right) => {
857
929
  }
858
930
  return result;
859
931
  };
932
+ var unionLiteralSets = (left, right) => {
933
+ const result = new Map;
934
+ for (const [key, leftValues] of left) {
935
+ const rightValues = right.get(key);
936
+ if (rightValues === undefined) {
937
+ continue;
938
+ }
939
+ result.set(key, new Set([...leftValues, ...rightValues]));
940
+ }
941
+ return result;
942
+ };
860
943
  var intersectContexts = (left, right) => {
861
944
  if (left.contradiction) {
862
945
  return cloneContext(right);
@@ -869,6 +952,7 @@ var intersectContexts = (left, right) => {
869
952
  nullKeys: new Set(Array.from(left.nullKeys).filter((key) => right.nullKeys.has(key))),
870
953
  eqLiterals: intersectEqLiterals(left.eqLiterals, right.eqLiterals),
871
954
  neqLiterals: intersectNeqLiterals(left.neqLiterals, right.neqLiterals),
955
+ literalSets: unionLiteralSets(left.literalSets, right.literalSets),
872
956
  sourceNames: new Set(Array.from(left.sourceNames).filter((name) => right.sourceNames.has(name))),
873
957
  contradiction: false,
874
958
  unknown: left.unknown || right.unknown
@@ -940,7 +1024,47 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
940
1024
  var astOf = (value) => value[TypeId3];
941
1025
  var columnKeyOfExpression = (value) => {
942
1026
  const ast = astOf(value);
943
- return ast.kind === "column" ? `${ast.tableName}.${ast.columnName}` : undefined;
1027
+ return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
1028
+ };
1029
+ var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
1030
+ var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
1031
+ var jsonPathPredicateKeyOfExpression = (value) => {
1032
+ const ast = astOf(value);
1033
+ switch (ast.kind) {
1034
+ case "jsonGetText":
1035
+ case "jsonPathText":
1036
+ case "jsonAccessText":
1037
+ case "jsonTraverseText": {
1038
+ const jsonAst = ast;
1039
+ const segments = jsonAst.segments;
1040
+ if (segments.length === 0 || segments.length > 8) {
1041
+ return;
1042
+ }
1043
+ const path = [];
1044
+ for (const segment of segments) {
1045
+ if (typeof segment !== "object" || segment === null || segment.kind !== "key") {
1046
+ return;
1047
+ }
1048
+ path.push(segment.key);
1049
+ }
1050
+ if (path.length === 0) {
1051
+ return;
1052
+ }
1053
+ const baseKey = columnKeyOfExpression(jsonAst.base);
1054
+ return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
1055
+ }
1056
+ default:
1057
+ return;
1058
+ }
1059
+ };
1060
+ var predicateKeyOfExpression = (value) => columnKeyOfExpression(value) ?? castPredicateKeyOfExpression(value) ?? jsonPathPredicateKeyOfExpression(value);
1061
+ var castPredicateKeyOfExpression = (value) => {
1062
+ const ast = astOf(value);
1063
+ if (ast.kind !== "cast") {
1064
+ return;
1065
+ }
1066
+ const source = ast.value;
1067
+ return sameDbType(source[TypeId2].dbType, ast.target) ? predicateKeyOfExpression(source) : undefined;
944
1068
  };
945
1069
  var valueKeyOfLiteral = (value) => {
946
1070
  if (typeof value === "string") {
@@ -961,7 +1085,7 @@ var valueKeyOfLiteral = (value) => {
961
1085
  return "unknown";
962
1086
  };
963
1087
  var nonNullFactsOfExpression = (value) => {
964
- const key = columnKeyOfExpression(value);
1088
+ const key = predicateKeyOfExpression(value);
965
1089
  return key === undefined ? undefined : atomFormula({ kind: "is-not-null", key });
966
1090
  };
967
1091
  var combineFacts = (left, right) => {
@@ -974,8 +1098,8 @@ var combineFacts = (left, right) => {
974
1098
  return andFormula(left, right);
975
1099
  };
976
1100
  var formulaOfEq = (left, right) => {
977
- const leftKey = columnKeyOfExpression(left);
978
- const rightKey = columnKeyOfExpression(right);
1101
+ const leftKey = predicateKeyOfExpression(left);
1102
+ const rightKey = predicateKeyOfExpression(right);
979
1103
  const leftAst = astOf(left);
980
1104
  const rightAst = astOf(right);
981
1105
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1022,8 +1146,8 @@ var formulaOfEq = (left, right) => {
1022
1146
  });
1023
1147
  };
1024
1148
  var formulaOfNeq = (left, right) => {
1025
- const leftKey = columnKeyOfExpression(left);
1026
- const rightKey = columnKeyOfExpression(right);
1149
+ const leftKey = predicateKeyOfExpression(left);
1150
+ const rightKey = predicateKeyOfExpression(right);
1027
1151
  const leftAst = astOf(left);
1028
1152
  const rightAst = astOf(right);
1029
1153
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1066,8 +1190,8 @@ var formulaOfNeq = (left, right) => {
1066
1190
  return combineFacts(nonNullFactsOfExpression(left), nonNullFactsOfExpression(right));
1067
1191
  };
1068
1192
  var formulaOfIsNotDistinctFrom = (left, right) => {
1069
- const leftKey = columnKeyOfExpression(left);
1070
- const rightKey = columnKeyOfExpression(right);
1193
+ const leftKey = predicateKeyOfExpression(left);
1194
+ const rightKey = predicateKeyOfExpression(right);
1071
1195
  const leftAst = astOf(left);
1072
1196
  const rightAst = astOf(right);
1073
1197
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1173,11 +1297,11 @@ var formulaOfExpression = (value) => {
1173
1297
  }
1174
1298
  return unknownTag("literal:non-boolean");
1175
1299
  case "isNull": {
1176
- const key = columnKeyOfExpression(ast.value);
1300
+ const key = predicateKeyOfExpression(ast.value);
1177
1301
  return key === undefined ? unknownTag("isNull:unsupported") : atomFormula({ kind: "is-null", key });
1178
1302
  }
1179
1303
  case "isNotNull": {
1180
- const key = columnKeyOfExpression(ast.value);
1304
+ const key = predicateKeyOfExpression(ast.value);
1181
1305
  return key === undefined ? unknownTag("isNotNull:unsupported") : atomFormula({ kind: "is-not-null", key });
1182
1306
  }
1183
1307
  case "not":
@@ -1196,7 +1320,15 @@ var formulaOfExpression = (value) => {
1196
1320
  return anyFormula(ast.values.map((value2) => formulaOfExpression(value2)));
1197
1321
  case "in": {
1198
1322
  const [left, ...rest] = ast.values;
1199
- return left === undefined ? falseFormula() : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
1323
+ if (left === undefined) {
1324
+ return falseFormula();
1325
+ }
1326
+ const key = predicateKeyOfExpression(left);
1327
+ const literalValues = rest.map((entry) => {
1328
+ const entryAst = astOf(entry);
1329
+ return entryAst.kind === "literal" && entryAst.value !== null ? valueKeyOfLiteral(entryAst.value) : undefined;
1330
+ });
1331
+ return key !== undefined && literalValues.every((entry) => entry !== undefined) ? atomFormula({ kind: "literal-set", key, values: literalValues }) : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
1200
1332
  }
1201
1333
  case "notIn": {
1202
1334
  const [left, ...rest] = ast.values;
@@ -1264,6 +1396,7 @@ var makeExpression = (state, ast) => {
1264
1396
  runtime: state.runtime,
1265
1397
  dbType: state.dbType,
1266
1398
  runtimeSchema: state.runtimeSchema,
1399
+ driverValueMapping: state.driverValueMapping,
1267
1400
  nullability: state.nullability,
1268
1401
  dialect: state.dialect,
1269
1402
  kind: state.kind ?? "scalar",
@@ -1272,7 +1405,7 @@ var makeExpression = (state, ast) => {
1272
1405
  expression[TypeId3] = ast;
1273
1406
  return expression;
1274
1407
  };
1275
- var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState) => {
1408
+ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState, _facts) => {
1276
1409
  const plan = Object.create(PlanProto);
1277
1410
  Object.defineProperty(plan, "pipe", {
1278
1411
  configurable: true,
@@ -1288,89 +1421,1845 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
1288
1421
  availableNames: undefined,
1289
1422
  grouped: undefined,
1290
1423
  assumptions: _assumptions ?? trueFormula(),
1424
+ facts: _facts ?? undefined,
1291
1425
  capabilities: undefined,
1292
1426
  statement: _statement ?? "select",
1293
1427
  target: _target ?? undefined,
1294
1428
  insertSource: _insertState ?? "ready"
1295
1429
  };
1296
- return plan;
1430
+ return plan;
1431
+ };
1432
+ var getAst = (plan) => plan[TypeId6];
1433
+ var getQueryState = (plan) => plan[QueryTypeId];
1434
+ var extractRequiredRuntime = (selection) => {
1435
+ const required = new Set;
1436
+ const visit = (value) => {
1437
+ if (TypeId2 in value) {
1438
+ for (const tableName of Object.keys(value[TypeId2].dependencies)) {
1439
+ required.add(tableName);
1440
+ }
1441
+ return;
1442
+ }
1443
+ for (const nested of Object.values(value)) {
1444
+ visit(nested);
1445
+ }
1446
+ };
1447
+ visit(selection);
1448
+ return [...required];
1449
+ };
1450
+ var extractSingleSelectedExpressionRuntime = (selection) => {
1451
+ const keys = Object.keys(selection);
1452
+ if (keys.length !== 1) {
1453
+ throw new Error("scalar subqueries must select exactly one top-level expression");
1454
+ }
1455
+ const record = selection;
1456
+ const value = record[keys[0]];
1457
+ if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
1458
+ throw new Error("scalar subqueries must select a scalar expression");
1459
+ }
1460
+ return value;
1461
+ };
1462
+ var currentRequiredList = (required) => Array.isArray(required) ? [...required] : required === undefined ? [] : [required];
1463
+
1464
+ // src/internal/json/path.ts
1465
+ var SegmentTypeId = Symbol.for("effect-qb/JsonPathSegment");
1466
+ var TypeId7 = Symbol.for("effect-qb/JsonPath");
1467
+ var makeSegment = (segment) => segment;
1468
+ var key = (value) => makeSegment({
1469
+ [SegmentTypeId]: {
1470
+ kind: "key"
1471
+ },
1472
+ kind: "key",
1473
+ key: value
1474
+ });
1475
+ var index2 = (value) => makeSegment({
1476
+ [SegmentTypeId]: {
1477
+ kind: "index"
1478
+ },
1479
+ kind: "index",
1480
+ index: value
1481
+ });
1482
+ var wildcard = () => makeSegment({
1483
+ [SegmentTypeId]: {
1484
+ kind: "wildcard"
1485
+ },
1486
+ kind: "wildcard"
1487
+ });
1488
+ var slice = (start, end) => makeSegment({
1489
+ [SegmentTypeId]: {
1490
+ kind: "slice"
1491
+ },
1492
+ kind: "slice",
1493
+ start,
1494
+ end
1495
+ });
1496
+ var descend = () => makeSegment({
1497
+ [SegmentTypeId]: {
1498
+ kind: "descend"
1499
+ },
1500
+ kind: "descend"
1501
+ });
1502
+ var path = (...segments) => ({
1503
+ [TypeId7]: {
1504
+ segments
1505
+ },
1506
+ segments
1507
+ });
1508
+
1509
+ // src/internal/dsl-plan-runtime.ts
1510
+ var renderSelectLockMode = (mode) => {
1511
+ switch (mode) {
1512
+ case "update":
1513
+ return "for update";
1514
+ case "share":
1515
+ return "for share";
1516
+ }
1517
+ throw new Error("lock(...) mode must be update or share for select statements");
1518
+ };
1519
+ var renderMysqlMutationLockMode = (mode, statement) => {
1520
+ switch (mode) {
1521
+ case "lowPriority":
1522
+ return " low_priority";
1523
+ case "ignore":
1524
+ return " ignore";
1525
+ case "quick":
1526
+ if (statement === "delete") {
1527
+ return " quick";
1528
+ }
1529
+ break;
1530
+ }
1531
+ throw new Error(statement === "update" ? "lock(...) mode must be lowPriority or ignore for update statements" : "lock(...) mode must be lowPriority, quick, or ignore for delete statements");
1532
+ };
1533
+ var makeDslPlanRuntime = (ctx) => {
1534
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
1535
+ const isRecord = (value) => typeof value === "object" && value !== null;
1536
+ const isPlan = (value) => isRecord(value) && (TypeId in value);
1537
+ const hasColumnRecord = (value) => isRecord(value.columns);
1538
+ const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
1539
+ const isAliasedSource = (source) => {
1540
+ if (!isRecord(source)) {
1541
+ return false;
1542
+ }
1543
+ if (TypeId4 in source) {
1544
+ return true;
1545
+ }
1546
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
1547
+ return false;
1548
+ }
1549
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
1550
+ return false;
1551
+ }
1552
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
1553
+ return false;
1554
+ }
1555
+ switch (source.kind) {
1556
+ case "derived":
1557
+ case "cte":
1558
+ case "lateral":
1559
+ return isPlan(source.plan) && hasColumnRecord(source);
1560
+ case "values":
1561
+ return Array.isArray(source.rows) && hasColumnRecord(source);
1562
+ case "unnest":
1563
+ return isRecord(source.arrays) && hasColumnRecord(source);
1564
+ case "tableFunction":
1565
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
1566
+ }
1567
+ return false;
1568
+ };
1569
+ const assertAliasedSource = (source, message) => {
1570
+ if (!isAliasedSource(source)) {
1571
+ throw new Error(message);
1572
+ }
1573
+ };
1574
+ const assertPlanComplete = (plan) => {
1575
+ const required = ctx.currentRequiredList(plan[TypeId].required);
1576
+ if (required.length > 0) {
1577
+ throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
1578
+ }
1579
+ };
1580
+ const assertSourceNameAvailable = (available, sourceName) => {
1581
+ if (sourceName in available) {
1582
+ throw new Error(`query source name is already in scope: ${sourceName}`);
1583
+ }
1584
+ };
1585
+ const assertSelectHasBaseSourceForJoin = (statement, available) => {
1586
+ if (statement === "select" && Object.keys(available).length === 0) {
1587
+ throw new Error("select joins require a from(...) source before joining");
1588
+ }
1589
+ };
1590
+ const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
1591
+ const assertSetOperandStatement = (plan) => {
1592
+ const statement = ctx.getQueryState(plan).statement;
1593
+ if (statement !== "select" && statement !== "set") {
1594
+ throw new Error("set operator operands only accept select-like query plans");
1595
+ }
1596
+ };
1597
+ const buildSetOperation = (kind, all, left, right) => {
1598
+ assertSetOperandStatement(left);
1599
+ assertSetOperandStatement(right);
1600
+ assertPlanComplete(left);
1601
+ assertPlanComplete(right);
1602
+ const leftState = left[TypeId];
1603
+ const leftAst = ctx.getAst(left);
1604
+ const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
1605
+ const leftOperations = leftAst.kind === "set" ? [...leftAst.setOperations ?? []] : [];
1606
+ return ctx.makePlan({
1607
+ selection: leftState.selection,
1608
+ required: undefined,
1609
+ available: {},
1610
+ dialect: leftState.dialect ?? right[TypeId].dialect
1611
+ }, {
1612
+ kind: "set",
1613
+ select: leftState.selection,
1614
+ where: [],
1615
+ having: [],
1616
+ joins: [],
1617
+ groupBy: [],
1618
+ orderBy: [],
1619
+ setBase: basePlan,
1620
+ setOperations: [
1621
+ ...leftOperations,
1622
+ {
1623
+ kind,
1624
+ all,
1625
+ query: right
1626
+ }
1627
+ ]
1628
+ }, undefined, undefined, "set");
1629
+ };
1630
+ const where = (predicate) => (plan) => {
1631
+ const current = plan[TypeId];
1632
+ const currentAst = ctx.getAst(plan);
1633
+ const currentQuery = ctx.getQueryState(plan);
1634
+ const predicateExpression = ctx.toDialectExpression(predicate);
1635
+ const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
1636
+ return ctx.makePlan({
1637
+ selection: current.selection,
1638
+ required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1639
+ available: current.available,
1640
+ dialect: current.dialect ?? predicateExpression[TypeId2].dialect
1641
+ }, {
1642
+ ...currentAst,
1643
+ where: [...currentAst.where, {
1644
+ kind: "where",
1645
+ predicate: predicateExpression
1646
+ }]
1647
+ }, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
1648
+ };
1649
+ const from = (source) => (plan) => {
1650
+ const current = plan[TypeId];
1651
+ const currentAst = ctx.getAst(plan);
1652
+ const currentQuery = ctx.getQueryState(plan);
1653
+ if (currentQuery.statement === "insert") {
1654
+ return ctx.attachInsertSource(plan, source);
1655
+ }
1656
+ assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
1657
+ if (currentQuery.statement === "select" && currentAst.from !== undefined) {
1658
+ throw new Error("select statements accept only one from(...) source; use joins for additional sources");
1659
+ }
1660
+ const sourceLike = source;
1661
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
1662
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
1663
+ const sourceRequired = sourceRequiredList(sourceLike);
1664
+ assertSourceNameAvailable(current.available, sourceName);
1665
+ if (currentQuery.statement === "select") {
1666
+ const nextAvailable = {
1667
+ [sourceName]: {
1668
+ name: sourceName,
1669
+ mode: "required",
1670
+ baseName: sourceBaseName,
1671
+ _presentFormula: ctx.trueFormula(),
1672
+ _presenceWitnesses: presenceWitnesses
1673
+ }
1674
+ };
1675
+ return ctx.makePlan({
1676
+ selection: current.selection,
1677
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1678
+ available: nextAvailable,
1679
+ dialect: current.dialect
1680
+ }, {
1681
+ ...currentAst,
1682
+ from: {
1683
+ kind: "from",
1684
+ tableName: sourceName,
1685
+ baseTableName: sourceBaseName,
1686
+ source: sourceLike
1687
+ }
1688
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1689
+ }
1690
+ if (currentQuery.statement === "update") {
1691
+ const nextAvailable = {
1692
+ ...current.available,
1693
+ [sourceName]: {
1694
+ name: sourceName,
1695
+ mode: "required",
1696
+ baseName: sourceBaseName,
1697
+ _presentFormula: ctx.trueFormula(),
1698
+ _presenceWitnesses: presenceWitnesses
1699
+ }
1700
+ };
1701
+ return ctx.makePlan({
1702
+ selection: current.selection,
1703
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1704
+ available: nextAvailable,
1705
+ dialect: current.dialect
1706
+ }, {
1707
+ ...currentAst,
1708
+ fromSources: [
1709
+ ...currentAst.fromSources ?? [],
1710
+ {
1711
+ kind: "from",
1712
+ tableName: sourceName,
1713
+ baseTableName: sourceBaseName,
1714
+ source: sourceLike
1715
+ }
1716
+ ]
1717
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1718
+ }
1719
+ throw new Error(`from(...) is not supported for ${currentQuery.statement} statements`);
1720
+ };
1721
+ const having = (predicate) => (plan) => {
1722
+ const current = plan[TypeId];
1723
+ const currentAst = ctx.getAst(plan);
1724
+ const currentQuery = ctx.getQueryState(plan);
1725
+ const predicateExpression = ctx.toDialectExpression(predicate);
1726
+ const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
1727
+ return ctx.makePlan({
1728
+ selection: current.selection,
1729
+ required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1730
+ available: current.available,
1731
+ dialect: current.dialect ?? predicateExpression[TypeId2].dialect
1732
+ }, {
1733
+ ...currentAst,
1734
+ having: [...currentAst.having, {
1735
+ kind: "having",
1736
+ predicate: predicateExpression
1737
+ }]
1738
+ }, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
1739
+ };
1740
+ const crossJoin = (table) => (plan) => {
1741
+ const current = plan[TypeId];
1742
+ const currentAst = ctx.getAst(plan);
1743
+ const currentQuery = ctx.getQueryState(plan);
1744
+ if (supportsJoinSources(currentQuery.statement)) {
1745
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1746
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1747
+ }
1748
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1749
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1750
+ const sourceRequired = sourceRequiredList(table);
1751
+ if (supportsJoinSources(currentQuery.statement)) {
1752
+ assertSourceNameAvailable(current.available, sourceName);
1753
+ }
1754
+ const nextAvailable = {
1755
+ ...current.available,
1756
+ [sourceName]: {
1757
+ name: sourceName,
1758
+ mode: "required",
1759
+ baseName: sourceBaseName,
1760
+ _presentFormula: ctx.trueFormula(),
1761
+ _presenceWitnesses: presenceWitnesses
1762
+ }
1763
+ };
1764
+ return ctx.makePlan({
1765
+ selection: current.selection,
1766
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1767
+ available: nextAvailable,
1768
+ dialect: current.dialect ?? table[TypeId]?.dialect ?? table.dialect
1769
+ }, {
1770
+ ...currentAst,
1771
+ joins: [...currentAst.joins, {
1772
+ kind: "cross",
1773
+ tableName: sourceName,
1774
+ baseTableName: sourceBaseName,
1775
+ source: table
1776
+ }]
1777
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1778
+ };
1779
+ const join = (kind, table, on) => (plan) => {
1780
+ const current = plan[TypeId];
1781
+ const currentAst = ctx.getAst(plan);
1782
+ const currentQuery = ctx.getQueryState(plan);
1783
+ const onExpression = ctx.toDialectExpression(on);
1784
+ const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
1785
+ if (supportsJoinSources(currentQuery.statement)) {
1786
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1787
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1788
+ }
1789
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1790
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1791
+ const sourceRequired = sourceRequiredList(table);
1792
+ if (supportsJoinSources(currentQuery.statement)) {
1793
+ assertSourceNameAvailable(current.available, sourceName);
1794
+ }
1795
+ const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
1796
+ name: source.name,
1797
+ mode: "optional",
1798
+ baseName: source.baseName,
1799
+ _presentFormula: source._presentFormula,
1800
+ _presenceWitnesses: source._presenceWitnesses
1801
+ }])) : current.available;
1802
+ const nextAvailable = {
1803
+ ...baseAvailable,
1804
+ [sourceName]: {
1805
+ name: sourceName,
1806
+ mode: kind === "left" || kind === "full" ? "optional" : "required",
1807
+ baseName: sourceBaseName,
1808
+ _presentFormula: kind === "inner" || kind === "left" ? onFormula : ctx.trueFormula(),
1809
+ _presenceWitnesses: presenceWitnesses
1810
+ }
1811
+ };
1812
+ return ctx.makePlan({
1813
+ selection: current.selection,
1814
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1815
+ available: nextAvailable,
1816
+ dialect: current.dialect ?? table.dialect ?? onExpression[TypeId2].dialect
1817
+ }, {
1818
+ ...currentAst,
1819
+ joins: [...currentAst.joins, {
1820
+ kind,
1821
+ tableName: sourceName,
1822
+ baseTableName: sourceBaseName,
1823
+ source: table,
1824
+ on: onExpression
1825
+ }]
1826
+ }, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1827
+ };
1828
+ const orderBy = (value, direction = "asc") => (plan) => {
1829
+ if (direction !== "asc" && direction !== "desc") {
1830
+ throw new Error("orderBy(...) direction must be asc or desc");
1831
+ }
1832
+ const current = plan[TypeId];
1833
+ const currentAst = ctx.getAst(plan);
1834
+ const currentQuery = ctx.getQueryState(plan);
1835
+ const expression = ctx.toDialectExpression(value);
1836
+ const required = ctx.extractRequiredFromDialectInputRuntime(value);
1837
+ return ctx.makePlan({
1838
+ selection: current.selection,
1839
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1840
+ available: current.available,
1841
+ dialect: current.dialect ?? expression[TypeId2].dialect
1842
+ }, {
1843
+ ...currentAst,
1844
+ orderBy: [...currentAst.orderBy, {
1845
+ kind: "orderBy",
1846
+ value: expression,
1847
+ direction
1848
+ }]
1849
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1850
+ };
1851
+ const lock = (mode, options2 = {}) => (plan) => {
1852
+ const current = plan[TypeId];
1853
+ const currentAst = ctx.getAst(plan);
1854
+ const currentQuery = ctx.getQueryState(plan);
1855
+ if (currentQuery.statement === "select") {
1856
+ renderSelectLockMode(mode);
1857
+ }
1858
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
1859
+ renderMysqlMutationLockMode(mode, "update");
1860
+ }
1861
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
1862
+ renderMysqlMutationLockMode(mode, "delete");
1863
+ }
1864
+ return ctx.makePlan({
1865
+ selection: current.selection,
1866
+ required: current.required,
1867
+ available: current.available,
1868
+ dialect: current.dialect
1869
+ }, {
1870
+ ...currentAst,
1871
+ lock: {
1872
+ kind: "lock",
1873
+ mode,
1874
+ nowait: options2.nowait ?? false,
1875
+ skipLocked: options2.skipLocked ?? false
1876
+ }
1877
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1878
+ };
1879
+ const distinct = () => (plan) => {
1880
+ const current = plan[TypeId];
1881
+ const currentAst = ctx.getAst(plan);
1882
+ const currentQuery = ctx.getQueryState(plan);
1883
+ return ctx.makePlan({
1884
+ selection: current.selection,
1885
+ required: current.required,
1886
+ available: current.available,
1887
+ dialect: current.dialect
1888
+ }, {
1889
+ ...currentAst,
1890
+ distinct: true
1891
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1892
+ };
1893
+ const limit = (value) => (plan) => {
1894
+ const current = plan[TypeId];
1895
+ const currentAst = ctx.getAst(plan);
1896
+ const currentQuery = ctx.getQueryState(plan);
1897
+ const expression = ctx.toDialectNumericExpression(value);
1898
+ const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
1899
+ return ctx.makePlan({
1900
+ selection: current.selection,
1901
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1902
+ available: current.available,
1903
+ dialect: current.dialect ?? expression[TypeId2].dialect
1904
+ }, {
1905
+ ...currentAst,
1906
+ limit: expression
1907
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1908
+ };
1909
+ const offset = (value) => (plan) => {
1910
+ const current = plan[TypeId];
1911
+ const currentAst = ctx.getAst(plan);
1912
+ const currentQuery = ctx.getQueryState(plan);
1913
+ const expression = ctx.toDialectNumericExpression(value);
1914
+ const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
1915
+ return ctx.makePlan({
1916
+ selection: current.selection,
1917
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1918
+ available: current.available,
1919
+ dialect: current.dialect ?? expression[TypeId2].dialect
1920
+ }, {
1921
+ ...currentAst,
1922
+ offset: expression
1923
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1924
+ };
1925
+ return {
1926
+ buildSetOperation,
1927
+ where,
1928
+ from,
1929
+ having,
1930
+ crossJoin,
1931
+ join,
1932
+ orderBy,
1933
+ lock,
1934
+ distinct,
1935
+ limit,
1936
+ offset
1937
+ };
1938
+ };
1939
+
1940
+ // src/internal/dsl-mutation-runtime.ts
1941
+ var expectInsertSourceKind = (source) => {
1942
+ if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
1943
+ throw new Error("Unsupported insert source kind");
1944
+ }
1945
+ return source;
1946
+ };
1947
+ var expectConflictClause = (conflict) => {
1948
+ if (conflict === undefined) {
1949
+ return conflict;
1950
+ }
1951
+ if (conflict.kind !== "conflict") {
1952
+ throw new Error("Unsupported conflict clause kind");
1953
+ }
1954
+ if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
1955
+ throw new Error("Unsupported conflict action");
1956
+ }
1957
+ if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
1958
+ throw new Error("Unsupported conflict target kind");
1959
+ }
1960
+ return conflict;
1961
+ };
1962
+ var makeDslMutationRuntime = (ctx) => {
1963
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
1964
+ const isRecord = (value) => typeof value === "object" && value !== null;
1965
+ const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId in target);
1966
+ const hasColumnRecord = (value) => isRecord(value.columns);
1967
+ const isAliasedSource = (source) => {
1968
+ if (!isRecord(source)) {
1969
+ return false;
1970
+ }
1971
+ if (isTableTarget(source)) {
1972
+ return true;
1973
+ }
1974
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
1975
+ return false;
1976
+ }
1977
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
1978
+ return false;
1979
+ }
1980
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
1981
+ return false;
1982
+ }
1983
+ switch (source.kind) {
1984
+ case "derived":
1985
+ case "cte":
1986
+ case "lateral":
1987
+ return isRecord(source.plan) && TypeId in source.plan && hasColumnRecord(source);
1988
+ case "values":
1989
+ return Array.isArray(source.rows) && hasColumnRecord(source);
1990
+ case "unnest":
1991
+ return isRecord(source.arrays) && hasColumnRecord(source);
1992
+ case "tableFunction":
1993
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
1994
+ }
1995
+ return false;
1996
+ };
1997
+ const assertMutationTarget = (target, apiName) => {
1998
+ if (!isTableTarget(target)) {
1999
+ throw new Error(`${apiName}(...) requires table targets`);
2000
+ }
2001
+ };
2002
+ const assertAliasedSource = (source, apiName) => {
2003
+ if (!isAliasedSource(source)) {
2004
+ throw new Error(`${apiName}(...) requires an aliased source`);
2005
+ }
2006
+ };
2007
+ const assertMutationTargets = (target, apiName, options2 = {}) => {
2008
+ const targets = Array.isArray(target) ? target : [target];
2009
+ if (targets.length === 0) {
2010
+ throw new Error(`${apiName}(...) requires at least one table target`);
2011
+ }
2012
+ if (Array.isArray(target) && targets.length === 1) {
2013
+ throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
2014
+ }
2015
+ for (const entry of targets) {
2016
+ assertMutationTarget(entry, apiName);
2017
+ }
2018
+ if (targets.length > 1 && options2.allowMultiple !== true) {
2019
+ throw new Error(`${apiName}(...) requires a single table target`);
2020
+ }
2021
+ if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
2022
+ throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
2023
+ }
2024
+ };
2025
+ const assertUniqueTargetNames = (targets) => {
2026
+ const seen = new Set;
2027
+ for (const target of targets) {
2028
+ if (seen.has(target.tableName)) {
2029
+ throw new Error(`mutation target source names must be unique: ${target.tableName}`);
2030
+ }
2031
+ seen.add(target.tableName);
2032
+ }
2033
+ };
2034
+ const assertInsertSelectSource = (sourcePlan, selection) => {
2035
+ const statement = ctx.getQueryState(sourcePlan).statement;
2036
+ if (statement !== "select" && statement !== "set") {
2037
+ throw new Error("insert sources only accept select-like query plans");
2038
+ }
2039
+ for (const value of Object.values(selection)) {
2040
+ if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
2041
+ throw new Error("insert sources require a flat selection object");
2042
+ }
2043
+ }
2044
+ };
2045
+ const insert = (target, values) => {
2046
+ assertMutationTargets(target, "insert");
2047
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2048
+ const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
2049
+ const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies));
2050
+ const insertState = values === undefined ? "missing" : "ready";
2051
+ return ctx.makePlan({
2052
+ selection: {},
2053
+ required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
2054
+ available: {
2055
+ [sourceName]: {
2056
+ name: sourceName,
2057
+ mode: "required",
2058
+ baseName: sourceBaseName
2059
+ }
2060
+ },
2061
+ dialect: target[TypeId].dialect
2062
+ }, {
2063
+ kind: "insert",
2064
+ select: {},
2065
+ into: {
2066
+ kind: "from",
2067
+ tableName: sourceName,
2068
+ baseTableName: sourceBaseName,
2069
+ source: target
2070
+ },
2071
+ values: assignments,
2072
+ conflict: undefined,
2073
+ where: [],
2074
+ having: [],
2075
+ joins: [],
2076
+ groupBy: [],
2077
+ orderBy: []
2078
+ }, undefined, "write", "insert", target, insertState);
2079
+ };
2080
+ const attachInsertSource = (plan, source) => {
2081
+ const current = plan[TypeId];
2082
+ const currentAst = ctx.getAst(plan);
2083
+ const currentQuery = ctx.getQueryState(plan);
2084
+ const target = currentQuery.target;
2085
+ const sourceName = currentAst.into.tableName;
2086
+ if (typeof source === "object" && source !== null && "kind" in source && source.kind === "values") {
2087
+ const normalized = ctx.buildInsertValuesRows(target, source.rows);
2088
+ return ctx.makePlan({
2089
+ selection: current.selection,
2090
+ required: normalized.required.filter((name) => name !== sourceName),
2091
+ available: current.available,
2092
+ dialect: current.dialect
2093
+ }, {
2094
+ ...currentAst,
2095
+ values: [],
2096
+ insertSource: {
2097
+ kind: "values",
2098
+ columns: normalized.columns,
2099
+ rows: normalized.rows
2100
+ }
2101
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2102
+ }
2103
+ if (typeof source === "object" && source !== null && "kind" in source && source.kind === "unnest") {
2104
+ const normalized = ctx.normalizeInsertUnnestValues(target, source.values);
2105
+ return ctx.makePlan({
2106
+ selection: current.selection,
2107
+ required: [],
2108
+ available: current.available,
2109
+ dialect: current.dialect
2110
+ }, {
2111
+ ...currentAst,
2112
+ values: [],
2113
+ insertSource: {
2114
+ kind: "unnest",
2115
+ columns: normalized.columns,
2116
+ values: normalized.values
2117
+ }
2118
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2119
+ }
2120
+ const sourcePlan = source;
2121
+ const selection = sourcePlan[TypeId].selection;
2122
+ assertInsertSelectSource(sourcePlan, selection);
2123
+ const columns = ctx.normalizeInsertSelectColumns(selection);
2124
+ return ctx.makePlan({
2125
+ selection: current.selection,
2126
+ required: ctx.currentRequiredList(sourcePlan[TypeId].required),
2127
+ available: current.available,
2128
+ dialect: current.dialect
2129
+ }, {
2130
+ ...currentAst,
2131
+ values: [],
2132
+ insertSource: {
2133
+ kind: "query",
2134
+ columns,
2135
+ query: sourcePlan
2136
+ }
2137
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2138
+ };
2139
+ const onConflict = (target, options2 = {}) => (plan) => {
2140
+ const current = plan[TypeId];
2141
+ const currentAst = ctx.getAst(plan);
2142
+ const currentQuery = ctx.getQueryState(plan);
2143
+ if (currentQuery.statement !== "insert") {
2144
+ throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
2145
+ }
2146
+ const insertTarget = currentAst.into.source;
2147
+ const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
2148
+ const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
2149
+ if (options2.update !== undefined && updateAssignments.length === 0) {
2150
+ throw new Error("conflict update assignments require at least one assignment");
2151
+ }
2152
+ const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
2153
+ const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
2154
+ const required = [
2155
+ ...ctx.currentRequiredList(current.required),
2156
+ ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2157
+ ...updateWhere ? Object.keys(updateWhere[TypeId2].dependencies) : [],
2158
+ ...targetWhere ? Object.keys(targetWhere[TypeId2].dependencies) : []
2159
+ ].filter((name, index3, list) => !(name in current.available) && list.indexOf(name) === index3);
2160
+ return ctx.makePlan({
2161
+ selection: current.selection,
2162
+ required,
2163
+ available: current.available,
2164
+ dialect: current.dialect
2165
+ }, {
2166
+ ...currentAst,
2167
+ conflict: {
2168
+ kind: "conflict",
2169
+ target: conflictTarget,
2170
+ action: updateAssignments.length === 0 ? "doNothing" : "doUpdate",
2171
+ values: updateAssignments.length === 0 ? undefined : updateAssignments,
2172
+ where: updateWhere
2173
+ }
2174
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
2175
+ };
2176
+ const update = (target, values) => {
2177
+ assertMutationTargets(target, "update", { allowMultiple: true });
2178
+ const targets = ctx.mutationTargetClauses(target);
2179
+ assertUniqueTargetNames(targets);
2180
+ const primaryTarget = targets[0];
2181
+ const assignments = ctx.buildMutationAssignments(target, values);
2182
+ const targetNames = new Set(targets.map((entry) => entry.tableName));
2183
+ const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)).filter((name, index3, list) => !targetNames.has(name) && list.indexOf(name) === index3);
2184
+ return ctx.makePlan({
2185
+ selection: {},
2186
+ required,
2187
+ available: ctx.mutationAvailableSources(target),
2188
+ dialect: primaryTarget.source[TypeId].dialect
2189
+ }, {
2190
+ kind: "update",
2191
+ select: {},
2192
+ target: primaryTarget,
2193
+ targets,
2194
+ set: assignments,
2195
+ where: [],
2196
+ having: [],
2197
+ joins: [],
2198
+ groupBy: [],
2199
+ orderBy: []
2200
+ }, undefined, "write", "update");
2201
+ };
2202
+ const upsert = (target, values, conflictColumns, updateValues) => {
2203
+ assertMutationTargets(target, "upsert");
2204
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2205
+ const assignments = ctx.buildMutationAssignments(target, values);
2206
+ const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
2207
+ if (updateValues !== undefined && updateAssignments.length === 0) {
2208
+ throw new Error("upsert update assignments require at least one assignment");
2209
+ }
2210
+ const required = [
2211
+ ...assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2212
+ ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies))
2213
+ ];
2214
+ return ctx.makePlan({
2215
+ selection: {},
2216
+ required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
2217
+ available: {
2218
+ [sourceName]: {
2219
+ name: sourceName,
2220
+ mode: "required",
2221
+ baseName: sourceBaseName
2222
+ }
2223
+ },
2224
+ dialect: target[TypeId].dialect
2225
+ }, {
2226
+ kind: "insert",
2227
+ select: {},
2228
+ into: {
2229
+ kind: "from",
2230
+ tableName: sourceName,
2231
+ baseTableName: sourceBaseName,
2232
+ source: target
2233
+ },
2234
+ values: assignments,
2235
+ conflict: {
2236
+ kind: "conflict",
2237
+ target: {
2238
+ kind: "columns",
2239
+ columns: ctx.normalizeConflictColumns(target, conflictColumns)
2240
+ },
2241
+ action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
2242
+ values: updateAssignments.length > 0 ? updateAssignments : undefined
2243
+ },
2244
+ where: [],
2245
+ having: [],
2246
+ joins: [],
2247
+ groupBy: [],
2248
+ orderBy: []
2249
+ }, undefined, "write", "insert", target, "ready");
2250
+ };
2251
+ const delete_ = (target) => {
2252
+ assertMutationTargets(target, "delete", { allowMultiple: true });
2253
+ const targets = ctx.mutationTargetClauses(target);
2254
+ assertUniqueTargetNames(targets);
2255
+ const primaryTarget = targets[0];
2256
+ return ctx.makePlan({
2257
+ selection: {},
2258
+ required: [],
2259
+ available: ctx.mutationAvailableSources(target),
2260
+ dialect: primaryTarget.source[TypeId].dialect
2261
+ }, {
2262
+ kind: "delete",
2263
+ select: {},
2264
+ target: primaryTarget,
2265
+ targets,
2266
+ where: [],
2267
+ having: [],
2268
+ joins: [],
2269
+ groupBy: [],
2270
+ orderBy: []
2271
+ }, undefined, "write", "delete");
2272
+ };
2273
+ const truncate = (target, options2 = {}) => {
2274
+ assertMutationTargets(target, "truncate");
2275
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2276
+ return ctx.makePlan({
2277
+ selection: {},
2278
+ required: [],
2279
+ available: {},
2280
+ dialect: target[TypeId].dialect
2281
+ }, {
2282
+ kind: "truncate",
2283
+ select: {},
2284
+ target: {
2285
+ kind: "from",
2286
+ tableName: sourceName,
2287
+ baseTableName: sourceBaseName,
2288
+ source: target
2289
+ },
2290
+ truncate: {
2291
+ kind: "truncate",
2292
+ restartIdentity: options2.restartIdentity ?? false,
2293
+ cascade: options2.cascade ?? false
2294
+ },
2295
+ where: [],
2296
+ having: [],
2297
+ joins: [],
2298
+ groupBy: [],
2299
+ orderBy: []
2300
+ }, undefined, "write", "truncate");
2301
+ };
2302
+ const merge = (target, source, on, options2 = {}) => {
2303
+ assertMutationTargets(target, "merge");
2304
+ assertAliasedSource(source, "merge");
2305
+ const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
2306
+ const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
2307
+ if (targetName === usingName) {
2308
+ throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
2309
+ }
2310
+ const onExpression = ctx.toDialectExpression(on);
2311
+ const matched = options2.whenMatched;
2312
+ const notMatched = options2.whenNotMatched;
2313
+ if (matched && "delete" in matched && "update" in matched) {
2314
+ throw new Error("merge whenMatched cannot specify both update and delete");
2315
+ }
2316
+ const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined;
2317
+ const matchedAssignments = matched && "update" in matched && matched.update ? ctx.buildMutationAssignments(target, matched.update) : [];
2318
+ const notMatchedPredicate = notMatched?.predicate ? ctx.toDialectExpression(notMatched.predicate) : undefined;
2319
+ const notMatchedAssignments = notMatched ? ctx.buildMutationAssignments(target, notMatched.values) : [];
2320
+ const required = [
2321
+ ...Object.keys(onExpression[TypeId2].dependencies),
2322
+ ...matchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2323
+ ...notMatchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2324
+ ...matchedPredicate ? Object.keys(matchedPredicate[TypeId2].dependencies) : [],
2325
+ ...notMatchedPredicate ? Object.keys(notMatchedPredicate[TypeId2].dependencies) : []
2326
+ ].filter((name, index3, values) => name !== targetName && name !== usingName && values.indexOf(name) === index3);
2327
+ return ctx.makePlan({
2328
+ selection: {},
2329
+ required,
2330
+ available: {
2331
+ [targetName]: {
2332
+ name: targetName,
2333
+ mode: "required",
2334
+ baseName: targetBaseName
2335
+ },
2336
+ [usingName]: {
2337
+ name: usingName,
2338
+ mode: "required",
2339
+ baseName: usingBaseName
2340
+ }
2341
+ },
2342
+ dialect: target[TypeId].dialect
2343
+ }, {
2344
+ kind: "merge",
2345
+ select: {},
2346
+ target: {
2347
+ kind: "from",
2348
+ tableName: targetName,
2349
+ baseTableName: targetBaseName,
2350
+ source: target
2351
+ },
2352
+ using: {
2353
+ kind: "from",
2354
+ tableName: usingName,
2355
+ baseTableName: usingBaseName,
2356
+ source
2357
+ },
2358
+ merge: {
2359
+ kind: "merge",
2360
+ on: onExpression,
2361
+ whenMatched: matched ? "delete" in matched && matched.delete ? {
2362
+ kind: "delete",
2363
+ predicate: matchedPredicate
2364
+ } : {
2365
+ kind: "update",
2366
+ values: matchedAssignments,
2367
+ predicate: matchedPredicate
2368
+ } : undefined,
2369
+ whenNotMatched: notMatched ? {
2370
+ kind: "insert",
2371
+ values: notMatchedAssignments,
2372
+ predicate: notMatchedPredicate
2373
+ } : undefined
2374
+ },
2375
+ where: [],
2376
+ having: [],
2377
+ joins: [],
2378
+ groupBy: [],
2379
+ orderBy: []
2380
+ }, undefined, "write", "merge");
2381
+ };
2382
+ return {
2383
+ insert,
2384
+ attachInsertSource,
2385
+ onConflict,
2386
+ update,
2387
+ upsert,
2388
+ delete_,
2389
+ truncate,
2390
+ merge
2391
+ };
2392
+ };
2393
+
2394
+ // src/internal/dsl-transaction-ddl-runtime.ts
2395
+ var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
2396
+ var renderTransactionIsolationLevel = (isolationLevel) => {
2397
+ if (isolationLevel === undefined) {
2398
+ return "";
2399
+ }
2400
+ if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
2401
+ throw new Error("Unsupported transaction isolation level");
2402
+ }
2403
+ return `isolation level ${isolationLevel}`;
2404
+ };
2405
+ var expectDdlClauseKind = (ddl, kind) => {
2406
+ if (ddl === undefined || ddl.kind !== kind) {
2407
+ throw new Error("Unsupported DDL statement kind");
2408
+ }
2409
+ return ddl;
2410
+ };
2411
+ var expectTruncateClause = (truncate) => {
2412
+ if (truncate === undefined || truncate.kind !== "truncate") {
2413
+ throw new Error("Unsupported truncate statement kind");
2414
+ }
2415
+ return truncate;
2416
+ };
2417
+ var validateIsolationLevel = (isolationLevel) => {
2418
+ renderTransactionIsolationLevel(isolationLevel);
2419
+ };
2420
+ var makeDslTransactionDdlRuntime = (ctx) => {
2421
+ const isRecord = (value) => typeof value === "object" && value !== null;
2422
+ const assertTableTarget = (target, apiName) => {
2423
+ if (!isRecord(target) || !(TypeId4 in target) || !(TypeId in target)) {
2424
+ throw new Error(`${apiName}(...) requires a table target`);
2425
+ }
2426
+ };
2427
+ const validateIndexColumns = (target, columns) => {
2428
+ const fields = target[TypeId4]?.fields;
2429
+ if (fields === undefined) {
2430
+ return;
2431
+ }
2432
+ for (const columnName of columns) {
2433
+ if (!(columnName in fields)) {
2434
+ throw new Error(`effect-qb: unknown index column '${columnName}'`);
2435
+ }
2436
+ }
2437
+ };
2438
+ const transaction = (options2 = {}) => {
2439
+ validateIsolationLevel(options2.isolationLevel);
2440
+ return ctx.makePlan({
2441
+ selection: {},
2442
+ required: [],
2443
+ available: {},
2444
+ dialect: ctx.profile.dialect
2445
+ }, {
2446
+ kind: "transaction",
2447
+ select: {},
2448
+ transaction: {
2449
+ kind: "transaction",
2450
+ isolationLevel: options2.isolationLevel,
2451
+ readOnly: options2.readOnly
2452
+ },
2453
+ where: [],
2454
+ having: [],
2455
+ joins: [],
2456
+ groupBy: [],
2457
+ orderBy: []
2458
+ }, undefined, "transaction", "transaction");
2459
+ };
2460
+ const commit = () => ctx.makePlan({
2461
+ selection: {},
2462
+ required: [],
2463
+ available: {},
2464
+ dialect: ctx.profile.dialect
2465
+ }, {
2466
+ kind: "commit",
2467
+ select: {},
2468
+ transaction: {
2469
+ kind: "commit"
2470
+ },
2471
+ where: [],
2472
+ having: [],
2473
+ joins: [],
2474
+ groupBy: [],
2475
+ orderBy: []
2476
+ }, undefined, "transaction", "commit");
2477
+ const rollback = () => ctx.makePlan({
2478
+ selection: {},
2479
+ required: [],
2480
+ available: {},
2481
+ dialect: ctx.profile.dialect
2482
+ }, {
2483
+ kind: "rollback",
2484
+ select: {},
2485
+ transaction: {
2486
+ kind: "rollback"
2487
+ },
2488
+ where: [],
2489
+ having: [],
2490
+ joins: [],
2491
+ groupBy: [],
2492
+ orderBy: []
2493
+ }, undefined, "transaction", "rollback");
2494
+ const savepoint = (name) => ctx.makePlan({
2495
+ selection: {},
2496
+ required: [],
2497
+ available: {},
2498
+ dialect: ctx.profile.dialect
2499
+ }, {
2500
+ kind: "savepoint",
2501
+ select: {},
2502
+ transaction: {
2503
+ kind: "savepoint",
2504
+ name
2505
+ },
2506
+ where: [],
2507
+ having: [],
2508
+ joins: [],
2509
+ groupBy: [],
2510
+ orderBy: []
2511
+ }, undefined, "transaction", "savepoint");
2512
+ const rollbackTo = (name) => ctx.makePlan({
2513
+ selection: {},
2514
+ required: [],
2515
+ available: {},
2516
+ dialect: ctx.profile.dialect
2517
+ }, {
2518
+ kind: "rollbackTo",
2519
+ select: {},
2520
+ transaction: {
2521
+ kind: "rollbackTo",
2522
+ name
2523
+ },
2524
+ where: [],
2525
+ having: [],
2526
+ joins: [],
2527
+ groupBy: [],
2528
+ orderBy: []
2529
+ }, undefined, "transaction", "rollbackTo");
2530
+ const releaseSavepoint = (name) => ctx.makePlan({
2531
+ selection: {},
2532
+ required: [],
2533
+ available: {},
2534
+ dialect: ctx.profile.dialect
2535
+ }, {
2536
+ kind: "releaseSavepoint",
2537
+ select: {},
2538
+ transaction: {
2539
+ kind: "releaseSavepoint",
2540
+ name
2541
+ },
2542
+ where: [],
2543
+ having: [],
2544
+ joins: [],
2545
+ groupBy: [],
2546
+ orderBy: []
2547
+ }, undefined, "transaction", "releaseSavepoint");
2548
+ const createTable = (target, options2 = {}) => {
2549
+ assertTableTarget(target, "createTable");
2550
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2551
+ return ctx.makePlan({
2552
+ selection: {},
2553
+ required: [],
2554
+ available: {},
2555
+ dialect: target[TypeId].dialect
2556
+ }, {
2557
+ kind: "createTable",
2558
+ select: {},
2559
+ target: {
2560
+ kind: "from",
2561
+ tableName: sourceName,
2562
+ baseTableName: sourceBaseName,
2563
+ source: target
2564
+ },
2565
+ ddl: {
2566
+ kind: "createTable",
2567
+ ifNotExists: options2.ifNotExists ?? false
2568
+ },
2569
+ where: [],
2570
+ having: [],
2571
+ joins: [],
2572
+ groupBy: [],
2573
+ orderBy: []
2574
+ }, undefined, "ddl", "createTable");
2575
+ };
2576
+ const dropTable = (target, options2 = {}) => {
2577
+ assertTableTarget(target, "dropTable");
2578
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2579
+ return ctx.makePlan({
2580
+ selection: {},
2581
+ required: [],
2582
+ available: {},
2583
+ dialect: target[TypeId].dialect
2584
+ }, {
2585
+ kind: "dropTable",
2586
+ select: {},
2587
+ target: {
2588
+ kind: "from",
2589
+ tableName: sourceName,
2590
+ baseTableName: sourceBaseName,
2591
+ source: target
2592
+ },
2593
+ ddl: {
2594
+ kind: "dropTable",
2595
+ ifExists: options2.ifExists ?? false
2596
+ },
2597
+ where: [],
2598
+ having: [],
2599
+ joins: [],
2600
+ groupBy: [],
2601
+ orderBy: []
2602
+ }, undefined, "ddl", "dropTable");
2603
+ };
2604
+ const createIndex = (target, columns, options2 = {}) => {
2605
+ assertTableTarget(target, "createIndex");
2606
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2607
+ validateIndexColumns(target, normalizedColumns);
2608
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2609
+ return ctx.makePlan({
2610
+ selection: {},
2611
+ required: [],
2612
+ available: {},
2613
+ dialect: target[TypeId].dialect
2614
+ }, {
2615
+ kind: "createIndex",
2616
+ select: {},
2617
+ target: {
2618
+ kind: "from",
2619
+ tableName: sourceName,
2620
+ baseTableName: sourceBaseName,
2621
+ source: target
2622
+ },
2623
+ ddl: {
2624
+ kind: "createIndex",
2625
+ name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options2.unique ?? false),
2626
+ columns: normalizedColumns,
2627
+ unique: options2.unique ?? false,
2628
+ ifNotExists: options2.ifNotExists ?? false
2629
+ },
2630
+ where: [],
2631
+ having: [],
2632
+ joins: [],
2633
+ groupBy: [],
2634
+ orderBy: []
2635
+ }, undefined, "ddl", "createIndex");
2636
+ };
2637
+ const dropIndex = (target, columns, options2 = {}) => {
2638
+ assertTableTarget(target, "dropIndex");
2639
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2640
+ validateIndexColumns(target, normalizedColumns);
2641
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2642
+ return ctx.makePlan({
2643
+ selection: {},
2644
+ required: [],
2645
+ available: {},
2646
+ dialect: target[TypeId].dialect
2647
+ }, {
2648
+ kind: "dropIndex",
2649
+ select: {},
2650
+ target: {
2651
+ kind: "from",
2652
+ tableName: sourceName,
2653
+ baseTableName: sourceBaseName,
2654
+ source: target
2655
+ },
2656
+ ddl: {
2657
+ kind: "dropIndex",
2658
+ name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
2659
+ ifExists: options2.ifExists ?? false
2660
+ },
2661
+ where: [],
2662
+ having: [],
2663
+ joins: [],
2664
+ groupBy: [],
2665
+ orderBy: []
2666
+ }, undefined, "ddl", "dropIndex");
2667
+ };
2668
+ return {
2669
+ transaction,
2670
+ commit,
2671
+ rollback,
2672
+ savepoint,
2673
+ rollbackTo,
2674
+ releaseSavepoint,
2675
+ createTable,
2676
+ dropTable,
2677
+ createIndex,
2678
+ dropIndex
2679
+ };
2680
+ };
2681
+
2682
+ // src/internal/runtime/driver-value-mapping.ts
2683
+ import * as Schema4 from "effect/Schema";
2684
+
2685
+ // src/internal/runtime/value.ts
2686
+ import * as Schema3 from "effect/Schema";
2687
+ var brandString = (pattern2, brand4) => Schema3.String.pipe(Schema3.pattern(pattern2), Schema3.brand(brand4));
2688
+ var localDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
2689
+ var isValidLocalDateString = (value) => {
2690
+ const match = localDatePattern.exec(value);
2691
+ if (match === null) {
2692
+ return false;
2693
+ }
2694
+ const year = Number(match[1]);
2695
+ const month = Number(match[2]);
2696
+ const day = Number(match[3]);
2697
+ const parsed = new Date(Date.UTC(year, month - 1, day));
2698
+ parsed.setUTCFullYear(year);
2699
+ return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
2700
+ };
2701
+ var localTimePattern = /^(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
2702
+ var isValidLocalTimeString = (value) => {
2703
+ const match = localTimePattern.exec(value);
2704
+ if (match === null) {
2705
+ return false;
2706
+ }
2707
+ const hour = Number(match[1]);
2708
+ const minute = Number(match[2]);
2709
+ const second = Number(match[3]);
2710
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
2711
+ };
2712
+ var offsetPattern = /^(?:Z|[+-](\d{2}):(\d{2}))$/;
2713
+ var isValidOffset = (value) => {
2714
+ const match = offsetPattern.exec(value);
2715
+ if (match === null) {
2716
+ return false;
2717
+ }
2718
+ if (value === "Z") {
2719
+ return true;
2720
+ }
2721
+ const hour = Number(match[1]);
2722
+ const minute = Number(match[2]);
2723
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59;
2724
+ };
2725
+ var offsetTimePattern = /^(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
2726
+ var isValidOffsetTimeString = (value) => {
2727
+ const match = offsetTimePattern.exec(value);
2728
+ return match !== null && isValidLocalTimeString(match[1]) && isValidOffset(match[2]);
2729
+ };
2730
+ var localDateTimePattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
2731
+ var isValidLocalDateTimeString = (value) => {
2732
+ const match = localDateTimePattern.exec(value);
2733
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]);
2734
+ };
2735
+ var instantPattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
2736
+ var isValidInstantString = (value) => {
2737
+ const match = instantPattern.exec(value);
2738
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]) && isValidOffset(match[3]);
2739
+ };
2740
+ var LocalDateStringSchema = Schema3.String.pipe(Schema3.pattern(localDatePattern), Schema3.filter(isValidLocalDateString), Schema3.brand("LocalDateString"));
2741
+ var LocalTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localTimePattern), Schema3.filter(isValidLocalTimeString), Schema3.brand("LocalTimeString"));
2742
+ var OffsetTimeStringSchema = Schema3.String.pipe(Schema3.pattern(offsetTimePattern), Schema3.filter(isValidOffsetTimeString), Schema3.brand("OffsetTimeString"));
2743
+ var LocalDateTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localDateTimePattern), Schema3.filter(isValidLocalDateTimeString), Schema3.brand("LocalDateTimeString"));
2744
+ var InstantStringSchema = Schema3.String.pipe(Schema3.pattern(instantPattern), Schema3.filter(isValidInstantString), Schema3.brand("InstantString"));
2745
+ var YearStringSchema = brandString(/^\d{4}$/, "YearString");
2746
+ var canonicalizeBigIntString = (input) => {
2747
+ const trimmed = input.trim();
2748
+ if (!/^-?\d+$/.test(trimmed)) {
2749
+ throw new Error("Expected an integer-like bigint value");
2750
+ }
2751
+ return BigInt(trimmed).toString();
2752
+ };
2753
+ var isCanonicalBigIntString = (value) => {
2754
+ try {
2755
+ return canonicalizeBigIntString(value) === value;
2756
+ } catch {
2757
+ return false;
2758
+ }
2759
+ };
2760
+ var canonicalizeDecimalString = (input) => {
2761
+ const trimmed = input.trim();
2762
+ const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
2763
+ if (match === null) {
2764
+ throw new Error("Expected a decimal string");
2765
+ }
2766
+ const sign = match[1] === "-" ? "-" : "";
2767
+ const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
2768
+ const fraction = (match[3] ?? "").replace(/0+$/, "");
2769
+ if (fraction.length === 0) {
2770
+ if (integer === "0") {
2771
+ return "0";
2772
+ }
2773
+ return `${sign}${integer}`;
2774
+ }
2775
+ return `${sign}${integer}.${fraction}`;
2776
+ };
2777
+ var isCanonicalDecimalString = (value) => {
2778
+ try {
2779
+ return canonicalizeDecimalString(value) === value;
2780
+ } catch {
2781
+ return false;
2782
+ }
2783
+ };
2784
+ var BigIntStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalBigIntString), Schema3.brand("BigIntString"));
2785
+ var DecimalStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalDecimalString), Schema3.brand("DecimalString"));
2786
+ var JsonValueSchema = Schema3.suspend(() => Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null, Schema3.Array(JsonValueSchema), Schema3.Record({
2787
+ key: Schema3.String,
2788
+ value: JsonValueSchema
2789
+ })));
2790
+ var JsonPrimitiveSchema = Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null);
2791
+
2792
+ // src/internal/runtime/normalize.ts
2793
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2794
+ var isPlainRecord = (value) => {
2795
+ if (!isRecord(value)) {
2796
+ return false;
2797
+ }
2798
+ const prototype = Object.getPrototypeOf(value);
2799
+ return prototype === Object.prototype || prototype === null;
2800
+ };
2801
+ var pad = (value, width = 2) => value.toString().padStart(width, "0");
2802
+ var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
2803
+ var formatLocalTime = (value) => {
2804
+ const milliseconds = value.getUTCMilliseconds();
2805
+ const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
2806
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
2807
+ };
2808
+ var formatLocalDateTime = (value) => {
2809
+ const milliseconds = value.getUTCMilliseconds();
2810
+ const base = `${formatLocalDate(value)}T${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
2811
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
2812
+ };
2813
+ var runtimeTagOfBaseDbType = (dbType) => {
2814
+ return dbType.runtime;
2815
+ };
2816
+ var expectString = (value, label) => {
2817
+ if (typeof value === "string") {
2818
+ return value;
2819
+ }
2820
+ throw new Error(`Expected ${label} as string`);
2821
+ };
2822
+ var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
2823
+ var normalizeNumber = (value) => {
2824
+ if (typeof value === "number" && Number.isFinite(value)) {
2825
+ return value;
2826
+ }
2827
+ if (typeof value === "string") {
2828
+ const trimmed = value.trim();
2829
+ const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
2830
+ if (Number.isFinite(parsed)) {
2831
+ return parsed;
2832
+ }
2833
+ }
2834
+ if (typeof value === "bigint" && Number.isSafeInteger(Number(value))) {
2835
+ return Number(value);
2836
+ }
2837
+ throw new Error("Expected a finite numeric value");
2838
+ };
2839
+ var normalizeBoolean = (value) => {
2840
+ if (typeof value === "boolean") {
2841
+ return value;
2842
+ }
2843
+ if (typeof value === "number") {
2844
+ if (value === 1) {
2845
+ return true;
2846
+ }
2847
+ if (value === 0) {
2848
+ return false;
2849
+ }
2850
+ }
2851
+ if (typeof value === "string") {
2852
+ const normalized = value.trim().toLowerCase();
2853
+ if (normalized === "true" || normalized === "t" || normalized === "1") {
2854
+ return true;
2855
+ }
2856
+ if (normalized === "false" || normalized === "f" || normalized === "0") {
2857
+ return false;
2858
+ }
2859
+ }
2860
+ throw new Error("Expected a boolean-like value");
2861
+ };
2862
+ var normalizeBigIntString = (value) => {
2863
+ if (typeof value === "bigint") {
2864
+ return value.toString();
2865
+ }
2866
+ if (typeof value === "number" && Number.isSafeInteger(value)) {
2867
+ return BigInt(value).toString();
2868
+ }
2869
+ if (typeof value === "string") {
2870
+ return canonicalizeBigIntString(value);
2871
+ }
2872
+ throw new Error("Expected an integer-like bigint value");
2873
+ };
2874
+ var normalizeDecimalString = (value) => {
2875
+ if (typeof value === "string") {
2876
+ return canonicalizeDecimalString(value);
2877
+ }
2878
+ if (typeof value === "number" && Number.isFinite(value)) {
2879
+ const rendered = String(value);
2880
+ if (/[eE]/.test(rendered)) {
2881
+ throw new Error("Scientific notation is not a supported decimal runtime");
2882
+ }
2883
+ return canonicalizeDecimalString(rendered);
2884
+ }
2885
+ throw new Error("Expected a decimal-like value");
2886
+ };
2887
+ var normalizeLocalDate = (value) => {
2888
+ if (value instanceof Date) {
2889
+ return formatLocalDate(value);
2890
+ }
2891
+ const raw = expectString(value, "local date").trim();
2892
+ if (isValidLocalDateString(raw)) {
2893
+ return raw;
2894
+ }
2895
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
2896
+ if (isValidInstantString(canonicalInstant)) {
2897
+ const parsed = new Date(canonicalInstant);
2898
+ if (!Number.isNaN(parsed.getTime())) {
2899
+ return formatLocalDate(parsed);
2900
+ }
2901
+ }
2902
+ throw new Error("Expected a local-date value");
2903
+ };
2904
+ var normalizeLocalTime = (value) => {
2905
+ if (value instanceof Date) {
2906
+ return formatLocalTime(value);
2907
+ }
2908
+ const raw = expectString(value, "local time").trim();
2909
+ if (isValidLocalTimeString(raw)) {
2910
+ return raw;
2911
+ }
2912
+ throw new Error("Expected a local-time value");
2913
+ };
2914
+ var normalizeOffsetTime = (value) => {
2915
+ if (value instanceof Date) {
2916
+ return `${formatLocalTime(value)}Z`;
2917
+ }
2918
+ const raw = expectString(value, "offset time").trim();
2919
+ if (isValidOffsetTimeString(raw)) {
2920
+ return raw;
2921
+ }
2922
+ throw new Error("Expected an offset-time value");
2923
+ };
2924
+ var normalizeLocalDateTime = (value) => {
2925
+ if (value instanceof Date) {
2926
+ return formatLocalDateTime(value);
2927
+ }
2928
+ const raw = expectString(value, "local datetime").trim();
2929
+ const canonicalLocalDateTime = raw.replace(" ", "T");
2930
+ if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
2931
+ return canonicalLocalDateTime;
2932
+ }
2933
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
2934
+ if (isValidInstantString(canonicalInstant)) {
2935
+ const parsed = new Date(canonicalInstant);
2936
+ if (!Number.isNaN(parsed.getTime())) {
2937
+ return formatLocalDateTime(parsed);
2938
+ }
2939
+ }
2940
+ throw new Error("Expected a local-datetime value");
2941
+ };
2942
+ var normalizeInstant = (value) => {
2943
+ if (value instanceof Date) {
2944
+ return value.toISOString();
2945
+ }
2946
+ const raw = expectString(value, "instant").trim();
2947
+ if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
2948
+ throw new Error("Instant values require a timezone offset");
2949
+ }
2950
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
2951
+ if (!isValidInstantString(canonicalInstant)) {
2952
+ throw new Error("Expected an ISO instant value");
2953
+ }
2954
+ const parsed = new Date(canonicalInstant);
2955
+ if (Number.isNaN(parsed.getTime())) {
2956
+ throw new Error("Expected an ISO instant value");
2957
+ }
2958
+ return parsed.toISOString();
2959
+ };
2960
+ var normalizeYear = (value) => {
2961
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 9999) {
2962
+ return pad(value, 4);
2963
+ }
2964
+ const raw = expectString(value, "year").trim();
2965
+ if (/^\d{4}$/.test(raw)) {
2966
+ return raw;
2967
+ }
2968
+ throw new Error("Expected a four-digit year");
2969
+ };
2970
+ var normalizeBytes = (value) => {
2971
+ if (value instanceof Uint8Array) {
2972
+ return new Uint8Array(value);
2973
+ }
2974
+ const BufferConstructor = globalThis.Buffer;
2975
+ if (BufferConstructor !== undefined && value instanceof BufferConstructor) {
2976
+ return new Uint8Array(value);
2977
+ }
2978
+ throw new Error("Expected a byte array value");
2979
+ };
2980
+ var isJsonValue = (value) => {
2981
+ if (value === null) {
2982
+ return true;
2983
+ }
2984
+ switch (typeof value) {
2985
+ case "string":
2986
+ case "boolean":
2987
+ return true;
2988
+ case "number":
2989
+ return Number.isFinite(value);
2990
+ case "object":
2991
+ if (Array.isArray(value)) {
2992
+ return value.every(isJsonValue);
2993
+ }
2994
+ return isPlainRecord(value) && Object.values(value).every(isJsonValue);
2995
+ default:
2996
+ return false;
2997
+ }
2998
+ };
2999
+ var normalizeJson = (value) => {
3000
+ if (typeof value === "string") {
3001
+ try {
3002
+ const parsed = JSON.parse(value);
3003
+ if (isJsonValue(parsed)) {
3004
+ return parsed;
3005
+ }
3006
+ throw new Error("Parsed JSON value is not a valid JSON runtime");
3007
+ } catch (error) {
3008
+ if (error instanceof SyntaxError) {
3009
+ return value;
3010
+ }
3011
+ throw error;
3012
+ }
3013
+ }
3014
+ if (isJsonValue(value)) {
3015
+ return value;
3016
+ }
3017
+ throw new Error("Expected a JSON value");
3018
+ };
3019
+ var normalizeDbValue = (dbType, value) => {
3020
+ if (value === null) {
3021
+ return null;
3022
+ }
3023
+ if ("base" in dbType) {
3024
+ return normalizeDbValue(dbType.base, value);
3025
+ }
3026
+ if ("element" in dbType) {
3027
+ if (!Array.isArray(value)) {
3028
+ throw new Error("Expected an array value");
3029
+ }
3030
+ return value.map((entry) => normalizeDbValue(dbType.element, entry));
3031
+ }
3032
+ if ("fields" in dbType) {
3033
+ if (!isRecord(value)) {
3034
+ throw new Error("Expected a record value");
3035
+ }
3036
+ const normalized = {};
3037
+ for (const [key2, fieldDbType] of Object.entries(dbType.fields)) {
3038
+ if (key2 in value) {
3039
+ normalized[key2] = normalizeDbValue(fieldDbType, value[key2]);
3040
+ }
3041
+ }
3042
+ return normalized;
3043
+ }
3044
+ if ("variant" in dbType && dbType.variant === "json") {
3045
+ return normalizeJson(value);
3046
+ }
3047
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
3048
+ return expectString(value, "text");
3049
+ }
3050
+ switch (runtimeTagOfBaseDbType(dbType)) {
3051
+ case "string":
3052
+ return expectString(value, "text");
3053
+ case "number":
3054
+ return normalizeNumber(value);
3055
+ case "bigintString":
3056
+ return normalizeBigIntString(value);
3057
+ case "boolean":
3058
+ return normalizeBoolean(value);
3059
+ case "json":
3060
+ return normalizeJson(value);
3061
+ case "localDate":
3062
+ return normalizeLocalDate(value);
3063
+ case "localTime":
3064
+ return normalizeLocalTime(value);
3065
+ case "offsetTime":
3066
+ return normalizeOffsetTime(value);
3067
+ case "localDateTime":
3068
+ return normalizeLocalDateTime(value);
3069
+ case "instant":
3070
+ return normalizeInstant(value);
3071
+ case "year":
3072
+ return normalizeYear(value);
3073
+ case "decimalString":
3074
+ return normalizeDecimalString(value);
3075
+ case "bytes":
3076
+ return normalizeBytes(value);
3077
+ case "array":
3078
+ if (!Array.isArray(value)) {
3079
+ throw new Error("Expected an array value");
3080
+ }
3081
+ return value;
3082
+ case "record":
3083
+ if (!isRecord(value)) {
3084
+ throw new Error("Expected a record value");
3085
+ }
3086
+ return value;
3087
+ case "null":
3088
+ return null;
3089
+ case "unknown":
3090
+ case undefined:
3091
+ return value;
3092
+ }
3093
+ };
3094
+
3095
+ // src/internal/runtime/driver-value-mapping.ts
3096
+ var runtimeTagOfDbType = (dbType) => {
3097
+ if (dbType === undefined) {
3098
+ return;
3099
+ }
3100
+ if ("base" in dbType) {
3101
+ return runtimeTagOfDbType(dbType.base);
3102
+ }
3103
+ if ("element" in dbType) {
3104
+ return "array";
3105
+ }
3106
+ if ("fields" in dbType) {
3107
+ return "record";
3108
+ }
3109
+ if ("variant" in dbType && dbType.variant === "json") {
3110
+ return "json";
3111
+ }
3112
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
3113
+ return "string";
3114
+ }
3115
+ return dbType.runtime;
3116
+ };
3117
+ var familyOfDbType = (dbType) => {
3118
+ if (dbType === undefined) {
3119
+ return;
3120
+ }
3121
+ if ("base" in dbType) {
3122
+ return familyOfDbType(dbType.base);
3123
+ }
3124
+ return dbType.family;
3125
+ };
3126
+ var mappingCandidates = (context) => {
3127
+ const dbType = context.dbType;
3128
+ const runtimeTag = runtimeTagOfDbType(dbType);
3129
+ const family = familyOfDbType(dbType);
3130
+ return [
3131
+ context.driverValueMapping,
3132
+ dbType?.driverValueMapping,
3133
+ dbType === undefined ? undefined : context.valueMappings?.[dbType.kind],
3134
+ family === undefined ? undefined : context.valueMappings?.[family],
3135
+ runtimeTag === undefined ? undefined : context.valueMappings?.[runtimeTag]
3136
+ ];
3137
+ };
3138
+ var findMapping = (context, key2) => {
3139
+ for (const candidate of mappingCandidates(context)) {
3140
+ const value = candidate?.[key2];
3141
+ if (value !== undefined) {
3142
+ return value;
3143
+ }
3144
+ }
3145
+ return;
3146
+ };
3147
+ var isJsonDbType = (dbType) => {
3148
+ if (dbType === undefined) {
3149
+ return false;
3150
+ }
3151
+ if ("base" in dbType) {
3152
+ return isJsonDbType(dbType.base);
3153
+ }
3154
+ if (!("variant" in dbType)) {
3155
+ return false;
3156
+ }
3157
+ const variant = dbType.variant;
3158
+ return variant === "json" || variant === "jsonb";
3159
+ };
3160
+ var schemaAccepts = (schema2, value) => schema2 !== undefined && Schema4.is(schema2)(value);
3161
+ var encodeWithSchema = (schema2, value) => {
3162
+ if (schema2 === undefined) {
3163
+ return { value, encoded: false };
3164
+ }
3165
+ if (!Schema4.is(schema2)(value)) {
3166
+ return { value, encoded: false };
3167
+ }
3168
+ return {
3169
+ value: Schema4.encodeUnknownSync(schema2)(value),
3170
+ encoded: true
3171
+ };
1297
3172
  };
1298
- var getAst = (plan) => plan[TypeId6];
1299
- var getQueryState = (plan) => plan[QueryTypeId];
1300
- var extractRequiredRuntime = (selection) => {
1301
- const required = new Set;
1302
- const visit = (value) => {
1303
- if (TypeId2 in value) {
1304
- for (const tableName of Object.keys(value[TypeId2].dependencies)) {
1305
- required.add(tableName);
1306
- }
1307
- return;
3173
+ var normalizeJsonDriverString = (value, context) => {
3174
+ if (!isJsonDbType(context.dbType) || context.runtimeSchema === undefined) {
3175
+ return;
3176
+ }
3177
+ try {
3178
+ const parsed = JSON.parse(value);
3179
+ if (value.trimStart().startsWith('"') && schemaAccepts(context.runtimeSchema, parsed)) {
3180
+ return parsed;
1308
3181
  }
1309
- for (const nested of Object.values(value)) {
1310
- visit(nested);
3182
+ if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
3183
+ return value;
1311
3184
  }
1312
- };
1313
- visit(selection);
1314
- return [...required];
3185
+ } catch (error) {
3186
+ if (error instanceof SyntaxError && schemaAccepts(context.runtimeSchema, value)) {
3187
+ return value;
3188
+ }
3189
+ if (!(error instanceof SyntaxError)) {
3190
+ throw error;
3191
+ }
3192
+ }
3193
+ return;
1315
3194
  };
1316
- var extractSingleSelectedExpressionRuntime = (selection) => {
1317
- const keys = Object.keys(selection);
1318
- if (keys.length !== 1) {
1319
- throw new Error("scalar subqueries must select exactly one top-level expression");
3195
+ var toDriverValue = (value, context) => {
3196
+ if (value === null) {
3197
+ return null;
1320
3198
  }
1321
- const record = selection;
1322
- const value = record[keys[0]];
1323
- if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
1324
- throw new Error("scalar subqueries must select a scalar expression");
3199
+ if (value instanceof Date && Number.isNaN(value.getTime())) {
3200
+ throw new Error("Expected a valid Date value");
1325
3201
  }
1326
- return value;
3202
+ const dbType = context.dbType;
3203
+ const encoded = encodeWithSchema(context.runtimeSchema, value);
3204
+ let current = encoded.value;
3205
+ const custom = findMapping(context, "toDriver");
3206
+ if (custom !== undefined && dbType !== undefined) {
3207
+ return custom(current, dbType);
3208
+ }
3209
+ if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
3210
+ return current;
3211
+ }
3212
+ return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
3213
+ };
3214
+ var fromDriverValue = (value, context) => {
3215
+ if (value === null) {
3216
+ return null;
3217
+ }
3218
+ const dbType = context.dbType;
3219
+ const custom = findMapping(context, "fromDriver");
3220
+ if (custom !== undefined && dbType !== undefined) {
3221
+ return custom(value, dbType);
3222
+ }
3223
+ if (typeof value === "string") {
3224
+ const normalizedJsonString = normalizeJsonDriverString(value, context);
3225
+ if (normalizedJsonString !== undefined) {
3226
+ return normalizedJsonString;
3227
+ }
3228
+ }
3229
+ return dbType === undefined ? value : normalizeDbValue(dbType, value);
3230
+ };
3231
+ var textCast = (sql) => `(${sql})::text`;
3232
+ var postgresJsonSql = (sql, dbType) => {
3233
+ const runtimeTag = runtimeTagOfDbType(dbType);
3234
+ switch (runtimeTag) {
3235
+ case "bigintString":
3236
+ case "decimalString":
3237
+ case "localDate":
3238
+ case "localTime":
3239
+ case "offsetTime":
3240
+ case "localDateTime":
3241
+ case "instant":
3242
+ case "year":
3243
+ return textCast(sql);
3244
+ case "bytes":
3245
+ return `encode(${sql}, 'base64')`;
3246
+ default:
3247
+ return sql;
3248
+ }
3249
+ };
3250
+ var renderSelectSql = (sql, context) => {
3251
+ const dbType = context.dbType;
3252
+ const custom = findMapping(context, "selectSql");
3253
+ return custom !== undefined && dbType !== undefined ? custom(sql, dbType) : sql;
3254
+ };
3255
+ var renderJsonSelectSql = (sql, context) => {
3256
+ const dbType = context.dbType;
3257
+ const custom = findMapping(context, "jsonSelectSql");
3258
+ if (custom !== undefined && dbType !== undefined) {
3259
+ return custom(sql, dbType);
3260
+ }
3261
+ return context.dialect === "postgres" && dbType !== undefined ? postgresJsonSql(sql, dbType) : sql;
1327
3262
  };
1328
- var currentRequiredList = (required) => Array.isArray(required) ? [...required] : required === undefined ? [] : [required];
1329
-
1330
- // src/internal/json/path.ts
1331
- var SegmentTypeId = Symbol.for("effect-qb/JsonPathSegment");
1332
- var TypeId7 = Symbol.for("effect-qb/JsonPath");
1333
- var makeSegment = (segment) => segment;
1334
- var key = (value) => makeSegment({
1335
- [SegmentTypeId]: {
1336
- kind: "key"
1337
- },
1338
- kind: "key",
1339
- key: value
1340
- });
1341
- var index2 = (value) => makeSegment({
1342
- [SegmentTypeId]: {
1343
- kind: "index"
1344
- },
1345
- kind: "index",
1346
- index: value
1347
- });
1348
- var wildcard = () => makeSegment({
1349
- [SegmentTypeId]: {
1350
- kind: "wildcard"
1351
- },
1352
- kind: "wildcard"
1353
- });
1354
- var slice = (start, end) => makeSegment({
1355
- [SegmentTypeId]: {
1356
- kind: "slice"
1357
- },
1358
- kind: "slice",
1359
- start,
1360
- end
1361
- });
1362
- var descend = () => makeSegment({
1363
- [SegmentTypeId]: {
1364
- kind: "descend"
1365
- },
1366
- kind: "descend"
1367
- });
1368
- var path = (...segments) => ({
1369
- [TypeId7]: {
1370
- segments
1371
- },
1372
- segments
1373
- });
1374
3263
 
1375
3264
  // src/internal/projection-alias.ts
1376
3265
  var TypeId8 = Symbol.for("effect-qb/ProjectionAlias");
@@ -1424,6 +3313,20 @@ var validateProjections = (projections) => {
1424
3313
  };
1425
3314
 
1426
3315
  // src/internal/grouping-key.ts
3316
+ var subqueryPlanIds = new WeakMap;
3317
+ var nextSubqueryPlanId = 0;
3318
+ var subqueryPlanGroupingKey = (plan) => {
3319
+ if (plan === null || typeof plan !== "object") {
3320
+ return "unknown";
3321
+ }
3322
+ const existing = subqueryPlanIds.get(plan);
3323
+ if (existing !== undefined) {
3324
+ return existing;
3325
+ }
3326
+ const next = `${nextSubqueryPlanId++}`;
3327
+ subqueryPlanIds.set(plan, next);
3328
+ return next;
3329
+ };
1427
3330
  var literalGroupingKey = (value) => {
1428
3331
  if (value instanceof Date) {
1429
3332
  return `date:${value.toISOString()}`;
@@ -1442,15 +3345,62 @@ var literalGroupingKey = (value) => {
1442
3345
  return `literal:${JSON.stringify(value)}`;
1443
3346
  }
1444
3347
  };
3348
+ var isExpression2 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3349
+ var expressionGroupingKey = (value) => isExpression2(value) ? groupingKeyOfExpression(value) : "missing";
3350
+ var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
3351
+ var jsonSegmentGroupingKey = (segment) => {
3352
+ if (segment !== null && typeof segment === "object" && "kind" in segment) {
3353
+ switch (segment.kind) {
3354
+ case "key":
3355
+ return `key:${escapeGroupingText(segment.key)}`;
3356
+ case "index":
3357
+ return `index:${segment.index}`;
3358
+ case "wildcard":
3359
+ return "wildcard";
3360
+ case "slice": {
3361
+ const slice2 = segment;
3362
+ return `slice:${slice2.start ?? ""}:${slice2.end ?? ""}`;
3363
+ }
3364
+ case "descend":
3365
+ return "descend";
3366
+ }
3367
+ }
3368
+ if (typeof segment === "string") {
3369
+ return `key:${escapeGroupingText(segment)}`;
3370
+ }
3371
+ if (typeof segment === "number") {
3372
+ return `index:${segment}`;
3373
+ }
3374
+ return "unknown";
3375
+ };
3376
+ var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
3377
+ var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
3378
+ var jsonOpaquePathGroupingKey = (value) => {
3379
+ if (isJsonPath(value)) {
3380
+ return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
3381
+ }
3382
+ if (typeof value === "string") {
3383
+ return `jsonpath:${escapeGroupingText(value)}`;
3384
+ }
3385
+ if (isExpression2(value)) {
3386
+ return `jsonpath:${groupingKeyOfExpression(value)}`;
3387
+ }
3388
+ return "jsonpath:unknown";
3389
+ };
3390
+ var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
1445
3391
  var groupingKeyOfExpression = (expression) => {
1446
3392
  const ast = expression[TypeId3];
1447
3393
  switch (ast.kind) {
1448
3394
  case "column":
1449
- return `column:${ast.tableName}.${ast.columnName}`;
3395
+ return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
1450
3396
  case "literal":
1451
3397
  return `literal:${literalGroupingKey(ast.value)}`;
1452
3398
  case "cast":
1453
3399
  return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
3400
+ case "collate":
3401
+ return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
3402
+ case "function":
3403
+ return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
1454
3404
  case "isNull":
1455
3405
  case "isNotNull":
1456
3406
  case "not":
@@ -1468,8 +3418,15 @@ var groupingKeyOfExpression = (expression) => {
1468
3418
  case "gte":
1469
3419
  case "like":
1470
3420
  case "ilike":
3421
+ case "regexMatch":
3422
+ case "regexIMatch":
3423
+ case "regexNotMatch":
3424
+ case "regexNotIMatch":
1471
3425
  case "isDistinctFrom":
1472
3426
  case "isNotDistinctFrom":
3427
+ case "contains":
3428
+ case "containedBy":
3429
+ case "overlaps":
1473
3430
  return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
1474
3431
  case "and":
1475
3432
  case "or":
@@ -1481,6 +3438,54 @@ var groupingKeyOfExpression = (expression) => {
1481
3438
  return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
1482
3439
  case "case":
1483
3440
  return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
3441
+ case "exists":
3442
+ return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
3443
+ case "scalarSubquery":
3444
+ return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
3445
+ case "inSubquery":
3446
+ return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3447
+ case "comparisonAny":
3448
+ case "comparisonAll":
3449
+ return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3450
+ case "jsonGet":
3451
+ case "jsonPath":
3452
+ case "jsonAccess":
3453
+ case "jsonTraverse":
3454
+ case "jsonGetText":
3455
+ case "jsonPathText":
3456
+ case "jsonAccessText":
3457
+ case "jsonTraverseText":
3458
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonPathGroupingKey(ast.segments)})`;
3459
+ case "jsonHasKey":
3460
+ case "jsonKeyExists":
3461
+ case "jsonHasAnyKeys":
3462
+ case "jsonHasAllKeys":
3463
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
3464
+ case "jsonConcat":
3465
+ case "jsonMerge":
3466
+ return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
3467
+ case "jsonDelete":
3468
+ case "jsonDeletePath":
3469
+ case "jsonRemove":
3470
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(undefined)},${jsonPathGroupingKey(ast.segments)})`;
3471
+ case "jsonSet":
3472
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.newValue)},${jsonPathGroupingKey(ast.segments)})`;
3473
+ case "jsonInsert":
3474
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.insert)},${jsonPathGroupingKey(ast.segments)})`;
3475
+ case "jsonPathExists":
3476
+ case "jsonPathMatch":
3477
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
3478
+ case "jsonBuildObject":
3479
+ return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
3480
+ case "jsonBuildArray":
3481
+ return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
3482
+ case "jsonToJson":
3483
+ case "jsonToJsonb":
3484
+ case "jsonTypeOf":
3485
+ case "jsonLength":
3486
+ case "jsonKeys":
3487
+ case "jsonStripNulls":
3488
+ return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
1484
3489
  default:
1485
3490
  throw new Error("Unsupported expression for grouping key generation");
1486
3491
  }
@@ -1498,15 +3503,15 @@ var dedupeGroupedExpressions = (values) => {
1498
3503
  };
1499
3504
 
1500
3505
  // src/internal/aggregation-validation.ts
1501
- var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
3506
+ var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
1502
3507
  var selectionHasAggregate = (selection) => {
1503
- if (isExpression2(selection)) {
3508
+ if (isExpression3(selection)) {
1504
3509
  return selection[TypeId2].kind === "aggregate";
1505
3510
  }
1506
3511
  return Object.values(selection).some((value) => selectionHasAggregate(value));
1507
3512
  };
1508
3513
  var isGroupedSelectionValid = (selection, groupedExpressions) => {
1509
- if (isExpression2(selection)) {
3514
+ if (isExpression3(selection)) {
1510
3515
  const aggregation = selection[TypeId2].kind;
1511
3516
  if (aggregation === "aggregate") {
1512
3517
  return true;
@@ -1559,7 +3564,46 @@ var renderCastType = (dialect, dbType) => {
1559
3564
  return dbType.kind;
1560
3565
  }
1561
3566
  };
1562
- var renderDdlExpression = (expression, state, dialect) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, state, dialect);
3567
+ var renderPostgresDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
3568
+ var renderPostgresDdlBytes = (value) => `decode('${Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("")}', 'hex')`;
3569
+ var renderPostgresDdlLiteral = (value, state, context = {}) => {
3570
+ const driverValue = toDriverValue(value, {
3571
+ dialect: "postgres",
3572
+ valueMappings: state.valueMappings,
3573
+ ...context
3574
+ });
3575
+ if (driverValue === null) {
3576
+ return "null";
3577
+ }
3578
+ switch (typeof driverValue) {
3579
+ case "boolean":
3580
+ return driverValue ? "true" : "false";
3581
+ case "number":
3582
+ if (!Number.isFinite(driverValue)) {
3583
+ throw new Error("Expected a finite numeric value");
3584
+ }
3585
+ return String(driverValue);
3586
+ case "bigint":
3587
+ return driverValue.toString();
3588
+ case "string":
3589
+ return renderPostgresDdlString(driverValue);
3590
+ case "object":
3591
+ if (driverValue instanceof Uint8Array) {
3592
+ return renderPostgresDdlBytes(driverValue);
3593
+ }
3594
+ break;
3595
+ }
3596
+ throw new Error("Unsupported postgres DDL literal value");
3597
+ };
3598
+ var renderDdlExpression = (expression, state, dialect) => {
3599
+ if (isSchemaExpression(expression)) {
3600
+ return render(expression);
3601
+ }
3602
+ return renderExpression(expression, state, {
3603
+ ...dialect,
3604
+ renderLiteral: renderPostgresDdlLiteral
3605
+ });
3606
+ };
1563
3607
  var renderColumnDefinition = (dialect, state, columnName, column) => {
1564
3608
  const clauses = [
1565
3609
  dialect.quoteIdentifier(columnName),
@@ -1591,14 +3635,16 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
1591
3635
  break;
1592
3636
  case "foreignKey": {
1593
3637
  const reference = option2.references();
1594
- definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete ? ` on delete ${option2.onDelete.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option2.onUpdate ? ` on update ${option2.onUpdate.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3638
+ definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
1595
3639
  break;
1596
3640
  }
1597
3641
  case "check":
1598
- definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, state, dialect)})${option2.noInherit ? " no inherit" : ""}`);
3642
+ definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
1599
3643
  break;
1600
3644
  case "index":
1601
3645
  break;
3646
+ default:
3647
+ throw new Error("Unsupported table option kind");
1602
3648
  }
1603
3649
  }
1604
3650
  return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
@@ -1607,10 +3653,56 @@ var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
1607
3653
  const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
1608
3654
  return `create${ddl.unique ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`;
1609
3655
  };
1610
- var renderDropIndexSql = (targetSource, ddl, state, dialect) => dialect.name === "postgres" ? `drop index${ddl.ifExists ? " if exists" : ""} ${dialect.quoteIdentifier(ddl.name)}` : `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
1611
- var isExpression3 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
1612
- var isJsonDbType = (dbType) => dbType.kind === "jsonb" || dbType.kind === "json" || ("variant" in dbType) && dbType.variant === "json";
1613
- var isJsonExpression = (value) => isExpression3(value) && isJsonDbType(value[TypeId2].dbType);
3656
+ var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
3657
+ if (dialect.name === "postgres") {
3658
+ const schemaName = typeof targetSource.source === "object" && targetSource.source !== null && TypeId4 in targetSource.source ? targetSource.source[TypeId4].schemaName : undefined;
3659
+ const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(ddl.name) : `${dialect.quoteIdentifier(schemaName)}.${dialect.quoteIdentifier(ddl.name)}`;
3660
+ return `drop index${ddl.ifExists ? " if exists" : ""} ${indexName}`;
3661
+ }
3662
+ return `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
3663
+ };
3664
+ var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3665
+ var isJsonDbType2 = (dbType) => {
3666
+ if (dbType.kind === "jsonb" || dbType.kind === "json") {
3667
+ return true;
3668
+ }
3669
+ if (!("variant" in dbType)) {
3670
+ return false;
3671
+ }
3672
+ const variant = dbType.variant;
3673
+ return variant === "json" || variant === "jsonb";
3674
+ };
3675
+ var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId2].dbType);
3676
+ var postgresRangeSubtypeByKind = {
3677
+ int4range: "int4",
3678
+ int8range: "int8",
3679
+ numrange: "numeric",
3680
+ tsrange: "timestamp",
3681
+ tstzrange: "timestamptz",
3682
+ daterange: "date",
3683
+ int4multirange: "int4",
3684
+ int8multirange: "int8",
3685
+ nummultirange: "numeric",
3686
+ tsmultirange: "timestamp",
3687
+ tstzmultirange: "timestamptz",
3688
+ datemultirange: "date"
3689
+ };
3690
+ var postgresRangeSubtypeKey = (dbType) => {
3691
+ if ("base" in dbType) {
3692
+ return postgresRangeSubtypeKey(dbType.base);
3693
+ }
3694
+ if ("subtype" in dbType) {
3695
+ return postgresRangeSubtypeKey(dbType.subtype) ?? dbType.subtype.kind;
3696
+ }
3697
+ return postgresRangeSubtypeByKind[dbType.kind];
3698
+ };
3699
+ var assertCompatiblePostgresRangeOperands = (left, right) => {
3700
+ const leftKey = postgresRangeSubtypeKey(left[TypeId2].dbType);
3701
+ const rightKey = postgresRangeSubtypeKey(right[TypeId2].dbType);
3702
+ if (leftKey !== undefined && rightKey !== undefined && leftKey !== rightKey) {
3703
+ throw new Error("Incompatible postgres range operands");
3704
+ }
3705
+ };
1614
3706
  var unsupportedJsonFeature = (dialect, feature) => {
1615
3707
  const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
1616
3708
  Object.assign(error, {
@@ -1653,15 +3745,16 @@ var extractJsonPathSegments = (node) => {
1653
3745
  };
1654
3746
  var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
1655
3747
  var renderJsonPathSegment = (segment) => {
3748
+ const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
1656
3749
  if (typeof segment === "string") {
1657
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) ? `.${segment}` : `."${segment.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3750
+ return renderKey(segment);
1658
3751
  }
1659
3752
  if (typeof segment === "number") {
1660
3753
  return `[${segment}]`;
1661
3754
  }
1662
3755
  switch (segment.kind) {
1663
3756
  case "key":
1664
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment.key) ? `.${segment.key}` : `."${segment.key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3757
+ return renderKey(segment.key);
1665
3758
  case "index":
1666
3759
  return `[${segment.index}]`;
1667
3760
  case "wildcard":
@@ -1704,18 +3797,45 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
1704
3797
  case "key":
1705
3798
  return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.key, state)}`;
1706
3799
  case "index":
1707
- return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(String(segment.index), state)}`;
3800
+ return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.index, state)}`;
1708
3801
  default:
1709
3802
  throw new Error("Postgres exact JSON access requires key/index segments");
1710
3803
  }
1711
3804
  };
1712
3805
  var renderPostgresJsonValue = (value, state, dialect) => {
1713
- if (!isExpression3(value)) {
3806
+ if (!isExpression4(value)) {
1714
3807
  throw new Error("Expected a JSON expression");
1715
3808
  }
1716
3809
  const rendered = renderExpression(value, state, dialect);
3810
+ const ast = value[TypeId3];
3811
+ if (ast.kind === "literal") {
3812
+ return `cast(${rendered} as jsonb)`;
3813
+ }
1717
3814
  return value[TypeId2].dbType.kind === "jsonb" ? rendered : `cast(${rendered} as jsonb)`;
1718
3815
  };
3816
+ var expressionDriverContext = (expression, state, dialect) => ({
3817
+ dialect: dialect.name,
3818
+ valueMappings: state.valueMappings,
3819
+ dbType: expression[TypeId2].dbType,
3820
+ runtimeSchema: expression[TypeId2].runtimeSchema,
3821
+ driverValueMapping: expression[TypeId2].driverValueMapping
3822
+ });
3823
+ var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
3824
+ var encodeArrayValues = (values, column, state, dialect) => values.map((value) => {
3825
+ if (value === null && column.metadata.nullable) {
3826
+ return null;
3827
+ }
3828
+ const runtimeSchemaAccepts = column.schema !== undefined && Schema5.is(column.schema)(value);
3829
+ const normalizedValue = runtimeSchemaAccepts ? value : normalizeDbValue(column.metadata.dbType, value);
3830
+ const encodedValue = column.schema === undefined || runtimeSchemaAccepts ? normalizedValue : Schema5.decodeUnknownSync(column.schema)(normalizedValue);
3831
+ return toDriverValue(encodedValue, {
3832
+ dialect: dialect.name,
3833
+ valueMappings: state.valueMappings,
3834
+ dbType: column.metadata.dbType,
3835
+ runtimeSchema: column.schema,
3836
+ driverValueMapping: column.metadata.driverValueMapping
3837
+ });
3838
+ });
1719
3839
  var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
1720
3840
  var renderJsonOpaquePath = (value, state, dialect) => {
1721
3841
  if (isJsonPathValue(value)) {
@@ -1724,7 +3844,7 @@ var renderJsonOpaquePath = (value, state, dialect) => {
1724
3844
  if (typeof value === "string") {
1725
3845
  return dialect.renderLiteral(value, state);
1726
3846
  }
1727
- if (isExpression3(value)) {
3847
+ if (isExpression4(value)) {
1728
3848
  return renderExpression(value, state, dialect);
1729
3849
  }
1730
3850
  throw new Error("Unsupported SQL/JSON path input");
@@ -1742,7 +3862,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
1742
3862
  if (source === undefined) {
1743
3863
  throw new Error("Unsupported SQL extract expression");
1744
3864
  }
1745
- const fieldRuntime = isExpression3(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
3865
+ const fieldRuntime = isExpression4(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
1746
3866
  const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
1747
3867
  return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
1748
3868
  }
@@ -1780,7 +3900,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1780
3900
  case "jsonPathText":
1781
3901
  case "jsonAccessText":
1782
3902
  case "jsonTraverseText": {
1783
- if (!isExpression3(base) || segments.length === 0) {
3903
+ if (!isExpression4(base) || segments.length === 0) {
1784
3904
  return;
1785
3905
  }
1786
3906
  const baseSql = renderExpression(base, state, dialect);
@@ -1803,7 +3923,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1803
3923
  case "jsonKeyExists":
1804
3924
  case "jsonHasAnyKeys":
1805
3925
  case "jsonHasAllKeys": {
1806
- if (!isExpression3(base)) {
3926
+ if (!isExpression4(base)) {
1807
3927
  return;
1808
3928
  }
1809
3929
  const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
@@ -1829,7 +3949,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1829
3949
  }
1830
3950
  case "jsonConcat":
1831
3951
  case "jsonMerge": {
1832
- if (!isExpression3(ast.left) || !isExpression3(ast.right)) {
3952
+ if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
1833
3953
  return;
1834
3954
  }
1835
3955
  if (dialect.name === "postgres") {
@@ -1844,7 +3964,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1844
3964
  const entries = Array.isArray(ast.entries) ? ast.entries : [];
1845
3965
  const renderedEntries = entries.flatMap((entry) => [
1846
3966
  dialect.renderLiteral(entry.key, state),
1847
- renderExpression(entry.value, state, dialect)
3967
+ renderJsonInputExpression(entry.value, state, dialect)
1848
3968
  ]);
1849
3969
  if (dialect.name === "postgres") {
1850
3970
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`;
@@ -1856,7 +3976,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1856
3976
  }
1857
3977
  case "jsonBuildArray": {
1858
3978
  const values = Array.isArray(ast.values) ? ast.values : [];
1859
- const renderedValues = values.map((value) => renderExpression(value, state, dialect)).join(", ");
3979
+ const renderedValues = values.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ");
1860
3980
  if (dialect.name === "postgres") {
1861
3981
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`;
1862
3982
  }
@@ -1866,29 +3986,29 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1866
3986
  return;
1867
3987
  }
1868
3988
  case "jsonToJson":
1869
- if (!isExpression3(base)) {
3989
+ if (!isExpression4(base)) {
1870
3990
  return;
1871
3991
  }
1872
3992
  if (dialect.name === "postgres") {
1873
- return `to_json(${renderExpression(base, state, dialect)})`;
3993
+ return `to_json(${renderJsonInputExpression(base, state, dialect)})`;
1874
3994
  }
1875
3995
  if (dialect.name === "mysql") {
1876
3996
  return `cast(${renderExpression(base, state, dialect)} as json)`;
1877
3997
  }
1878
3998
  return;
1879
3999
  case "jsonToJsonb":
1880
- if (!isExpression3(base)) {
4000
+ if (!isExpression4(base)) {
1881
4001
  return;
1882
4002
  }
1883
4003
  if (dialect.name === "postgres") {
1884
- return `to_jsonb(${renderExpression(base, state, dialect)})`;
4004
+ return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`;
1885
4005
  }
1886
4006
  if (dialect.name === "mysql") {
1887
4007
  return `cast(${renderExpression(base, state, dialect)} as json)`;
1888
4008
  }
1889
4009
  return;
1890
4010
  case "jsonTypeOf":
1891
- if (!isExpression3(base)) {
4011
+ if (!isExpression4(base)) {
1892
4012
  return;
1893
4013
  }
1894
4014
  if (dialect.name === "postgres") {
@@ -1900,7 +4020,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1900
4020
  }
1901
4021
  return;
1902
4022
  case "jsonLength":
1903
- if (!isExpression3(base)) {
4023
+ if (!isExpression4(base)) {
1904
4024
  return;
1905
4025
  }
1906
4026
  if (dialect.name === "postgres") {
@@ -1915,21 +4035,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1915
4035
  }
1916
4036
  return;
1917
4037
  case "jsonKeys":
1918
- if (!isExpression3(base)) {
4038
+ if (!isExpression4(base)) {
1919
4039
  return;
1920
4040
  }
1921
4041
  if (dialect.name === "postgres") {
1922
4042
  const baseSql = renderExpression(base, state, dialect);
1923
4043
  const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
1924
4044
  const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
1925
- return `(case when ${typeOf}(${baseSql}) = 'object' then array(select ${objectKeys}(${baseSql})) else null end)`;
4045
+ return `(case when ${typeOf}(${baseSql}) = 'object' then to_json(array(select ${objectKeys}(${baseSql}))) else null end)`;
1926
4046
  }
1927
4047
  if (dialect.name === "mysql") {
1928
4048
  return `json_keys(${renderExpression(base, state, dialect)})`;
1929
4049
  }
1930
4050
  return;
1931
4051
  case "jsonStripNulls":
1932
- if (!isExpression3(base)) {
4052
+ if (!isExpression4(base)) {
1933
4053
  return;
1934
4054
  }
1935
4055
  if (dialect.name === "postgres") {
@@ -1940,14 +4060,14 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1940
4060
  case "jsonDelete":
1941
4061
  case "jsonDeletePath":
1942
4062
  case "jsonRemove": {
1943
- if (!isExpression3(base) || segments.length === 0) {
4063
+ if (!isExpression4(base) || segments.length === 0) {
1944
4064
  return;
1945
4065
  }
1946
4066
  if (dialect.name === "postgres") {
1947
4067
  const baseSql = renderPostgresJsonValue(base, state, dialect);
1948
4068
  if (segments.length === 1 && (segments[0].kind === "key" || segments[0].kind === "index")) {
1949
4069
  const segment = segments[0];
1950
- return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(String(segment.index), state)})`;
4070
+ return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(segment.index, state)})`;
1951
4071
  }
1952
4072
  return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
1953
4073
  }
@@ -1958,11 +4078,11 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1958
4078
  }
1959
4079
  case "jsonSet":
1960
4080
  case "jsonInsert": {
1961
- if (!isExpression3(base) || segments.length === 0) {
4081
+ if (!isExpression4(base) || segments.length === 0) {
1962
4082
  return;
1963
4083
  }
1964
4084
  const nextValue = extractJsonValue(ast);
1965
- if (!isExpression3(nextValue)) {
4085
+ if (!isExpression4(nextValue)) {
1966
4086
  return;
1967
4087
  }
1968
4088
  const createMissing = ast.createMissing === true;
@@ -1979,7 +4099,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1979
4099
  return;
1980
4100
  }
1981
4101
  case "jsonPathExists": {
1982
- if (!isExpression3(base)) {
4102
+ if (!isExpression4(base)) {
1983
4103
  return;
1984
4104
  }
1985
4105
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -1995,7 +4115,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1995
4115
  return;
1996
4116
  }
1997
4117
  case "jsonPathMatch": {
1998
- if (!isExpression3(base)) {
4118
+ if (!isExpression4(base)) {
1999
4119
  return;
2000
4120
  }
2001
4121
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -2022,6 +4142,11 @@ var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) =
2022
4142
  var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
2023
4143
  var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
2024
4144
  var renderDeleteTargets = (targets, dialect) => targets.map((target) => dialect.quoteIdentifier(target.tableName)).join(", ");
4145
+ var assertMergeActionKind = (kind, allowed) => {
4146
+ if (typeof kind !== "string" || !allowed.includes(kind)) {
4147
+ throw new Error("Unsupported merge action kind");
4148
+ }
4149
+ };
2025
4150
  var renderMysqlMutationLock = (lock, statement) => {
2026
4151
  if (!lock) {
2027
4152
  return "";
@@ -2041,8 +4166,9 @@ var renderTransactionClause = (clause, dialect) => {
2041
4166
  switch (clause.kind) {
2042
4167
  case "transaction": {
2043
4168
  const modes = [];
2044
- if (clause.isolationLevel) {
2045
- modes.push(`isolation level ${clause.isolationLevel}`);
4169
+ const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
4170
+ if (isolationLevel) {
4171
+ modes.push(isolationLevel);
2046
4172
  }
2047
4173
  if (clause.readOnly === true) {
2048
4174
  modes.push("read only");
@@ -2060,21 +4186,101 @@ var renderTransactionClause = (clause, dialect) => {
2060
4186
  case "releaseSavepoint":
2061
4187
  return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
2062
4188
  }
2063
- return "";
4189
+ throw new Error("Unsupported transaction statement kind");
2064
4190
  };
2065
4191
  var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2066
4192
  if (validateAggregation) {
2067
4193
  validateAggregationSelection(selection, []);
2068
4194
  }
2069
4195
  const flattened = flattenSelection(selection);
4196
+ if (dialect.name === "mysql" && flattened.length === 0) {
4197
+ throw new Error("mysql select statements require at least one selected expression");
4198
+ }
2070
4199
  const projections = selectionProjections(selection);
2071
- const sql = flattened.map(({ expression, alias: alias2 }) => `${renderExpression(expression, state, dialect)} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
4200
+ const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
2072
4201
  return {
2073
4202
  sql,
2074
4203
  projections
2075
4204
  };
2076
4205
  };
2077
- var renderQueryAst = (ast, state, dialect) => {
4206
+ var nestedRenderState = (state) => ({
4207
+ params: state.params,
4208
+ valueMappings: state.valueMappings,
4209
+ ctes: [],
4210
+ cteNames: new Set(state.cteNames),
4211
+ cteSources: new Map(state.cteSources)
4212
+ });
4213
+ var assertMatchingSetProjections = (left, right) => {
4214
+ const leftKeys = left.map((projection) => JSON.stringify(projection.path));
4215
+ const rightKeys = right.map((projection) => JSON.stringify(projection.path));
4216
+ if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index3) => key2 !== rightKeys[index3])) {
4217
+ throw new Error("set operator operands must have matching result rows");
4218
+ }
4219
+ };
4220
+ var assertNoGroupedMutationClauses = (ast, statement) => {
4221
+ if (ast.groupBy.length > 0) {
4222
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4223
+ }
4224
+ if (ast.having.length > 0) {
4225
+ throw new Error(`having(...) is not supported for ${statement} statements`);
4226
+ }
4227
+ };
4228
+ var assertNoInsertQueryClauses = (ast) => {
4229
+ if (ast.where.length > 0) {
4230
+ throw new Error("where(...) is not supported for insert statements");
4231
+ }
4232
+ if (ast.joins.length > 0) {
4233
+ throw new Error("join(...) is not supported for insert statements");
4234
+ }
4235
+ if (ast.orderBy.length > 0) {
4236
+ throw new Error("orderBy(...) is not supported for insert statements");
4237
+ }
4238
+ if (ast.limit) {
4239
+ throw new Error("limit(...) is not supported for insert statements");
4240
+ }
4241
+ if (ast.offset) {
4242
+ throw new Error("offset(...) is not supported for insert statements");
4243
+ }
4244
+ if (ast.lock) {
4245
+ throw new Error("lock(...) is not supported for insert statements");
4246
+ }
4247
+ };
4248
+ var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
4249
+ if (ast.distinct) {
4250
+ throw new Error(`distinct(...) is not supported for ${statement} statements`);
4251
+ }
4252
+ if (ast.where.length > 0) {
4253
+ throw new Error(`where(...) is not supported for ${statement} statements`);
4254
+ }
4255
+ if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
4256
+ throw new Error(`from(...) is not supported for ${statement} statements`);
4257
+ }
4258
+ if (ast.joins.length > 0) {
4259
+ throw new Error(`join(...) is not supported for ${statement} statements`);
4260
+ }
4261
+ if (ast.groupBy.length > 0) {
4262
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4263
+ }
4264
+ if (ast.having.length > 0) {
4265
+ throw new Error(`having(...) is not supported for ${statement} statements`);
4266
+ }
4267
+ if (ast.orderBy.length > 0) {
4268
+ throw new Error(`orderBy(...) is not supported for ${statement} statements`);
4269
+ }
4270
+ if (ast.limit) {
4271
+ throw new Error(`limit(...) is not supported for ${statement} statements`);
4272
+ }
4273
+ if (ast.offset) {
4274
+ throw new Error(`offset(...) is not supported for ${statement} statements`);
4275
+ }
4276
+ if (ast.lock) {
4277
+ throw new Error(`lock(...) is not supported for ${statement} statements`);
4278
+ }
4279
+ if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
4280
+ throw new Error(`returning(...) is not supported for ${statement} statements`);
4281
+ }
4282
+ };
4283
+ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
2078
4284
  let sql = "";
2079
4285
  let projections = [];
2080
4286
  switch (ast.kind) {
@@ -2082,8 +4288,9 @@ var renderQueryAst = (ast, state, dialect) => {
2082
4288
  validateAggregationSelection(ast.select, ast.groupBy);
2083
4289
  const rendered = renderSelectionList(ast.select, state, dialect, false);
2084
4290
  projections = rendered.projections;
4291
+ const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
2085
4292
  const clauses = [
2086
- ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")}) ${rendered.sql}` : `select${ast.distinct ? " distinct" : ""} ${rendered.sql}`
4293
+ ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
2087
4294
  ];
2088
4295
  if (ast.from) {
2089
4296
  clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
@@ -2111,19 +4318,25 @@ var renderQueryAst = (ast, state, dialect) => {
2111
4318
  clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
2112
4319
  }
2113
4320
  if (ast.lock) {
2114
- clauses.push(`${ast.lock.mode === "update" ? "for update" : "for share"}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
4321
+ if (ast.lock.nowait && ast.lock.skipLocked) {
4322
+ throw new Error("lock(...) cannot specify both nowait and skipLocked");
4323
+ }
4324
+ clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
2115
4325
  }
2116
4326
  sql = clauses.join(" ");
2117
4327
  break;
2118
4328
  }
2119
4329
  case "set": {
2120
4330
  const setAst = ast;
4331
+ assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
2121
4332
  const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
2122
4333
  projections = selectionProjections(setAst.select);
4334
+ assertMatchingSetProjections(projections, base.projections);
2123
4335
  sql = [
2124
4336
  `(${base.sql})`,
2125
4337
  ...(setAst.setOperations ?? []).map((entry) => {
2126
4338
  const rendered = renderQueryAst(getAst(entry.query), state, dialect);
4339
+ assertMatchingSetProjections(projections, rendered.projections);
2127
4340
  return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
2128
4341
  })
2129
4342
  ].join(" ");
@@ -2131,28 +4344,34 @@ var renderQueryAst = (ast, state, dialect) => {
2131
4344
  }
2132
4345
  case "insert": {
2133
4346
  const insertAst = ast;
4347
+ if (insertAst.distinct) {
4348
+ throw new Error("distinct(...) is not supported for insert statements");
4349
+ }
4350
+ assertNoGroupedMutationClauses(insertAst, "insert");
4351
+ assertNoInsertQueryClauses(insertAst);
2134
4352
  const targetSource = insertAst.into;
2135
4353
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4354
+ const insertSource = expectInsertSourceKind(insertAst.insertSource);
4355
+ const conflict = expectConflictClause(insertAst.conflict);
2136
4356
  sql = `insert into ${target}`;
2137
- if (insertAst.insertSource?.kind === "values") {
2138
- const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2139
- const rows = insertAst.insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
4357
+ if (insertSource?.kind === "values") {
4358
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4359
+ const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
2140
4360
  sql += ` (${columns}) values ${rows}`;
2141
- } else if (insertAst.insertSource?.kind === "query") {
2142
- const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2143
- const renderedQuery = renderQueryAst(getAst(insertAst.insertSource.query), state, dialect);
4361
+ } else if (insertSource?.kind === "query") {
4362
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4363
+ const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
2144
4364
  sql += ` (${columns}) ${renderedQuery.sql}`;
2145
- } else if (insertAst.insertSource?.kind === "unnest") {
2146
- const unnestSource = insertAst.insertSource;
2147
- const columns = unnestSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4365
+ } else if (insertSource?.kind === "unnest") {
4366
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2148
4367
  if (dialect.name === "postgres") {
2149
4368
  const table = targetSource.source;
2150
4369
  const fields = table[TypeId4].fields;
2151
- const rendered = unnestSource.values.map((entry) => `cast(${dialect.renderLiteral(entry.values, state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
4370
+ const rendered = insertSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName], state, dialect), state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
2152
4371
  sql += ` (${columns}) select * from unnest(${rendered})`;
2153
4372
  } else {
2154
- const rowCount = unnestSource.values[0]?.values.length ?? 0;
2155
- const rows = Array.from({ length: rowCount }, (_, index3) => `(${unnestSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state)).join(", ")})`).join(", ");
4373
+ const rowCount = insertSource.values[0]?.values.length ?? 0;
4374
+ const rows = Array.from({ length: rowCount }, (_, index3) => `(${insertSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
2156
4375
  sql += ` (${columns}) values ${rows}`;
2157
4376
  }
2158
4377
  } else {
@@ -2164,13 +4383,16 @@ var renderQueryAst = (ast, state, dialect) => {
2164
4383
  sql += " default values";
2165
4384
  }
2166
4385
  }
2167
- if (insertAst.conflict) {
2168
- const updateValues = (insertAst.conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
4386
+ if (conflict) {
4387
+ if (conflict.action === "doNothing" && conflict.where) {
4388
+ throw new Error("conflict action predicates require update assignments");
4389
+ }
4390
+ const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
2169
4391
  if (dialect.name === "postgres") {
2170
- const targetSql = insertAst.conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(insertAst.conflict.target.name)}` : insertAst.conflict.target?.kind === "columns" ? ` on conflict (${insertAst.conflict.target.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${insertAst.conflict.target.where ? ` where ${renderExpression(insertAst.conflict.target.where, state, dialect)}` : ""}` : " on conflict";
4392
+ const targetSql = conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(conflict.target.name)}` : conflict.target?.kind === "columns" ? ` on conflict (${conflict.target.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${conflict.target.where ? ` where ${renderExpression(conflict.target.where, state, dialect)}` : ""}` : " on conflict";
2171
4393
  sql += targetSql;
2172
- sql += insertAst.conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${insertAst.conflict.where ? ` where ${renderExpression(insertAst.conflict.where, state, dialect)}` : ""}`;
2173
- } else if (insertAst.conflict.action === "doNothing") {
4394
+ sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
4395
+ } else if (conflict.action === "doNothing") {
2174
4396
  sql = sql.replace(/^insert/, "insert ignore");
2175
4397
  } else {
2176
4398
  sql += ` on duplicate key update ${updateValues}`;
@@ -2185,10 +4407,29 @@ var renderQueryAst = (ast, state, dialect) => {
2185
4407
  }
2186
4408
  case "update": {
2187
4409
  const updateAst = ast;
4410
+ if (updateAst.distinct) {
4411
+ throw new Error("distinct(...) is not supported for update statements");
4412
+ }
4413
+ assertNoGroupedMutationClauses(updateAst, "update");
4414
+ if (updateAst.orderBy.length > 0) {
4415
+ throw new Error("orderBy(...) is not supported for update statements");
4416
+ }
4417
+ if (updateAst.limit) {
4418
+ throw new Error("limit(...) is not supported for update statements");
4419
+ }
4420
+ if (updateAst.offset) {
4421
+ throw new Error("offset(...) is not supported for update statements");
4422
+ }
4423
+ if (updateAst.lock) {
4424
+ throw new Error("lock(...) is not supported for update statements");
4425
+ }
2188
4426
  const targetSource = updateAst.target;
2189
4427
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2190
4428
  const targets = updateAst.targets ?? [targetSource];
2191
4429
  const fromSources = updateAst.fromSources ?? [];
4430
+ if ((updateAst.set ?? []).length === 0) {
4431
+ throw new Error("update statements require at least one assignment");
4432
+ }
2192
4433
  const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
2193
4434
  if (dialect.name === "mysql") {
2194
4435
  const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
@@ -2231,6 +4472,22 @@ var renderQueryAst = (ast, state, dialect) => {
2231
4472
  }
2232
4473
  case "delete": {
2233
4474
  const deleteAst = ast;
4475
+ if (deleteAst.distinct) {
4476
+ throw new Error("distinct(...) is not supported for delete statements");
4477
+ }
4478
+ assertNoGroupedMutationClauses(deleteAst, "delete");
4479
+ if (deleteAst.orderBy.length > 0 && dialect.name === "postgres") {
4480
+ throw new Error("orderBy(...) is not supported for delete statements");
4481
+ }
4482
+ if (deleteAst.limit && dialect.name === "postgres") {
4483
+ throw new Error("limit(...) is not supported for delete statements");
4484
+ }
4485
+ if (deleteAst.offset) {
4486
+ throw new Error("offset(...) is not supported for delete statements");
4487
+ }
4488
+ if (deleteAst.lock) {
4489
+ throw new Error("lock(...) is not supported for delete statements");
4490
+ }
2234
4491
  const targetSource = deleteAst.target;
2235
4492
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2236
4493
  const targets = deleteAst.targets ?? [targetSource];
@@ -2269,12 +4526,14 @@ var renderQueryAst = (ast, state, dialect) => {
2269
4526
  }
2270
4527
  case "truncate": {
2271
4528
  const truncateAst = ast;
4529
+ assertNoStatementQueryClauses(truncateAst, "truncate");
4530
+ const truncate = expectTruncateClause(truncateAst.truncate);
2272
4531
  const targetSource = truncateAst.target;
2273
4532
  sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
2274
- if (truncateAst.truncate?.restartIdentity) {
4533
+ if (truncate.restartIdentity) {
2275
4534
  sql += " restart identity";
2276
4535
  }
2277
- if (truncateAst.truncate?.cascade) {
4536
+ if (truncate.cascade) {
2278
4537
  sql += " cascade";
2279
4538
  }
2280
4539
  break;
@@ -2287,8 +4546,18 @@ var renderQueryAst = (ast, state, dialect) => {
2287
4546
  const targetSource = mergeAst.target;
2288
4547
  const usingSource = mergeAst.using;
2289
4548
  const merge = mergeAst.merge;
4549
+ if (merge.kind !== "merge") {
4550
+ throw new Error("Unsupported merge statement kind");
4551
+ }
4552
+ if (Object.keys(mergeAst.select).length > 0) {
4553
+ throw new Error("returning(...) is not supported for merge statements");
4554
+ }
4555
+ if (!merge.whenMatched && !merge.whenNotMatched) {
4556
+ throw new Error("merge statements require at least one action");
4557
+ }
2290
4558
  sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression(merge.on, state, dialect)}`;
2291
4559
  if (merge.whenMatched) {
4560
+ assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
2292
4561
  sql += " when matched";
2293
4562
  if (merge.whenMatched.predicate) {
2294
4563
  sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
@@ -2296,14 +4565,21 @@ var renderQueryAst = (ast, state, dialect) => {
2296
4565
  if (merge.whenMatched.kind === "delete") {
2297
4566
  sql += " then delete";
2298
4567
  } else {
4568
+ if (merge.whenMatched.values.length === 0) {
4569
+ throw new Error("merge update actions require at least one assignment");
4570
+ }
2299
4571
  sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
2300
4572
  }
2301
4573
  }
2302
4574
  if (merge.whenNotMatched) {
4575
+ assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
2303
4576
  sql += " when not matched";
2304
4577
  if (merge.whenNotMatched.predicate) {
2305
4578
  sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
2306
4579
  }
4580
+ if (merge.whenNotMatched.values.length === 0) {
4581
+ throw new Error("merge insert actions require at least one value");
4582
+ }
2307
4583
  sql += ` then insert (${merge.whenNotMatched.values.map((entry) => dialect.quoteIdentifier(entry.columnName)).join(", ")}) values (${merge.whenNotMatched.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`;
2308
4584
  }
2309
4585
  break;
@@ -2314,32 +4590,40 @@ var renderQueryAst = (ast, state, dialect) => {
2314
4590
  case "savepoint":
2315
4591
  case "rollbackTo":
2316
4592
  case "releaseSavepoint": {
4593
+ assertNoStatementQueryClauses(ast, ast.kind);
2317
4594
  sql = renderTransactionClause(ast.transaction, dialect);
2318
4595
  break;
2319
4596
  }
2320
4597
  case "createTable": {
2321
4598
  const createTableAst = ast;
2322
- sql = renderCreateTableSql(createTableAst.target, state, dialect, createTableAst.ddl?.kind === "createTable" && createTableAst.ddl.ifNotExists);
4599
+ assertNoStatementQueryClauses(createTableAst, "createTable");
4600
+ const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
4601
+ sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
2323
4602
  break;
2324
4603
  }
2325
4604
  case "dropTable": {
2326
4605
  const dropTableAst = ast;
2327
- const ifExists = dropTableAst.ddl?.kind === "dropTable" && dropTableAst.ddl.ifExists;
2328
- sql = `drop table${ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
4606
+ assertNoStatementQueryClauses(dropTableAst, "dropTable");
4607
+ const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
4608
+ sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
2329
4609
  break;
2330
4610
  }
2331
4611
  case "createIndex": {
2332
4612
  const createIndexAst = ast;
2333
- sql = renderCreateIndexSql(createIndexAst.target, createIndexAst.ddl, state, dialect);
4613
+ assertNoStatementQueryClauses(createIndexAst, "createIndex");
4614
+ sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
2334
4615
  break;
2335
4616
  }
2336
4617
  case "dropIndex": {
2337
4618
  const dropIndexAst = ast;
2338
- sql = renderDropIndexSql(dropIndexAst.target, dropIndexAst.ddl, state, dialect);
4619
+ assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
4620
+ sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
2339
4621
  break;
2340
4622
  }
4623
+ default:
4624
+ throw new Error("Unsupported query statement kind");
2341
4625
  }
2342
- if (state.ctes.length === 0) {
4626
+ if (state.ctes.length === 0 || options2.emitCtes === false) {
2343
4627
  return {
2344
4628
  sql,
2345
4629
  projections
@@ -2362,9 +4646,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2362
4646
  };
2363
4647
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
2364
4648
  const cte = source;
4649
+ const registeredCteSource = state.cteSources.get(cte.name);
4650
+ if (registeredCteSource !== undefined && registeredCteSource !== cte.plan) {
4651
+ throw new Error(`common table expression name is already registered with a different plan: ${cte.name}`);
4652
+ }
2365
4653
  if (!state.cteNames.has(cte.name)) {
2366
4654
  state.cteNames.add(cte.name);
2367
- const rendered = renderQueryAst(getAst(cte.plan), state, dialect);
4655
+ state.cteSources.set(cte.name, cte.plan);
4656
+ const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
2368
4657
  state.ctes.push({
2369
4658
  name: cte.name,
2370
4659
  sql: rendered.sql,
@@ -2376,11 +4665,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2376
4665
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
2377
4666
  const derived = source;
2378
4667
  if (!state.cteNames.has(derived.name)) {}
2379
- return `(${renderQueryAst(getAst(derived.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
4668
+ return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
2380
4669
  }
2381
4670
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
2382
4671
  const lateral = source;
2383
- return `lateral (${renderQueryAst(getAst(lateral.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
4672
+ return `lateral (${renderQueryAst(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
2384
4673
  }
2385
4674
  if (typeof source === "object" && source !== null && source.kind === "values") {
2386
4675
  const values = source;
@@ -2401,6 +4690,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2401
4690
  const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
2402
4691
  return dialect.renderTableReference(tableName, baseTableName, schemaName);
2403
4692
  };
4693
+ var renderSubqueryExpressionPlan = (plan, state, dialect) => {
4694
+ const statement = getQueryState(plan).statement;
4695
+ if (statement !== "select" && statement !== "set") {
4696
+ throw new Error("subquery expressions only accept select-like query plans");
4697
+ }
4698
+ return renderQueryAst(getAst(plan), state, dialect).sql;
4699
+ };
2404
4700
  var renderExpression = (expression, state, dialect) => {
2405
4701
  const rawAst = expression[TypeId3];
2406
4702
  const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
@@ -2411,9 +4707,12 @@ var renderExpression = (expression, state, dialect) => {
2411
4707
  const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
2412
4708
  switch (ast.kind) {
2413
4709
  case "column":
2414
- return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
4710
+ return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
2415
4711
  case "literal":
2416
- return dialect.renderLiteral(ast.value, state);
4712
+ if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
4713
+ throw new Error("Expected a finite numeric value");
4714
+ }
4715
+ return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
2417
4716
  case "excluded":
2418
4717
  return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
2419
4718
  case "cast":
@@ -2452,6 +4751,7 @@ var renderExpression = (expression, state, dialect) => {
2452
4751
  return dialect.name === "mysql" ? `(${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} is not distinct from ${renderExpression(ast.right, state, dialect)})`;
2453
4752
  case "contains":
2454
4753
  if (dialect.name === "postgres") {
4754
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2455
4755
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2456
4756
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2457
4757
  return `(${left} @> ${right})`;
@@ -2462,6 +4762,7 @@ var renderExpression = (expression, state, dialect) => {
2462
4762
  throw new Error("Unsupported container operator for SQL rendering");
2463
4763
  case "containedBy":
2464
4764
  if (dialect.name === "postgres") {
4765
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2465
4766
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2466
4767
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2467
4768
  return `(${left} <@ ${right})`;
@@ -2472,6 +4773,7 @@ var renderExpression = (expression, state, dialect) => {
2472
4773
  throw new Error("Unsupported container operator for SQL rendering");
2473
4774
  case "overlaps":
2474
4775
  if (dialect.name === "postgres") {
4776
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2475
4777
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2476
4778
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2477
4779
  return `(${left} && ${right})`;
@@ -2497,14 +4799,26 @@ var renderExpression = (expression, state, dialect) => {
2497
4799
  case "min":
2498
4800
  return `min(${renderExpression(ast.value, state, dialect)})`;
2499
4801
  case "and":
4802
+ if (ast.values.length === 0) {
4803
+ throw new Error("and(...) requires at least one predicate");
4804
+ }
2500
4805
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
2501
4806
  case "or":
4807
+ if (ast.values.length === 0) {
4808
+ throw new Error("or(...) requires at least one predicate");
4809
+ }
2502
4810
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
2503
4811
  case "coalesce":
2504
4812
  return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
2505
4813
  case "in":
4814
+ if (ast.values.length < 2) {
4815
+ throw new Error("in(...) requires at least one candidate value");
4816
+ }
2506
4817
  return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
2507
4818
  case "notIn":
4819
+ if (ast.values.length < 2) {
4820
+ throw new Error("notIn(...) requires at least one candidate value");
4821
+ }
2508
4822
  return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
2509
4823
  case "between":
2510
4824
  return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
@@ -2513,15 +4827,15 @@ var renderExpression = (expression, state, dialect) => {
2513
4827
  case "case":
2514
4828
  return `case ${ast.branches.map((branch) => `when ${renderExpression(branch.when, state, dialect)} then ${renderExpression(branch.then, state, dialect)}`).join(" ")} else ${renderExpression(ast.else, state, dialect)} end`;
2515
4829
  case "exists":
2516
- return `exists (${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4830
+ return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
2517
4831
  case "scalarSubquery":
2518
- return `(${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4832
+ return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
2519
4833
  case "inSubquery":
2520
- return `(${renderExpression(ast.left, state, dialect)} in (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4834
+ return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
2521
4835
  case "comparisonAny":
2522
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4836
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
2523
4837
  case "comparisonAll":
2524
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4838
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
2525
4839
  case "window": {
2526
4840
  if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
2527
4841
  break;
@@ -2555,14 +4869,19 @@ import { parse as parse2, toSql as toSql2 } from "pgsql-ast-parser";
2555
4869
 
2556
4870
  // src/postgres/internal/dialect.ts
2557
4871
  var quoteIdentifier = (value) => `"${value.replaceAll('"', '""')}"`;
2558
- var renderLiteral = (value, state) => {
2559
- if (value === null) {
4872
+ var renderLiteral = (value, state, context = {}) => {
4873
+ const driverValue = toDriverValue(value, {
4874
+ dialect: "postgres",
4875
+ valueMappings: state.valueMappings,
4876
+ ...context
4877
+ });
4878
+ if (driverValue === null) {
2560
4879
  return "null";
2561
4880
  }
2562
- if (typeof value === "boolean") {
2563
- return value ? "true" : "false";
4881
+ if (typeof driverValue === "boolean") {
4882
+ return driverValue ? "true" : "false";
2564
4883
  }
2565
- state.params.push(value);
4884
+ state.params.push(driverValue);
2566
4885
  return `$${state.params.length}`;
2567
4886
  };
2568
4887
  var postgresDialect = {
@@ -2601,7 +4920,8 @@ var inlineLiteralDialect = {
2601
4920
  var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
2602
4921
  params: [],
2603
4922
  ctes: [],
2604
- cteNames: new Set
4923
+ cteNames: new Set,
4924
+ cteSources: new Map
2605
4925
  }, inlineLiteralDialect);
2606
4926
  var stripRedundantOuterParens = (value) => {
2607
4927
  let current = value.trim();
@@ -2652,10 +4972,14 @@ var normalizeDdlExpressionSql = (expression) => {
2652
4972
  };
2653
4973
 
2654
4974
  // src/postgres/schema-management.ts
2655
- import * as Schema3 from "effect/Schema";
4975
+ import * as Schema6 from "effect/Schema";
2656
4976
  import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
2657
4977
  var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
2658
4978
  var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
4979
+ var safeUnquotedIdentifier = /^[a-z_][a-z0-9_$]*$/;
4980
+ var quoteIdentifier2 = (value) => `"${value.replaceAll('"', '""')}"`;
4981
+ var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier2(value);
4982
+ var renderQualifiedTypeName = (name, schemaName) => schemaName === undefined || schemaName === "public" ? renderIdentifier(name) : `${renderIdentifier(schemaName)}.${renderIdentifier(name)}`;
2659
4983
  var EnumProto = {
2660
4984
  pipe() {
2661
4985
  return pipeArguments5(this, arguments);
@@ -2666,13 +4990,13 @@ var EnumProto = {
2666
4990
  type() {
2667
4991
  return {
2668
4992
  dialect: "postgres",
2669
- kind: this.qualifiedName(),
4993
+ kind: renderQualifiedTypeName(this.name, this.schemaName),
2670
4994
  variant: "enum"
2671
4995
  };
2672
4996
  },
2673
4997
  column() {
2674
- const values = this.values.map((value) => Schema3.Literal(value));
2675
- return makeColumnDefinition(values.length === 1 ? values[0] : Schema3.Union(...values), {
4998
+ const values = this.values.map((value) => Schema6.Literal(value));
4999
+ return makeColumnDefinition(values.length === 1 ? values[0] : Schema6.Union(...values), {
2676
5000
  dbType: this.type(),
2677
5001
  nullable: false,
2678
5002
  hasDefault: false,
@@ -2680,7 +5004,7 @@ var EnumProto = {
2680
5004
  primaryKey: false,
2681
5005
  unique: false,
2682
5006
  references: undefined,
2683
- ddlType: this.qualifiedName(),
5007
+ ddlType: renderQualifiedTypeName(this.name, this.schemaName),
2684
5008
  identity: undefined,
2685
5009
  enum: {
2686
5010
  name: this.name,
@@ -2781,17 +5105,17 @@ var fromDiscoveredValues = (values) => {
2781
5105
  const enums = new Map;
2782
5106
  for (const value of values) {
2783
5107
  if (isEnumDefinition(value)) {
2784
- enums.set(enumKey(value.schemaName, value.name), toEnumModel(value));
5108
+ enums.set(modelIdentityKey(value.schemaName, value.name), toEnumModel(value));
2785
5109
  } else if (isTableDefinition(value)) {
2786
5110
  for (const enumModel of enumModelsOfTable(value)) {
2787
- const key2 = enumKey(enumModel.schemaName, enumModel.name);
5111
+ const key2 = modelIdentityKey(enumModel.schemaName, enumModel.name);
2788
5112
  const existing = enums.get(key2);
2789
5113
  if (existing === undefined) {
2790
5114
  enums.set(key2, enumModel);
2791
5115
  continue;
2792
5116
  }
2793
5117
  if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
2794
- throw new Error(`Conflicting enum definitions discovered for '${key2}'`);
5118
+ throw new Error(`Conflicting enum definitions discovered for '${enumKey(enumModel.schemaName, enumModel.name)}'`);
2795
5119
  }
2796
5120
  }
2797
5121
  }
@@ -2804,6 +5128,7 @@ var fromDiscoveredValues = (values) => {
2804
5128
  };
2805
5129
  var tableKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
2806
5130
  var enumKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
5131
+ var modelIdentityKey = (schemaName, name) => JSON.stringify([schemaName ?? "public", name]);
2807
5132
  export {
2808
5133
  toTableModel,
2809
5134
  toEnumModel,