effect-qb 0.16.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 (75) hide show
  1. package/dist/mysql.js +1661 -591
  2. package/dist/postgres/metadata.js +1930 -135
  3. package/dist/postgres.js +7808 -6718
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +6 -1
  6. package/src/internal/derived-table.ts +29 -3
  7. package/src/internal/dialect.ts +2 -0
  8. package/src/internal/dsl-mutation-runtime.ts +173 -4
  9. package/src/internal/dsl-plan-runtime.ts +165 -20
  10. package/src/internal/dsl-query-runtime.ts +60 -6
  11. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  12. package/src/internal/executor.ts +47 -9
  13. package/src/internal/expression-ast.ts +3 -2
  14. package/src/internal/grouping-key.ts +141 -1
  15. package/src/internal/implication-runtime.ts +2 -1
  16. package/src/internal/json/types.ts +155 -40
  17. package/src/internal/predicate/context.ts +14 -1
  18. package/src/internal/predicate/key.ts +19 -2
  19. package/src/internal/predicate/runtime.ts +27 -3
  20. package/src/internal/query.ts +252 -30
  21. package/src/internal/renderer.ts +35 -2
  22. package/src/internal/runtime/driver-value-mapping.ts +58 -0
  23. package/src/internal/runtime/normalize.ts +62 -38
  24. package/src/internal/runtime/schema.ts +5 -3
  25. package/src/internal/runtime/value.ts +153 -30
  26. package/src/internal/table-options.ts +108 -1
  27. package/src/internal/table.ts +87 -29
  28. package/src/mysql/column.ts +18 -2
  29. package/src/mysql/datatypes/index.ts +21 -0
  30. package/src/mysql/errors/catalog.ts +5 -5
  31. package/src/mysql/errors/normalize.ts +2 -2
  32. package/src/mysql/internal/dsl.ts +736 -218
  33. package/src/mysql/internal/renderer.ts +2 -1
  34. package/src/mysql/internal/sql-expression-renderer.ts +486 -130
  35. package/src/mysql/query.ts +9 -2
  36. package/src/mysql/table.ts +38 -12
  37. package/src/postgres/column.ts +4 -2
  38. package/src/postgres/errors/normalize.ts +2 -2
  39. package/src/postgres/executor.ts +48 -5
  40. package/src/postgres/function/core.ts +19 -1
  41. package/src/postgres/internal/dsl.ts +683 -240
  42. package/src/postgres/internal/renderer.ts +2 -1
  43. package/src/postgres/internal/schema-ddl.ts +2 -1
  44. package/src/postgres/internal/schema-model.ts +6 -3
  45. package/src/postgres/internal/sql-expression-renderer.ts +420 -91
  46. package/src/postgres/json.ts +57 -17
  47. package/src/postgres/query.ts +9 -2
  48. package/src/postgres/schema-management.ts +91 -4
  49. package/src/postgres/schema.ts +1 -1
  50. package/src/postgres/table.ts +189 -53
  51. package/src/sqlite/column.ts +128 -0
  52. package/src/sqlite/datatypes/index.ts +79 -0
  53. package/src/sqlite/datatypes/spec.ts +98 -0
  54. package/src/sqlite/errors/catalog.ts +103 -0
  55. package/src/sqlite/errors/fields.ts +19 -0
  56. package/src/sqlite/errors/index.ts +19 -0
  57. package/src/sqlite/errors/normalize.ts +229 -0
  58. package/src/sqlite/errors/requirements.ts +71 -0
  59. package/src/sqlite/errors/types.ts +29 -0
  60. package/src/sqlite/executor.ts +227 -0
  61. package/src/sqlite/function/aggregate.ts +2 -0
  62. package/src/sqlite/function/core.ts +2 -0
  63. package/src/sqlite/function/index.ts +19 -0
  64. package/src/sqlite/function/string.ts +2 -0
  65. package/src/sqlite/function/temporal.ts +100 -0
  66. package/src/sqlite/function/window.ts +2 -0
  67. package/src/sqlite/internal/dialect.ts +37 -0
  68. package/src/sqlite/internal/dsl.ts +6926 -0
  69. package/src/sqlite/internal/renderer.ts +47 -0
  70. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  71. package/src/sqlite/json.ts +2 -0
  72. package/src/sqlite/query.ts +196 -0
  73. package/src/sqlite/renderer.ts +24 -0
  74. package/src/sqlite/table.ts +183 -0
  75. package/src/sqlite.ts +22 -0
@@ -176,6 +176,27 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
176
176
  };
177
177
 
178
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
+ };
179
200
  var normalizeColumnList = (columns) => {
180
201
  const normalized = Array.isArray(columns) ? [...columns] : [columns];
181
202
  if (normalized.length === 0) {
@@ -203,6 +224,8 @@ var collectInlineOptions = (fields) => {
203
224
  });
204
225
  }
205
226
  if (column.metadata.references) {
227
+ validateReferentialAction(column.metadata.references.onUpdate);
228
+ validateReferentialAction(column.metadata.references.onDelete);
206
229
  const local = [columnName];
207
230
  options.push({
208
231
  kind: "foreignKey",
@@ -279,6 +302,8 @@ var validateOptions = (tableName, fields, options) => {
279
302
  }
280
303
  }
281
304
  if (option.kind === "foreignKey") {
305
+ validateReferentialAction(option.onUpdate);
306
+ validateReferentialAction(option.onDelete);
282
307
  const reference = option.references();
283
308
  if (reference.columns.length !== columns.length) {
284
309
  throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
@@ -303,7 +328,7 @@ var validateOptions = (tableName, fields, options) => {
303
328
  throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
304
329
  }
305
330
  }
306
- if (option.columns === undefined && (option.keys === undefined || option.keys.length === 0)) {
331
+ if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
307
332
  throw new Error(`Index on table '${tableName}' requires at least one column or key`);
308
333
  }
309
334
  }
@@ -517,10 +542,13 @@ function make2(name, fields, schemaName) {
517
542
  const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
518
543
  return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
519
544
  }
520
- var schema = (schemaName) => ({
521
- schemaName,
522
- table: (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2)
523
- });
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
+ };
524
552
  var alias = (table, aliasName) => {
525
553
  const state = table[TypeId4];
526
554
  const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
@@ -696,6 +724,9 @@ var normalize = (expression) => (() => {
696
724
  }
697
725
  })();
698
726
 
727
+ // src/postgres/internal/sql-expression-renderer.ts
728
+ import * as Schema5 from "effect/Schema";
729
+
699
730
  // src/internal/query.ts
700
731
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
701
732
 
@@ -732,7 +763,18 @@ var cloneContext = (context) => ({
732
763
  unknown: context.unknown
733
764
  });
734
765
  var freezeContext = (context) => context;
735
- 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;
736
778
  var addSourceName = (context, key) => {
737
779
  context.sourceNames.add(sourceNameOfKey(key));
738
780
  };
@@ -982,9 +1024,10 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
982
1024
  var astOf = (value) => value[TypeId3];
983
1025
  var columnKeyOfExpression = (value) => {
984
1026
  const ast = astOf(value);
985
- return ast.kind === "column" ? `${ast.tableName}.${ast.columnName}` : undefined;
1027
+ return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
986
1028
  };
987
1029
  var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
1030
+ var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
988
1031
  var jsonPathPredicateKeyOfExpression = (value) => {
989
1032
  const ast = astOf(value);
990
1033
  switch (ast.kind) {
@@ -1008,7 +1051,7 @@ var jsonPathPredicateKeyOfExpression = (value) => {
1008
1051
  return;
1009
1052
  }
1010
1053
  const baseKey = columnKeyOfExpression(jsonAst.base);
1011
- return baseKey === undefined ? undefined : `${baseKey}#json:${path.join(".")}`;
1054
+ return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
1012
1055
  }
1013
1056
  default:
1014
1057
  return;
@@ -1463,13 +1506,1300 @@ var path = (...segments) => ({
1463
1506
  segments
1464
1507
  });
1465
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
+
1466
2682
  // src/internal/runtime/driver-value-mapping.ts
2683
+ import * as Schema4 from "effect/Schema";
2684
+
2685
+ // src/internal/runtime/value.ts
1467
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);
1468
2791
 
1469
2792
  // src/internal/runtime/normalize.ts
1470
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
+ };
1471
2801
  var pad = (value, width = 2) => value.toString().padStart(width, "0");
1472
- var formatLocalDate = (value) => `${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
2802
+ var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
1473
2803
  var formatLocalTime = (value) => {
1474
2804
  const milliseconds = value.getUTCMilliseconds();
1475
2805
  const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
@@ -1489,12 +2819,14 @@ var expectString = (value, label) => {
1489
2819
  }
1490
2820
  throw new Error(`Expected ${label} as string`);
1491
2821
  };
2822
+ var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
1492
2823
  var normalizeNumber = (value) => {
1493
2824
  if (typeof value === "number" && Number.isFinite(value)) {
1494
2825
  return value;
1495
2826
  }
1496
- if (typeof value === "string" && value.trim() !== "") {
1497
- const parsed = Number(value);
2827
+ if (typeof value === "string") {
2828
+ const trimmed = value.trim();
2829
+ const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
1498
2830
  if (Number.isFinite(parsed)) {
1499
2831
  return parsed;
1500
2832
  }
@@ -1534,25 +2866,11 @@ var normalizeBigIntString = (value) => {
1534
2866
  if (typeof value === "number" && Number.isSafeInteger(value)) {
1535
2867
  return BigInt(value).toString();
1536
2868
  }
1537
- if (typeof value === "string" && /^-?\d+$/.test(value.trim())) {
1538
- return BigInt(value.trim()).toString();
2869
+ if (typeof value === "string") {
2870
+ return canonicalizeBigIntString(value);
1539
2871
  }
1540
2872
  throw new Error("Expected an integer-like bigint value");
1541
2873
  };
1542
- var canonicalizeDecimalString = (input) => {
1543
- const trimmed = input.trim();
1544
- const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
1545
- if (match === null) {
1546
- throw new Error("Expected a decimal string");
1547
- }
1548
- const sign = match[1] === "-" ? "-" : "";
1549
- const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
1550
- const fraction = (match[3] ?? "").replace(/0+$/, "");
1551
- if (fraction.length === 0) {
1552
- return `${sign}${integer}`;
1553
- }
1554
- return `${sign}${integer}.${fraction}`;
1555
- };
1556
2874
  var normalizeDecimalString = (value) => {
1557
2875
  if (typeof value === "string") {
1558
2876
  return canonicalizeDecimalString(value);
@@ -1571,12 +2889,15 @@ var normalizeLocalDate = (value) => {
1571
2889
  return formatLocalDate(value);
1572
2890
  }
1573
2891
  const raw = expectString(value, "local date").trim();
1574
- if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
2892
+ if (isValidLocalDateString(raw)) {
1575
2893
  return raw;
1576
2894
  }
1577
- const parsed = new Date(raw);
1578
- if (!Number.isNaN(parsed.getTime())) {
1579
- return formatLocalDate(parsed);
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
+ }
1580
2901
  }
1581
2902
  throw new Error("Expected a local-date value");
1582
2903
  };
@@ -1585,7 +2906,7 @@ var normalizeLocalTime = (value) => {
1585
2906
  return formatLocalTime(value);
1586
2907
  }
1587
2908
  const raw = expectString(value, "local time").trim();
1588
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
2909
+ if (isValidLocalTimeString(raw)) {
1589
2910
  return raw;
1590
2911
  }
1591
2912
  throw new Error("Expected a local-time value");
@@ -1595,7 +2916,7 @@ var normalizeOffsetTime = (value) => {
1595
2916
  return `${formatLocalTime(value)}Z`;
1596
2917
  }
1597
2918
  const raw = expectString(value, "offset time").trim();
1598
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
2919
+ if (isValidOffsetTimeString(raw)) {
1599
2920
  return raw;
1600
2921
  }
1601
2922
  throw new Error("Expected an offset-time value");
@@ -1605,11 +2926,13 @@ var normalizeLocalDateTime = (value) => {
1605
2926
  return formatLocalDateTime(value);
1606
2927
  }
1607
2928
  const raw = expectString(value, "local datetime").trim();
1608
- if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
1609
- return raw.replace(" ", "T");
2929
+ const canonicalLocalDateTime = raw.replace(" ", "T");
2930
+ if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
2931
+ return canonicalLocalDateTime;
1610
2932
  }
1611
- if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
1612
- const parsed = new Date(raw);
2933
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
2934
+ if (isValidInstantString(canonicalInstant)) {
2935
+ const parsed = new Date(canonicalInstant);
1613
2936
  if (!Number.isNaN(parsed.getTime())) {
1614
2937
  return formatLocalDateTime(parsed);
1615
2938
  }
@@ -1624,7 +2947,11 @@ var normalizeInstant = (value) => {
1624
2947
  if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
1625
2948
  throw new Error("Instant values require a timezone offset");
1626
2949
  }
1627
- const parsed = new Date(raw);
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);
1628
2955
  if (Number.isNaN(parsed.getTime())) {
1629
2956
  throw new Error("Expected an ISO instant value");
1630
2957
  }
@@ -1656,25 +2983,33 @@ var isJsonValue = (value) => {
1656
2983
  }
1657
2984
  switch (typeof value) {
1658
2985
  case "string":
1659
- case "number":
1660
2986
  case "boolean":
1661
2987
  return true;
2988
+ case "number":
2989
+ return Number.isFinite(value);
1662
2990
  case "object":
1663
2991
  if (Array.isArray(value)) {
1664
2992
  return value.every(isJsonValue);
1665
2993
  }
1666
- return isRecord(value) && Object.values(value).every(isJsonValue);
2994
+ return isPlainRecord(value) && Object.values(value).every(isJsonValue);
1667
2995
  default:
1668
2996
  return false;
1669
2997
  }
1670
2998
  };
1671
2999
  var normalizeJson = (value) => {
1672
3000
  if (typeof value === "string") {
1673
- const parsed = JSON.parse(value);
1674
- if (isJsonValue(parsed)) {
1675
- return parsed;
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;
1676
3012
  }
1677
- throw new Error("Parsed JSON value is not a valid JSON runtime");
1678
3013
  }
1679
3014
  if (isJsonValue(value)) {
1680
3015
  return value;
@@ -1809,22 +3144,61 @@ var findMapping = (context, key2) => {
1809
3144
  }
1810
3145
  return;
1811
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);
1812
3161
  var encodeWithSchema = (schema2, value) => {
1813
3162
  if (schema2 === undefined) {
1814
3163
  return { value, encoded: false };
1815
3164
  }
1816
- if (!Schema3.is(schema2)(value)) {
3165
+ if (!Schema4.is(schema2)(value)) {
1817
3166
  return { value, encoded: false };
1818
3167
  }
1819
3168
  return {
1820
- value: Schema3.encodeUnknownSync(schema2)(value),
3169
+ value: Schema4.encodeUnknownSync(schema2)(value),
1821
3170
  encoded: true
1822
3171
  };
1823
3172
  };
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;
3181
+ }
3182
+ if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
3183
+ return value;
3184
+ }
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;
3194
+ };
1824
3195
  var toDriverValue = (value, context) => {
1825
3196
  if (value === null) {
1826
3197
  return null;
1827
3198
  }
3199
+ if (value instanceof Date && Number.isNaN(value.getTime())) {
3200
+ throw new Error("Expected a valid Date value");
3201
+ }
1828
3202
  const dbType = context.dbType;
1829
3203
  const encoded = encodeWithSchema(context.runtimeSchema, value);
1830
3204
  let current = encoded.value;
@@ -1832,6 +3206,9 @@ var toDriverValue = (value, context) => {
1832
3206
  if (custom !== undefined && dbType !== undefined) {
1833
3207
  return custom(current, dbType);
1834
3208
  }
3209
+ if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
3210
+ return current;
3211
+ }
1835
3212
  return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
1836
3213
  };
1837
3214
  var fromDriverValue = (value, context) => {
@@ -1843,6 +3220,12 @@ var fromDriverValue = (value, context) => {
1843
3220
  if (custom !== undefined && dbType !== undefined) {
1844
3221
  return custom(value, dbType);
1845
3222
  }
3223
+ if (typeof value === "string") {
3224
+ const normalizedJsonString = normalizeJsonDriverString(value, context);
3225
+ if (normalizedJsonString !== undefined) {
3226
+ return normalizedJsonString;
3227
+ }
3228
+ }
1846
3229
  return dbType === undefined ? value : normalizeDbValue(dbType, value);
1847
3230
  };
1848
3231
  var textCast = (sql) => `(${sql})::text`;
@@ -1930,6 +3313,20 @@ var validateProjections = (projections) => {
1930
3313
  };
1931
3314
 
1932
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
+ };
1933
3330
  var literalGroupingKey = (value) => {
1934
3331
  if (value instanceof Date) {
1935
3332
  return `date:${value.toISOString()}`;
@@ -1948,15 +3345,62 @@ var literalGroupingKey = (value) => {
1948
3345
  return `literal:${JSON.stringify(value)}`;
1949
3346
  }
1950
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)}`;
1951
3391
  var groupingKeyOfExpression = (expression) => {
1952
3392
  const ast = expression[TypeId3];
1953
3393
  switch (ast.kind) {
1954
3394
  case "column":
1955
- return `column:${ast.tableName}.${ast.columnName}`;
3395
+ return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
1956
3396
  case "literal":
1957
3397
  return `literal:${literalGroupingKey(ast.value)}`;
1958
3398
  case "cast":
1959
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(",")})`;
1960
3404
  case "isNull":
1961
3405
  case "isNotNull":
1962
3406
  case "not":
@@ -1974,8 +3418,15 @@ var groupingKeyOfExpression = (expression) => {
1974
3418
  case "gte":
1975
3419
  case "like":
1976
3420
  case "ilike":
3421
+ case "regexMatch":
3422
+ case "regexIMatch":
3423
+ case "regexNotMatch":
3424
+ case "regexNotIMatch":
1977
3425
  case "isDistinctFrom":
1978
3426
  case "isNotDistinctFrom":
3427
+ case "contains":
3428
+ case "containedBy":
3429
+ case "overlaps":
1979
3430
  return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
1980
3431
  case "and":
1981
3432
  case "or":
@@ -1987,6 +3438,54 @@ var groupingKeyOfExpression = (expression) => {
1987
3438
  return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
1988
3439
  case "case":
1989
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)})`;
1990
3489
  default:
1991
3490
  throw new Error("Unsupported expression for grouping key generation");
1992
3491
  }
@@ -2004,15 +3503,15 @@ var dedupeGroupedExpressions = (values) => {
2004
3503
  };
2005
3504
 
2006
3505
  // src/internal/aggregation-validation.ts
2007
- var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
3506
+ var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
2008
3507
  var selectionHasAggregate = (selection) => {
2009
- if (isExpression2(selection)) {
3508
+ if (isExpression3(selection)) {
2010
3509
  return selection[TypeId2].kind === "aggregate";
2011
3510
  }
2012
3511
  return Object.values(selection).some((value) => selectionHasAggregate(value));
2013
3512
  };
2014
3513
  var isGroupedSelectionValid = (selection, groupedExpressions) => {
2015
- if (isExpression2(selection)) {
3514
+ if (isExpression3(selection)) {
2016
3515
  const aggregation = selection[TypeId2].kind;
2017
3516
  if (aggregation === "aggregate") {
2018
3517
  return true;
@@ -2065,7 +3564,46 @@ var renderCastType = (dialect, dbType) => {
2065
3564
  return dbType.kind;
2066
3565
  }
2067
3566
  };
2068
- 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
+ };
2069
3607
  var renderColumnDefinition = (dialect, state, columnName, column) => {
2070
3608
  const clauses = [
2071
3609
  dialect.quoteIdentifier(columnName),
@@ -2097,14 +3635,16 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
2097
3635
  break;
2098
3636
  case "foreignKey": {
2099
3637
  const reference = option2.references();
2100
- 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" : ""}` : ""}`);
2101
3639
  break;
2102
3640
  }
2103
3641
  case "check":
2104
- 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" : ""}`);
2105
3643
  break;
2106
3644
  case "index":
2107
3645
  break;
3646
+ default:
3647
+ throw new Error("Unsupported table option kind");
2108
3648
  }
2109
3649
  }
2110
3650
  return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
@@ -2113,10 +3653,56 @@ var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
2113
3653
  const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
2114
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(", ")})`;
2115
3655
  };
2116
- 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)}`;
2117
- var isExpression3 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
2118
- var isJsonDbType = (dbType) => dbType.kind === "jsonb" || dbType.kind === "json" || ("variant" in dbType) && dbType.variant === "json";
2119
- 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
+ };
2120
3706
  var unsupportedJsonFeature = (dialect, feature) => {
2121
3707
  const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
2122
3708
  Object.assign(error, {
@@ -2159,15 +3745,16 @@ var extractJsonPathSegments = (node) => {
2159
3745
  };
2160
3746
  var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
2161
3747
  var renderJsonPathSegment = (segment) => {
3748
+ const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
2162
3749
  if (typeof segment === "string") {
2163
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) ? `.${segment}` : `."${segment.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3750
+ return renderKey(segment);
2164
3751
  }
2165
3752
  if (typeof segment === "number") {
2166
3753
  return `[${segment}]`;
2167
3754
  }
2168
3755
  switch (segment.kind) {
2169
3756
  case "key":
2170
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment.key) ? `.${segment.key}` : `."${segment.key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3757
+ return renderKey(segment.key);
2171
3758
  case "index":
2172
3759
  return `[${segment.index}]`;
2173
3760
  case "wildcard":
@@ -2210,13 +3797,13 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
2210
3797
  case "key":
2211
3798
  return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.key, state)}`;
2212
3799
  case "index":
2213
- return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(String(segment.index), state)}`;
3800
+ return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.index, state)}`;
2214
3801
  default:
2215
3802
  throw new Error("Postgres exact JSON access requires key/index segments");
2216
3803
  }
2217
3804
  };
2218
3805
  var renderPostgresJsonValue = (value, state, dialect) => {
2219
- if (!isExpression3(value)) {
3806
+ if (!isExpression4(value)) {
2220
3807
  throw new Error("Expected a JSON expression");
2221
3808
  }
2222
3809
  const rendered = renderExpression(value, state, dialect);
@@ -2234,13 +3821,21 @@ var expressionDriverContext = (expression, state, dialect) => ({
2234
3821
  driverValueMapping: expression[TypeId2].driverValueMapping
2235
3822
  });
2236
3823
  var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
2237
- var encodeArrayValues = (values, column, state, dialect) => values.map((value) => toDriverValue(value, {
2238
- dialect: dialect.name,
2239
- valueMappings: state.valueMappings,
2240
- dbType: column.metadata.dbType,
2241
- runtimeSchema: column.schema,
2242
- driverValueMapping: column.metadata.driverValueMapping
2243
- }));
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
+ });
2244
3839
  var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
2245
3840
  var renderJsonOpaquePath = (value, state, dialect) => {
2246
3841
  if (isJsonPathValue(value)) {
@@ -2249,7 +3844,7 @@ var renderJsonOpaquePath = (value, state, dialect) => {
2249
3844
  if (typeof value === "string") {
2250
3845
  return dialect.renderLiteral(value, state);
2251
3846
  }
2252
- if (isExpression3(value)) {
3847
+ if (isExpression4(value)) {
2253
3848
  return renderExpression(value, state, dialect);
2254
3849
  }
2255
3850
  throw new Error("Unsupported SQL/JSON path input");
@@ -2267,7 +3862,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
2267
3862
  if (source === undefined) {
2268
3863
  throw new Error("Unsupported SQL extract expression");
2269
3864
  }
2270
- 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;
2271
3866
  const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
2272
3867
  return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
2273
3868
  }
@@ -2305,7 +3900,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2305
3900
  case "jsonPathText":
2306
3901
  case "jsonAccessText":
2307
3902
  case "jsonTraverseText": {
2308
- if (!isExpression3(base) || segments.length === 0) {
3903
+ if (!isExpression4(base) || segments.length === 0) {
2309
3904
  return;
2310
3905
  }
2311
3906
  const baseSql = renderExpression(base, state, dialect);
@@ -2328,7 +3923,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2328
3923
  case "jsonKeyExists":
2329
3924
  case "jsonHasAnyKeys":
2330
3925
  case "jsonHasAllKeys": {
2331
- if (!isExpression3(base)) {
3926
+ if (!isExpression4(base)) {
2332
3927
  return;
2333
3928
  }
2334
3929
  const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
@@ -2354,7 +3949,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2354
3949
  }
2355
3950
  case "jsonConcat":
2356
3951
  case "jsonMerge": {
2357
- if (!isExpression3(ast.left) || !isExpression3(ast.right)) {
3952
+ if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
2358
3953
  return;
2359
3954
  }
2360
3955
  if (dialect.name === "postgres") {
@@ -2391,7 +3986,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2391
3986
  return;
2392
3987
  }
2393
3988
  case "jsonToJson":
2394
- if (!isExpression3(base)) {
3989
+ if (!isExpression4(base)) {
2395
3990
  return;
2396
3991
  }
2397
3992
  if (dialect.name === "postgres") {
@@ -2402,7 +3997,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2402
3997
  }
2403
3998
  return;
2404
3999
  case "jsonToJsonb":
2405
- if (!isExpression3(base)) {
4000
+ if (!isExpression4(base)) {
2406
4001
  return;
2407
4002
  }
2408
4003
  if (dialect.name === "postgres") {
@@ -2413,7 +4008,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2413
4008
  }
2414
4009
  return;
2415
4010
  case "jsonTypeOf":
2416
- if (!isExpression3(base)) {
4011
+ if (!isExpression4(base)) {
2417
4012
  return;
2418
4013
  }
2419
4014
  if (dialect.name === "postgres") {
@@ -2425,7 +4020,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2425
4020
  }
2426
4021
  return;
2427
4022
  case "jsonLength":
2428
- if (!isExpression3(base)) {
4023
+ if (!isExpression4(base)) {
2429
4024
  return;
2430
4025
  }
2431
4026
  if (dialect.name === "postgres") {
@@ -2440,21 +4035,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2440
4035
  }
2441
4036
  return;
2442
4037
  case "jsonKeys":
2443
- if (!isExpression3(base)) {
4038
+ if (!isExpression4(base)) {
2444
4039
  return;
2445
4040
  }
2446
4041
  if (dialect.name === "postgres") {
2447
4042
  const baseSql = renderExpression(base, state, dialect);
2448
4043
  const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
2449
4044
  const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
2450
- 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)`;
2451
4046
  }
2452
4047
  if (dialect.name === "mysql") {
2453
4048
  return `json_keys(${renderExpression(base, state, dialect)})`;
2454
4049
  }
2455
4050
  return;
2456
4051
  case "jsonStripNulls":
2457
- if (!isExpression3(base)) {
4052
+ if (!isExpression4(base)) {
2458
4053
  return;
2459
4054
  }
2460
4055
  if (dialect.name === "postgres") {
@@ -2465,14 +4060,14 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2465
4060
  case "jsonDelete":
2466
4061
  case "jsonDeletePath":
2467
4062
  case "jsonRemove": {
2468
- if (!isExpression3(base) || segments.length === 0) {
4063
+ if (!isExpression4(base) || segments.length === 0) {
2469
4064
  return;
2470
4065
  }
2471
4066
  if (dialect.name === "postgres") {
2472
4067
  const baseSql = renderPostgresJsonValue(base, state, dialect);
2473
4068
  if (segments.length === 1 && (segments[0].kind === "key" || segments[0].kind === "index")) {
2474
4069
  const segment = segments[0];
2475
- 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)})`;
2476
4071
  }
2477
4072
  return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
2478
4073
  }
@@ -2483,11 +4078,11 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2483
4078
  }
2484
4079
  case "jsonSet":
2485
4080
  case "jsonInsert": {
2486
- if (!isExpression3(base) || segments.length === 0) {
4081
+ if (!isExpression4(base) || segments.length === 0) {
2487
4082
  return;
2488
4083
  }
2489
4084
  const nextValue = extractJsonValue(ast);
2490
- if (!isExpression3(nextValue)) {
4085
+ if (!isExpression4(nextValue)) {
2491
4086
  return;
2492
4087
  }
2493
4088
  const createMissing = ast.createMissing === true;
@@ -2504,7 +4099,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2504
4099
  return;
2505
4100
  }
2506
4101
  case "jsonPathExists": {
2507
- if (!isExpression3(base)) {
4102
+ if (!isExpression4(base)) {
2508
4103
  return;
2509
4104
  }
2510
4105
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -2520,7 +4115,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2520
4115
  return;
2521
4116
  }
2522
4117
  case "jsonPathMatch": {
2523
- if (!isExpression3(base)) {
4118
+ if (!isExpression4(base)) {
2524
4119
  return;
2525
4120
  }
2526
4121
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -2547,6 +4142,11 @@ var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) =
2547
4142
  var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
2548
4143
  var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
2549
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
+ };
2550
4150
  var renderMysqlMutationLock = (lock, statement) => {
2551
4151
  if (!lock) {
2552
4152
  return "";
@@ -2566,8 +4166,9 @@ var renderTransactionClause = (clause, dialect) => {
2566
4166
  switch (clause.kind) {
2567
4167
  case "transaction": {
2568
4168
  const modes = [];
2569
- if (clause.isolationLevel) {
2570
- modes.push(`isolation level ${clause.isolationLevel}`);
4169
+ const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
4170
+ if (isolationLevel) {
4171
+ modes.push(isolationLevel);
2571
4172
  }
2572
4173
  if (clause.readOnly === true) {
2573
4174
  modes.push("read only");
@@ -2585,13 +4186,16 @@ var renderTransactionClause = (clause, dialect) => {
2585
4186
  case "releaseSavepoint":
2586
4187
  return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
2587
4188
  }
2588
- return "";
4189
+ throw new Error("Unsupported transaction statement kind");
2589
4190
  };
2590
4191
  var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2591
4192
  if (validateAggregation) {
2592
4193
  validateAggregationSelection(selection, []);
2593
4194
  }
2594
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
+ }
2595
4199
  const projections = selectionProjections(selection);
2596
4200
  const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
2597
4201
  return {
@@ -2599,7 +4203,84 @@ var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2599
4203
  projections
2600
4204
  };
2601
4205
  };
2602
- 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 = {}) => {
2603
4284
  let sql = "";
2604
4285
  let projections = [];
2605
4286
  switch (ast.kind) {
@@ -2607,8 +4288,9 @@ var renderQueryAst = (ast, state, dialect) => {
2607
4288
  validateAggregationSelection(ast.select, ast.groupBy);
2608
4289
  const rendered = renderSelectionList(ast.select, state, dialect, false);
2609
4290
  projections = rendered.projections;
4291
+ const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
2610
4292
  const clauses = [
2611
- 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}`
2612
4294
  ];
2613
4295
  if (ast.from) {
2614
4296
  clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
@@ -2636,19 +4318,25 @@ var renderQueryAst = (ast, state, dialect) => {
2636
4318
  clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
2637
4319
  }
2638
4320
  if (ast.lock) {
2639
- 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" : ""}`);
2640
4325
  }
2641
4326
  sql = clauses.join(" ");
2642
4327
  break;
2643
4328
  }
2644
4329
  case "set": {
2645
4330
  const setAst = ast;
4331
+ assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
2646
4332
  const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
2647
4333
  projections = selectionProjections(setAst.select);
4334
+ assertMatchingSetProjections(projections, base.projections);
2648
4335
  sql = [
2649
4336
  `(${base.sql})`,
2650
4337
  ...(setAst.setOperations ?? []).map((entry) => {
2651
4338
  const rendered = renderQueryAst(getAst(entry.query), state, dialect);
4339
+ assertMatchingSetProjections(projections, rendered.projections);
2652
4340
  return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
2653
4341
  })
2654
4342
  ].join(" ");
@@ -2656,28 +4344,34 @@ var renderQueryAst = (ast, state, dialect) => {
2656
4344
  }
2657
4345
  case "insert": {
2658
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);
2659
4352
  const targetSource = insertAst.into;
2660
4353
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4354
+ const insertSource = expectInsertSourceKind(insertAst.insertSource);
4355
+ const conflict = expectConflictClause(insertAst.conflict);
2661
4356
  sql = `insert into ${target}`;
2662
- if (insertAst.insertSource?.kind === "values") {
2663
- const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2664
- 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(", ");
2665
4360
  sql += ` (${columns}) values ${rows}`;
2666
- } else if (insertAst.insertSource?.kind === "query") {
2667
- const columns = insertAst.insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2668
- 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);
2669
4364
  sql += ` (${columns}) ${renderedQuery.sql}`;
2670
- } else if (insertAst.insertSource?.kind === "unnest") {
2671
- const unnestSource = insertAst.insertSource;
2672
- 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(", ");
2673
4367
  if (dialect.name === "postgres") {
2674
4368
  const table = targetSource.source;
2675
4369
  const fields = table[TypeId4].fields;
2676
- const rendered = unnestSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName], state, dialect), 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(", ");
2677
4371
  sql += ` (${columns}) select * from unnest(${rendered})`;
2678
4372
  } else {
2679
- const rowCount = unnestSource.values[0]?.values.length ?? 0;
2680
- const rows = Array.from({ length: rowCount }, (_, index3) => `(${unnestSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).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(", ");
2681
4375
  sql += ` (${columns}) values ${rows}`;
2682
4376
  }
2683
4377
  } else {
@@ -2689,13 +4383,16 @@ var renderQueryAst = (ast, state, dialect) => {
2689
4383
  sql += " default values";
2690
4384
  }
2691
4385
  }
2692
- if (insertAst.conflict) {
2693
- 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(", ");
2694
4391
  if (dialect.name === "postgres") {
2695
- 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";
2696
4393
  sql += targetSql;
2697
- sql += insertAst.conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${insertAst.conflict.where ? ` where ${renderExpression(insertAst.conflict.where, state, dialect)}` : ""}`;
2698
- } 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") {
2699
4396
  sql = sql.replace(/^insert/, "insert ignore");
2700
4397
  } else {
2701
4398
  sql += ` on duplicate key update ${updateValues}`;
@@ -2710,10 +4407,29 @@ var renderQueryAst = (ast, state, dialect) => {
2710
4407
  }
2711
4408
  case "update": {
2712
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
+ }
2713
4426
  const targetSource = updateAst.target;
2714
4427
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2715
4428
  const targets = updateAst.targets ?? [targetSource];
2716
4429
  const fromSources = updateAst.fromSources ?? [];
4430
+ if ((updateAst.set ?? []).length === 0) {
4431
+ throw new Error("update statements require at least one assignment");
4432
+ }
2717
4433
  const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
2718
4434
  if (dialect.name === "mysql") {
2719
4435
  const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
@@ -2756,6 +4472,22 @@ var renderQueryAst = (ast, state, dialect) => {
2756
4472
  }
2757
4473
  case "delete": {
2758
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
+ }
2759
4491
  const targetSource = deleteAst.target;
2760
4492
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2761
4493
  const targets = deleteAst.targets ?? [targetSource];
@@ -2794,12 +4526,14 @@ var renderQueryAst = (ast, state, dialect) => {
2794
4526
  }
2795
4527
  case "truncate": {
2796
4528
  const truncateAst = ast;
4529
+ assertNoStatementQueryClauses(truncateAst, "truncate");
4530
+ const truncate = expectTruncateClause(truncateAst.truncate);
2797
4531
  const targetSource = truncateAst.target;
2798
4532
  sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
2799
- if (truncateAst.truncate?.restartIdentity) {
4533
+ if (truncate.restartIdentity) {
2800
4534
  sql += " restart identity";
2801
4535
  }
2802
- if (truncateAst.truncate?.cascade) {
4536
+ if (truncate.cascade) {
2803
4537
  sql += " cascade";
2804
4538
  }
2805
4539
  break;
@@ -2812,8 +4546,18 @@ var renderQueryAst = (ast, state, dialect) => {
2812
4546
  const targetSource = mergeAst.target;
2813
4547
  const usingSource = mergeAst.using;
2814
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
+ }
2815
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)}`;
2816
4559
  if (merge.whenMatched) {
4560
+ assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
2817
4561
  sql += " when matched";
2818
4562
  if (merge.whenMatched.predicate) {
2819
4563
  sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
@@ -2821,14 +4565,21 @@ var renderQueryAst = (ast, state, dialect) => {
2821
4565
  if (merge.whenMatched.kind === "delete") {
2822
4566
  sql += " then delete";
2823
4567
  } else {
4568
+ if (merge.whenMatched.values.length === 0) {
4569
+ throw new Error("merge update actions require at least one assignment");
4570
+ }
2824
4571
  sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
2825
4572
  }
2826
4573
  }
2827
4574
  if (merge.whenNotMatched) {
4575
+ assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
2828
4576
  sql += " when not matched";
2829
4577
  if (merge.whenNotMatched.predicate) {
2830
4578
  sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
2831
4579
  }
4580
+ if (merge.whenNotMatched.values.length === 0) {
4581
+ throw new Error("merge insert actions require at least one value");
4582
+ }
2832
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(", ")})`;
2833
4584
  }
2834
4585
  break;
@@ -2839,32 +4590,40 @@ var renderQueryAst = (ast, state, dialect) => {
2839
4590
  case "savepoint":
2840
4591
  case "rollbackTo":
2841
4592
  case "releaseSavepoint": {
4593
+ assertNoStatementQueryClauses(ast, ast.kind);
2842
4594
  sql = renderTransactionClause(ast.transaction, dialect);
2843
4595
  break;
2844
4596
  }
2845
4597
  case "createTable": {
2846
4598
  const createTableAst = ast;
2847
- 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);
2848
4602
  break;
2849
4603
  }
2850
4604
  case "dropTable": {
2851
4605
  const dropTableAst = ast;
2852
- const ifExists = dropTableAst.ddl?.kind === "dropTable" && dropTableAst.ddl.ifExists;
2853
- 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)}`;
2854
4609
  break;
2855
4610
  }
2856
4611
  case "createIndex": {
2857
4612
  const createIndexAst = ast;
2858
- sql = renderCreateIndexSql(createIndexAst.target, createIndexAst.ddl, state, dialect);
4613
+ assertNoStatementQueryClauses(createIndexAst, "createIndex");
4614
+ sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
2859
4615
  break;
2860
4616
  }
2861
4617
  case "dropIndex": {
2862
4618
  const dropIndexAst = ast;
2863
- sql = renderDropIndexSql(dropIndexAst.target, dropIndexAst.ddl, state, dialect);
4619
+ assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
4620
+ sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
2864
4621
  break;
2865
4622
  }
4623
+ default:
4624
+ throw new Error("Unsupported query statement kind");
2866
4625
  }
2867
- if (state.ctes.length === 0) {
4626
+ if (state.ctes.length === 0 || options2.emitCtes === false) {
2868
4627
  return {
2869
4628
  sql,
2870
4629
  projections
@@ -2887,9 +4646,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2887
4646
  };
2888
4647
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
2889
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
+ }
2890
4653
  if (!state.cteNames.has(cte.name)) {
2891
4654
  state.cteNames.add(cte.name);
2892
- 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 });
2893
4657
  state.ctes.push({
2894
4658
  name: cte.name,
2895
4659
  sql: rendered.sql,
@@ -2901,11 +4665,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2901
4665
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
2902
4666
  const derived = source;
2903
4667
  if (!state.cteNames.has(derived.name)) {}
2904
- 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)}`;
2905
4669
  }
2906
4670
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
2907
4671
  const lateral = source;
2908
- 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)}`;
2909
4673
  }
2910
4674
  if (typeof source === "object" && source !== null && source.kind === "values") {
2911
4675
  const values = source;
@@ -2926,6 +4690,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2926
4690
  const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
2927
4691
  return dialect.renderTableReference(tableName, baseTableName, schemaName);
2928
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
+ };
2929
4700
  var renderExpression = (expression, state, dialect) => {
2930
4701
  const rawAst = expression[TypeId3];
2931
4702
  const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
@@ -2936,8 +4707,11 @@ var renderExpression = (expression, state, dialect) => {
2936
4707
  const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
2937
4708
  switch (ast.kind) {
2938
4709
  case "column":
2939
- 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)}`;
2940
4711
  case "literal":
4712
+ if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
4713
+ throw new Error("Expected a finite numeric value");
4714
+ }
2941
4715
  return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
2942
4716
  case "excluded":
2943
4717
  return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
@@ -2977,6 +4751,7 @@ var renderExpression = (expression, state, dialect) => {
2977
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)})`;
2978
4752
  case "contains":
2979
4753
  if (dialect.name === "postgres") {
4754
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2980
4755
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2981
4756
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2982
4757
  return `(${left} @> ${right})`;
@@ -2987,6 +4762,7 @@ var renderExpression = (expression, state, dialect) => {
2987
4762
  throw new Error("Unsupported container operator for SQL rendering");
2988
4763
  case "containedBy":
2989
4764
  if (dialect.name === "postgres") {
4765
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2990
4766
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2991
4767
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2992
4768
  return `(${left} <@ ${right})`;
@@ -2997,6 +4773,7 @@ var renderExpression = (expression, state, dialect) => {
2997
4773
  throw new Error("Unsupported container operator for SQL rendering");
2998
4774
  case "overlaps":
2999
4775
  if (dialect.name === "postgres") {
4776
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
3000
4777
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
3001
4778
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
3002
4779
  return `(${left} && ${right})`;
@@ -3022,14 +4799,26 @@ var renderExpression = (expression, state, dialect) => {
3022
4799
  case "min":
3023
4800
  return `min(${renderExpression(ast.value, state, dialect)})`;
3024
4801
  case "and":
4802
+ if (ast.values.length === 0) {
4803
+ throw new Error("and(...) requires at least one predicate");
4804
+ }
3025
4805
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
3026
4806
  case "or":
4807
+ if (ast.values.length === 0) {
4808
+ throw new Error("or(...) requires at least one predicate");
4809
+ }
3027
4810
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
3028
4811
  case "coalesce":
3029
4812
  return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
3030
4813
  case "in":
4814
+ if (ast.values.length < 2) {
4815
+ throw new Error("in(...) requires at least one candidate value");
4816
+ }
3031
4817
  return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
3032
4818
  case "notIn":
4819
+ if (ast.values.length < 2) {
4820
+ throw new Error("notIn(...) requires at least one candidate value");
4821
+ }
3033
4822
  return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
3034
4823
  case "between":
3035
4824
  return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
@@ -3038,15 +4827,15 @@ var renderExpression = (expression, state, dialect) => {
3038
4827
  case "case":
3039
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`;
3040
4829
  case "exists":
3041
- return `exists (${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4830
+ return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
3042
4831
  case "scalarSubquery":
3043
- return `(${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4832
+ return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
3044
4833
  case "inSubquery":
3045
- 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)}))`;
3046
4835
  case "comparisonAny":
3047
- 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)}))`;
3048
4837
  case "comparisonAll":
3049
- 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)}))`;
3050
4839
  case "window": {
3051
4840
  if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
3052
4841
  break;
@@ -3131,7 +4920,8 @@ var inlineLiteralDialect = {
3131
4920
  var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
3132
4921
  params: [],
3133
4922
  ctes: [],
3134
- cteNames: new Set
4923
+ cteNames: new Set,
4924
+ cteSources: new Map
3135
4925
  }, inlineLiteralDialect);
3136
4926
  var stripRedundantOuterParens = (value) => {
3137
4927
  let current = value.trim();
@@ -3182,10 +4972,14 @@ var normalizeDdlExpressionSql = (expression) => {
3182
4972
  };
3183
4973
 
3184
4974
  // src/postgres/schema-management.ts
3185
- import * as Schema4 from "effect/Schema";
4975
+ import * as Schema6 from "effect/Schema";
3186
4976
  import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
3187
4977
  var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
3188
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)}`;
3189
4983
  var EnumProto = {
3190
4984
  pipe() {
3191
4985
  return pipeArguments5(this, arguments);
@@ -3196,13 +4990,13 @@ var EnumProto = {
3196
4990
  type() {
3197
4991
  return {
3198
4992
  dialect: "postgres",
3199
- kind: this.qualifiedName(),
4993
+ kind: renderQualifiedTypeName(this.name, this.schemaName),
3200
4994
  variant: "enum"
3201
4995
  };
3202
4996
  },
3203
4997
  column() {
3204
- const values = this.values.map((value) => Schema4.Literal(value));
3205
- return makeColumnDefinition(values.length === 1 ? values[0] : Schema4.Union(...values), {
4998
+ const values = this.values.map((value) => Schema6.Literal(value));
4999
+ return makeColumnDefinition(values.length === 1 ? values[0] : Schema6.Union(...values), {
3206
5000
  dbType: this.type(),
3207
5001
  nullable: false,
3208
5002
  hasDefault: false,
@@ -3210,7 +5004,7 @@ var EnumProto = {
3210
5004
  primaryKey: false,
3211
5005
  unique: false,
3212
5006
  references: undefined,
3213
- ddlType: this.qualifiedName(),
5007
+ ddlType: renderQualifiedTypeName(this.name, this.schemaName),
3214
5008
  identity: undefined,
3215
5009
  enum: {
3216
5010
  name: this.name,
@@ -3311,17 +5105,17 @@ var fromDiscoveredValues = (values) => {
3311
5105
  const enums = new Map;
3312
5106
  for (const value of values) {
3313
5107
  if (isEnumDefinition(value)) {
3314
- enums.set(enumKey(value.schemaName, value.name), toEnumModel(value));
5108
+ enums.set(modelIdentityKey(value.schemaName, value.name), toEnumModel(value));
3315
5109
  } else if (isTableDefinition(value)) {
3316
5110
  for (const enumModel of enumModelsOfTable(value)) {
3317
- const key2 = enumKey(enumModel.schemaName, enumModel.name);
5111
+ const key2 = modelIdentityKey(enumModel.schemaName, enumModel.name);
3318
5112
  const existing = enums.get(key2);
3319
5113
  if (existing === undefined) {
3320
5114
  enums.set(key2, enumModel);
3321
5115
  continue;
3322
5116
  }
3323
5117
  if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
3324
- throw new Error(`Conflicting enum definitions discovered for '${key2}'`);
5118
+ throw new Error(`Conflicting enum definitions discovered for '${enumKey(enumModel.schemaName, enumModel.name)}'`);
3325
5119
  }
3326
5120
  }
3327
5121
  }
@@ -3334,6 +5128,7 @@ var fromDiscoveredValues = (values) => {
3334
5128
  };
3335
5129
  var tableKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
3336
5130
  var enumKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
5131
+ var modelIdentityKey = (schemaName, name) => JSON.stringify([schemaName ?? "public", name]);
3337
5132
  export {
3338
5133
  toTableModel,
3339
5134
  toEnumModel,