effect-qb 0.16.0 → 4.0.0-beta.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +7 -0
  2. package/dist/mysql.js +1858 -715
  3. package/dist/postgres/metadata.js +2036 -172
  4. package/dist/postgres.js +8011 -6849
  5. package/dist/sqlite.js +8433 -0
  6. package/package.json +7 -4
  7. package/src/internal/column-state.d.ts +3 -3
  8. package/src/internal/column-state.ts +3 -3
  9. package/src/internal/column.ts +8 -8
  10. package/src/internal/derived-table.ts +29 -3
  11. package/src/internal/dialect.ts +3 -1
  12. package/src/internal/dsl-mutation-runtime.ts +173 -4
  13. package/src/internal/dsl-plan-runtime.ts +165 -20
  14. package/src/internal/dsl-query-runtime.ts +60 -6
  15. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  16. package/src/internal/executor.ts +100 -43
  17. package/src/internal/expression-ast.ts +3 -2
  18. package/src/internal/grouping-key.ts +141 -1
  19. package/src/internal/implication-runtime.ts +2 -1
  20. package/src/internal/json/types.ts +155 -40
  21. package/src/internal/predicate/context.ts +14 -1
  22. package/src/internal/predicate/key.ts +19 -2
  23. package/src/internal/predicate/runtime.ts +27 -3
  24. package/src/internal/query.d.ts +1 -1
  25. package/src/internal/query.ts +253 -31
  26. package/src/internal/renderer.ts +35 -2
  27. package/src/internal/runtime/driver-value-mapping.ts +60 -2
  28. package/src/internal/runtime/normalize.ts +62 -38
  29. package/src/internal/runtime/schema.ts +32 -40
  30. package/src/internal/runtime/value.ts +159 -39
  31. package/src/internal/scalar.d.ts +1 -1
  32. package/src/internal/scalar.ts +1 -1
  33. package/src/internal/schema-derivation.d.ts +12 -61
  34. package/src/internal/schema-derivation.ts +95 -43
  35. package/src/internal/table-options.ts +108 -1
  36. package/src/internal/table.d.ts +29 -22
  37. package/src/internal/table.ts +260 -53
  38. package/src/mysql/column.ts +24 -8
  39. package/src/mysql/datatypes/index.ts +21 -0
  40. package/src/mysql/errors/catalog.ts +5 -5
  41. package/src/mysql/errors/normalize.ts +2 -2
  42. package/src/mysql/executor.ts +4 -4
  43. package/src/mysql/function/temporal.ts +1 -1
  44. package/src/mysql/internal/dsl.ts +759 -235
  45. package/src/mysql/internal/renderer.ts +2 -1
  46. package/src/mysql/internal/sql-expression-renderer.ts +486 -130
  47. package/src/mysql/query.ts +9 -2
  48. package/src/mysql/table.ts +64 -35
  49. package/src/postgres/column.ts +14 -12
  50. package/src/postgres/errors/normalize.ts +2 -2
  51. package/src/postgres/executor.ts +52 -9
  52. package/src/postgres/function/core.ts +19 -1
  53. package/src/postgres/function/temporal.ts +1 -1
  54. package/src/postgres/internal/dsl.ts +705 -256
  55. package/src/postgres/internal/renderer.ts +2 -1
  56. package/src/postgres/internal/schema-ddl.ts +2 -1
  57. package/src/postgres/internal/schema-model.ts +6 -3
  58. package/src/postgres/internal/sql-expression-renderer.ts +420 -91
  59. package/src/postgres/json.ts +57 -17
  60. package/src/postgres/query.ts +9 -2
  61. package/src/postgres/schema-management.ts +92 -6
  62. package/src/postgres/schema.ts +1 -1
  63. package/src/postgres/table.ts +203 -75
  64. package/src/sqlite/column.ts +128 -0
  65. package/src/sqlite/datatypes/index.ts +79 -0
  66. package/src/sqlite/datatypes/spec.ts +98 -0
  67. package/src/sqlite/errors/catalog.ts +103 -0
  68. package/src/sqlite/errors/fields.ts +19 -0
  69. package/src/sqlite/errors/index.ts +19 -0
  70. package/src/sqlite/errors/normalize.ts +229 -0
  71. package/src/sqlite/errors/requirements.ts +71 -0
  72. package/src/sqlite/errors/types.ts +29 -0
  73. package/src/sqlite/executor.ts +227 -0
  74. package/src/sqlite/function/aggregate.ts +2 -0
  75. package/src/sqlite/function/core.ts +2 -0
  76. package/src/sqlite/function/index.ts +19 -0
  77. package/src/sqlite/function/string.ts +2 -0
  78. package/src/sqlite/function/temporal.ts +100 -0
  79. package/src/sqlite/function/window.ts +2 -0
  80. package/src/sqlite/internal/dialect.ts +37 -0
  81. package/src/sqlite/internal/dsl.ts +6927 -0
  82. package/src/sqlite/internal/renderer.ts +47 -0
  83. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  84. package/src/sqlite/json.ts +2 -0
  85. package/src/sqlite/query.ts +196 -0
  86. package/src/sqlite/renderer.ts +24 -0
  87. package/src/sqlite/table.ts +175 -0
  88. 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
  }
@@ -322,12 +347,7 @@ var validateOptions = (tableName, fields, options) => {
322
347
  };
323
348
 
324
349
  // src/internal/schema-derivation.ts
325
- import * as VariantSchema from "@effect/experimental/VariantSchema";
326
350
  import * as Schema2 from "effect/Schema";
327
- var TableSchema = VariantSchema.make({
328
- variants: ["select", "insert", "update"],
329
- defaultVariant: "select"
330
- });
331
351
  var maybeBrandSchema = (column, tableName, columnName) => column.metadata.brand === true ? Schema2.brand(`${tableName}.${columnName}`)(column.schema) : column.schema;
332
352
  var selectSchema = (column, tableName, columnName) => column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
333
353
  var insertSchema = (column, tableName, columnName) => {
@@ -344,42 +364,37 @@ var updateSchema = (column, tableName, columnName, isPrimaryKey) => {
344
364
  const base = column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
345
365
  return Schema2.optional(base);
346
366
  };
347
- var deriveSchemas = (tableName, fields, primaryKeyColumns) => {
367
+ var fieldSchemaForVariant = (variant, column, tableName, columnName, primaryKeySet) => {
368
+ switch (variant) {
369
+ case "select":
370
+ return selectSchema(column, tableName, columnName);
371
+ case "insert":
372
+ return insertSchema(column, tableName, columnName);
373
+ case "update":
374
+ return updateSchema(column, tableName, columnName, primaryKeySet.has(columnName));
375
+ }
376
+ };
377
+ var deriveSchema = (variant, tableName, fields, primaryKeyColumns) => {
348
378
  const primaryKeySet = new Set(primaryKeyColumns);
349
- const variants = {};
379
+ const structFields = {};
350
380
  for (const [key, column] of Object.entries(fields)) {
351
- const config = {
352
- select: selectSchema(column, tableName, key),
353
- insert: undefined,
354
- update: undefined
355
- };
356
- const insert = insertSchema(column, tableName, key);
357
- const update = updateSchema(column, tableName, key, primaryKeySet.has(key));
358
- if (insert !== undefined) {
359
- config.insert = insert;
360
- } else {
361
- delete config.insert;
362
- }
363
- if (update !== undefined) {
364
- config.update = update;
365
- } else {
366
- delete config.update;
381
+ const schema = fieldSchemaForVariant(variant, column, tableName, key, primaryKeySet);
382
+ if (schema !== undefined) {
383
+ structFields[key] = schema;
367
384
  }
368
- variants[key] = TableSchema.Field(config);
369
385
  }
370
- const struct = TableSchema.Struct(variants);
371
- return {
372
- select: TableSchema.extract(struct, "select"),
373
- insert: TableSchema.extract(struct, "insert"),
374
- update: TableSchema.extract(struct, "update")
375
- };
386
+ return Schema2.Struct(structFields);
376
387
  };
388
+ var deriveSelectSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("select", tableName, fields, primaryKeyColumns);
389
+ var deriveInsertSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("insert", tableName, fields, primaryKeyColumns);
390
+ var deriveUpdateSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("update", tableName, fields, primaryKeyColumns);
377
391
 
378
392
  // src/internal/table.ts
379
393
  var TypeId4 = Symbol.for("effect-qb/Table");
380
394
  var OptionsSymbol = Symbol.for("effect-qb/Table/normalizedOptions");
381
395
  var options = Symbol.for("effect-qb/Table/declaredOptions");
382
396
  var CacheSymbol = Symbol.for("effect-qb/Table/cache");
397
+ var SchemaCacheSymbol = Symbol.for("effect-qb/Table/schemaCache");
383
398
  var DeclaredOptionsSymbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions");
384
399
  var TableProto = {
385
400
  pipe() {
@@ -402,14 +417,86 @@ var buildArtifacts = (name, fields, declaredOptions, schemaName) => {
402
417
  validateOptions(name, fields, declaredOptions);
403
418
  const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions);
404
419
  const columns = Object.fromEntries(Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)]));
405
- const schemas = deriveSchemas(name, fields, primaryKey);
406
420
  return {
407
421
  columns,
408
- schemas,
409
422
  normalizedOptions,
410
423
  primaryKey
411
424
  };
412
425
  };
426
+ var getSchemaCache = (table) => {
427
+ const target = table;
428
+ if (target[SchemaCacheSymbol] !== undefined) {
429
+ return target[SchemaCacheSymbol];
430
+ }
431
+ const cache = {};
432
+ Object.defineProperty(table, SchemaCacheSymbol, {
433
+ configurable: true,
434
+ value: cache
435
+ });
436
+ return cache;
437
+ };
438
+ var deriveTableSchema = (table, variant) => {
439
+ const state = table[TypeId4];
440
+ switch (variant) {
441
+ case "select":
442
+ return deriveSelectSchema(state.name, state.fields, state.primaryKey);
443
+ case "insert":
444
+ return deriveInsertSchema(state.name, state.fields, state.primaryKey);
445
+ case "update":
446
+ return deriveUpdateSchema(state.name, state.fields, state.primaryKey);
447
+ }
448
+ };
449
+ var schemaFor = (table, variant) => {
450
+ const cache = getSchemaCache(table);
451
+ const cached = cache[variant];
452
+ if (cached !== undefined) {
453
+ return cached;
454
+ }
455
+ const schema = deriveTableSchema(table, variant);
456
+ cache[variant] = schema;
457
+ return schema;
458
+ };
459
+ function selectSchema2(table) {
460
+ return schemaFor(table, "select");
461
+ }
462
+ function insertSchema2(table) {
463
+ return schemaFor(table, "insert");
464
+ }
465
+ function updateSchema2(table) {
466
+ return schemaFor(table, "update");
467
+ }
468
+ var schemasFor = (table) => {
469
+ const cache = getSchemaCache(table);
470
+ if (cache.schemas !== undefined) {
471
+ return cache.schemas;
472
+ }
473
+ const schemas = {};
474
+ Object.defineProperties(schemas, {
475
+ select: {
476
+ enumerable: true,
477
+ get: () => selectSchema2(table)
478
+ },
479
+ insert: {
480
+ enumerable: true,
481
+ get: () => insertSchema2(table)
482
+ },
483
+ update: {
484
+ enumerable: true,
485
+ get: () => updateSchema2(table)
486
+ }
487
+ });
488
+ cache.schemas = schemas;
489
+ return schemas;
490
+ };
491
+ var defineSchemasGetter = (table) => {
492
+ Object.defineProperty(table, "schemas", {
493
+ configurable: true,
494
+ enumerable: true,
495
+ get() {
496
+ return schemasFor(table);
497
+ }
498
+ });
499
+ };
413
500
  var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema", schemaName, schemaMode = "default") => {
414
501
  const resolvedSchemaName = schemaMode === "explicit" ? schemaName : "public";
415
502
  const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName);
@@ -417,7 +504,7 @@ var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema"
417
504
  const table = attachPipe2(Object.create(TableProto));
418
505
  table.name = name;
419
506
  table.columns = artifacts.columns;
420
- table.schemas = artifacts.schemas;
507
+ defineSchemasGetter(table);
421
508
  table[TypeId4] = {
422
509
  name,
423
510
  baseName,
@@ -490,7 +577,6 @@ var ensureClassArtifacts = (self) => {
490
577
  const table = applyDeclaredOptions(makeTable(state.name, state.fields, [], state.name, "schema", state.schemaName, state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"), classOptions);
491
578
  const artifacts = {
492
579
  columns: table.columns,
493
- schemas: table.schemas,
494
580
  normalizedOptions: table[OptionsSymbol],
495
581
  primaryKey: table[TypeId4].primaryKey
496
582
  };
@@ -513,21 +599,24 @@ var makeOption = (option) => {
513
599
  return builder;
514
600
  };
515
601
  var option = (spec) => makeOption(spec);
516
- function make2(name, fields, schemaName) {
602
+ function make(name, fields, schemaName) {
517
603
  const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
518
604
  return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
519
605
  }
520
- var schema = (schemaName) => ({
521
- schemaName,
522
- table: (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2)
523
- });
606
+ var schema = (schemaName) => {
607
+ const table = (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2);
608
+ return {
609
+ schemaName,
610
+ table
611
+ };
612
+ };
524
613
  var alias = (table, aliasName) => {
525
614
  const state = table[TypeId4];
526
615
  const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
527
616
  const aliased = attachPipe2(Object.create(TableProto));
528
617
  aliased.name = aliasName;
529
618
  aliased.columns = columns;
530
- aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey);
619
+ defineSchemasGetter(aliased);
531
620
  aliased[TypeId4] = {
532
621
  name: aliasName,
533
622
  baseName: state.baseName,
@@ -568,7 +657,7 @@ function Class(name, schemaName) {
568
657
  return ensureClassArtifacts(this).columns;
569
658
  }
570
659
  static get schemas() {
571
- return ensureClassArtifacts(this).schemas;
660
+ return schemasFor(this);
572
661
  }
573
662
  static get [TypeId4]() {
574
663
  const declaredOptions = extractDeclaredOptions(this[options]);
@@ -696,6 +785,9 @@ var normalize = (expression) => (() => {
696
785
  }
697
786
  })();
698
787
 
788
+ // src/postgres/internal/sql-expression-renderer.ts
789
+ import * as Schema5 from "effect/Schema";
790
+
699
791
  // src/internal/query.ts
700
792
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
701
793
 
@@ -732,7 +824,18 @@ var cloneContext = (context) => ({
732
824
  unknown: context.unknown
733
825
  });
734
826
  var freezeContext = (context) => context;
735
- var sourceNameOfKey = (key) => key.split(".", 1)[0] ?? key;
827
+ var columnPredicateKey = (tableName, columnName) => JSON.stringify([tableName, columnName]);
828
+ var columnPredicateKeyParts = (key) => {
829
+ const jsonSeparator = key.indexOf("#json:");
830
+ const columnKey = jsonSeparator === -1 ? key : key.slice(0, jsonSeparator);
831
+ try {
832
+ const parsed = JSON.parse(columnKey);
833
+ return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : undefined;
834
+ } catch {
835
+ return;
836
+ }
837
+ };
838
+ var sourceNameOfKey = (key) => columnPredicateKeyParts(key)?.[0] ?? key.split(".", 1)[0] ?? key;
736
839
  var addSourceName = (context, key) => {
737
840
  context.sourceNames.add(sourceNameOfKey(key));
738
841
  };
@@ -982,9 +1085,10 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
982
1085
  var astOf = (value) => value[TypeId3];
983
1086
  var columnKeyOfExpression = (value) => {
984
1087
  const ast = astOf(value);
985
- return ast.kind === "column" ? `${ast.tableName}.${ast.columnName}` : undefined;
1088
+ return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
986
1089
  };
987
1090
  var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
1091
+ var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
988
1092
  var jsonPathPredicateKeyOfExpression = (value) => {
989
1093
  const ast = astOf(value);
990
1094
  switch (ast.kind) {
@@ -1008,7 +1112,7 @@ var jsonPathPredicateKeyOfExpression = (value) => {
1008
1112
  return;
1009
1113
  }
1010
1114
  const baseKey = columnKeyOfExpression(jsonAst.base);
1011
- return baseKey === undefined ? undefined : `${baseKey}#json:${path.join(".")}`;
1115
+ return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
1012
1116
  }
1013
1117
  default:
1014
1118
  return;
@@ -1463,13 +1567,1309 @@ var path = (...segments) => ({
1463
1567
  segments
1464
1568
  });
1465
1569
 
1570
+ // src/internal/dsl-plan-runtime.ts
1571
+ var renderSelectLockMode = (mode) => {
1572
+ switch (mode) {
1573
+ case "update":
1574
+ return "for update";
1575
+ case "share":
1576
+ return "for share";
1577
+ }
1578
+ throw new Error("lock(...) mode must be update or share for select statements");
1579
+ };
1580
+ var renderMysqlMutationLockMode = (mode, statement) => {
1581
+ switch (mode) {
1582
+ case "lowPriority":
1583
+ return " low_priority";
1584
+ case "ignore":
1585
+ return " ignore";
1586
+ case "quick":
1587
+ if (statement === "delete") {
1588
+ return " quick";
1589
+ }
1590
+ break;
1591
+ }
1592
+ 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");
1593
+ };
1594
+ var makeDslPlanRuntime = (ctx) => {
1595
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
1596
+ const isRecord = (value) => typeof value === "object" && value !== null;
1597
+ const isPlan = (value) => isRecord(value) && (TypeId in value);
1598
+ const hasColumnRecord = (value) => isRecord(value.columns);
1599
+ const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
1600
+ const isAliasedSource = (source) => {
1601
+ if (!isRecord(source)) {
1602
+ return false;
1603
+ }
1604
+ if (TypeId4 in source) {
1605
+ return true;
1606
+ }
1607
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
1608
+ return false;
1609
+ }
1610
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
1611
+ return false;
1612
+ }
1613
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
1614
+ return false;
1615
+ }
1616
+ switch (source.kind) {
1617
+ case "derived":
1618
+ case "cte":
1619
+ case "lateral":
1620
+ return isPlan(source.plan) && hasColumnRecord(source);
1621
+ case "values":
1622
+ return Array.isArray(source.rows) && hasColumnRecord(source);
1623
+ case "unnest":
1624
+ return isRecord(source.arrays) && hasColumnRecord(source);
1625
+ case "tableFunction":
1626
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
1627
+ }
1628
+ return false;
1629
+ };
1630
+ const assertAliasedSource = (source, message) => {
1631
+ if (!isAliasedSource(source)) {
1632
+ throw new Error(message);
1633
+ }
1634
+ };
1635
+ const assertPlanComplete = (plan) => {
1636
+ const required = ctx.currentRequiredList(plan[TypeId].required);
1637
+ if (required.length > 0) {
1638
+ throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
1639
+ }
1640
+ };
1641
+ const assertSourceNameAvailable = (available, sourceName) => {
1642
+ if (sourceName in available) {
1643
+ throw new Error(`query source name is already in scope: ${sourceName}`);
1644
+ }
1645
+ };
1646
+ const assertSelectHasBaseSourceForJoin = (statement, available) => {
1647
+ if (statement === "select" && Object.keys(available).length === 0) {
1648
+ throw new Error("select joins require a from(...) source before joining");
1649
+ }
1650
+ };
1651
+ const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
1652
+ const assertSetOperandStatement = (plan) => {
1653
+ const statement = ctx.getQueryState(plan).statement;
1654
+ if (statement !== "select" && statement !== "set") {
1655
+ throw new Error("set operator operands only accept select-like query plans");
1656
+ }
1657
+ };
1658
+ const buildSetOperation = (kind, all, left, right) => {
1659
+ assertSetOperandStatement(left);
1660
+ assertSetOperandStatement(right);
1661
+ assertPlanComplete(left);
1662
+ assertPlanComplete(right);
1663
+ const leftState = left[TypeId];
1664
+ const leftAst = ctx.getAst(left);
1665
+ const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
1666
+ const leftOperations = leftAst.kind === "set" ? [...leftAst.setOperations ?? []] : [];
1667
+ return ctx.makePlan({
1668
+ selection: leftState.selection,
1669
+ required: undefined,
1670
+ available: {},
1671
+ dialect: leftState.dialect ?? right[TypeId].dialect
1672
+ }, {
1673
+ kind: "set",
1674
+ select: leftState.selection,
1675
+ where: [],
1676
+ having: [],
1677
+ joins: [],
1678
+ groupBy: [],
1679
+ orderBy: [],
1680
+ setBase: basePlan,
1681
+ setOperations: [
1682
+ ...leftOperations,
1683
+ {
1684
+ kind,
1685
+ all,
1686
+ query: right
1687
+ }
1688
+ ]
1689
+ }, undefined, undefined, "set");
1690
+ };
1691
+ const where = (predicate) => (plan) => {
1692
+ const current = plan[TypeId];
1693
+ const currentAst = ctx.getAst(plan);
1694
+ const currentQuery = ctx.getQueryState(plan);
1695
+ const predicateExpression = ctx.toDialectExpression(predicate);
1696
+ const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
1697
+ return ctx.makePlan({
1698
+ selection: current.selection,
1699
+ required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1700
+ available: current.available,
1701
+ dialect: current.dialect ?? predicateExpression[TypeId2].dialect
1702
+ }, {
1703
+ ...currentAst,
1704
+ where: [...currentAst.where, {
1705
+ kind: "where",
1706
+ predicate: predicateExpression
1707
+ }]
1708
+ }, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
1709
+ };
1710
+ const from = (source) => (plan) => {
1711
+ const current = plan[TypeId];
1712
+ const currentAst = ctx.getAst(plan);
1713
+ const currentQuery = ctx.getQueryState(plan);
1714
+ if (currentQuery.statement === "insert") {
1715
+ return ctx.attachInsertSource(plan, source);
1716
+ }
1717
+ assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
1718
+ if (currentQuery.statement === "select" && currentAst.from !== undefined) {
1719
+ throw new Error("select statements accept only one from(...) source; use joins for additional sources");
1720
+ }
1721
+ const sourceLike = source;
1722
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
1723
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
1724
+ const sourceRequired = sourceRequiredList(sourceLike);
1725
+ assertSourceNameAvailable(current.available, sourceName);
1726
+ if (currentQuery.statement === "select") {
1727
+ const nextAvailable = {
1728
+ [sourceName]: {
1729
+ name: sourceName,
1730
+ mode: "required",
1731
+ baseName: sourceBaseName,
1732
+ _presentFormula: ctx.trueFormula(),
1733
+ _presenceWitnesses: presenceWitnesses
1734
+ }
1735
+ };
1736
+ return ctx.makePlan({
1737
+ selection: current.selection,
1738
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1739
+ available: nextAvailable,
1740
+ dialect: current.dialect
1741
+ }, {
1742
+ ...currentAst,
1743
+ from: {
1744
+ kind: "from",
1745
+ tableName: sourceName,
1746
+ baseTableName: sourceBaseName,
1747
+ source: sourceLike
1748
+ }
1749
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1750
+ }
1751
+ if (currentQuery.statement === "update") {
1752
+ const nextAvailable = {
1753
+ ...current.available,
1754
+ [sourceName]: {
1755
+ name: sourceName,
1756
+ mode: "required",
1757
+ baseName: sourceBaseName,
1758
+ _presentFormula: ctx.trueFormula(),
1759
+ _presenceWitnesses: presenceWitnesses
1760
+ }
1761
+ };
1762
+ return ctx.makePlan({
1763
+ selection: current.selection,
1764
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1765
+ available: nextAvailable,
1766
+ dialect: current.dialect
1767
+ }, {
1768
+ ...currentAst,
1769
+ fromSources: [
1770
+ ...currentAst.fromSources ?? [],
1771
+ {
1772
+ kind: "from",
1773
+ tableName: sourceName,
1774
+ baseTableName: sourceBaseName,
1775
+ source: sourceLike
1776
+ }
1777
+ ]
1778
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1779
+ }
1780
+ throw new Error(`from(...) is not supported for ${currentQuery.statement} statements`);
1781
+ };
1782
+ const having = (predicate) => (plan) => {
1783
+ const current = plan[TypeId];
1784
+ const currentAst = ctx.getAst(plan);
1785
+ const currentQuery = ctx.getQueryState(plan);
1786
+ const predicateExpression = ctx.toDialectExpression(predicate);
1787
+ const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
1788
+ return ctx.makePlan({
1789
+ selection: current.selection,
1790
+ required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1791
+ available: current.available,
1792
+ dialect: current.dialect ?? predicateExpression[TypeId2].dialect
1793
+ }, {
1794
+ ...currentAst,
1795
+ having: [...currentAst.having, {
1796
+ kind: "having",
1797
+ predicate: predicateExpression
1798
+ }]
1799
+ }, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
1800
+ };
1801
+ const crossJoin = (table) => (plan) => {
1802
+ const current = plan[TypeId];
1803
+ const currentAst = ctx.getAst(plan);
1804
+ const currentQuery = ctx.getQueryState(plan);
1805
+ if (supportsJoinSources(currentQuery.statement)) {
1806
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1807
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1808
+ }
1809
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1810
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1811
+ const sourceRequired = sourceRequiredList(table);
1812
+ if (supportsJoinSources(currentQuery.statement)) {
1813
+ assertSourceNameAvailable(current.available, sourceName);
1814
+ }
1815
+ const nextAvailable = {
1816
+ ...current.available,
1817
+ [sourceName]: {
1818
+ name: sourceName,
1819
+ mode: "required",
1820
+ baseName: sourceBaseName,
1821
+ _presentFormula: ctx.trueFormula(),
1822
+ _presenceWitnesses: presenceWitnesses
1823
+ }
1824
+ };
1825
+ return ctx.makePlan({
1826
+ selection: current.selection,
1827
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1828
+ available: nextAvailable,
1829
+ dialect: current.dialect ?? table[TypeId]?.dialect ?? table.dialect
1830
+ }, {
1831
+ ...currentAst,
1832
+ joins: [...currentAst.joins, {
1833
+ kind: "cross",
1834
+ tableName: sourceName,
1835
+ baseTableName: sourceBaseName,
1836
+ source: table
1837
+ }]
1838
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1839
+ };
1840
+ const join = (kind, table, on) => (plan) => {
1841
+ const current = plan[TypeId];
1842
+ const currentAst = ctx.getAst(plan);
1843
+ const currentQuery = ctx.getQueryState(plan);
1844
+ const onExpression = ctx.toDialectExpression(on);
1845
+ const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
1846
+ if (supportsJoinSources(currentQuery.statement)) {
1847
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1848
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1849
+ }
1850
+ const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1851
+ const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1852
+ const sourceRequired = sourceRequiredList(table);
1853
+ if (supportsJoinSources(currentQuery.statement)) {
1854
+ assertSourceNameAvailable(current.available, sourceName);
1855
+ }
1856
+ const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
1857
+ name: source.name,
1858
+ mode: "optional",
1859
+ baseName: source.baseName,
1860
+ _presentFormula: source._presentFormula,
1861
+ _presenceWitnesses: source._presenceWitnesses
1862
+ }])) : current.available;
1863
+ const nextAvailable = {
1864
+ ...baseAvailable,
1865
+ [sourceName]: {
1866
+ name: sourceName,
1867
+ mode: kind === "left" || kind === "full" ? "optional" : "required",
1868
+ baseName: sourceBaseName,
1869
+ _presentFormula: kind === "inner" || kind === "left" ? onFormula : ctx.trueFormula(),
1870
+ _presenceWitnesses: presenceWitnesses
1871
+ }
1872
+ };
1873
+ return ctx.makePlan({
1874
+ selection: current.selection,
1875
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
1876
+ available: nextAvailable,
1877
+ dialect: current.dialect ?? table.dialect ?? onExpression[TypeId2].dialect
1878
+ }, {
1879
+ ...currentAst,
1880
+ joins: [...currentAst.joins, {
1881
+ kind,
1882
+ tableName: sourceName,
1883
+ baseTableName: sourceBaseName,
1884
+ source: table,
1885
+ on: onExpression
1886
+ }]
1887
+ }, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1888
+ };
1889
+ const orderBy = (value, direction = "asc") => (plan) => {
1890
+ if (direction !== "asc" && direction !== "desc") {
1891
+ throw new Error("orderBy(...) direction must be asc or desc");
1892
+ }
1893
+ const current = plan[TypeId];
1894
+ const currentAst = ctx.getAst(plan);
1895
+ const currentQuery = ctx.getQueryState(plan);
1896
+ const expression = ctx.toDialectExpression(value);
1897
+ const required = ctx.extractRequiredFromDialectInputRuntime(value);
1898
+ return ctx.makePlan({
1899
+ selection: current.selection,
1900
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1901
+ available: current.available,
1902
+ dialect: current.dialect ?? expression[TypeId2].dialect
1903
+ }, {
1904
+ ...currentAst,
1905
+ orderBy: [...currentAst.orderBy, {
1906
+ kind: "orderBy",
1907
+ value: expression,
1908
+ direction
1909
+ }]
1910
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1911
+ };
1912
+ const lock = (mode, options2 = {}) => (plan) => {
1913
+ const current = plan[TypeId];
1914
+ const currentAst = ctx.getAst(plan);
1915
+ const currentQuery = ctx.getQueryState(plan);
1916
+ if (currentQuery.statement === "select") {
1917
+ renderSelectLockMode(mode);
1918
+ }
1919
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
1920
+ renderMysqlMutationLockMode(mode, "update");
1921
+ }
1922
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
1923
+ renderMysqlMutationLockMode(mode, "delete");
1924
+ }
1925
+ return ctx.makePlan({
1926
+ selection: current.selection,
1927
+ required: current.required,
1928
+ available: current.available,
1929
+ dialect: current.dialect
1930
+ }, {
1931
+ ...currentAst,
1932
+ lock: {
1933
+ kind: "lock",
1934
+ mode,
1935
+ nowait: options2.nowait ?? false,
1936
+ skipLocked: options2.skipLocked ?? false
1937
+ }
1938
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1939
+ };
1940
+ const distinct = () => (plan) => {
1941
+ const current = plan[TypeId];
1942
+ const currentAst = ctx.getAst(plan);
1943
+ const currentQuery = ctx.getQueryState(plan);
1944
+ return ctx.makePlan({
1945
+ selection: current.selection,
1946
+ required: current.required,
1947
+ available: current.available,
1948
+ dialect: current.dialect
1949
+ }, {
1950
+ ...currentAst,
1951
+ distinct: true
1952
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1953
+ };
1954
+ const limit = (value) => (plan) => {
1955
+ const current = plan[TypeId];
1956
+ const currentAst = ctx.getAst(plan);
1957
+ const currentQuery = ctx.getQueryState(plan);
1958
+ const expression = ctx.toDialectNumericExpression(value);
1959
+ const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
1960
+ return ctx.makePlan({
1961
+ selection: current.selection,
1962
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1963
+ available: current.available,
1964
+ dialect: current.dialect ?? expression[TypeId2].dialect
1965
+ }, {
1966
+ ...currentAst,
1967
+ limit: expression
1968
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1969
+ };
1970
+ const offset = (value) => (plan) => {
1971
+ const current = plan[TypeId];
1972
+ const currentAst = ctx.getAst(plan);
1973
+ const currentQuery = ctx.getQueryState(plan);
1974
+ const expression = ctx.toDialectNumericExpression(value);
1975
+ const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
1976
+ return ctx.makePlan({
1977
+ selection: current.selection,
1978
+ required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
1979
+ available: current.available,
1980
+ dialect: current.dialect ?? expression[TypeId2].dialect
1981
+ }, {
1982
+ ...currentAst,
1983
+ offset: expression
1984
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1985
+ };
1986
+ return {
1987
+ buildSetOperation,
1988
+ where,
1989
+ from,
1990
+ having,
1991
+ crossJoin,
1992
+ join,
1993
+ orderBy,
1994
+ lock,
1995
+ distinct,
1996
+ limit,
1997
+ offset
1998
+ };
1999
+ };
2000
+
2001
+ // src/internal/dsl-mutation-runtime.ts
2002
+ var expectInsertSourceKind = (source) => {
2003
+ if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
2004
+ throw new Error("Unsupported insert source kind");
2005
+ }
2006
+ return source;
2007
+ };
2008
+ var expectConflictClause = (conflict) => {
2009
+ if (conflict === undefined) {
2010
+ return conflict;
2011
+ }
2012
+ if (conflict.kind !== "conflict") {
2013
+ throw new Error("Unsupported conflict clause kind");
2014
+ }
2015
+ if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
2016
+ throw new Error("Unsupported conflict action");
2017
+ }
2018
+ if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
2019
+ throw new Error("Unsupported conflict target kind");
2020
+ }
2021
+ return conflict;
2022
+ };
2023
+ var makeDslMutationRuntime = (ctx) => {
2024
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
2025
+ const isRecord = (value) => typeof value === "object" && value !== null;
2026
+ const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId in target);
2027
+ const hasColumnRecord = (value) => isRecord(value.columns);
2028
+ const isAliasedSource = (source) => {
2029
+ if (!isRecord(source)) {
2030
+ return false;
2031
+ }
2032
+ if (isTableTarget(source)) {
2033
+ return true;
2034
+ }
2035
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
2036
+ return false;
2037
+ }
2038
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
2039
+ return false;
2040
+ }
2041
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
2042
+ return false;
2043
+ }
2044
+ switch (source.kind) {
2045
+ case "derived":
2046
+ case "cte":
2047
+ case "lateral":
2048
+ return isRecord(source.plan) && TypeId in source.plan && hasColumnRecord(source);
2049
+ case "values":
2050
+ return Array.isArray(source.rows) && hasColumnRecord(source);
2051
+ case "unnest":
2052
+ return isRecord(source.arrays) && hasColumnRecord(source);
2053
+ case "tableFunction":
2054
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
2055
+ }
2056
+ return false;
2057
+ };
2058
+ const assertMutationTarget = (target, apiName) => {
2059
+ if (!isTableTarget(target)) {
2060
+ throw new Error(`${apiName}(...) requires table targets`);
2061
+ }
2062
+ };
2063
+ const assertAliasedSource = (source, apiName) => {
2064
+ if (!isAliasedSource(source)) {
2065
+ throw new Error(`${apiName}(...) requires an aliased source`);
2066
+ }
2067
+ };
2068
+ const assertMutationTargets = (target, apiName, options2 = {}) => {
2069
+ const targets = Array.isArray(target) ? target : [target];
2070
+ if (targets.length === 0) {
2071
+ throw new Error(`${apiName}(...) requires at least one table target`);
2072
+ }
2073
+ if (Array.isArray(target) && targets.length === 1) {
2074
+ throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
2075
+ }
2076
+ for (const entry of targets) {
2077
+ assertMutationTarget(entry, apiName);
2078
+ }
2079
+ if (targets.length > 1 && options2.allowMultiple !== true) {
2080
+ throw new Error(`${apiName}(...) requires a single table target`);
2081
+ }
2082
+ if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
2083
+ throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
2084
+ }
2085
+ };
2086
+ const assertUniqueTargetNames = (targets) => {
2087
+ const seen = new Set;
2088
+ for (const target of targets) {
2089
+ if (seen.has(target.tableName)) {
2090
+ throw new Error(`mutation target source names must be unique: ${target.tableName}`);
2091
+ }
2092
+ seen.add(target.tableName);
2093
+ }
2094
+ };
2095
+ const assertInsertSelectSource = (sourcePlan, selection) => {
2096
+ const statement = ctx.getQueryState(sourcePlan).statement;
2097
+ if (statement !== "select" && statement !== "set") {
2098
+ throw new Error("insert sources only accept select-like query plans");
2099
+ }
2100
+ for (const value of Object.values(selection)) {
2101
+ if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
2102
+ throw new Error("insert sources require a flat selection object");
2103
+ }
2104
+ }
2105
+ };
2106
+ const insert = (target, values) => {
2107
+ assertMutationTargets(target, "insert");
2108
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2109
+ const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
2110
+ const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies));
2111
+ const insertState = values === undefined ? "missing" : "ready";
2112
+ return ctx.makePlan({
2113
+ selection: {},
2114
+ required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
2115
+ available: {
2116
+ [sourceName]: {
2117
+ name: sourceName,
2118
+ mode: "required",
2119
+ baseName: sourceBaseName
2120
+ }
2121
+ },
2122
+ dialect: target[TypeId].dialect
2123
+ }, {
2124
+ kind: "insert",
2125
+ select: {},
2126
+ into: {
2127
+ kind: "from",
2128
+ tableName: sourceName,
2129
+ baseTableName: sourceBaseName,
2130
+ source: target
2131
+ },
2132
+ values: assignments,
2133
+ conflict: undefined,
2134
+ where: [],
2135
+ having: [],
2136
+ joins: [],
2137
+ groupBy: [],
2138
+ orderBy: []
2139
+ }, undefined, "write", "insert", target, insertState);
2140
+ };
2141
+ const attachInsertSource = (plan, source) => {
2142
+ const current = plan[TypeId];
2143
+ const currentAst = ctx.getAst(plan);
2144
+ const currentQuery = ctx.getQueryState(plan);
2145
+ const target = currentQuery.target;
2146
+ const sourceName = currentAst.into.tableName;
2147
+ if (typeof source === "object" && source !== null && "kind" in source && source.kind === "values") {
2148
+ const normalized = ctx.buildInsertValuesRows(target, source.rows);
2149
+ return ctx.makePlan({
2150
+ selection: current.selection,
2151
+ required: normalized.required.filter((name) => name !== sourceName),
2152
+ available: current.available,
2153
+ dialect: current.dialect
2154
+ }, {
2155
+ ...currentAst,
2156
+ values: [],
2157
+ insertSource: {
2158
+ kind: "values",
2159
+ columns: normalized.columns,
2160
+ rows: normalized.rows
2161
+ }
2162
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2163
+ }
2164
+ if (typeof source === "object" && source !== null && "kind" in source && source.kind === "unnest") {
2165
+ const normalized = ctx.normalizeInsertUnnestValues(target, source.values);
2166
+ return ctx.makePlan({
2167
+ selection: current.selection,
2168
+ required: [],
2169
+ available: current.available,
2170
+ dialect: current.dialect
2171
+ }, {
2172
+ ...currentAst,
2173
+ values: [],
2174
+ insertSource: {
2175
+ kind: "unnest",
2176
+ columns: normalized.columns,
2177
+ values: normalized.values
2178
+ }
2179
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2180
+ }
2181
+ const sourcePlan = source;
2182
+ const selection = sourcePlan[TypeId].selection;
2183
+ assertInsertSelectSource(sourcePlan, selection);
2184
+ const columns = ctx.normalizeInsertSelectColumns(selection);
2185
+ return ctx.makePlan({
2186
+ selection: current.selection,
2187
+ required: ctx.currentRequiredList(sourcePlan[TypeId].required),
2188
+ available: current.available,
2189
+ dialect: current.dialect
2190
+ }, {
2191
+ ...currentAst,
2192
+ values: [],
2193
+ insertSource: {
2194
+ kind: "query",
2195
+ columns,
2196
+ query: sourcePlan
2197
+ }
2198
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
2199
+ };
2200
+ const onConflict = (target, options2 = {}) => (plan) => {
2201
+ const current = plan[TypeId];
2202
+ const currentAst = ctx.getAst(plan);
2203
+ const currentQuery = ctx.getQueryState(plan);
2204
+ if (currentQuery.statement !== "insert") {
2205
+ throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
2206
+ }
2207
+ const insertTarget = currentAst.into.source;
2208
+ const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
2209
+ const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
2210
+ if (options2.update !== undefined && updateAssignments.length === 0) {
2211
+ throw new Error("conflict update assignments require at least one assignment");
2212
+ }
2213
+ const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
2214
+ const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
2215
+ const required = [
2216
+ ...ctx.currentRequiredList(current.required),
2217
+ ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2218
+ ...updateWhere ? Object.keys(updateWhere[TypeId2].dependencies) : [],
2219
+ ...targetWhere ? Object.keys(targetWhere[TypeId2].dependencies) : []
2220
+ ].filter((name, index3, list) => !(name in current.available) && list.indexOf(name) === index3);
2221
+ return ctx.makePlan({
2222
+ selection: current.selection,
2223
+ required,
2224
+ available: current.available,
2225
+ dialect: current.dialect
2226
+ }, {
2227
+ ...currentAst,
2228
+ conflict: {
2229
+ kind: "conflict",
2230
+ target: conflictTarget,
2231
+ action: updateAssignments.length === 0 ? "doNothing" : "doUpdate",
2232
+ values: updateAssignments.length === 0 ? undefined : updateAssignments,
2233
+ where: updateWhere
2234
+ }
2235
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
2236
+ };
2237
+ const update = (target, values) => {
2238
+ assertMutationTargets(target, "update", { allowMultiple: true });
2239
+ const targets = ctx.mutationTargetClauses(target);
2240
+ assertUniqueTargetNames(targets);
2241
+ const primaryTarget = targets[0];
2242
+ const assignments = ctx.buildMutationAssignments(target, values);
2243
+ const targetNames = new Set(targets.map((entry) => entry.tableName));
2244
+ const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)).filter((name, index3, list) => !targetNames.has(name) && list.indexOf(name) === index3);
2245
+ return ctx.makePlan({
2246
+ selection: {},
2247
+ required,
2248
+ available: ctx.mutationAvailableSources(target),
2249
+ dialect: primaryTarget.source[TypeId].dialect
2250
+ }, {
2251
+ kind: "update",
2252
+ select: {},
2253
+ target: primaryTarget,
2254
+ targets,
2255
+ set: assignments,
2256
+ where: [],
2257
+ having: [],
2258
+ joins: [],
2259
+ groupBy: [],
2260
+ orderBy: []
2261
+ }, undefined, "write", "update");
2262
+ };
2263
+ const upsert = (target, values, conflictColumns, updateValues) => {
2264
+ assertMutationTargets(target, "upsert");
2265
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2266
+ const assignments = ctx.buildMutationAssignments(target, values);
2267
+ const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
2268
+ if (updateValues !== undefined && updateAssignments.length === 0) {
2269
+ throw new Error("upsert update assignments require at least one assignment");
2270
+ }
2271
+ const required = [
2272
+ ...assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2273
+ ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies))
2274
+ ];
2275
+ return ctx.makePlan({
2276
+ selection: {},
2277
+ required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
2278
+ available: {
2279
+ [sourceName]: {
2280
+ name: sourceName,
2281
+ mode: "required",
2282
+ baseName: sourceBaseName
2283
+ }
2284
+ },
2285
+ dialect: target[TypeId].dialect
2286
+ }, {
2287
+ kind: "insert",
2288
+ select: {},
2289
+ into: {
2290
+ kind: "from",
2291
+ tableName: sourceName,
2292
+ baseTableName: sourceBaseName,
2293
+ source: target
2294
+ },
2295
+ values: assignments,
2296
+ conflict: {
2297
+ kind: "conflict",
2298
+ target: {
2299
+ kind: "columns",
2300
+ columns: ctx.normalizeConflictColumns(target, conflictColumns)
2301
+ },
2302
+ action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
2303
+ values: updateAssignments.length > 0 ? updateAssignments : undefined
2304
+ },
2305
+ where: [],
2306
+ having: [],
2307
+ joins: [],
2308
+ groupBy: [],
2309
+ orderBy: []
2310
+ }, undefined, "write", "insert", target, "ready");
2311
+ };
2312
+ const delete_ = (target) => {
2313
+ assertMutationTargets(target, "delete", { allowMultiple: true });
2314
+ const targets = ctx.mutationTargetClauses(target);
2315
+ assertUniqueTargetNames(targets);
2316
+ const primaryTarget = targets[0];
2317
+ return ctx.makePlan({
2318
+ selection: {},
2319
+ required: [],
2320
+ available: ctx.mutationAvailableSources(target),
2321
+ dialect: primaryTarget.source[TypeId].dialect
2322
+ }, {
2323
+ kind: "delete",
2324
+ select: {},
2325
+ target: primaryTarget,
2326
+ targets,
2327
+ where: [],
2328
+ having: [],
2329
+ joins: [],
2330
+ groupBy: [],
2331
+ orderBy: []
2332
+ }, undefined, "write", "delete");
2333
+ };
2334
+ const truncate = (target, options2 = {}) => {
2335
+ assertMutationTargets(target, "truncate");
2336
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2337
+ return ctx.makePlan({
2338
+ selection: {},
2339
+ required: [],
2340
+ available: {},
2341
+ dialect: target[TypeId].dialect
2342
+ }, {
2343
+ kind: "truncate",
2344
+ select: {},
2345
+ target: {
2346
+ kind: "from",
2347
+ tableName: sourceName,
2348
+ baseTableName: sourceBaseName,
2349
+ source: target
2350
+ },
2351
+ truncate: {
2352
+ kind: "truncate",
2353
+ restartIdentity: options2.restartIdentity ?? false,
2354
+ cascade: options2.cascade ?? false
2355
+ },
2356
+ where: [],
2357
+ having: [],
2358
+ joins: [],
2359
+ groupBy: [],
2360
+ orderBy: []
2361
+ }, undefined, "write", "truncate");
2362
+ };
2363
+ const merge = (target, source, on, options2 = {}) => {
2364
+ assertMutationTargets(target, "merge");
2365
+ assertAliasedSource(source, "merge");
2366
+ const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
2367
+ const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
2368
+ if (targetName === usingName) {
2369
+ throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
2370
+ }
2371
+ const onExpression = ctx.toDialectExpression(on);
2372
+ const matched = options2.whenMatched;
2373
+ const notMatched = options2.whenNotMatched;
2374
+ if (matched && "delete" in matched && "update" in matched) {
2375
+ throw new Error("merge whenMatched cannot specify both update and delete");
2376
+ }
2377
+ const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined;
2378
+ const matchedAssignments = matched && "update" in matched && matched.update ? ctx.buildMutationAssignments(target, matched.update) : [];
2379
+ const notMatchedPredicate = notMatched?.predicate ? ctx.toDialectExpression(notMatched.predicate) : undefined;
2380
+ const notMatchedAssignments = notMatched ? ctx.buildMutationAssignments(target, notMatched.values) : [];
2381
+ const required = [
2382
+ ...Object.keys(onExpression[TypeId2].dependencies),
2383
+ ...matchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2384
+ ...notMatchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2385
+ ...matchedPredicate ? Object.keys(matchedPredicate[TypeId2].dependencies) : [],
2386
+ ...notMatchedPredicate ? Object.keys(notMatchedPredicate[TypeId2].dependencies) : []
2387
+ ].filter((name, index3, values) => name !== targetName && name !== usingName && values.indexOf(name) === index3);
2388
+ return ctx.makePlan({
2389
+ selection: {},
2390
+ required,
2391
+ available: {
2392
+ [targetName]: {
2393
+ name: targetName,
2394
+ mode: "required",
2395
+ baseName: targetBaseName
2396
+ },
2397
+ [usingName]: {
2398
+ name: usingName,
2399
+ mode: "required",
2400
+ baseName: usingBaseName
2401
+ }
2402
+ },
2403
+ dialect: target[TypeId].dialect
2404
+ }, {
2405
+ kind: "merge",
2406
+ select: {},
2407
+ target: {
2408
+ kind: "from",
2409
+ tableName: targetName,
2410
+ baseTableName: targetBaseName,
2411
+ source: target
2412
+ },
2413
+ using: {
2414
+ kind: "from",
2415
+ tableName: usingName,
2416
+ baseTableName: usingBaseName,
2417
+ source
2418
+ },
2419
+ merge: {
2420
+ kind: "merge",
2421
+ on: onExpression,
2422
+ whenMatched: matched ? "delete" in matched && matched.delete ? {
2423
+ kind: "delete",
2424
+ predicate: matchedPredicate
2425
+ } : {
2426
+ kind: "update",
2427
+ values: matchedAssignments,
2428
+ predicate: matchedPredicate
2429
+ } : undefined,
2430
+ whenNotMatched: notMatched ? {
2431
+ kind: "insert",
2432
+ values: notMatchedAssignments,
2433
+ predicate: notMatchedPredicate
2434
+ } : undefined
2435
+ },
2436
+ where: [],
2437
+ having: [],
2438
+ joins: [],
2439
+ groupBy: [],
2440
+ orderBy: []
2441
+ }, undefined, "write", "merge");
2442
+ };
2443
+ return {
2444
+ insert,
2445
+ attachInsertSource,
2446
+ onConflict,
2447
+ update,
2448
+ upsert,
2449
+ delete_,
2450
+ truncate,
2451
+ merge
2452
+ };
2453
+ };
2454
+
2455
+ // src/internal/dsl-transaction-ddl-runtime.ts
2456
+ var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
2457
+ var renderTransactionIsolationLevel = (isolationLevel) => {
2458
+ if (isolationLevel === undefined) {
2459
+ return "";
2460
+ }
2461
+ if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
2462
+ throw new Error("Unsupported transaction isolation level");
2463
+ }
2464
+ return `isolation level ${isolationLevel}`;
2465
+ };
2466
+ var expectDdlClauseKind = (ddl, kind) => {
2467
+ if (ddl === undefined || ddl.kind !== kind) {
2468
+ throw new Error("Unsupported DDL statement kind");
2469
+ }
2470
+ return ddl;
2471
+ };
2472
+ var expectTruncateClause = (truncate) => {
2473
+ if (truncate === undefined || truncate.kind !== "truncate") {
2474
+ throw new Error("Unsupported truncate statement kind");
2475
+ }
2476
+ return truncate;
2477
+ };
2478
+ var validateIsolationLevel = (isolationLevel) => {
2479
+ renderTransactionIsolationLevel(isolationLevel);
2480
+ };
2481
+ var makeDslTransactionDdlRuntime = (ctx) => {
2482
+ const isRecord = (value) => typeof value === "object" && value !== null;
2483
+ const assertTableTarget = (target, apiName) => {
2484
+ if (!isRecord(target) || !(TypeId4 in target) || !(TypeId in target)) {
2485
+ throw new Error(`${apiName}(...) requires a table target`);
2486
+ }
2487
+ };
2488
+ const validateIndexColumns = (target, columns) => {
2489
+ const fields = target[TypeId4]?.fields;
2490
+ if (fields === undefined) {
2491
+ return;
2492
+ }
2493
+ for (const columnName of columns) {
2494
+ if (!(columnName in fields)) {
2495
+ throw new Error(`effect-qb: unknown index column '${columnName}'`);
2496
+ }
2497
+ }
2498
+ };
2499
+ const transaction = (options2 = {}) => {
2500
+ validateIsolationLevel(options2.isolationLevel);
2501
+ return ctx.makePlan({
2502
+ selection: {},
2503
+ required: [],
2504
+ available: {},
2505
+ dialect: ctx.profile.dialect
2506
+ }, {
2507
+ kind: "transaction",
2508
+ select: {},
2509
+ transaction: {
2510
+ kind: "transaction",
2511
+ isolationLevel: options2.isolationLevel,
2512
+ readOnly: options2.readOnly
2513
+ },
2514
+ where: [],
2515
+ having: [],
2516
+ joins: [],
2517
+ groupBy: [],
2518
+ orderBy: []
2519
+ }, undefined, "transaction", "transaction");
2520
+ };
2521
+ const commit = () => ctx.makePlan({
2522
+ selection: {},
2523
+ required: [],
2524
+ available: {},
2525
+ dialect: ctx.profile.dialect
2526
+ }, {
2527
+ kind: "commit",
2528
+ select: {},
2529
+ transaction: {
2530
+ kind: "commit"
2531
+ },
2532
+ where: [],
2533
+ having: [],
2534
+ joins: [],
2535
+ groupBy: [],
2536
+ orderBy: []
2537
+ }, undefined, "transaction", "commit");
2538
+ const rollback = () => ctx.makePlan({
2539
+ selection: {},
2540
+ required: [],
2541
+ available: {},
2542
+ dialect: ctx.profile.dialect
2543
+ }, {
2544
+ kind: "rollback",
2545
+ select: {},
2546
+ transaction: {
2547
+ kind: "rollback"
2548
+ },
2549
+ where: [],
2550
+ having: [],
2551
+ joins: [],
2552
+ groupBy: [],
2553
+ orderBy: []
2554
+ }, undefined, "transaction", "rollback");
2555
+ const savepoint = (name) => ctx.makePlan({
2556
+ selection: {},
2557
+ required: [],
2558
+ available: {},
2559
+ dialect: ctx.profile.dialect
2560
+ }, {
2561
+ kind: "savepoint",
2562
+ select: {},
2563
+ transaction: {
2564
+ kind: "savepoint",
2565
+ name
2566
+ },
2567
+ where: [],
2568
+ having: [],
2569
+ joins: [],
2570
+ groupBy: [],
2571
+ orderBy: []
2572
+ }, undefined, "transaction", "savepoint");
2573
+ const rollbackTo = (name) => ctx.makePlan({
2574
+ selection: {},
2575
+ required: [],
2576
+ available: {},
2577
+ dialect: ctx.profile.dialect
2578
+ }, {
2579
+ kind: "rollbackTo",
2580
+ select: {},
2581
+ transaction: {
2582
+ kind: "rollbackTo",
2583
+ name
2584
+ },
2585
+ where: [],
2586
+ having: [],
2587
+ joins: [],
2588
+ groupBy: [],
2589
+ orderBy: []
2590
+ }, undefined, "transaction", "rollbackTo");
2591
+ const releaseSavepoint = (name) => ctx.makePlan({
2592
+ selection: {},
2593
+ required: [],
2594
+ available: {},
2595
+ dialect: ctx.profile.dialect
2596
+ }, {
2597
+ kind: "releaseSavepoint",
2598
+ select: {},
2599
+ transaction: {
2600
+ kind: "releaseSavepoint",
2601
+ name
2602
+ },
2603
+ where: [],
2604
+ having: [],
2605
+ joins: [],
2606
+ groupBy: [],
2607
+ orderBy: []
2608
+ }, undefined, "transaction", "releaseSavepoint");
2609
+ const createTable = (target, options2 = {}) => {
2610
+ assertTableTarget(target, "createTable");
2611
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2612
+ return ctx.makePlan({
2613
+ selection: {},
2614
+ required: [],
2615
+ available: {},
2616
+ dialect: target[TypeId].dialect
2617
+ }, {
2618
+ kind: "createTable",
2619
+ select: {},
2620
+ target: {
2621
+ kind: "from",
2622
+ tableName: sourceName,
2623
+ baseTableName: sourceBaseName,
2624
+ source: target
2625
+ },
2626
+ ddl: {
2627
+ kind: "createTable",
2628
+ ifNotExists: options2.ifNotExists ?? false
2629
+ },
2630
+ where: [],
2631
+ having: [],
2632
+ joins: [],
2633
+ groupBy: [],
2634
+ orderBy: []
2635
+ }, undefined, "ddl", "createTable");
2636
+ };
2637
+ const dropTable = (target, options2 = {}) => {
2638
+ assertTableTarget(target, "dropTable");
2639
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2640
+ return ctx.makePlan({
2641
+ selection: {},
2642
+ required: [],
2643
+ available: {},
2644
+ dialect: target[TypeId].dialect
2645
+ }, {
2646
+ kind: "dropTable",
2647
+ select: {},
2648
+ target: {
2649
+ kind: "from",
2650
+ tableName: sourceName,
2651
+ baseTableName: sourceBaseName,
2652
+ source: target
2653
+ },
2654
+ ddl: {
2655
+ kind: "dropTable",
2656
+ ifExists: options2.ifExists ?? false
2657
+ },
2658
+ where: [],
2659
+ having: [],
2660
+ joins: [],
2661
+ groupBy: [],
2662
+ orderBy: []
2663
+ }, undefined, "ddl", "dropTable");
2664
+ };
2665
+ const createIndex = (target, columns, options2 = {}) => {
2666
+ assertTableTarget(target, "createIndex");
2667
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2668
+ validateIndexColumns(target, normalizedColumns);
2669
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2670
+ return ctx.makePlan({
2671
+ selection: {},
2672
+ required: [],
2673
+ available: {},
2674
+ dialect: target[TypeId].dialect
2675
+ }, {
2676
+ kind: "createIndex",
2677
+ select: {},
2678
+ target: {
2679
+ kind: "from",
2680
+ tableName: sourceName,
2681
+ baseTableName: sourceBaseName,
2682
+ source: target
2683
+ },
2684
+ ddl: {
2685
+ kind: "createIndex",
2686
+ name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options2.unique ?? false),
2687
+ columns: normalizedColumns,
2688
+ unique: options2.unique ?? false,
2689
+ ifNotExists: options2.ifNotExists ?? false
2690
+ },
2691
+ where: [],
2692
+ having: [],
2693
+ joins: [],
2694
+ groupBy: [],
2695
+ orderBy: []
2696
+ }, undefined, "ddl", "createIndex");
2697
+ };
2698
+ const dropIndex = (target, columns, options2 = {}) => {
2699
+ assertTableTarget(target, "dropIndex");
2700
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2701
+ validateIndexColumns(target, normalizedColumns);
2702
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2703
+ return ctx.makePlan({
2704
+ selection: {},
2705
+ required: [],
2706
+ available: {},
2707
+ dialect: target[TypeId].dialect
2708
+ }, {
2709
+ kind: "dropIndex",
2710
+ select: {},
2711
+ target: {
2712
+ kind: "from",
2713
+ tableName: sourceName,
2714
+ baseTableName: sourceBaseName,
2715
+ source: target
2716
+ },
2717
+ ddl: {
2718
+ kind: "dropIndex",
2719
+ name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
2720
+ ifExists: options2.ifExists ?? false
2721
+ },
2722
+ where: [],
2723
+ having: [],
2724
+ joins: [],
2725
+ groupBy: [],
2726
+ orderBy: []
2727
+ }, undefined, "ddl", "dropIndex");
2728
+ };
2729
+ return {
2730
+ transaction,
2731
+ commit,
2732
+ rollback,
2733
+ savepoint,
2734
+ rollbackTo,
2735
+ releaseSavepoint,
2736
+ createTable,
2737
+ dropTable,
2738
+ createIndex,
2739
+ dropIndex
2740
+ };
2741
+ };
2742
+
1466
2743
  // src/internal/runtime/driver-value-mapping.ts
2744
+ import * as Schema4 from "effect/Schema";
2745
+
2746
+ // src/internal/runtime/value.ts
1467
2747
  import * as Schema3 from "effect/Schema";
2748
+ var brandString = (pattern, brand4) => Schema3.String.pipe(Schema3.check(Schema3.isPattern(pattern)), Schema3.brand(brand4));
2749
+ var localDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
2750
+ var isValidLocalDateString = (value) => {
2751
+ const match = localDatePattern.exec(value);
2752
+ if (match === null) {
2753
+ return false;
2754
+ }
2755
+ const year = Number(match[1]);
2756
+ const month = Number(match[2]);
2757
+ const day = Number(match[3]);
2758
+ const parsed = new Date(Date.UTC(year, month - 1, day));
2759
+ parsed.setUTCFullYear(year);
2760
+ return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
2761
+ };
2762
+ var localTimePattern = /^(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
2763
+ var isValidLocalTimeString = (value) => {
2764
+ const match = localTimePattern.exec(value);
2765
+ if (match === null) {
2766
+ return false;
2767
+ }
2768
+ const hour = Number(match[1]);
2769
+ const minute = Number(match[2]);
2770
+ const second = Number(match[3]);
2771
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
2772
+ };
2773
+ var offsetPattern = /^(?:Z|[+-](\d{2}):(\d{2}))$/;
2774
+ var isValidOffset = (value) => {
2775
+ const match = offsetPattern.exec(value);
2776
+ if (match === null) {
2777
+ return false;
2778
+ }
2779
+ if (value === "Z") {
2780
+ return true;
2781
+ }
2782
+ const hour = Number(match[1]);
2783
+ const minute = Number(match[2]);
2784
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59;
2785
+ };
2786
+ var offsetTimePattern = /^(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
2787
+ var isValidOffsetTimeString = (value) => {
2788
+ const match = offsetTimePattern.exec(value);
2789
+ return match !== null && isValidLocalTimeString(match[1]) && isValidOffset(match[2]);
2790
+ };
2791
+ var localDateTimePattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
2792
+ var isValidLocalDateTimeString = (value) => {
2793
+ const match = localDateTimePattern.exec(value);
2794
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]);
2795
+ };
2796
+ var instantPattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
2797
+ var isValidInstantString = (value) => {
2798
+ const match = instantPattern.exec(value);
2799
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]) && isValidOffset(match[3]);
2800
+ };
2801
+ var LocalDateStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localDatePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalDateString(value))), Schema3.brand("LocalDateString"));
2802
+ var LocalTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalTimeString(value))), Schema3.brand("LocalTimeString"));
2803
+ var OffsetTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(offsetTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidOffsetTimeString(value))), Schema3.brand("OffsetTimeString"));
2804
+ var LocalDateTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localDateTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalDateTimeString(value))), Schema3.brand("LocalDateTimeString"));
2805
+ var InstantStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(instantPattern)), Schema3.check(Schema3.makeFilter((value) => isValidInstantString(value))), Schema3.brand("InstantString"));
2806
+ var YearStringSchema = brandString(/^\d{4}$/, "YearString");
2807
+ var canonicalizeBigIntString = (input) => {
2808
+ const trimmed = input.trim();
2809
+ if (!/^-?\d+$/.test(trimmed)) {
2810
+ throw new Error("Expected an integer-like bigint value");
2811
+ }
2812
+ return BigInt(trimmed).toString();
2813
+ };
2814
+ var isCanonicalBigIntString = (value) => {
2815
+ try {
2816
+ return canonicalizeBigIntString(value) === value;
2817
+ } catch {
2818
+ return false;
2819
+ }
2820
+ };
2821
+ var canonicalizeDecimalString = (input) => {
2822
+ const trimmed = input.trim();
2823
+ const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
2824
+ if (match === null) {
2825
+ throw new Error("Expected a decimal string");
2826
+ }
2827
+ const sign = match[1] === "-" ? "-" : "";
2828
+ const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
2829
+ const fraction = (match[3] ?? "").replace(/0+$/, "");
2830
+ if (fraction.length === 0) {
2831
+ if (integer === "0") {
2832
+ return "0";
2833
+ }
2834
+ return `${sign}${integer}`;
2835
+ }
2836
+ return `${sign}${integer}.${fraction}`;
2837
+ };
2838
+ var isCanonicalDecimalString = (value) => {
2839
+ try {
2840
+ return canonicalizeDecimalString(value) === value;
2841
+ } catch {
2842
+ return false;
2843
+ }
2844
+ };
2845
+ var BigIntStringSchema = Schema3.String.pipe(Schema3.check(Schema3.makeFilter((value) => isCanonicalBigIntString(value))), Schema3.brand("BigIntString"));
2846
+ var DecimalStringSchema = Schema3.String.pipe(Schema3.check(Schema3.makeFilter((value) => isCanonicalDecimalString(value))), Schema3.brand("DecimalString"));
2847
+ var JsonValueSchema = Schema3.suspend(() => Schema3.Union([
2848
+ Schema3.String,
2849
+ Schema3.Number.check(Schema3.isFinite()),
2850
+ Schema3.Boolean,
2851
+ Schema3.Null,
2852
+ Schema3.Array(JsonValueSchema),
2853
+ Schema3.Record(Schema3.String, JsonValueSchema)
2854
+ ]));
2855
+ var JsonPrimitiveSchema = Schema3.Union([
2856
+ Schema3.String,
2857
+ Schema3.Number.check(Schema3.isFinite()),
2858
+ Schema3.Boolean,
2859
+ Schema3.Null
2860
+ ]);
1468
2861
 
1469
2862
  // src/internal/runtime/normalize.ts
1470
2863
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2864
+ var isPlainRecord = (value) => {
2865
+ if (!isRecord(value)) {
2866
+ return false;
2867
+ }
2868
+ const prototype = Object.getPrototypeOf(value);
2869
+ return prototype === Object.prototype || prototype === null;
2870
+ };
1471
2871
  var pad = (value, width = 2) => value.toString().padStart(width, "0");
1472
- var formatLocalDate = (value) => `${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
2872
+ var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
1473
2873
  var formatLocalTime = (value) => {
1474
2874
  const milliseconds = value.getUTCMilliseconds();
1475
2875
  const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
@@ -1489,12 +2889,14 @@ var expectString = (value, label) => {
1489
2889
  }
1490
2890
  throw new Error(`Expected ${label} as string`);
1491
2891
  };
2892
+ var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
1492
2893
  var normalizeNumber = (value) => {
1493
2894
  if (typeof value === "number" && Number.isFinite(value)) {
1494
2895
  return value;
1495
2896
  }
1496
- if (typeof value === "string" && value.trim() !== "") {
1497
- const parsed = Number(value);
2897
+ if (typeof value === "string") {
2898
+ const trimmed = value.trim();
2899
+ const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
1498
2900
  if (Number.isFinite(parsed)) {
1499
2901
  return parsed;
1500
2902
  }
@@ -1534,25 +2936,11 @@ var normalizeBigIntString = (value) => {
1534
2936
  if (typeof value === "number" && Number.isSafeInteger(value)) {
1535
2937
  return BigInt(value).toString();
1536
2938
  }
1537
- if (typeof value === "string" && /^-?\d+$/.test(value.trim())) {
1538
- return BigInt(value.trim()).toString();
2939
+ if (typeof value === "string") {
2940
+ return canonicalizeBigIntString(value);
1539
2941
  }
1540
2942
  throw new Error("Expected an integer-like bigint value");
1541
2943
  };
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
2944
  var normalizeDecimalString = (value) => {
1557
2945
  if (typeof value === "string") {
1558
2946
  return canonicalizeDecimalString(value);
@@ -1571,12 +2959,15 @@ var normalizeLocalDate = (value) => {
1571
2959
  return formatLocalDate(value);
1572
2960
  }
1573
2961
  const raw = expectString(value, "local date").trim();
1574
- if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
2962
+ if (isValidLocalDateString(raw)) {
1575
2963
  return raw;
1576
2964
  }
1577
- const parsed = new Date(raw);
1578
- if (!Number.isNaN(parsed.getTime())) {
1579
- return formatLocalDate(parsed);
2965
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
2966
+ if (isValidInstantString(canonicalInstant)) {
2967
+ const parsed = new Date(canonicalInstant);
2968
+ if (!Number.isNaN(parsed.getTime())) {
2969
+ return formatLocalDate(parsed);
2970
+ }
1580
2971
  }
1581
2972
  throw new Error("Expected a local-date value");
1582
2973
  };
@@ -1585,7 +2976,7 @@ var normalizeLocalTime = (value) => {
1585
2976
  return formatLocalTime(value);
1586
2977
  }
1587
2978
  const raw = expectString(value, "local time").trim();
1588
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
2979
+ if (isValidLocalTimeString(raw)) {
1589
2980
  return raw;
1590
2981
  }
1591
2982
  throw new Error("Expected a local-time value");
@@ -1595,7 +2986,7 @@ var normalizeOffsetTime = (value) => {
1595
2986
  return `${formatLocalTime(value)}Z`;
1596
2987
  }
1597
2988
  const raw = expectString(value, "offset time").trim();
1598
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
2989
+ if (isValidOffsetTimeString(raw)) {
1599
2990
  return raw;
1600
2991
  }
1601
2992
  throw new Error("Expected an offset-time value");
@@ -1605,11 +2996,13 @@ var normalizeLocalDateTime = (value) => {
1605
2996
  return formatLocalDateTime(value);
1606
2997
  }
1607
2998
  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");
2999
+ const canonicalLocalDateTime = raw.replace(" ", "T");
3000
+ if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
3001
+ return canonicalLocalDateTime;
1610
3002
  }
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);
3003
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
3004
+ if (isValidInstantString(canonicalInstant)) {
3005
+ const parsed = new Date(canonicalInstant);
1613
3006
  if (!Number.isNaN(parsed.getTime())) {
1614
3007
  return formatLocalDateTime(parsed);
1615
3008
  }
@@ -1624,7 +3017,11 @@ var normalizeInstant = (value) => {
1624
3017
  if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
1625
3018
  throw new Error("Instant values require a timezone offset");
1626
3019
  }
1627
- const parsed = new Date(raw);
3020
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
3021
+ if (!isValidInstantString(canonicalInstant)) {
3022
+ throw new Error("Expected an ISO instant value");
3023
+ }
3024
+ const parsed = new Date(canonicalInstant);
1628
3025
  if (Number.isNaN(parsed.getTime())) {
1629
3026
  throw new Error("Expected an ISO instant value");
1630
3027
  }
@@ -1656,25 +3053,33 @@ var isJsonValue = (value) => {
1656
3053
  }
1657
3054
  switch (typeof value) {
1658
3055
  case "string":
1659
- case "number":
1660
3056
  case "boolean":
1661
3057
  return true;
3058
+ case "number":
3059
+ return Number.isFinite(value);
1662
3060
  case "object":
1663
3061
  if (Array.isArray(value)) {
1664
3062
  return value.every(isJsonValue);
1665
3063
  }
1666
- return isRecord(value) && Object.values(value).every(isJsonValue);
3064
+ return isPlainRecord(value) && Object.values(value).every(isJsonValue);
1667
3065
  default:
1668
3066
  return false;
1669
3067
  }
1670
3068
  };
1671
3069
  var normalizeJson = (value) => {
1672
3070
  if (typeof value === "string") {
1673
- const parsed = JSON.parse(value);
1674
- if (isJsonValue(parsed)) {
1675
- return parsed;
3071
+ try {
3072
+ const parsed = JSON.parse(value);
3073
+ if (isJsonValue(parsed)) {
3074
+ return parsed;
3075
+ }
3076
+ throw new Error("Parsed JSON value is not a valid JSON runtime");
3077
+ } catch (error) {
3078
+ if (error instanceof SyntaxError) {
3079
+ return value;
3080
+ }
3081
+ throw error;
1676
3082
  }
1677
- throw new Error("Parsed JSON value is not a valid JSON runtime");
1678
3083
  }
1679
3084
  if (isJsonValue(value)) {
1680
3085
  return value;
@@ -1809,22 +3214,61 @@ var findMapping = (context, key2) => {
1809
3214
  }
1810
3215
  return;
1811
3216
  };
3217
+ var isJsonDbType = (dbType) => {
3218
+ if (dbType === undefined) {
3219
+ return false;
3220
+ }
3221
+ if ("base" in dbType) {
3222
+ return isJsonDbType(dbType.base);
3223
+ }
3224
+ if (!("variant" in dbType)) {
3225
+ return false;
3226
+ }
3227
+ const variant = dbType.variant;
3228
+ return variant === "json" || variant === "jsonb";
3229
+ };
3230
+ var schemaAccepts = (schema2, value) => schema2 !== undefined && Schema4.is(schema2)(value);
1812
3231
  var encodeWithSchema = (schema2, value) => {
1813
3232
  if (schema2 === undefined) {
1814
3233
  return { value, encoded: false };
1815
3234
  }
1816
- if (!Schema3.is(schema2)(value)) {
3235
+ if (!Schema4.is(schema2)(value)) {
1817
3236
  return { value, encoded: false };
1818
3237
  }
1819
3238
  return {
1820
- value: Schema3.encodeUnknownSync(schema2)(value),
3239
+ value: Schema4.encodeUnknownSync(schema2)(value),
1821
3240
  encoded: true
1822
3241
  };
1823
3242
  };
3243
+ var normalizeJsonDriverString = (value, context) => {
3244
+ if (!isJsonDbType(context.dbType) || context.runtimeSchema === undefined) {
3245
+ return;
3246
+ }
3247
+ try {
3248
+ const parsed = JSON.parse(value);
3249
+ if (value.trimStart().startsWith('"') && schemaAccepts(context.runtimeSchema, parsed)) {
3250
+ return parsed;
3251
+ }
3252
+ if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
3253
+ return value;
3254
+ }
3255
+ } catch (error) {
3256
+ if (error instanceof SyntaxError && schemaAccepts(context.runtimeSchema, value)) {
3257
+ return value;
3258
+ }
3259
+ if (!(error instanceof SyntaxError)) {
3260
+ throw error;
3261
+ }
3262
+ }
3263
+ return;
3264
+ };
1824
3265
  var toDriverValue = (value, context) => {
1825
3266
  if (value === null) {
1826
3267
  return null;
1827
3268
  }
3269
+ if (value instanceof Date && Number.isNaN(value.getTime())) {
3270
+ throw new Error("Expected a valid Date value");
3271
+ }
1828
3272
  const dbType = context.dbType;
1829
3273
  const encoded = encodeWithSchema(context.runtimeSchema, value);
1830
3274
  let current = encoded.value;
@@ -1832,6 +3276,9 @@ var toDriverValue = (value, context) => {
1832
3276
  if (custom !== undefined && dbType !== undefined) {
1833
3277
  return custom(current, dbType);
1834
3278
  }
3279
+ if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
3280
+ return current;
3281
+ }
1835
3282
  return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
1836
3283
  };
1837
3284
  var fromDriverValue = (value, context) => {
@@ -1843,6 +3290,12 @@ var fromDriverValue = (value, context) => {
1843
3290
  if (custom !== undefined && dbType !== undefined) {
1844
3291
  return custom(value, dbType);
1845
3292
  }
3293
+ if (typeof value === "string") {
3294
+ const normalizedJsonString = normalizeJsonDriverString(value, context);
3295
+ if (normalizedJsonString !== undefined) {
3296
+ return normalizedJsonString;
3297
+ }
3298
+ }
1846
3299
  return dbType === undefined ? value : normalizeDbValue(dbType, value);
1847
3300
  };
1848
3301
  var textCast = (sql) => `(${sql})::text`;
@@ -1930,6 +3383,20 @@ var validateProjections = (projections) => {
1930
3383
  };
1931
3384
 
1932
3385
  // src/internal/grouping-key.ts
3386
+ var subqueryPlanIds = new WeakMap;
3387
+ var nextSubqueryPlanId = 0;
3388
+ var subqueryPlanGroupingKey = (plan) => {
3389
+ if (plan === null || typeof plan !== "object") {
3390
+ return "unknown";
3391
+ }
3392
+ const existing = subqueryPlanIds.get(plan);
3393
+ if (existing !== undefined) {
3394
+ return existing;
3395
+ }
3396
+ const next = `${nextSubqueryPlanId++}`;
3397
+ subqueryPlanIds.set(plan, next);
3398
+ return next;
3399
+ };
1933
3400
  var literalGroupingKey = (value) => {
1934
3401
  if (value instanceof Date) {
1935
3402
  return `date:${value.toISOString()}`;
@@ -1948,15 +3415,62 @@ var literalGroupingKey = (value) => {
1948
3415
  return `literal:${JSON.stringify(value)}`;
1949
3416
  }
1950
3417
  };
3418
+ var isExpression2 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3419
+ var expressionGroupingKey = (value) => isExpression2(value) ? groupingKeyOfExpression(value) : "missing";
3420
+ var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
3421
+ var jsonSegmentGroupingKey = (segment) => {
3422
+ if (segment !== null && typeof segment === "object" && "kind" in segment) {
3423
+ switch (segment.kind) {
3424
+ case "key":
3425
+ return `key:${escapeGroupingText(segment.key)}`;
3426
+ case "index":
3427
+ return `index:${segment.index}`;
3428
+ case "wildcard":
3429
+ return "wildcard";
3430
+ case "slice": {
3431
+ const slice2 = segment;
3432
+ return `slice:${slice2.start ?? ""}:${slice2.end ?? ""}`;
3433
+ }
3434
+ case "descend":
3435
+ return "descend";
3436
+ }
3437
+ }
3438
+ if (typeof segment === "string") {
3439
+ return `key:${escapeGroupingText(segment)}`;
3440
+ }
3441
+ if (typeof segment === "number") {
3442
+ return `index:${segment}`;
3443
+ }
3444
+ return "unknown";
3445
+ };
3446
+ var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
3447
+ var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
3448
+ var jsonOpaquePathGroupingKey = (value) => {
3449
+ if (isJsonPath(value)) {
3450
+ return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
3451
+ }
3452
+ if (typeof value === "string") {
3453
+ return `jsonpath:${escapeGroupingText(value)}`;
3454
+ }
3455
+ if (isExpression2(value)) {
3456
+ return `jsonpath:${groupingKeyOfExpression(value)}`;
3457
+ }
3458
+ return "jsonpath:unknown";
3459
+ };
3460
+ var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
1951
3461
  var groupingKeyOfExpression = (expression) => {
1952
3462
  const ast = expression[TypeId3];
1953
3463
  switch (ast.kind) {
1954
3464
  case "column":
1955
- return `column:${ast.tableName}.${ast.columnName}`;
3465
+ return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
1956
3466
  case "literal":
1957
3467
  return `literal:${literalGroupingKey(ast.value)}`;
1958
3468
  case "cast":
1959
3469
  return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
3470
+ case "collate":
3471
+ return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
3472
+ case "function":
3473
+ return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
1960
3474
  case "isNull":
1961
3475
  case "isNotNull":
1962
3476
  case "not":
@@ -1974,8 +3488,15 @@ var groupingKeyOfExpression = (expression) => {
1974
3488
  case "gte":
1975
3489
  case "like":
1976
3490
  case "ilike":
3491
+ case "regexMatch":
3492
+ case "regexIMatch":
3493
+ case "regexNotMatch":
3494
+ case "regexNotIMatch":
1977
3495
  case "isDistinctFrom":
1978
3496
  case "isNotDistinctFrom":
3497
+ case "contains":
3498
+ case "containedBy":
3499
+ case "overlaps":
1979
3500
  return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
1980
3501
  case "and":
1981
3502
  case "or":
@@ -1987,6 +3508,54 @@ var groupingKeyOfExpression = (expression) => {
1987
3508
  return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
1988
3509
  case "case":
1989
3510
  return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
3511
+ case "exists":
3512
+ return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
3513
+ case "scalarSubquery":
3514
+ return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
3515
+ case "inSubquery":
3516
+ return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3517
+ case "comparisonAny":
3518
+ case "comparisonAll":
3519
+ return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3520
+ case "jsonGet":
3521
+ case "jsonPath":
3522
+ case "jsonAccess":
3523
+ case "jsonTraverse":
3524
+ case "jsonGetText":
3525
+ case "jsonPathText":
3526
+ case "jsonAccessText":
3527
+ case "jsonTraverseText":
3528
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonPathGroupingKey(ast.segments)})`;
3529
+ case "jsonHasKey":
3530
+ case "jsonKeyExists":
3531
+ case "jsonHasAnyKeys":
3532
+ case "jsonHasAllKeys":
3533
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
3534
+ case "jsonConcat":
3535
+ case "jsonMerge":
3536
+ return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
3537
+ case "jsonDelete":
3538
+ case "jsonDeletePath":
3539
+ case "jsonRemove":
3540
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(undefined)},${jsonPathGroupingKey(ast.segments)})`;
3541
+ case "jsonSet":
3542
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.newValue)},${jsonPathGroupingKey(ast.segments)})`;
3543
+ case "jsonInsert":
3544
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.insert)},${jsonPathGroupingKey(ast.segments)})`;
3545
+ case "jsonPathExists":
3546
+ case "jsonPathMatch":
3547
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
3548
+ case "jsonBuildObject":
3549
+ return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
3550
+ case "jsonBuildArray":
3551
+ return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
3552
+ case "jsonToJson":
3553
+ case "jsonToJsonb":
3554
+ case "jsonTypeOf":
3555
+ case "jsonLength":
3556
+ case "jsonKeys":
3557
+ case "jsonStripNulls":
3558
+ return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
1990
3559
  default:
1991
3560
  throw new Error("Unsupported expression for grouping key generation");
1992
3561
  }
@@ -2004,15 +3573,15 @@ var dedupeGroupedExpressions = (values) => {
2004
3573
  };
2005
3574
 
2006
3575
  // src/internal/aggregation-validation.ts
2007
- var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
3576
+ var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
2008
3577
  var selectionHasAggregate = (selection) => {
2009
- if (isExpression2(selection)) {
3578
+ if (isExpression3(selection)) {
2010
3579
  return selection[TypeId2].kind === "aggregate";
2011
3580
  }
2012
3581
  return Object.values(selection).some((value) => selectionHasAggregate(value));
2013
3582
  };
2014
3583
  var isGroupedSelectionValid = (selection, groupedExpressions) => {
2015
- if (isExpression2(selection)) {
3584
+ if (isExpression3(selection)) {
2016
3585
  const aggregation = selection[TypeId2].kind;
2017
3586
  if (aggregation === "aggregate") {
2018
3587
  return true;
@@ -2065,7 +3634,46 @@ var renderCastType = (dialect, dbType) => {
2065
3634
  return dbType.kind;
2066
3635
  }
2067
3636
  };
2068
- var renderDdlExpression = (expression, state, dialect) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, state, dialect);
3637
+ var renderPostgresDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
3638
+ var renderPostgresDdlBytes = (value) => `decode('${Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("")}', 'hex')`;
3639
+ var renderPostgresDdlLiteral = (value, state, context = {}) => {
3640
+ const driverValue = toDriverValue(value, {
3641
+ dialect: "postgres",
3642
+ valueMappings: state.valueMappings,
3643
+ ...context
3644
+ });
3645
+ if (driverValue === null) {
3646
+ return "null";
3647
+ }
3648
+ switch (typeof driverValue) {
3649
+ case "boolean":
3650
+ return driverValue ? "true" : "false";
3651
+ case "number":
3652
+ if (!Number.isFinite(driverValue)) {
3653
+ throw new Error("Expected a finite numeric value");
3654
+ }
3655
+ return String(driverValue);
3656
+ case "bigint":
3657
+ return driverValue.toString();
3658
+ case "string":
3659
+ return renderPostgresDdlString(driverValue);
3660
+ case "object":
3661
+ if (driverValue instanceof Uint8Array) {
3662
+ return renderPostgresDdlBytes(driverValue);
3663
+ }
3664
+ break;
3665
+ }
3666
+ throw new Error("Unsupported postgres DDL literal value");
3667
+ };
3668
+ var renderDdlExpression = (expression, state, dialect) => {
3669
+ if (isSchemaExpression(expression)) {
3670
+ return render(expression);
3671
+ }
3672
+ return renderExpression(expression, state, {
3673
+ ...dialect,
3674
+ renderLiteral: renderPostgresDdlLiteral
3675
+ });
3676
+ };
2069
3677
  var renderColumnDefinition = (dialect, state, columnName, column) => {
2070
3678
  const clauses = [
2071
3679
  dialect.quoteIdentifier(columnName),
@@ -2097,14 +3705,16 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
2097
3705
  break;
2098
3706
  case "foreignKey": {
2099
3707
  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" : ""}` : ""}`);
3708
+ 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
3709
  break;
2102
3710
  }
2103
3711
  case "check":
2104
- definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, state, dialect)})${option2.noInherit ? " no inherit" : ""}`);
3712
+ definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
2105
3713
  break;
2106
3714
  case "index":
2107
3715
  break;
3716
+ default:
3717
+ throw new Error("Unsupported table option kind");
2108
3718
  }
2109
3719
  }
2110
3720
  return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
@@ -2113,10 +3723,56 @@ var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
2113
3723
  const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
2114
3724
  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
3725
  };
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);
3726
+ var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
3727
+ if (dialect.name === "postgres") {
3728
+ const schemaName = typeof targetSource.source === "object" && targetSource.source !== null && TypeId4 in targetSource.source ? targetSource.source[TypeId4].schemaName : undefined;
3729
+ const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(ddl.name) : `${dialect.quoteIdentifier(schemaName)}.${dialect.quoteIdentifier(ddl.name)}`;
3730
+ return `drop index${ddl.ifExists ? " if exists" : ""} ${indexName}`;
3731
+ }
3732
+ return `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
3733
+ };
3734
+ var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3735
+ var isJsonDbType2 = (dbType) => {
3736
+ if (dbType.kind === "jsonb" || dbType.kind === "json") {
3737
+ return true;
3738
+ }
3739
+ if (!("variant" in dbType)) {
3740
+ return false;
3741
+ }
3742
+ const variant = dbType.variant;
3743
+ return variant === "json" || variant === "jsonb";
3744
+ };
3745
+ var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId2].dbType);
3746
+ var postgresRangeSubtypeByKind = {
3747
+ int4range: "int4",
3748
+ int8range: "int8",
3749
+ numrange: "numeric",
3750
+ tsrange: "timestamp",
3751
+ tstzrange: "timestamptz",
3752
+ daterange: "date",
3753
+ int4multirange: "int4",
3754
+ int8multirange: "int8",
3755
+ nummultirange: "numeric",
3756
+ tsmultirange: "timestamp",
3757
+ tstzmultirange: "timestamptz",
3758
+ datemultirange: "date"
3759
+ };
3760
+ var postgresRangeSubtypeKey = (dbType) => {
3761
+ if ("base" in dbType) {
3762
+ return postgresRangeSubtypeKey(dbType.base);
3763
+ }
3764
+ if ("subtype" in dbType) {
3765
+ return postgresRangeSubtypeKey(dbType.subtype) ?? dbType.subtype.kind;
3766
+ }
3767
+ return postgresRangeSubtypeByKind[dbType.kind];
3768
+ };
3769
+ var assertCompatiblePostgresRangeOperands = (left, right) => {
3770
+ const leftKey = postgresRangeSubtypeKey(left[TypeId2].dbType);
3771
+ const rightKey = postgresRangeSubtypeKey(right[TypeId2].dbType);
3772
+ if (leftKey !== undefined && rightKey !== undefined && leftKey !== rightKey) {
3773
+ throw new Error("Incompatible postgres range operands");
3774
+ }
3775
+ };
2120
3776
  var unsupportedJsonFeature = (dialect, feature) => {
2121
3777
  const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
2122
3778
  Object.assign(error, {
@@ -2159,15 +3815,16 @@ var extractJsonPathSegments = (node) => {
2159
3815
  };
2160
3816
  var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
2161
3817
  var renderJsonPathSegment = (segment) => {
3818
+ const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
2162
3819
  if (typeof segment === "string") {
2163
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) ? `.${segment}` : `."${segment.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3820
+ return renderKey(segment);
2164
3821
  }
2165
3822
  if (typeof segment === "number") {
2166
3823
  return `[${segment}]`;
2167
3824
  }
2168
3825
  switch (segment.kind) {
2169
3826
  case "key":
2170
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment.key) ? `.${segment.key}` : `."${segment.key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
3827
+ return renderKey(segment.key);
2171
3828
  case "index":
2172
3829
  return `[${segment.index}]`;
2173
3830
  case "wildcard":
@@ -2210,13 +3867,13 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
2210
3867
  case "key":
2211
3868
  return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.key, state)}`;
2212
3869
  case "index":
2213
- return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(String(segment.index), state)}`;
3870
+ return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.index, state)}`;
2214
3871
  default:
2215
3872
  throw new Error("Postgres exact JSON access requires key/index segments");
2216
3873
  }
2217
3874
  };
2218
3875
  var renderPostgresJsonValue = (value, state, dialect) => {
2219
- if (!isExpression3(value)) {
3876
+ if (!isExpression4(value)) {
2220
3877
  throw new Error("Expected a JSON expression");
2221
3878
  }
2222
3879
  const rendered = renderExpression(value, state, dialect);
@@ -2234,13 +3891,21 @@ var expressionDriverContext = (expression, state, dialect) => ({
2234
3891
  driverValueMapping: expression[TypeId2].driverValueMapping
2235
3892
  });
2236
3893
  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
- }));
3894
+ var encodeArrayValues = (values, column, state, dialect) => values.map((value) => {
3895
+ if (value === null && column.metadata.nullable) {
3896
+ return null;
3897
+ }
3898
+ const runtimeSchemaAccepts = column.schema !== undefined && Schema5.is(column.schema)(value);
3899
+ const normalizedValue = runtimeSchemaAccepts ? value : normalizeDbValue(column.metadata.dbType, value);
3900
+ const encodedValue = column.schema === undefined || runtimeSchemaAccepts ? normalizedValue : Schema5.decodeUnknownSync(column.schema)(normalizedValue);
3901
+ return toDriverValue(encodedValue, {
3902
+ dialect: dialect.name,
3903
+ valueMappings: state.valueMappings,
3904
+ dbType: column.metadata.dbType,
3905
+ runtimeSchema: column.schema,
3906
+ driverValueMapping: column.metadata.driverValueMapping
3907
+ });
3908
+ });
2244
3909
  var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
2245
3910
  var renderJsonOpaquePath = (value, state, dialect) => {
2246
3911
  if (isJsonPathValue(value)) {
@@ -2249,7 +3914,7 @@ var renderJsonOpaquePath = (value, state, dialect) => {
2249
3914
  if (typeof value === "string") {
2250
3915
  return dialect.renderLiteral(value, state);
2251
3916
  }
2252
- if (isExpression3(value)) {
3917
+ if (isExpression4(value)) {
2253
3918
  return renderExpression(value, state, dialect);
2254
3919
  }
2255
3920
  throw new Error("Unsupported SQL/JSON path input");
@@ -2267,7 +3932,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
2267
3932
  if (source === undefined) {
2268
3933
  throw new Error("Unsupported SQL extract expression");
2269
3934
  }
2270
- const fieldRuntime = isExpression3(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
3935
+ const fieldRuntime = isExpression4(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
2271
3936
  const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
2272
3937
  return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
2273
3938
  }
@@ -2305,7 +3970,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2305
3970
  case "jsonPathText":
2306
3971
  case "jsonAccessText":
2307
3972
  case "jsonTraverseText": {
2308
- if (!isExpression3(base) || segments.length === 0) {
3973
+ if (!isExpression4(base) || segments.length === 0) {
2309
3974
  return;
2310
3975
  }
2311
3976
  const baseSql = renderExpression(base, state, dialect);
@@ -2328,7 +3993,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2328
3993
  case "jsonKeyExists":
2329
3994
  case "jsonHasAnyKeys":
2330
3995
  case "jsonHasAllKeys": {
2331
- if (!isExpression3(base)) {
3996
+ if (!isExpression4(base)) {
2332
3997
  return;
2333
3998
  }
2334
3999
  const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
@@ -2354,7 +4019,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2354
4019
  }
2355
4020
  case "jsonConcat":
2356
4021
  case "jsonMerge": {
2357
- if (!isExpression3(ast.left) || !isExpression3(ast.right)) {
4022
+ if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
2358
4023
  return;
2359
4024
  }
2360
4025
  if (dialect.name === "postgres") {
@@ -2391,7 +4056,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2391
4056
  return;
2392
4057
  }
2393
4058
  case "jsonToJson":
2394
- if (!isExpression3(base)) {
4059
+ if (!isExpression4(base)) {
2395
4060
  return;
2396
4061
  }
2397
4062
  if (dialect.name === "postgres") {
@@ -2402,7 +4067,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2402
4067
  }
2403
4068
  return;
2404
4069
  case "jsonToJsonb":
2405
- if (!isExpression3(base)) {
4070
+ if (!isExpression4(base)) {
2406
4071
  return;
2407
4072
  }
2408
4073
  if (dialect.name === "postgres") {
@@ -2413,7 +4078,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2413
4078
  }
2414
4079
  return;
2415
4080
  case "jsonTypeOf":
2416
- if (!isExpression3(base)) {
4081
+ if (!isExpression4(base)) {
2417
4082
  return;
2418
4083
  }
2419
4084
  if (dialect.name === "postgres") {
@@ -2425,7 +4090,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2425
4090
  }
2426
4091
  return;
2427
4092
  case "jsonLength":
2428
- if (!isExpression3(base)) {
4093
+ if (!isExpression4(base)) {
2429
4094
  return;
2430
4095
  }
2431
4096
  if (dialect.name === "postgres") {
@@ -2440,21 +4105,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2440
4105
  }
2441
4106
  return;
2442
4107
  case "jsonKeys":
2443
- if (!isExpression3(base)) {
4108
+ if (!isExpression4(base)) {
2444
4109
  return;
2445
4110
  }
2446
4111
  if (dialect.name === "postgres") {
2447
4112
  const baseSql = renderExpression(base, state, dialect);
2448
4113
  const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
2449
4114
  const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
2450
- return `(case when ${typeOf}(${baseSql}) = 'object' then array(select ${objectKeys}(${baseSql})) else null end)`;
4115
+ return `(case when ${typeOf}(${baseSql}) = 'object' then to_json(array(select ${objectKeys}(${baseSql}))) else null end)`;
2451
4116
  }
2452
4117
  if (dialect.name === "mysql") {
2453
4118
  return `json_keys(${renderExpression(base, state, dialect)})`;
2454
4119
  }
2455
4120
  return;
2456
4121
  case "jsonStripNulls":
2457
- if (!isExpression3(base)) {
4122
+ if (!isExpression4(base)) {
2458
4123
  return;
2459
4124
  }
2460
4125
  if (dialect.name === "postgres") {
@@ -2465,14 +4130,14 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2465
4130
  case "jsonDelete":
2466
4131
  case "jsonDeletePath":
2467
4132
  case "jsonRemove": {
2468
- if (!isExpression3(base) || segments.length === 0) {
4133
+ if (!isExpression4(base) || segments.length === 0) {
2469
4134
  return;
2470
4135
  }
2471
4136
  if (dialect.name === "postgres") {
2472
4137
  const baseSql = renderPostgresJsonValue(base, state, dialect);
2473
4138
  if (segments.length === 1 && (segments[0].kind === "key" || segments[0].kind === "index")) {
2474
4139
  const segment = segments[0];
2475
- return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(String(segment.index), state)})`;
4140
+ return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(segment.index, state)})`;
2476
4141
  }
2477
4142
  return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
2478
4143
  }
@@ -2483,11 +4148,11 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2483
4148
  }
2484
4149
  case "jsonSet":
2485
4150
  case "jsonInsert": {
2486
- if (!isExpression3(base) || segments.length === 0) {
4151
+ if (!isExpression4(base) || segments.length === 0) {
2487
4152
  return;
2488
4153
  }
2489
4154
  const nextValue = extractJsonValue(ast);
2490
- if (!isExpression3(nextValue)) {
4155
+ if (!isExpression4(nextValue)) {
2491
4156
  return;
2492
4157
  }
2493
4158
  const createMissing = ast.createMissing === true;
@@ -2504,7 +4169,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2504
4169
  return;
2505
4170
  }
2506
4171
  case "jsonPathExists": {
2507
- if (!isExpression3(base)) {
4172
+ if (!isExpression4(base)) {
2508
4173
  return;
2509
4174
  }
2510
4175
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -2520,7 +4185,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
2520
4185
  return;
2521
4186
  }
2522
4187
  case "jsonPathMatch": {
2523
- if (!isExpression3(base)) {
4188
+ if (!isExpression4(base)) {
2524
4189
  return;
2525
4190
  }
2526
4191
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -2547,6 +4212,11 @@ var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) =
2547
4212
  var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
2548
4213
  var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
2549
4214
  var renderDeleteTargets = (targets, dialect) => targets.map((target) => dialect.quoteIdentifier(target.tableName)).join(", ");
4215
+ var assertMergeActionKind = (kind, allowed) => {
4216
+ if (typeof kind !== "string" || !allowed.includes(kind)) {
4217
+ throw new Error("Unsupported merge action kind");
4218
+ }
4219
+ };
2550
4220
  var renderMysqlMutationLock = (lock, statement) => {
2551
4221
  if (!lock) {
2552
4222
  return "";
@@ -2566,8 +4236,9 @@ var renderTransactionClause = (clause, dialect) => {
2566
4236
  switch (clause.kind) {
2567
4237
  case "transaction": {
2568
4238
  const modes = [];
2569
- if (clause.isolationLevel) {
2570
- modes.push(`isolation level ${clause.isolationLevel}`);
4239
+ const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
4240
+ if (isolationLevel) {
4241
+ modes.push(isolationLevel);
2571
4242
  }
2572
4243
  if (clause.readOnly === true) {
2573
4244
  modes.push("read only");
@@ -2585,13 +4256,16 @@ var renderTransactionClause = (clause, dialect) => {
2585
4256
  case "releaseSavepoint":
2586
4257
  return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
2587
4258
  }
2588
- return "";
4259
+ throw new Error("Unsupported transaction statement kind");
2589
4260
  };
2590
4261
  var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2591
4262
  if (validateAggregation) {
2592
4263
  validateAggregationSelection(selection, []);
2593
4264
  }
2594
4265
  const flattened = flattenSelection(selection);
4266
+ if (dialect.name === "mysql" && flattened.length === 0) {
4267
+ throw new Error("mysql select statements require at least one selected expression");
4268
+ }
2595
4269
  const projections = selectionProjections(selection);
2596
4270
  const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
2597
4271
  return {
@@ -2599,7 +4273,84 @@ var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2599
4273
  projections
2600
4274
  };
2601
4275
  };
2602
- var renderQueryAst = (ast, state, dialect) => {
4276
+ var nestedRenderState = (state) => ({
4277
+ params: state.params,
4278
+ valueMappings: state.valueMappings,
4279
+ ctes: [],
4280
+ cteNames: new Set(state.cteNames),
4281
+ cteSources: new Map(state.cteSources)
4282
+ });
4283
+ var assertMatchingSetProjections = (left, right) => {
4284
+ const leftKeys = left.map((projection) => JSON.stringify(projection.path));
4285
+ const rightKeys = right.map((projection) => JSON.stringify(projection.path));
4286
+ if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index3) => key2 !== rightKeys[index3])) {
4287
+ throw new Error("set operator operands must have matching result rows");
4288
+ }
4289
+ };
4290
+ var assertNoGroupedMutationClauses = (ast, statement) => {
4291
+ if (ast.groupBy.length > 0) {
4292
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4293
+ }
4294
+ if (ast.having.length > 0) {
4295
+ throw new Error(`having(...) is not supported for ${statement} statements`);
4296
+ }
4297
+ };
4298
+ var assertNoInsertQueryClauses = (ast) => {
4299
+ if (ast.where.length > 0) {
4300
+ throw new Error("where(...) is not supported for insert statements");
4301
+ }
4302
+ if (ast.joins.length > 0) {
4303
+ throw new Error("join(...) is not supported for insert statements");
4304
+ }
4305
+ if (ast.orderBy.length > 0) {
4306
+ throw new Error("orderBy(...) is not supported for insert statements");
4307
+ }
4308
+ if (ast.limit) {
4309
+ throw new Error("limit(...) is not supported for insert statements");
4310
+ }
4311
+ if (ast.offset) {
4312
+ throw new Error("offset(...) is not supported for insert statements");
4313
+ }
4314
+ if (ast.lock) {
4315
+ throw new Error("lock(...) is not supported for insert statements");
4316
+ }
4317
+ };
4318
+ var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
4319
+ if (ast.distinct) {
4320
+ throw new Error(`distinct(...) is not supported for ${statement} statements`);
4321
+ }
4322
+ if (ast.where.length > 0) {
4323
+ throw new Error(`where(...) is not supported for ${statement} statements`);
4324
+ }
4325
+ if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
4326
+ throw new Error(`from(...) is not supported for ${statement} statements`);
4327
+ }
4328
+ if (ast.joins.length > 0) {
4329
+ throw new Error(`join(...) is not supported for ${statement} statements`);
4330
+ }
4331
+ if (ast.groupBy.length > 0) {
4332
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4333
+ }
4334
+ if (ast.having.length > 0) {
4335
+ throw new Error(`having(...) is not supported for ${statement} statements`);
4336
+ }
4337
+ if (ast.orderBy.length > 0) {
4338
+ throw new Error(`orderBy(...) is not supported for ${statement} statements`);
4339
+ }
4340
+ if (ast.limit) {
4341
+ throw new Error(`limit(...) is not supported for ${statement} statements`);
4342
+ }
4343
+ if (ast.offset) {
4344
+ throw new Error(`offset(...) is not supported for ${statement} statements`);
4345
+ }
4346
+ if (ast.lock) {
4347
+ throw new Error(`lock(...) is not supported for ${statement} statements`);
4348
+ }
4349
+ if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
4350
+ throw new Error(`returning(...) is not supported for ${statement} statements`);
4351
+ }
4352
+ };
4353
+ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
2603
4354
  let sql = "";
2604
4355
  let projections = [];
2605
4356
  switch (ast.kind) {
@@ -2607,8 +4358,9 @@ var renderQueryAst = (ast, state, dialect) => {
2607
4358
  validateAggregationSelection(ast.select, ast.groupBy);
2608
4359
  const rendered = renderSelectionList(ast.select, state, dialect, false);
2609
4360
  projections = rendered.projections;
4361
+ const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
2610
4362
  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}`
4363
+ 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
4364
  ];
2613
4365
  if (ast.from) {
2614
4366
  clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
@@ -2636,19 +4388,25 @@ var renderQueryAst = (ast, state, dialect) => {
2636
4388
  clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
2637
4389
  }
2638
4390
  if (ast.lock) {
2639
- clauses.push(`${ast.lock.mode === "update" ? "for update" : "for share"}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
4391
+ if (ast.lock.nowait && ast.lock.skipLocked) {
4392
+ throw new Error("lock(...) cannot specify both nowait and skipLocked");
4393
+ }
4394
+ clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
2640
4395
  }
2641
4396
  sql = clauses.join(" ");
2642
4397
  break;
2643
4398
  }
2644
4399
  case "set": {
2645
4400
  const setAst = ast;
4401
+ assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
2646
4402
  const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
2647
4403
  projections = selectionProjections(setAst.select);
4404
+ assertMatchingSetProjections(projections, base.projections);
2648
4405
  sql = [
2649
4406
  `(${base.sql})`,
2650
4407
  ...(setAst.setOperations ?? []).map((entry) => {
2651
4408
  const rendered = renderQueryAst(getAst(entry.query), state, dialect);
4409
+ assertMatchingSetProjections(projections, rendered.projections);
2652
4410
  return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
2653
4411
  })
2654
4412
  ].join(" ");
@@ -2656,28 +4414,34 @@ var renderQueryAst = (ast, state, dialect) => {
2656
4414
  }
2657
4415
  case "insert": {
2658
4416
  const insertAst = ast;
4417
+ if (insertAst.distinct) {
4418
+ throw new Error("distinct(...) is not supported for insert statements");
4419
+ }
4420
+ assertNoGroupedMutationClauses(insertAst, "insert");
4421
+ assertNoInsertQueryClauses(insertAst);
2659
4422
  const targetSource = insertAst.into;
2660
4423
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4424
+ const insertSource = expectInsertSourceKind(insertAst.insertSource);
4425
+ const conflict = expectConflictClause(insertAst.conflict);
2661
4426
  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(", ");
4427
+ if (insertSource?.kind === "values") {
4428
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4429
+ const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
2665
4430
  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);
4431
+ } else if (insertSource?.kind === "query") {
4432
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4433
+ const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
2669
4434
  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(", ");
4435
+ } else if (insertSource?.kind === "unnest") {
4436
+ const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
2673
4437
  if (dialect.name === "postgres") {
2674
4438
  const table = targetSource.source;
2675
4439
  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(", ");
4440
+ 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
4441
  sql += ` (${columns}) select * from unnest(${rendered})`;
2678
4442
  } 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(", ");
4443
+ const rowCount = insertSource.values[0]?.values.length ?? 0;
4444
+ 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
4445
  sql += ` (${columns}) values ${rows}`;
2682
4446
  }
2683
4447
  } else {
@@ -2689,13 +4453,16 @@ var renderQueryAst = (ast, state, dialect) => {
2689
4453
  sql += " default values";
2690
4454
  }
2691
4455
  }
2692
- if (insertAst.conflict) {
2693
- const updateValues = (insertAst.conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
4456
+ if (conflict) {
4457
+ if (conflict.action === "doNothing" && conflict.where) {
4458
+ throw new Error("conflict action predicates require update assignments");
4459
+ }
4460
+ const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
2694
4461
  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";
4462
+ 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
4463
  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") {
4464
+ sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
4465
+ } else if (conflict.action === "doNothing") {
2699
4466
  sql = sql.replace(/^insert/, "insert ignore");
2700
4467
  } else {
2701
4468
  sql += ` on duplicate key update ${updateValues}`;
@@ -2710,10 +4477,29 @@ var renderQueryAst = (ast, state, dialect) => {
2710
4477
  }
2711
4478
  case "update": {
2712
4479
  const updateAst = ast;
4480
+ if (updateAst.distinct) {
4481
+ throw new Error("distinct(...) is not supported for update statements");
4482
+ }
4483
+ assertNoGroupedMutationClauses(updateAst, "update");
4484
+ if (updateAst.orderBy.length > 0) {
4485
+ throw new Error("orderBy(...) is not supported for update statements");
4486
+ }
4487
+ if (updateAst.limit) {
4488
+ throw new Error("limit(...) is not supported for update statements");
4489
+ }
4490
+ if (updateAst.offset) {
4491
+ throw new Error("offset(...) is not supported for update statements");
4492
+ }
4493
+ if (updateAst.lock) {
4494
+ throw new Error("lock(...) is not supported for update statements");
4495
+ }
2713
4496
  const targetSource = updateAst.target;
2714
4497
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2715
4498
  const targets = updateAst.targets ?? [targetSource];
2716
4499
  const fromSources = updateAst.fromSources ?? [];
4500
+ if ((updateAst.set ?? []).length === 0) {
4501
+ throw new Error("update statements require at least one assignment");
4502
+ }
2717
4503
  const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
2718
4504
  if (dialect.name === "mysql") {
2719
4505
  const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
@@ -2756,6 +4542,22 @@ var renderQueryAst = (ast, state, dialect) => {
2756
4542
  }
2757
4543
  case "delete": {
2758
4544
  const deleteAst = ast;
4545
+ if (deleteAst.distinct) {
4546
+ throw new Error("distinct(...) is not supported for delete statements");
4547
+ }
4548
+ assertNoGroupedMutationClauses(deleteAst, "delete");
4549
+ if (deleteAst.orderBy.length > 0 && dialect.name === "postgres") {
4550
+ throw new Error("orderBy(...) is not supported for delete statements");
4551
+ }
4552
+ if (deleteAst.limit && dialect.name === "postgres") {
4553
+ throw new Error("limit(...) is not supported for delete statements");
4554
+ }
4555
+ if (deleteAst.offset) {
4556
+ throw new Error("offset(...) is not supported for delete statements");
4557
+ }
4558
+ if (deleteAst.lock) {
4559
+ throw new Error("lock(...) is not supported for delete statements");
4560
+ }
2759
4561
  const targetSource = deleteAst.target;
2760
4562
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
2761
4563
  const targets = deleteAst.targets ?? [targetSource];
@@ -2794,12 +4596,14 @@ var renderQueryAst = (ast, state, dialect) => {
2794
4596
  }
2795
4597
  case "truncate": {
2796
4598
  const truncateAst = ast;
4599
+ assertNoStatementQueryClauses(truncateAst, "truncate");
4600
+ const truncate = expectTruncateClause(truncateAst.truncate);
2797
4601
  const targetSource = truncateAst.target;
2798
4602
  sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
2799
- if (truncateAst.truncate?.restartIdentity) {
4603
+ if (truncate.restartIdentity) {
2800
4604
  sql += " restart identity";
2801
4605
  }
2802
- if (truncateAst.truncate?.cascade) {
4606
+ if (truncate.cascade) {
2803
4607
  sql += " cascade";
2804
4608
  }
2805
4609
  break;
@@ -2812,8 +4616,18 @@ var renderQueryAst = (ast, state, dialect) => {
2812
4616
  const targetSource = mergeAst.target;
2813
4617
  const usingSource = mergeAst.using;
2814
4618
  const merge = mergeAst.merge;
4619
+ if (merge.kind !== "merge") {
4620
+ throw new Error("Unsupported merge statement kind");
4621
+ }
4622
+ if (Object.keys(mergeAst.select).length > 0) {
4623
+ throw new Error("returning(...) is not supported for merge statements");
4624
+ }
4625
+ if (!merge.whenMatched && !merge.whenNotMatched) {
4626
+ throw new Error("merge statements require at least one action");
4627
+ }
2815
4628
  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
4629
  if (merge.whenMatched) {
4630
+ assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
2817
4631
  sql += " when matched";
2818
4632
  if (merge.whenMatched.predicate) {
2819
4633
  sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
@@ -2821,14 +4635,21 @@ var renderQueryAst = (ast, state, dialect) => {
2821
4635
  if (merge.whenMatched.kind === "delete") {
2822
4636
  sql += " then delete";
2823
4637
  } else {
4638
+ if (merge.whenMatched.values.length === 0) {
4639
+ throw new Error("merge update actions require at least one assignment");
4640
+ }
2824
4641
  sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
2825
4642
  }
2826
4643
  }
2827
4644
  if (merge.whenNotMatched) {
4645
+ assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
2828
4646
  sql += " when not matched";
2829
4647
  if (merge.whenNotMatched.predicate) {
2830
4648
  sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
2831
4649
  }
4650
+ if (merge.whenNotMatched.values.length === 0) {
4651
+ throw new Error("merge insert actions require at least one value");
4652
+ }
2832
4653
  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
4654
  }
2834
4655
  break;
@@ -2839,32 +4660,40 @@ var renderQueryAst = (ast, state, dialect) => {
2839
4660
  case "savepoint":
2840
4661
  case "rollbackTo":
2841
4662
  case "releaseSavepoint": {
4663
+ assertNoStatementQueryClauses(ast, ast.kind);
2842
4664
  sql = renderTransactionClause(ast.transaction, dialect);
2843
4665
  break;
2844
4666
  }
2845
4667
  case "createTable": {
2846
4668
  const createTableAst = ast;
2847
- sql = renderCreateTableSql(createTableAst.target, state, dialect, createTableAst.ddl?.kind === "createTable" && createTableAst.ddl.ifNotExists);
4669
+ assertNoStatementQueryClauses(createTableAst, "createTable");
4670
+ const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
4671
+ sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
2848
4672
  break;
2849
4673
  }
2850
4674
  case "dropTable": {
2851
4675
  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)}`;
4676
+ assertNoStatementQueryClauses(dropTableAst, "dropTable");
4677
+ const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
4678
+ sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
2854
4679
  break;
2855
4680
  }
2856
4681
  case "createIndex": {
2857
4682
  const createIndexAst = ast;
2858
- sql = renderCreateIndexSql(createIndexAst.target, createIndexAst.ddl, state, dialect);
4683
+ assertNoStatementQueryClauses(createIndexAst, "createIndex");
4684
+ sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
2859
4685
  break;
2860
4686
  }
2861
4687
  case "dropIndex": {
2862
4688
  const dropIndexAst = ast;
2863
- sql = renderDropIndexSql(dropIndexAst.target, dropIndexAst.ddl, state, dialect);
4689
+ assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
4690
+ sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
2864
4691
  break;
2865
4692
  }
4693
+ default:
4694
+ throw new Error("Unsupported query statement kind");
2866
4695
  }
2867
- if (state.ctes.length === 0) {
4696
+ if (state.ctes.length === 0 || options2.emitCtes === false) {
2868
4697
  return {
2869
4698
  sql,
2870
4699
  projections
@@ -2887,9 +4716,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2887
4716
  };
2888
4717
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
2889
4718
  const cte = source;
4719
+ const registeredCteSource = state.cteSources.get(cte.name);
4720
+ if (registeredCteSource !== undefined && registeredCteSource !== cte.plan) {
4721
+ throw new Error(`common table expression name is already registered with a different plan: ${cte.name}`);
4722
+ }
2890
4723
  if (!state.cteNames.has(cte.name)) {
2891
4724
  state.cteNames.add(cte.name);
2892
- const rendered = renderQueryAst(getAst(cte.plan), state, dialect);
4725
+ state.cteSources.set(cte.name, cte.plan);
4726
+ const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
2893
4727
  state.ctes.push({
2894
4728
  name: cte.name,
2895
4729
  sql: rendered.sql,
@@ -2901,11 +4735,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2901
4735
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
2902
4736
  const derived = source;
2903
4737
  if (!state.cteNames.has(derived.name)) {}
2904
- return `(${renderQueryAst(getAst(derived.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
4738
+ return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
2905
4739
  }
2906
4740
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
2907
4741
  const lateral = source;
2908
- return `lateral (${renderQueryAst(getAst(lateral.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
4742
+ return `lateral (${renderQueryAst(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
2909
4743
  }
2910
4744
  if (typeof source === "object" && source !== null && source.kind === "values") {
2911
4745
  const values = source;
@@ -2926,6 +4760,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
2926
4760
  const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
2927
4761
  return dialect.renderTableReference(tableName, baseTableName, schemaName);
2928
4762
  };
4763
+ var renderSubqueryExpressionPlan = (plan, state, dialect) => {
4764
+ const statement = getQueryState(plan).statement;
4765
+ if (statement !== "select" && statement !== "set") {
4766
+ throw new Error("subquery expressions only accept select-like query plans");
4767
+ }
4768
+ return renderQueryAst(getAst(plan), state, dialect).sql;
4769
+ };
2929
4770
  var renderExpression = (expression, state, dialect) => {
2930
4771
  const rawAst = expression[TypeId3];
2931
4772
  const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
@@ -2936,8 +4777,11 @@ var renderExpression = (expression, state, dialect) => {
2936
4777
  const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
2937
4778
  switch (ast.kind) {
2938
4779
  case "column":
2939
- return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
4780
+ return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
2940
4781
  case "literal":
4782
+ if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
4783
+ throw new Error("Expected a finite numeric value");
4784
+ }
2941
4785
  return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
2942
4786
  case "excluded":
2943
4787
  return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
@@ -2977,6 +4821,7 @@ var renderExpression = (expression, state, dialect) => {
2977
4821
  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
4822
  case "contains":
2979
4823
  if (dialect.name === "postgres") {
4824
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2980
4825
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2981
4826
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2982
4827
  return `(${left} @> ${right})`;
@@ -2987,6 +4832,7 @@ var renderExpression = (expression, state, dialect) => {
2987
4832
  throw new Error("Unsupported container operator for SQL rendering");
2988
4833
  case "containedBy":
2989
4834
  if (dialect.name === "postgres") {
4835
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
2990
4836
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
2991
4837
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
2992
4838
  return `(${left} <@ ${right})`;
@@ -2997,6 +4843,7 @@ var renderExpression = (expression, state, dialect) => {
2997
4843
  throw new Error("Unsupported container operator for SQL rendering");
2998
4844
  case "overlaps":
2999
4845
  if (dialect.name === "postgres") {
4846
+ assertCompatiblePostgresRangeOperands(ast.left, ast.right);
3000
4847
  const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
3001
4848
  const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
3002
4849
  return `(${left} && ${right})`;
@@ -3022,14 +4869,26 @@ var renderExpression = (expression, state, dialect) => {
3022
4869
  case "min":
3023
4870
  return `min(${renderExpression(ast.value, state, dialect)})`;
3024
4871
  case "and":
4872
+ if (ast.values.length === 0) {
4873
+ throw new Error("and(...) requires at least one predicate");
4874
+ }
3025
4875
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
3026
4876
  case "or":
4877
+ if (ast.values.length === 0) {
4878
+ throw new Error("or(...) requires at least one predicate");
4879
+ }
3027
4880
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
3028
4881
  case "coalesce":
3029
4882
  return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
3030
4883
  case "in":
4884
+ if (ast.values.length < 2) {
4885
+ throw new Error("in(...) requires at least one candidate value");
4886
+ }
3031
4887
  return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
3032
4888
  case "notIn":
4889
+ if (ast.values.length < 2) {
4890
+ throw new Error("notIn(...) requires at least one candidate value");
4891
+ }
3033
4892
  return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
3034
4893
  case "between":
3035
4894
  return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
@@ -3038,15 +4897,15 @@ var renderExpression = (expression, state, dialect) => {
3038
4897
  case "case":
3039
4898
  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
4899
  case "exists":
3041
- return `exists (${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4900
+ return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
3042
4901
  case "scalarSubquery":
3043
- return `(${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
4902
+ return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
3044
4903
  case "inSubquery":
3045
- return `(${renderExpression(ast.left, state, dialect)} in (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4904
+ return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
3046
4905
  case "comparisonAny":
3047
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4906
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
3048
4907
  case "comparisonAll":
3049
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
4908
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
3050
4909
  case "window": {
3051
4910
  if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
3052
4911
  break;
@@ -3131,7 +4990,8 @@ var inlineLiteralDialect = {
3131
4990
  var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
3132
4991
  params: [],
3133
4992
  ctes: [],
3134
- cteNames: new Set
4993
+ cteNames: new Set,
4994
+ cteSources: new Map
3135
4995
  }, inlineLiteralDialect);
3136
4996
  var stripRedundantOuterParens = (value) => {
3137
4997
  let current = value.trim();
@@ -3182,10 +5042,14 @@ var normalizeDdlExpressionSql = (expression) => {
3182
5042
  };
3183
5043
 
3184
5044
  // src/postgres/schema-management.ts
3185
- import * as Schema4 from "effect/Schema";
5045
+ import * as Schema6 from "effect/Schema";
3186
5046
  import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
3187
5047
  var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
3188
5048
  var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
5049
+ var safeUnquotedIdentifier = /^[a-z_][a-z0-9_$]*$/;
5050
+ var quoteIdentifier2 = (value) => `"${value.replaceAll('"', '""')}"`;
5051
+ var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier2(value);
5052
+ var renderQualifiedTypeName = (name, schemaName) => schemaName === undefined || schemaName === "public" ? renderIdentifier(name) : `${renderIdentifier(schemaName)}.${renderIdentifier(name)}`;
3189
5053
  var EnumProto = {
3190
5054
  pipe() {
3191
5055
  return pipeArguments5(this, arguments);
@@ -3196,13 +5060,12 @@ var EnumProto = {
3196
5060
  type() {
3197
5061
  return {
3198
5062
  dialect: "postgres",
3199
- kind: this.qualifiedName(),
5063
+ kind: renderQualifiedTypeName(this.name, this.schemaName),
3200
5064
  variant: "enum"
3201
5065
  };
3202
5066
  },
3203
5067
  column() {
3204
- const values = this.values.map((value) => Schema4.Literal(value));
3205
- return makeColumnDefinition(values.length === 1 ? values[0] : Schema4.Union(...values), {
5068
+ return makeColumnDefinition(Schema6.Literals(this.values), {
3206
5069
  dbType: this.type(),
3207
5070
  nullable: false,
3208
5071
  hasDefault: false,
@@ -3210,7 +5073,7 @@ var EnumProto = {
3210
5073
  primaryKey: false,
3211
5074
  unique: false,
3212
5075
  references: undefined,
3213
- ddlType: this.qualifiedName(),
5076
+ ddlType: renderQualifiedTypeName(this.name, this.schemaName),
3214
5077
  identity: undefined,
3215
5078
  enum: {
3216
5079
  name: this.name,
@@ -3311,17 +5174,17 @@ var fromDiscoveredValues = (values) => {
3311
5174
  const enums = new Map;
3312
5175
  for (const value of values) {
3313
5176
  if (isEnumDefinition(value)) {
3314
- enums.set(enumKey(value.schemaName, value.name), toEnumModel(value));
5177
+ enums.set(modelIdentityKey(value.schemaName, value.name), toEnumModel(value));
3315
5178
  } else if (isTableDefinition(value)) {
3316
5179
  for (const enumModel of enumModelsOfTable(value)) {
3317
- const key2 = enumKey(enumModel.schemaName, enumModel.name);
5180
+ const key2 = modelIdentityKey(enumModel.schemaName, enumModel.name);
3318
5181
  const existing = enums.get(key2);
3319
5182
  if (existing === undefined) {
3320
5183
  enums.set(key2, enumModel);
3321
5184
  continue;
3322
5185
  }
3323
5186
  if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
3324
- throw new Error(`Conflicting enum definitions discovered for '${key2}'`);
5187
+ throw new Error(`Conflicting enum definitions discovered for '${enumKey(enumModel.schemaName, enumModel.name)}'`);
3325
5188
  }
3326
5189
  }
3327
5190
  }
@@ -3334,6 +5197,7 @@ var fromDiscoveredValues = (values) => {
3334
5197
  };
3335
5198
  var tableKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
3336
5199
  var enumKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
5200
+ var modelIdentityKey = (schemaName, name) => JSON.stringify([schemaName ?? "public", name]);
3337
5201
  export {
3338
5202
  toTableModel,
3339
5203
  toEnumModel,