effect-qb 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +4 -0
  2. package/dist/index.js +8065 -0
  3. package/dist/mysql.js +3053 -2505
  4. package/dist/postgres/metadata.js +1366 -1250
  5. package/dist/postgres.js +2020 -2719
  6. package/dist/sqlite.js +3226 -2732
  7. package/dist/standard.js +8019 -0
  8. package/package.json +10 -3
  9. package/src/casing.ts +71 -0
  10. package/src/index.ts +2 -0
  11. package/src/internal/casing.ts +89 -0
  12. package/src/internal/column-state.ts +11 -6
  13. package/src/internal/column.ts +44 -7
  14. package/src/internal/datatypes/define.ts +2 -1
  15. package/src/internal/datatypes/enrich.ts +23 -0
  16. package/src/internal/datatypes/lookup.ts +14 -7
  17. package/src/internal/derived-table.ts +4 -36
  18. package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/mysql.ts} +548 -359
  19. package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +654 -399
  20. package/src/{sqlite/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +501 -345
  21. package/src/internal/dialect.ts +35 -0
  22. package/src/internal/dsl-mutation-runtime.ts +12 -162
  23. package/src/internal/dsl-plan-runtime.ts +10 -138
  24. package/src/internal/dsl-query-runtime.ts +5 -79
  25. package/src/internal/dsl-transaction-ddl-runtime.ts +41 -65
  26. package/src/internal/executor.ts +10 -6
  27. package/src/internal/grouping-key.ts +87 -20
  28. package/src/internal/implication-runtime.ts +1 -1
  29. package/src/internal/predicate/runtime.ts +3 -0
  30. package/src/internal/query.d.ts +38 -11
  31. package/src/internal/query.ts +64 -25
  32. package/src/internal/renderer.ts +26 -14
  33. package/src/internal/runtime/normalize.ts +12 -5
  34. package/src/internal/scalar.ts +6 -1
  35. package/src/internal/schema-derivation.d.ts +12 -61
  36. package/src/internal/schema-derivation.ts +90 -38
  37. package/src/internal/schema-expression.ts +2 -2
  38. package/src/internal/sql-expression-renderer.ts +19 -0
  39. package/src/internal/standard-dsl.ts +6885 -0
  40. package/src/internal/table-options.ts +126 -66
  41. package/src/internal/table.d.ts +33 -32
  42. package/src/internal/table.ts +406 -155
  43. package/src/mysql/column-extension.ts +3 -0
  44. package/src/mysql/column.ts +10 -11
  45. package/src/mysql/datatypes/index.ts +3 -2
  46. package/src/mysql/executor.ts +7 -5
  47. package/src/mysql/internal/dialect.ts +9 -4
  48. package/src/mysql/internal/dsl.ts +219 -155
  49. package/src/mysql/internal/renderer.ts +6 -2
  50. package/src/mysql/json.ts +37 -0
  51. package/src/mysql/query-extension.ts +16 -0
  52. package/src/mysql/renderer.ts +31 -4
  53. package/src/mysql.ts +4 -12
  54. package/src/postgres/column-extension.ts +28 -0
  55. package/src/postgres/column.ts +5 -11
  56. package/src/postgres/datatypes/index.d.ts +2 -1
  57. package/src/postgres/datatypes/index.ts +3 -2
  58. package/src/postgres/executor.ts +7 -5
  59. package/src/postgres/function/core.ts +1 -3
  60. package/src/postgres/function/index.ts +1 -17
  61. package/src/postgres/internal/dialect.ts +9 -4
  62. package/src/postgres/internal/dsl.ts +208 -160
  63. package/src/postgres/internal/renderer.ts +6 -2
  64. package/src/postgres/internal/schema-ddl.ts +22 -10
  65. package/src/postgres/internal/schema-model.ts +238 -7
  66. package/src/postgres/json.ts +43 -7
  67. package/src/postgres/jsonb.ts +38 -0
  68. package/src/postgres/query-extension.ts +2 -0
  69. package/src/postgres/renderer.ts +31 -4
  70. package/src/postgres/schema-management.ts +17 -12
  71. package/src/postgres/schema.ts +98 -15
  72. package/src/postgres/table.ts +193 -524
  73. package/src/postgres/type.ts +8 -7
  74. package/src/postgres.ts +9 -11
  75. package/src/sqlite/column-extension.ts +3 -0
  76. package/src/sqlite/column.ts +10 -11
  77. package/src/sqlite/datatypes/index.ts +3 -2
  78. package/src/sqlite/executor.ts +7 -5
  79. package/src/sqlite/internal/dialect.ts +9 -4
  80. package/src/sqlite/internal/dsl.ts +208 -155
  81. package/src/sqlite/internal/renderer.ts +6 -2
  82. package/src/sqlite/json.ts +37 -0
  83. package/src/sqlite/query-extension.ts +2 -0
  84. package/src/sqlite/renderer.ts +31 -4
  85. package/src/sqlite.ts +4 -12
  86. package/src/standard/column.ts +163 -0
  87. package/src/standard/datatypes/index.ts +83 -0
  88. package/src/standard/datatypes/spec.ts +98 -0
  89. package/src/standard/dialect.ts +40 -0
  90. package/src/standard/function/aggregate.ts +2 -0
  91. package/src/standard/function/core.ts +2 -0
  92. package/src/standard/function/index.ts +18 -0
  93. package/src/standard/function/string.ts +2 -0
  94. package/src/standard/function/temporal.ts +78 -0
  95. package/src/standard/function/window.ts +2 -0
  96. package/src/standard/internal/renderer.ts +45 -0
  97. package/src/standard/query.ts +152 -0
  98. package/src/standard/renderer.ts +21 -0
  99. package/src/standard/table.ts +147 -0
  100. package/src/standard.ts +18 -0
  101. package/src/internal/aggregation-validation.ts +0 -57
  102. package/src/mysql/table.ts +0 -183
  103. package/src/sqlite/table.ts +0 -183
@@ -25,7 +25,7 @@ __export(exports_metadata, {
25
25
  });
26
26
 
27
27
  // src/internal/table.ts
28
- import { pipeArguments as pipeArguments2 } from "effect/Pipeable";
28
+ import { pipeArguments as pipeArguments3 } from "effect/Pipeable";
29
29
 
30
30
  // src/internal/row-set.ts
31
31
  var exports_row_set = {};
@@ -142,7 +142,7 @@ var remapColumnDefinition = (column, options = {}) => {
142
142
  }
143
143
  return next;
144
144
  };
145
- var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
145
+ var bindColumn = (tableName, columnName, column, baseTableName, schemaName, casing) => {
146
146
  const brandName = `${tableName}.${columnName}`;
147
147
  const schema = column.metadata.brand === true ? Schema.brand(brandName)(column.schema) : column.schema;
148
148
  const bound = attachPipe(Object.create(ColumnProto));
@@ -170,11 +170,64 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
170
170
  tableName,
171
171
  columnName,
172
172
  baseTableName,
173
- schemaName
173
+ schemaName,
174
+ casing
174
175
  };
175
176
  return bound;
176
177
  };
177
178
 
179
+ // src/internal/schema-expression.ts
180
+ import { parse, toSql } from "pgsql-ast-parser";
181
+ import { pipeArguments as pipeArguments2 } from "effect/Pipeable";
182
+ var TypeId4 = Symbol.for("effect-qb/SchemaExpression");
183
+ var SchemaExpressionProto = {
184
+ pipe() {
185
+ return pipeArguments2(this, arguments);
186
+ }
187
+ };
188
+ var attachPipe2 = (value) => {
189
+ Object.defineProperty(value, "pipe", {
190
+ configurable: true,
191
+ writable: true,
192
+ value: function() {
193
+ return pipeArguments2(value, arguments);
194
+ }
195
+ });
196
+ return value;
197
+ };
198
+ var isSchemaExpression = (value) => typeof value === "object" && value !== null && (TypeId4 in value);
199
+ var fromAst = (ast) => {
200
+ const expression = attachPipe2(Object.create(SchemaExpressionProto));
201
+ expression[TypeId4] = {
202
+ ast
203
+ };
204
+ return expression;
205
+ };
206
+ var fromSql = (sql) => {
207
+ const expression = attachPipe2(Object.create(SchemaExpressionProto));
208
+ expression[TypeId4] = {
209
+ sql: sql.trim()
210
+ };
211
+ return expression;
212
+ };
213
+ var parseExpression = (sql) => fromAst(parse(sql, "expr"));
214
+ var toAst = (expression) => {
215
+ const ast = expression[TypeId4].ast;
216
+ if (ast !== undefined) {
217
+ return ast;
218
+ }
219
+ return parse(render(expression), "expr");
220
+ };
221
+ var render = (expression) => expression[TypeId4].sql ?? toSql.expr(toAst(expression));
222
+ var normalize = (expression) => (() => {
223
+ const sql = render(expression);
224
+ try {
225
+ return parseExpression(sql);
226
+ } catch {
227
+ return fromSql(sql);
228
+ }
229
+ })();
230
+
178
231
  // src/internal/table-options.ts
179
232
  var referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault";
180
233
  var renderReferentialAction = (action) => {
@@ -192,17 +245,11 @@ var renderReferentialAction = (action) => {
192
245
  }
193
246
  throw new Error(referentialActionError);
194
247
  };
195
- var validateReferentialAction = (action) => {
196
- if (action !== undefined) {
197
- renderReferentialAction(action);
198
- }
199
- };
200
248
  var normalizeColumnList = (columns) => {
201
- const normalized = Array.isArray(columns) ? [...columns] : [columns];
202
- if (normalized.length === 0) {
203
- throw new Error("Table options require at least one column");
249
+ if (typeof columns === "string") {
250
+ return [columns];
204
251
  }
205
- return normalized;
252
+ return [columns[0], ...columns.slice(1)];
206
253
  };
207
254
  var collectInlineOptions = (fields) => {
208
255
  const options = [];
@@ -224,8 +271,6 @@ var collectInlineOptions = (fields) => {
224
271
  });
225
272
  }
226
273
  if (column.metadata.references) {
227
- validateReferentialAction(column.metadata.references.onUpdate);
228
- validateReferentialAction(column.metadata.references.onDelete);
229
274
  const local = [columnName];
230
275
  options.push({
231
276
  kind: "foreignKey",
@@ -236,6 +281,7 @@ var collectInlineOptions = (fields) => {
236
281
  return {
237
282
  tableName: bound.baseTableName,
238
283
  schemaName: bound.schemaName,
284
+ casing: bound.casing,
239
285
  columns: [bound.columnName]
240
286
  };
241
287
  },
@@ -268,91 +314,50 @@ var collectInlineOptions = (fields) => {
268
314
  };
269
315
  var resolvePrimaryKeyColumns = (fields, declaredOptions) => {
270
316
  const inline = Object.entries(fields).filter(([, column]) => column.metadata.primaryKey).map(([key]) => key);
271
- const explicit = declaredOptions.filter((option) => option.kind === "primaryKey").map((option) => option.columns);
272
- if (explicit.length > 1) {
273
- throw new Error("Only one primary key declaration is allowed");
274
- }
317
+ const explicit = declaredOptions.flatMap((option) => {
318
+ if (typeof option !== "object" || option === null || !("kind" in option) || option.kind !== "primaryKey") {
319
+ return [];
320
+ }
321
+ return Array.isArray(option.columns) ? [option.columns] : [];
322
+ });
275
323
  if (explicit.length === 0) {
276
324
  return inline;
277
325
  }
278
326
  const tablePrimaryKey = [...explicit[0]];
279
- if (inline.length > 0) {
280
- const same = inline.length === tablePrimaryKey.length && inline.every((column) => tablePrimaryKey.includes(column));
281
- if (!same) {
282
- throw new Error("Inline primary keys conflict with table-level primary key declaration");
283
- }
284
- }
285
327
  return tablePrimaryKey;
286
328
  };
287
329
  var validateOptions = (tableName, fields, options) => {
288
- const knownColumns = new Set(Object.keys(fields));
289
- for (const option of options) {
330
+ const tableOptions = Array.isArray(options) ? options : [options];
331
+ for (const option of tableOptions) {
332
+ if (typeof option !== "object" || option === null || !("kind" in option)) {
333
+ continue;
334
+ }
290
335
  switch (option.kind) {
291
336
  case "index":
292
337
  case "primaryKey":
293
338
  case "unique":
294
339
  case "foreignKey": {
295
- const columns = option.kind === "index" ? option.columns ?? [] : option.columns;
296
- if (columns.length === 0 && option.kind !== "index") {
297
- throw new Error(`Option '${option.kind}' on table '${tableName}' requires at least one column`);
298
- }
299
- for (const column of columns) {
300
- if (!knownColumns.has(column)) {
301
- throw new Error(`Unknown column '${column}' on table '${tableName}'`);
302
- }
303
- }
304
- if (option.kind === "foreignKey") {
305
- validateReferentialAction(option.onUpdate);
306
- validateReferentialAction(option.onDelete);
307
- const reference = option.references();
308
- if (reference.columns.length !== columns.length) {
309
- throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
310
- }
311
- if (reference.knownColumns) {
312
- const referenced = new Set(reference.knownColumns);
313
- for (const column of reference.columns) {
314
- if (!referenced.has(column)) {
315
- throw new Error(`Unknown referenced column '${column}' on table '${reference.tableName}'`);
316
- }
317
- }
318
- }
319
- }
320
340
  if (option.kind === "index") {
321
- for (const column of option.include ?? []) {
322
- if (!knownColumns.has(column)) {
323
- throw new Error(`Unknown included column '${column}' on table '${tableName}'`);
341
+ const keys = Array.isArray(option.keys) ? option.keys : [];
342
+ for (const key of keys) {
343
+ if (typeof key !== "object" || key === null || !("kind" in key)) {
344
+ continue;
324
345
  }
325
346
  }
326
- for (const key of option.keys ?? []) {
327
- if (key.kind === "column" && !knownColumns.has(key.column)) {
328
- throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
329
- }
330
- }
331
- if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
332
- throw new Error(`Index on table '${tableName}' requires at least one column or key`);
333
- }
334
347
  }
335
348
  break;
336
349
  }
337
350
  case "check": {
338
351
  break;
339
352
  }
340
- }
341
- }
342
- for (const column of resolvePrimaryKeyColumns(fields, options)) {
343
- if (fields[column].metadata.nullable) {
344
- throw new Error(`Primary key column '${String(column)}' cannot be nullable`);
353
+ default:
354
+ break;
345
355
  }
346
356
  }
347
357
  };
348
358
 
349
359
  // src/internal/schema-derivation.ts
350
- import * as VariantSchema from "@effect/experimental/VariantSchema";
351
360
  import * as Schema2 from "effect/Schema";
352
- var TableSchema = VariantSchema.make({
353
- variants: ["select", "insert", "update"],
354
- defaultVariant: "select"
355
- });
356
361
  var maybeBrandSchema = (column, tableName, columnName) => column.metadata.brand === true ? Schema2.brand(`${tableName}.${columnName}`)(column.schema) : column.schema;
357
362
  var selectSchema = (column, tableName, columnName) => column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
358
363
  var insertSchema = (column, tableName, columnName) => {
@@ -369,87 +374,196 @@ var updateSchema = (column, tableName, columnName, isPrimaryKey) => {
369
374
  const base = column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
370
375
  return Schema2.optional(base);
371
376
  };
372
- var deriveSchemas = (tableName, fields, primaryKeyColumns) => {
377
+ var fieldSchemaForVariant = (variant, column, tableName, columnName, primaryKeySet) => {
378
+ switch (variant) {
379
+ case "select":
380
+ return selectSchema(column, tableName, columnName);
381
+ case "insert":
382
+ return insertSchema(column, tableName, columnName);
383
+ case "update":
384
+ return updateSchema(column, tableName, columnName, primaryKeySet.has(columnName));
385
+ }
386
+ };
387
+ var deriveSchema = (variant, tableName, fields, primaryKeyColumns) => {
373
388
  const primaryKeySet = new Set(primaryKeyColumns);
374
- const variants = {};
389
+ const structFields = {};
375
390
  for (const [key, column] of Object.entries(fields)) {
376
- const config = {
377
- select: selectSchema(column, tableName, key),
378
- insert: undefined,
379
- update: undefined
380
- };
381
- const insert = insertSchema(column, tableName, key);
382
- const update = updateSchema(column, tableName, key, primaryKeySet.has(key));
383
- if (insert !== undefined) {
384
- config.insert = insert;
385
- } else {
386
- delete config.insert;
391
+ const schema = fieldSchemaForVariant(variant, column, tableName, key, primaryKeySet);
392
+ if (schema !== undefined) {
393
+ structFields[key] = schema;
387
394
  }
388
- if (update !== undefined) {
389
- config.update = update;
390
- } else {
391
- delete config.update;
392
- }
393
- variants[key] = TableSchema.Field(config);
394
395
  }
395
- const struct = TableSchema.Struct(variants);
396
- return {
397
- select: TableSchema.extract(struct, "select"),
398
- insert: TableSchema.extract(struct, "insert"),
399
- update: TableSchema.extract(struct, "update")
400
- };
396
+ return Schema2.Struct(structFields);
401
397
  };
398
+ var deriveSelectSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("select", tableName, fields, primaryKeyColumns);
399
+ var deriveInsertSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("insert", tableName, fields, primaryKeyColumns);
400
+ var deriveUpdateSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("update", tableName, fields, primaryKeyColumns);
401
+
402
+ // src/internal/casing.ts
403
+ var TypeId5 = Symbol.for("effect-qb/Casing");
404
+ var merge = (base, override) => {
405
+ if (base === undefined) {
406
+ return override;
407
+ }
408
+ if (override === undefined) {
409
+ return base;
410
+ }
411
+ return { ...base, ...override };
412
+ };
413
+ var words = (name) => name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(/[^A-Za-z0-9]+/).filter((part) => part.length > 0);
414
+ var capitalize = (value) => value.length === 0 ? value : `${value[0].toUpperCase()}${value.slice(1)}`;
415
+ var lowerWords = (name) => words(name).map((part) => part.toLowerCase());
416
+ var applyNamedStyle = (style, name) => {
417
+ switch (style) {
418
+ case "preserve":
419
+ return name;
420
+ case "snake_case":
421
+ return lowerWords(name).join("_");
422
+ case "camelCase": {
423
+ const parts = lowerWords(name);
424
+ const [head, ...tail] = parts;
425
+ return head === undefined ? "" : `${head}${tail.map(capitalize).join("")}`;
426
+ }
427
+ case "PascalCase":
428
+ return lowerWords(name).map(capitalize).join("");
429
+ case "kebab-case":
430
+ return lowerWords(name).join("-");
431
+ case "SCREAMING_SNAKE_CASE":
432
+ return lowerWords(name).join("_").toUpperCase();
433
+ }
434
+ };
435
+ var apply = (style, name) => {
436
+ if (style === undefined) {
437
+ return name;
438
+ }
439
+ return typeof style === "function" ? style(name) : applyNamedStyle(style, name);
440
+ };
441
+ var applyCategory = (options, category, name) => apply(options?.[category], name);
402
442
 
403
443
  // src/internal/table.ts
404
- var TypeId4 = Symbol.for("effect-qb/Table");
444
+ var TypeId6 = Symbol.for("effect-qb/Table");
405
445
  var OptionsSymbol = Symbol.for("effect-qb/Table/normalizedOptions");
406
446
  var options = Symbol.for("effect-qb/Table/declaredOptions");
407
447
  var CacheSymbol = Symbol.for("effect-qb/Table/cache");
448
+ var SchemaCacheSymbol = Symbol.for("effect-qb/Table/schemaCache");
408
449
  var DeclaredOptionsSymbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions");
409
450
  var TableProto = {
410
451
  pipe() {
411
- return pipeArguments2(this, arguments);
452
+ return pipeArguments3(this, arguments);
412
453
  }
413
454
  };
414
- var attachPipe2 = (value) => {
455
+ var attachPipe3 = (value) => {
415
456
  Object.defineProperty(value, "pipe", {
416
457
  configurable: true,
417
458
  writable: true,
418
459
  value: function() {
419
- return pipeArguments2(value, arguments);
460
+ return pipeArguments3(value, arguments);
420
461
  }
421
462
  });
422
463
  return value;
423
464
  };
424
- var buildArtifacts = (name, fields, declaredOptions, schemaName) => {
465
+ var buildArtifacts = (name, fields, declaredOptions, schemaName, casing) => {
425
466
  const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions];
426
467
  validateFieldDialects(name, fields);
427
468
  validateOptions(name, fields, declaredOptions);
428
469
  const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions);
429
- const columns = Object.fromEntries(Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)]));
430
- const schemas = deriveSchemas(name, fields, primaryKey);
470
+ const columns = Object.fromEntries(Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName, casing)]));
431
471
  return {
432
472
  columns,
433
- schemas,
434
473
  normalizedOptions,
435
474
  primaryKey
436
475
  };
437
476
  };
438
- var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema", schemaName, schemaMode = "default") => {
477
+ var getSchemaCache = (table) => {
478
+ const target = table;
479
+ if (target[SchemaCacheSymbol] !== undefined) {
480
+ return target[SchemaCacheSymbol];
481
+ }
482
+ const cache = {};
483
+ Object.defineProperty(table, SchemaCacheSymbol, {
484
+ configurable: true,
485
+ value: cache
486
+ });
487
+ return cache;
488
+ };
489
+ var deriveTableSchema = (table, variant) => {
490
+ const state = table[TypeId6];
491
+ switch (variant) {
492
+ case "select":
493
+ return deriveSelectSchema(state.name, state.fields, state.primaryKey);
494
+ case "insert":
495
+ return deriveInsertSchema(state.name, state.fields, state.primaryKey);
496
+ case "update":
497
+ return deriveUpdateSchema(state.name, state.fields, state.primaryKey);
498
+ }
499
+ };
500
+ var schemaFor = (table, variant) => {
501
+ const cache = getSchemaCache(table);
502
+ const cached = cache[variant];
503
+ if (cached !== undefined) {
504
+ return cached;
505
+ }
506
+ const schema = deriveTableSchema(table, variant);
507
+ cache[variant] = schema;
508
+ return schema;
509
+ };
510
+ function selectSchema2(table) {
511
+ return schemaFor(table, "select");
512
+ }
513
+ function insertSchema2(table) {
514
+ return schemaFor(table, "insert");
515
+ }
516
+ function updateSchema2(table) {
517
+ return schemaFor(table, "update");
518
+ }
519
+ var schemasFor = (table) => {
520
+ const cache = getSchemaCache(table);
521
+ if (cache.schemas !== undefined) {
522
+ return cache.schemas;
523
+ }
524
+ const schemas = {};
525
+ Object.defineProperties(schemas, {
526
+ select: {
527
+ enumerable: true,
528
+ get: () => selectSchema2(table)
529
+ },
530
+ insert: {
531
+ enumerable: true,
532
+ get: () => insertSchema2(table)
533
+ },
534
+ update: {
535
+ enumerable: true,
536
+ get: () => updateSchema2(table)
537
+ }
538
+ });
539
+ cache.schemas = schemas;
540
+ return schemas;
541
+ };
542
+ var defineSchemasGetter = (table) => {
543
+ Object.defineProperty(table, "schemas", {
544
+ configurable: true,
545
+ enumerable: true,
546
+ get() {
547
+ return schemasFor(table);
548
+ }
549
+ });
550
+ };
551
+ var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema", schemaName, schemaMode = "default", casing) => {
439
552
  const resolvedSchemaName = schemaMode === "explicit" ? schemaName : "public";
440
- const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName);
553
+ const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName, casing);
441
554
  const dialect = resolveFieldDialect(fields);
442
- const table = attachPipe2(Object.create(TableProto));
555
+ const table = attachPipe3(Object.create(TableProto));
443
556
  table.name = name;
444
557
  table.columns = artifacts.columns;
445
- table.schemas = artifacts.schemas;
446
- table[TypeId4] = {
558
+ defineSchemasGetter(table);
559
+ table[TypeId6] = {
447
560
  name,
448
561
  baseName,
449
562
  schemaName: resolvedSchemaName,
450
563
  fields,
451
564
  primaryKey: artifacts.primaryKey,
452
- kind
565
+ kind,
566
+ casing
453
567
  };
454
568
  table[TypeId] = {
455
569
  selection: artifacts.columns,
@@ -480,22 +594,17 @@ var applyDeclaredOptions = (table, declaredOptions) => {
480
594
  }
481
595
  return declaredOptions.reduce((current, option) => option(current), table);
482
596
  };
483
- var validateClassOptions = (declaredOptions) => {
484
- for (const option of declaredOptions) {
485
- if (option.kind === "primaryKey") {
486
- throw new Error("Table.Class does not support table-level primary keys; declare primary keys inline on columns");
487
- }
488
- }
489
- };
490
597
  var resolveFieldDialect = (fields) => {
491
598
  const dialects = [...new Set(Object.values(fields).map((field) => field.metadata.dbType.dialect))];
492
599
  if (dialects.length === 0) {
493
600
  throw new Error("Cannot infer table dialect from an empty field set");
494
601
  }
495
- if (dialects.length > 1) {
602
+ const concreteDialects = dialects.filter((dialect) => dialect !== "standard");
603
+ const uniqueConcreteDialects = [...new Set(concreteDialects)];
604
+ if (uniqueConcreteDialects.length > 1) {
496
605
  throw new Error(`Mixed table dialects are not supported: ${dialects.join(", ")}`);
497
606
  }
498
- return dialects[0];
607
+ return uniqueConcreteDialects[0] ?? "standard";
499
608
  };
500
609
  var validateFieldDialects = (tableName, fields) => {
501
610
  try {
@@ -509,15 +618,13 @@ var ensureClassArtifacts = (self) => {
509
618
  if (cached) {
510
619
  return cached;
511
620
  }
512
- const state = self[TypeId4];
621
+ const state = self[TypeId6];
513
622
  const classOptions = self[options];
514
- validateClassOptions(extractDeclaredOptions(classOptions));
515
- const table = applyDeclaredOptions(makeTable(state.name, state.fields, [], state.name, "schema", state.schemaName, state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"), classOptions);
623
+ const table = applyDeclaredOptions(makeTable(state.name, state.fields, [], state.name, "schema", state.schemaName, state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit", state.casing), classOptions);
516
624
  const artifacts = {
517
625
  columns: table.columns,
518
- schemas: table.schemas,
519
626
  normalizedOptions: table[OptionsSymbol],
520
- primaryKey: table[TypeId4].primaryKey
627
+ primaryKey: table[TypeId6].primaryKey
521
628
  };
522
629
  Object.defineProperty(self, CacheSymbol, {
523
630
  configurable: true,
@@ -526,43 +633,40 @@ var ensureClassArtifacts = (self) => {
526
633
  return artifacts;
527
634
  };
528
635
  var appendOption = (table, option) => {
529
- const state = table[TypeId4];
530
- if (state.kind !== "schema") {
531
- throw new Error("Table options can only be applied to schema tables, not aliased query sources");
532
- }
533
- return makeTable(state.name, state.fields, [...table[DeclaredOptionsSymbol], option], state.baseName, state.kind, state.schemaName, "explicit");
636
+ const state = table[TypeId6];
637
+ return makeTable(state.name, state.fields, [...table[DeclaredOptionsSymbol], option], state.baseName, state.kind, state.schemaName, "explicit", state.casing);
534
638
  };
535
639
  var makeOption = (option) => {
536
- const builder = (table) => appendOption(table, option);
537
- builder.option = option;
538
- return builder;
640
+ return attachPipe3(Object.assign((table, ..._validation) => appendOption(table, option), { option }));
539
641
  };
540
642
  var option = (spec) => makeOption(spec);
541
- function make2(name, fields, schemaName) {
643
+ function make(name, fields, schemaName) {
542
644
  const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
543
645
  return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
544
646
  }
545
- var schema = (schemaName) => {
546
- const table = (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2);
547
- return {
548
- schemaName,
549
- table
550
- };
647
+ var withCasing = (table, casing) => {
648
+ const state = table[TypeId6];
649
+ return makeTable(state.name, state.fields, table[DeclaredOptionsSymbol], state.baseName, state.kind, state.schemaName, "explicit", merge(state.casing, casing));
650
+ };
651
+ var withSchema = (table, schemaName, schemaCasing) => {
652
+ const state = table[TypeId6];
653
+ return makeTable(state.name, state.fields, table[DeclaredOptionsSymbol], state.baseName, state.kind, schemaName, "explicit", merge(schemaCasing, state.casing));
551
654
  };
552
655
  var alias = (table, aliasName) => {
553
- const state = table[TypeId4];
554
- const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
555
- const aliased = attachPipe2(Object.create(TableProto));
656
+ const state = table[TypeId6];
657
+ const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName, state.casing)]));
658
+ const aliased = attachPipe3(Object.create(TableProto));
556
659
  aliased.name = aliasName;
557
660
  aliased.columns = columns;
558
- aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey);
559
- aliased[TypeId4] = {
661
+ defineSchemasGetter(aliased);
662
+ aliased[TypeId6] = {
560
663
  name: aliasName,
561
664
  baseName: state.baseName,
562
665
  schemaName: state.schemaName,
563
666
  fields: state.fields,
564
667
  primaryKey: state.primaryKey,
565
- kind: "alias"
668
+ kind: "alias",
669
+ casing: state.casing
566
670
  };
567
671
  aliased[TypeId] = {
568
672
  selection: columns,
@@ -596,11 +700,10 @@ function Class(name, schemaName) {
596
700
  return ensureClassArtifacts(this).columns;
597
701
  }
598
702
  static get schemas() {
599
- return ensureClassArtifacts(this).schemas;
703
+ return schemasFor(this);
600
704
  }
601
- static get [TypeId4]() {
705
+ static get [TypeId6]() {
602
706
  const declaredOptions = extractDeclaredOptions(this[options]);
603
- validateClassOptions(declaredOptions);
604
707
  return {
605
708
  name,
606
709
  baseName: name,
@@ -629,7 +732,7 @@ function Class(name, schemaName) {
629
732
  return ensureClassArtifacts(this).normalizedOptions;
630
733
  }
631
734
  static pipe() {
632
- return pipeArguments2(this, arguments);
735
+ return pipeArguments3(this, arguments);
633
736
  }
634
737
  }
635
738
  for (const key of Object.keys(fields)) {
@@ -660,10 +763,11 @@ var foreignKey = (columns, target, referencedColumns) => makeOption({
660
763
  kind: "foreignKey",
661
764
  columns: normalizeColumnList(columns),
662
765
  references: () => ({
663
- tableName: target()[TypeId4].baseName,
664
- schemaName: target()[TypeId4].schemaName,
766
+ tableName: target()[TypeId6].baseName,
767
+ schemaName: target()[TypeId6].schemaName,
768
+ casing: target()[TypeId6].casing,
665
769
  columns: normalizeColumnList(referencedColumns),
666
- knownColumns: Object.keys(target()[TypeId4].fields)
770
+ knownColumns: Object.keys(target()[TypeId6].fields).map((key) => key)
667
771
  })
668
772
  });
669
773
  var check = (name, predicate) => makeOption({
@@ -672,66 +776,34 @@ var check = (name, predicate) => makeOption({
672
776
  predicate
673
777
  });
674
778
 
675
- // src/internal/schema-expression.ts
676
- import { parse, toSql } from "pgsql-ast-parser";
677
- import { pipeArguments as pipeArguments3 } from "effect/Pipeable";
678
- var TypeId5 = Symbol.for("effect-qb/SchemaExpression");
679
- var SchemaExpressionProto = {
680
- pipe() {
681
- return pipeArguments3(this, arguments);
682
- }
683
- };
684
- var attachPipe3 = (value) => {
685
- Object.defineProperty(value, "pipe", {
686
- configurable: true,
687
- writable: true,
688
- value: function() {
689
- return pipeArguments3(value, arguments);
690
- }
691
- });
692
- return value;
779
+ // src/internal/sql-expression-renderer.ts
780
+ var renderQueryAst = (ast, state, dialect) => {
781
+ return dialect.renderQueryAst(ast, state, dialect);
693
782
  };
694
- var isSchemaExpression = (value) => typeof value === "object" && value !== null && (TypeId5 in value);
695
- var fromAst = (ast) => {
696
- const expression = attachPipe3(Object.create(SchemaExpressionProto));
697
- expression[TypeId5] = {
698
- ast
699
- };
700
- return expression;
783
+ var renderExpression = (expression, state, dialect) => {
784
+ return dialect.renderExpression(expression, state, dialect);
701
785
  };
702
- var fromSql = (sql) => {
703
- const expression = attachPipe3(Object.create(SchemaExpressionProto));
704
- expression[TypeId5] = {
705
- sql: sql.trim()
706
- };
707
- return expression;
786
+
787
+ // src/postgres/internal/schema-ddl.ts
788
+ import { parse as parse2, toSql as toSql2 } from "pgsql-ast-parser";
789
+
790
+ // src/internal/dialect.ts
791
+ var quoteDoubleQuotedIdentifier = (value) => {
792
+ return `"${value.replaceAll('"', '""')}"`;
708
793
  };
709
- var parseExpression = (sql) => fromAst(parse(sql, "expr"));
710
- var toAst = (expression) => {
711
- const ast = expression[TypeId5].ast;
712
- if (ast !== undefined) {
713
- return ast;
714
- }
715
- return parse(render(expression), "expr");
794
+ var quoteBacktickIdentifier = (value) => {
795
+ return `\`${value.replaceAll("`", "``")}\``;
716
796
  };
717
- var render = (expression) => expression[TypeId5].sql ?? toSql.expr(toAst(expression));
718
- var normalize = (expression) => (() => {
719
- const sql = render(expression);
720
- try {
721
- return parseExpression(sql);
722
- } catch {
723
- return fromSql(sql);
724
- }
725
- })();
797
+ var renderDbTypeName = (value) => value;
726
798
 
727
- // src/postgres/internal/sql-expression-renderer.ts
799
+ // src/internal/dialect-renderers/postgres.ts
728
800
  import * as Schema5 from "effect/Schema";
729
801
 
730
802
  // src/internal/query.ts
731
803
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
732
804
 
733
805
  // src/internal/query-ast.ts
734
- var TypeId6 = Symbol.for("effect-qb/QueryAst");
806
+ var TypeId7 = Symbol.for("effect-qb/QueryAst");
735
807
 
736
808
  // src/internal/predicate/runtime.ts
737
809
  var trueFormula = () => ({ kind: "true" });
@@ -1080,6 +1152,9 @@ var valueKeyOfLiteral = (value) => {
1080
1152
  return "null";
1081
1153
  }
1082
1154
  if (value instanceof Date) {
1155
+ if (Number.isNaN(value.getTime())) {
1156
+ throw new Error("Expected a valid Date value");
1157
+ }
1083
1158
  return `date:${value.toISOString()}`;
1084
1159
  }
1085
1160
  return "unknown";
@@ -1415,7 +1490,7 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
1415
1490
  }
1416
1491
  });
1417
1492
  plan[TypeId] = state;
1418
- plan[TypeId6] = ast;
1493
+ plan[TypeId7] = ast;
1419
1494
  plan[QueryTypeId] = {
1420
1495
  required: undefined,
1421
1496
  availableNames: undefined,
@@ -1429,7 +1504,7 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
1429
1504
  };
1430
1505
  return plan;
1431
1506
  };
1432
- var getAst = (plan) => plan[TypeId6];
1507
+ var getAst = (plan) => plan[TypeId7];
1433
1508
  var getQueryState = (plan) => plan[QueryTypeId];
1434
1509
  var extractRequiredRuntime = (selection) => {
1435
1510
  const required = new Set;
@@ -1448,22 +1523,14 @@ var extractRequiredRuntime = (selection) => {
1448
1523
  return [...required];
1449
1524
  };
1450
1525
  var extractSingleSelectedExpressionRuntime = (selection) => {
1451
- const keys = Object.keys(selection);
1452
- if (keys.length !== 1) {
1453
- throw new Error("scalar subqueries must select exactly one top-level expression");
1454
- }
1455
1526
  const record = selection;
1456
- const value = record[keys[0]];
1457
- if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
1458
- throw new Error("scalar subqueries must select a scalar expression");
1459
- }
1460
- return value;
1527
+ return record[Object.keys(record)[0]];
1461
1528
  };
1462
1529
  var currentRequiredList = (required) => Array.isArray(required) ? [...required] : required === undefined ? [] : [required];
1463
1530
 
1464
1531
  // src/internal/json/path.ts
1465
1532
  var SegmentTypeId = Symbol.for("effect-qb/JsonPathSegment");
1466
- var TypeId7 = Symbol.for("effect-qb/JsonPath");
1533
+ var TypeId8 = Symbol.for("effect-qb/JsonPath");
1467
1534
  var makeSegment = (segment) => segment;
1468
1535
  var key = (value) => makeSegment({
1469
1536
  [SegmentTypeId]: {
@@ -1500,105 +1567,23 @@ var descend = () => makeSegment({
1500
1567
  kind: "descend"
1501
1568
  });
1502
1569
  var path = (...segments) => ({
1503
- [TypeId7]: {
1570
+ [TypeId8]: {
1504
1571
  segments
1505
1572
  },
1506
1573
  segments
1507
1574
  });
1508
1575
 
1509
1576
  // src/internal/dsl-plan-runtime.ts
1510
- var renderSelectLockMode = (mode) => {
1511
- switch (mode) {
1512
- case "update":
1513
- return "for update";
1514
- case "share":
1515
- return "for share";
1516
- }
1517
- throw new Error("lock(...) mode must be update or share for select statements");
1518
- };
1519
- var renderMysqlMutationLockMode = (mode, statement) => {
1520
- switch (mode) {
1521
- case "lowPriority":
1522
- return " low_priority";
1523
- case "ignore":
1524
- return " ignore";
1525
- case "quick":
1526
- if (statement === "delete") {
1527
- return " quick";
1528
- }
1529
- break;
1577
+ var renderSelectLockMode = (mode) => mode === "update" ? "for update" : "for share";
1578
+ var renderMysqlMutationLockMode = (mode, _statement) => {
1579
+ if (mode === "lowPriority") {
1580
+ return " low_priority";
1530
1581
  }
1531
- throw new Error(statement === "update" ? "lock(...) mode must be lowPriority or ignore for update statements" : "lock(...) mode must be lowPriority, quick, or ignore for delete statements");
1582
+ return mode === "ignore" ? " ignore" : " quick";
1532
1583
  };
1533
1584
  var makeDslPlanRuntime = (ctx) => {
1534
- const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
1535
- const isRecord = (value) => typeof value === "object" && value !== null;
1536
- const isPlan = (value) => isRecord(value) && (TypeId in value);
1537
- const hasColumnRecord = (value) => isRecord(value.columns);
1538
1585
  const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
1539
- const isAliasedSource = (source) => {
1540
- if (!isRecord(source)) {
1541
- return false;
1542
- }
1543
- if (TypeId4 in source) {
1544
- return true;
1545
- }
1546
- if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
1547
- return false;
1548
- }
1549
- if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
1550
- return false;
1551
- }
1552
- if (typeof source.name !== "string" || typeof source.baseName !== "string") {
1553
- return false;
1554
- }
1555
- switch (source.kind) {
1556
- case "derived":
1557
- case "cte":
1558
- case "lateral":
1559
- return isPlan(source.plan) && hasColumnRecord(source);
1560
- case "values":
1561
- return Array.isArray(source.rows) && hasColumnRecord(source);
1562
- case "unnest":
1563
- return isRecord(source.arrays) && hasColumnRecord(source);
1564
- case "tableFunction":
1565
- return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
1566
- }
1567
- return false;
1568
- };
1569
- const assertAliasedSource = (source, message) => {
1570
- if (!isAliasedSource(source)) {
1571
- throw new Error(message);
1572
- }
1573
- };
1574
- const assertPlanComplete = (plan) => {
1575
- const required = ctx.currentRequiredList(plan[TypeId].required);
1576
- if (required.length > 0) {
1577
- throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
1578
- }
1579
- };
1580
- const assertSourceNameAvailable = (available, sourceName) => {
1581
- if (sourceName in available) {
1582
- throw new Error(`query source name is already in scope: ${sourceName}`);
1583
- }
1584
- };
1585
- const assertSelectHasBaseSourceForJoin = (statement, available) => {
1586
- if (statement === "select" && Object.keys(available).length === 0) {
1587
- throw new Error("select joins require a from(...) source before joining");
1588
- }
1589
- };
1590
- const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
1591
- const assertSetOperandStatement = (plan) => {
1592
- const statement = ctx.getQueryState(plan).statement;
1593
- if (statement !== "select" && statement !== "set") {
1594
- throw new Error("set operator operands only accept select-like query plans");
1595
- }
1596
- };
1597
1586
  const buildSetOperation = (kind, all, left, right) => {
1598
- assertSetOperandStatement(left);
1599
- assertSetOperandStatement(right);
1600
- assertPlanComplete(left);
1601
- assertPlanComplete(right);
1602
1587
  const leftState = left[TypeId];
1603
1588
  const leftAst = ctx.getAst(left);
1604
1589
  const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
@@ -1653,15 +1638,10 @@ var makeDslPlanRuntime = (ctx) => {
1653
1638
  if (currentQuery.statement === "insert") {
1654
1639
  return ctx.attachInsertSource(plan, source);
1655
1640
  }
1656
- assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
1657
- if (currentQuery.statement === "select" && currentAst.from !== undefined) {
1658
- throw new Error("select statements accept only one from(...) source; use joins for additional sources");
1659
- }
1660
1641
  const sourceLike = source;
1661
1642
  const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
1662
1643
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
1663
1644
  const sourceRequired = sourceRequiredList(sourceLike);
1664
- assertSourceNameAvailable(current.available, sourceName);
1665
1645
  if (currentQuery.statement === "select") {
1666
1646
  const nextAvailable = {
1667
1647
  [sourceName]: {
@@ -1716,7 +1696,7 @@ var makeDslPlanRuntime = (ctx) => {
1716
1696
  ]
1717
1697
  }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1718
1698
  }
1719
- throw new Error(`from(...) is not supported for ${currentQuery.statement} statements`);
1699
+ return plan;
1720
1700
  };
1721
1701
  const having = (predicate) => (plan) => {
1722
1702
  const current = plan[TypeId];
@@ -1741,16 +1721,9 @@ var makeDslPlanRuntime = (ctx) => {
1741
1721
  const current = plan[TypeId];
1742
1722
  const currentAst = ctx.getAst(plan);
1743
1723
  const currentQuery = ctx.getQueryState(plan);
1744
- if (supportsJoinSources(currentQuery.statement)) {
1745
- assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1746
- assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1747
- }
1748
1724
  const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1749
1725
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1750
1726
  const sourceRequired = sourceRequiredList(table);
1751
- if (supportsJoinSources(currentQuery.statement)) {
1752
- assertSourceNameAvailable(current.available, sourceName);
1753
- }
1754
1727
  const nextAvailable = {
1755
1728
  ...current.available,
1756
1729
  [sourceName]: {
@@ -1782,16 +1755,9 @@ var makeDslPlanRuntime = (ctx) => {
1782
1755
  const currentQuery = ctx.getQueryState(plan);
1783
1756
  const onExpression = ctx.toDialectExpression(on);
1784
1757
  const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
1785
- if (supportsJoinSources(currentQuery.statement)) {
1786
- assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
1787
- assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
1788
- }
1789
1758
  const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
1790
1759
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
1791
1760
  const sourceRequired = sourceRequiredList(table);
1792
- if (supportsJoinSources(currentQuery.statement)) {
1793
- assertSourceNameAvailable(current.available, sourceName);
1794
- }
1795
1761
  const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
1796
1762
  name: source.name,
1797
1763
  mode: "optional",
@@ -1826,9 +1792,6 @@ var makeDslPlanRuntime = (ctx) => {
1826
1792
  }, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
1827
1793
  };
1828
1794
  const orderBy = (value, direction = "asc") => (plan) => {
1829
- if (direction !== "asc" && direction !== "desc") {
1830
- throw new Error("orderBy(...) direction must be asc or desc");
1831
- }
1832
1795
  const current = plan[TypeId];
1833
1796
  const currentAst = ctx.getAst(plan);
1834
1797
  const currentQuery = ctx.getQueryState(plan);
@@ -1852,15 +1815,6 @@ var makeDslPlanRuntime = (ctx) => {
1852
1815
  const current = plan[TypeId];
1853
1816
  const currentAst = ctx.getAst(plan);
1854
1817
  const currentQuery = ctx.getQueryState(plan);
1855
- if (currentQuery.statement === "select") {
1856
- renderSelectLockMode(mode);
1857
- }
1858
- if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
1859
- renderMysqlMutationLockMode(mode, "update");
1860
- }
1861
- if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
1862
- renderMysqlMutationLockMode(mode, "delete");
1863
- }
1864
1818
  return ctx.makePlan({
1865
1819
  selection: current.selection,
1866
1820
  required: current.required,
@@ -1937,113 +1891,272 @@ var makeDslPlanRuntime = (ctx) => {
1937
1891
  };
1938
1892
  };
1939
1893
 
1940
- // src/internal/dsl-mutation-runtime.ts
1941
- var expectInsertSourceKind = (source) => {
1942
- if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
1943
- throw new Error("Unsupported insert source kind");
1944
- }
1945
- return source;
1946
- };
1947
- var expectConflictClause = (conflict) => {
1948
- if (conflict === undefined) {
1949
- return conflict;
1950
- }
1951
- if (conflict.kind !== "conflict") {
1952
- throw new Error("Unsupported conflict clause kind");
1953
- }
1954
- if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
1955
- throw new Error("Unsupported conflict action");
1956
- }
1957
- if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
1958
- throw new Error("Unsupported conflict target kind");
1894
+ // src/internal/dsl-transaction-ddl-runtime.ts
1895
+ var renderTransactionIsolationLevel = (isolationLevel) => {
1896
+ if (isolationLevel === undefined) {
1897
+ return "";
1959
1898
  }
1960
- return conflict;
1899
+ return `isolation level ${isolationLevel}`;
1961
1900
  };
1962
- var makeDslMutationRuntime = (ctx) => {
1963
- const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
1964
- const isRecord = (value) => typeof value === "object" && value !== null;
1965
- const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId in target);
1966
- const hasColumnRecord = (value) => isRecord(value.columns);
1967
- const isAliasedSource = (source) => {
1968
- if (!isRecord(source)) {
1969
- return false;
1970
- }
1971
- if (isTableTarget(source)) {
1972
- return true;
1973
- }
1974
- if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
1975
- return false;
1976
- }
1977
- if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
1978
- return false;
1979
- }
1980
- if (typeof source.name !== "string" || typeof source.baseName !== "string") {
1981
- return false;
1982
- }
1983
- switch (source.kind) {
1984
- case "derived":
1985
- case "cte":
1986
- case "lateral":
1987
- return isRecord(source.plan) && TypeId in source.plan && hasColumnRecord(source);
1988
- case "values":
1989
- return Array.isArray(source.rows) && hasColumnRecord(source);
1990
- case "unnest":
1991
- return isRecord(source.arrays) && hasColumnRecord(source);
1992
- case "tableFunction":
1993
- return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
1994
- }
1995
- return false;
1901
+ var expectDdlClauseKind = (ddl, _kind) => ddl;
1902
+ var expectTruncateClause = (truncate) => truncate;
1903
+ var normalizeStatementFlag = (value) => value ?? false;
1904
+ var normalizeStatementIdentifier = (_apiName, _identifierName, value) => value;
1905
+ var makeDslTransactionDdlRuntime = (ctx) => {
1906
+ const transaction = (options2 = {}) => {
1907
+ return ctx.makePlan({
1908
+ selection: {},
1909
+ required: [],
1910
+ available: {},
1911
+ dialect: ctx.profile.dialect
1912
+ }, {
1913
+ kind: "transaction",
1914
+ select: {},
1915
+ transaction: {
1916
+ kind: "transaction",
1917
+ isolationLevel: options2.isolationLevel,
1918
+ readOnly: options2.readOnly
1919
+ },
1920
+ where: [],
1921
+ having: [],
1922
+ joins: [],
1923
+ groupBy: [],
1924
+ orderBy: []
1925
+ }, undefined, "transaction", "transaction");
1996
1926
  };
1997
- const assertMutationTarget = (target, apiName) => {
1998
- if (!isTableTarget(target)) {
1999
- throw new Error(`${apiName}(...) requires table targets`);
2000
- }
1927
+ const commit = () => ctx.makePlan({
1928
+ selection: {},
1929
+ required: [],
1930
+ available: {},
1931
+ dialect: ctx.profile.dialect
1932
+ }, {
1933
+ kind: "commit",
1934
+ select: {},
1935
+ transaction: {
1936
+ kind: "commit"
1937
+ },
1938
+ where: [],
1939
+ having: [],
1940
+ joins: [],
1941
+ groupBy: [],
1942
+ orderBy: []
1943
+ }, undefined, "transaction", "commit");
1944
+ const rollback = () => ctx.makePlan({
1945
+ selection: {},
1946
+ required: [],
1947
+ available: {},
1948
+ dialect: ctx.profile.dialect
1949
+ }, {
1950
+ kind: "rollback",
1951
+ select: {},
1952
+ transaction: {
1953
+ kind: "rollback"
1954
+ },
1955
+ where: [],
1956
+ having: [],
1957
+ joins: [],
1958
+ groupBy: [],
1959
+ orderBy: []
1960
+ }, undefined, "transaction", "rollback");
1961
+ const savepoint = (name) => {
1962
+ return ctx.makePlan({
1963
+ selection: {},
1964
+ required: [],
1965
+ available: {},
1966
+ dialect: ctx.profile.dialect
1967
+ }, {
1968
+ kind: "savepoint",
1969
+ select: {},
1970
+ transaction: {
1971
+ kind: "savepoint",
1972
+ name
1973
+ },
1974
+ where: [],
1975
+ having: [],
1976
+ joins: [],
1977
+ groupBy: [],
1978
+ orderBy: []
1979
+ }, undefined, "transaction", "savepoint");
2001
1980
  };
2002
- const assertAliasedSource = (source, apiName) => {
2003
- if (!isAliasedSource(source)) {
2004
- throw new Error(`${apiName}(...) requires an aliased source`);
2005
- }
1981
+ const rollbackTo = (name) => {
1982
+ return ctx.makePlan({
1983
+ selection: {},
1984
+ required: [],
1985
+ available: {},
1986
+ dialect: ctx.profile.dialect
1987
+ }, {
1988
+ kind: "rollbackTo",
1989
+ select: {},
1990
+ transaction: {
1991
+ kind: "rollbackTo",
1992
+ name
1993
+ },
1994
+ where: [],
1995
+ having: [],
1996
+ joins: [],
1997
+ groupBy: [],
1998
+ orderBy: []
1999
+ }, undefined, "transaction", "rollbackTo");
2006
2000
  };
2007
- const assertMutationTargets = (target, apiName, options2 = {}) => {
2008
- const targets = Array.isArray(target) ? target : [target];
2009
- if (targets.length === 0) {
2010
- throw new Error(`${apiName}(...) requires at least one table target`);
2011
- }
2012
- if (Array.isArray(target) && targets.length === 1) {
2013
- throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
2014
- }
2015
- for (const entry of targets) {
2016
- assertMutationTarget(entry, apiName);
2017
- }
2018
- if (targets.length > 1 && options2.allowMultiple !== true) {
2019
- throw new Error(`${apiName}(...) requires a single table target`);
2020
- }
2021
- if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
2022
- throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
2023
- }
2001
+ const releaseSavepoint = (name) => {
2002
+ return ctx.makePlan({
2003
+ selection: {},
2004
+ required: [],
2005
+ available: {},
2006
+ dialect: ctx.profile.dialect
2007
+ }, {
2008
+ kind: "releaseSavepoint",
2009
+ select: {},
2010
+ transaction: {
2011
+ kind: "releaseSavepoint",
2012
+ name
2013
+ },
2014
+ where: [],
2015
+ having: [],
2016
+ joins: [],
2017
+ groupBy: [],
2018
+ orderBy: []
2019
+ }, undefined, "transaction", "releaseSavepoint");
2024
2020
  };
2025
- const assertUniqueTargetNames = (targets) => {
2026
- const seen = new Set;
2027
- for (const target of targets) {
2028
- if (seen.has(target.tableName)) {
2029
- throw new Error(`mutation target source names must be unique: ${target.tableName}`);
2030
- }
2031
- seen.add(target.tableName);
2032
- }
2021
+ const createTable = (target, options2 = {}) => {
2022
+ const ifNotExists = normalizeStatementFlag(options2.ifNotExists);
2023
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2024
+ return ctx.makePlan({
2025
+ selection: {},
2026
+ required: [],
2027
+ available: {},
2028
+ dialect: target[TypeId].dialect
2029
+ }, {
2030
+ kind: "createTable",
2031
+ select: {},
2032
+ target: {
2033
+ kind: "from",
2034
+ tableName: sourceName,
2035
+ baseTableName: sourceBaseName,
2036
+ source: target
2037
+ },
2038
+ ddl: {
2039
+ kind: "createTable",
2040
+ ifNotExists
2041
+ },
2042
+ where: [],
2043
+ having: [],
2044
+ joins: [],
2045
+ groupBy: [],
2046
+ orderBy: []
2047
+ }, undefined, "ddl", "createTable");
2033
2048
  };
2034
- const assertInsertSelectSource = (sourcePlan, selection) => {
2035
- const statement = ctx.getQueryState(sourcePlan).statement;
2036
- if (statement !== "select" && statement !== "set") {
2037
- throw new Error("insert sources only accept select-like query plans");
2038
- }
2039
- for (const value of Object.values(selection)) {
2040
- if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
2041
- throw new Error("insert sources require a flat selection object");
2042
- }
2043
- }
2049
+ const dropTable = (target, options2 = {}) => {
2050
+ const ifExists = normalizeStatementFlag(options2.ifExists);
2051
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2052
+ return ctx.makePlan({
2053
+ selection: {},
2054
+ required: [],
2055
+ available: {},
2056
+ dialect: target[TypeId].dialect
2057
+ }, {
2058
+ kind: "dropTable",
2059
+ select: {},
2060
+ target: {
2061
+ kind: "from",
2062
+ tableName: sourceName,
2063
+ baseTableName: sourceBaseName,
2064
+ source: target
2065
+ },
2066
+ ddl: {
2067
+ kind: "dropTable",
2068
+ ifExists
2069
+ },
2070
+ where: [],
2071
+ having: [],
2072
+ joins: [],
2073
+ groupBy: [],
2074
+ orderBy: []
2075
+ }, undefined, "ddl", "dropTable");
2076
+ };
2077
+ const createIndex = (target, columns, options2 = {}) => {
2078
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2079
+ const unique2 = normalizeStatementFlag(options2.unique);
2080
+ const ifNotExists = normalizeStatementFlag(options2.ifNotExists);
2081
+ const name = options2.name;
2082
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2083
+ return ctx.makePlan({
2084
+ selection: {},
2085
+ required: [],
2086
+ available: {},
2087
+ dialect: target[TypeId].dialect
2088
+ }, {
2089
+ kind: "createIndex",
2090
+ select: {},
2091
+ target: {
2092
+ kind: "from",
2093
+ tableName: sourceName,
2094
+ baseTableName: sourceBaseName,
2095
+ source: target
2096
+ },
2097
+ ddl: {
2098
+ kind: "createIndex",
2099
+ name: name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, unique2),
2100
+ columns: normalizedColumns,
2101
+ unique: unique2,
2102
+ ifNotExists
2103
+ },
2104
+ where: [],
2105
+ having: [],
2106
+ joins: [],
2107
+ groupBy: [],
2108
+ orderBy: []
2109
+ }, undefined, "ddl", "createIndex");
2110
+ };
2111
+ const dropIndex = (target, columns, options2 = {}) => {
2112
+ const normalizedColumns = ctx.normalizeColumnList(columns);
2113
+ const ifExists = normalizeStatementFlag(options2.ifExists);
2114
+ const name = options2.name;
2115
+ const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2116
+ return ctx.makePlan({
2117
+ selection: {},
2118
+ required: [],
2119
+ available: {},
2120
+ dialect: target[TypeId].dialect
2121
+ }, {
2122
+ kind: "dropIndex",
2123
+ select: {},
2124
+ target: {
2125
+ kind: "from",
2126
+ tableName: sourceName,
2127
+ baseTableName: sourceBaseName,
2128
+ source: target
2129
+ },
2130
+ ddl: {
2131
+ kind: "dropIndex",
2132
+ name: name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
2133
+ ifExists
2134
+ },
2135
+ where: [],
2136
+ having: [],
2137
+ joins: [],
2138
+ groupBy: [],
2139
+ orderBy: []
2140
+ }, undefined, "ddl", "dropIndex");
2141
+ };
2142
+ return {
2143
+ transaction,
2144
+ commit,
2145
+ rollback,
2146
+ savepoint,
2147
+ rollbackTo,
2148
+ releaseSavepoint,
2149
+ createTable,
2150
+ dropTable,
2151
+ createIndex,
2152
+ dropIndex
2044
2153
  };
2154
+ };
2155
+
2156
+ // src/internal/dsl-mutation-runtime.ts
2157
+ var expectConflictClause = (conflict) => conflict;
2158
+ var makeDslMutationRuntime = (ctx) => {
2045
2159
  const insert = (target, values) => {
2046
- assertMutationTargets(target, "insert");
2047
2160
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2048
2161
  const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
2049
2162
  const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies));
@@ -2119,7 +2232,6 @@ var makeDslMutationRuntime = (ctx) => {
2119
2232
  }
2120
2233
  const sourcePlan = source;
2121
2234
  const selection = sourcePlan[TypeId].selection;
2122
- assertInsertSelectSource(sourcePlan, selection);
2123
2235
  const columns = ctx.normalizeInsertSelectColumns(selection);
2124
2236
  return ctx.makePlan({
2125
2237
  selection: current.selection,
@@ -2140,15 +2252,13 @@ var makeDslMutationRuntime = (ctx) => {
2140
2252
  const current = plan[TypeId];
2141
2253
  const currentAst = ctx.getAst(plan);
2142
2254
  const currentQuery = ctx.getQueryState(plan);
2143
- if (currentQuery.statement !== "insert") {
2144
- throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
2145
- }
2146
2255
  const insertTarget = currentAst.into.source;
2147
- const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
2256
+ const conflictTarget = expectConflictClause({
2257
+ kind: "conflict",
2258
+ action: "doNothing",
2259
+ target: ctx.buildConflictTarget(insertTarget, target)
2260
+ }).target;
2148
2261
  const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
2149
- if (options2.update !== undefined && updateAssignments.length === 0) {
2150
- throw new Error("conflict update assignments require at least one assignment");
2151
- }
2152
2262
  const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
2153
2263
  const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
2154
2264
  const required = [
@@ -2174,9 +2284,7 @@ var makeDslMutationRuntime = (ctx) => {
2174
2284
  }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
2175
2285
  };
2176
2286
  const update = (target, values) => {
2177
- assertMutationTargets(target, "update", { allowMultiple: true });
2178
2287
  const targets = ctx.mutationTargetClauses(target);
2179
- assertUniqueTargetNames(targets);
2180
2288
  const primaryTarget = targets[0];
2181
2289
  const assignments = ctx.buildMutationAssignments(target, values);
2182
2290
  const targetNames = new Set(targets.map((entry) => entry.tableName));
@@ -2200,13 +2308,9 @@ var makeDslMutationRuntime = (ctx) => {
2200
2308
  }, undefined, "write", "update");
2201
2309
  };
2202
2310
  const upsert = (target, values, conflictColumns, updateValues) => {
2203
- assertMutationTargets(target, "upsert");
2204
2311
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2205
2312
  const assignments = ctx.buildMutationAssignments(target, values);
2206
2313
  const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
2207
- if (updateValues !== undefined && updateAssignments.length === 0) {
2208
- throw new Error("upsert update assignments require at least one assignment");
2209
- }
2210
2314
  const required = [
2211
2315
  ...assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
2212
2316
  ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies))
@@ -2249,9 +2353,7 @@ var makeDslMutationRuntime = (ctx) => {
2249
2353
  }, undefined, "write", "insert", target, "ready");
2250
2354
  };
2251
2355
  const delete_ = (target) => {
2252
- assertMutationTargets(target, "delete", { allowMultiple: true });
2253
2356
  const targets = ctx.mutationTargetClauses(target);
2254
- assertUniqueTargetNames(targets);
2255
2357
  const primaryTarget = targets[0];
2256
2358
  return ctx.makePlan({
2257
2359
  selection: {},
@@ -2271,7 +2373,8 @@ var makeDslMutationRuntime = (ctx) => {
2271
2373
  }, undefined, "write", "delete");
2272
2374
  };
2273
2375
  const truncate = (target, options2 = {}) => {
2274
- assertMutationTargets(target, "truncate");
2376
+ const restartIdentity = normalizeStatementFlag(options2.restartIdentity);
2377
+ const cascade = normalizeStatementFlag(options2.cascade);
2275
2378
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2276
2379
  return ctx.makePlan({
2277
2380
  selection: {},
@@ -2289,8 +2392,8 @@ var makeDslMutationRuntime = (ctx) => {
2289
2392
  },
2290
2393
  truncate: {
2291
2394
  kind: "truncate",
2292
- restartIdentity: options2.restartIdentity ?? false,
2293
- cascade: options2.cascade ?? false
2395
+ restartIdentity,
2396
+ cascade
2294
2397
  },
2295
2398
  where: [],
2296
2399
  having: [],
@@ -2299,20 +2402,12 @@ var makeDslMutationRuntime = (ctx) => {
2299
2402
  orderBy: []
2300
2403
  }, undefined, "write", "truncate");
2301
2404
  };
2302
- const merge = (target, source, on, options2 = {}) => {
2303
- assertMutationTargets(target, "merge");
2304
- assertAliasedSource(source, "merge");
2405
+ const merge2 = (target, source, on, options2 = {}) => {
2305
2406
  const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
2306
2407
  const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
2307
- if (targetName === usingName) {
2308
- throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
2309
- }
2310
2408
  const onExpression = ctx.toDialectExpression(on);
2311
2409
  const matched = options2.whenMatched;
2312
2410
  const notMatched = options2.whenNotMatched;
2313
- if (matched && "delete" in matched && "update" in matched) {
2314
- throw new Error("merge whenMatched cannot specify both update and delete");
2315
- }
2316
2411
  const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined;
2317
2412
  const matchedAssignments = matched && "update" in matched && matched.update ? ctx.buildMutationAssignments(target, matched.update) : [];
2318
2413
  const notMatchedPredicate = notMatched?.predicate ? ctx.toDialectExpression(notMatched.predicate) : undefined;
@@ -2377,305 +2472,17 @@ var makeDslMutationRuntime = (ctx) => {
2377
2472
  joins: [],
2378
2473
  groupBy: [],
2379
2474
  orderBy: []
2380
- }, undefined, "write", "merge");
2381
- };
2382
- return {
2383
- insert,
2384
- attachInsertSource,
2385
- onConflict,
2386
- update,
2387
- upsert,
2388
- delete_,
2389
- truncate,
2390
- merge
2391
- };
2392
- };
2393
-
2394
- // src/internal/dsl-transaction-ddl-runtime.ts
2395
- var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
2396
- var renderTransactionIsolationLevel = (isolationLevel) => {
2397
- if (isolationLevel === undefined) {
2398
- return "";
2399
- }
2400
- if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
2401
- throw new Error("Unsupported transaction isolation level");
2402
- }
2403
- return `isolation level ${isolationLevel}`;
2404
- };
2405
- var expectDdlClauseKind = (ddl, kind) => {
2406
- if (ddl === undefined || ddl.kind !== kind) {
2407
- throw new Error("Unsupported DDL statement kind");
2408
- }
2409
- return ddl;
2410
- };
2411
- var expectTruncateClause = (truncate) => {
2412
- if (truncate === undefined || truncate.kind !== "truncate") {
2413
- throw new Error("Unsupported truncate statement kind");
2414
- }
2415
- return truncate;
2416
- };
2417
- var validateIsolationLevel = (isolationLevel) => {
2418
- renderTransactionIsolationLevel(isolationLevel);
2419
- };
2420
- var makeDslTransactionDdlRuntime = (ctx) => {
2421
- const isRecord = (value) => typeof value === "object" && value !== null;
2422
- const assertTableTarget = (target, apiName) => {
2423
- if (!isRecord(target) || !(TypeId4 in target) || !(TypeId in target)) {
2424
- throw new Error(`${apiName}(...) requires a table target`);
2425
- }
2426
- };
2427
- const validateIndexColumns = (target, columns) => {
2428
- const fields = target[TypeId4]?.fields;
2429
- if (fields === undefined) {
2430
- return;
2431
- }
2432
- for (const columnName of columns) {
2433
- if (!(columnName in fields)) {
2434
- throw new Error(`effect-qb: unknown index column '${columnName}'`);
2435
- }
2436
- }
2437
- };
2438
- const transaction = (options2 = {}) => {
2439
- validateIsolationLevel(options2.isolationLevel);
2440
- return ctx.makePlan({
2441
- selection: {},
2442
- required: [],
2443
- available: {},
2444
- dialect: ctx.profile.dialect
2445
- }, {
2446
- kind: "transaction",
2447
- select: {},
2448
- transaction: {
2449
- kind: "transaction",
2450
- isolationLevel: options2.isolationLevel,
2451
- readOnly: options2.readOnly
2452
- },
2453
- where: [],
2454
- having: [],
2455
- joins: [],
2456
- groupBy: [],
2457
- orderBy: []
2458
- }, undefined, "transaction", "transaction");
2459
- };
2460
- const commit = () => ctx.makePlan({
2461
- selection: {},
2462
- required: [],
2463
- available: {},
2464
- dialect: ctx.profile.dialect
2465
- }, {
2466
- kind: "commit",
2467
- select: {},
2468
- transaction: {
2469
- kind: "commit"
2470
- },
2471
- where: [],
2472
- having: [],
2473
- joins: [],
2474
- groupBy: [],
2475
- orderBy: []
2476
- }, undefined, "transaction", "commit");
2477
- const rollback = () => ctx.makePlan({
2478
- selection: {},
2479
- required: [],
2480
- available: {},
2481
- dialect: ctx.profile.dialect
2482
- }, {
2483
- kind: "rollback",
2484
- select: {},
2485
- transaction: {
2486
- kind: "rollback"
2487
- },
2488
- where: [],
2489
- having: [],
2490
- joins: [],
2491
- groupBy: [],
2492
- orderBy: []
2493
- }, undefined, "transaction", "rollback");
2494
- const savepoint = (name) => ctx.makePlan({
2495
- selection: {},
2496
- required: [],
2497
- available: {},
2498
- dialect: ctx.profile.dialect
2499
- }, {
2500
- kind: "savepoint",
2501
- select: {},
2502
- transaction: {
2503
- kind: "savepoint",
2504
- name
2505
- },
2506
- where: [],
2507
- having: [],
2508
- joins: [],
2509
- groupBy: [],
2510
- orderBy: []
2511
- }, undefined, "transaction", "savepoint");
2512
- const rollbackTo = (name) => ctx.makePlan({
2513
- selection: {},
2514
- required: [],
2515
- available: {},
2516
- dialect: ctx.profile.dialect
2517
- }, {
2518
- kind: "rollbackTo",
2519
- select: {},
2520
- transaction: {
2521
- kind: "rollbackTo",
2522
- name
2523
- },
2524
- where: [],
2525
- having: [],
2526
- joins: [],
2527
- groupBy: [],
2528
- orderBy: []
2529
- }, undefined, "transaction", "rollbackTo");
2530
- const releaseSavepoint = (name) => ctx.makePlan({
2531
- selection: {},
2532
- required: [],
2533
- available: {},
2534
- dialect: ctx.profile.dialect
2535
- }, {
2536
- kind: "releaseSavepoint",
2537
- select: {},
2538
- transaction: {
2539
- kind: "releaseSavepoint",
2540
- name
2541
- },
2542
- where: [],
2543
- having: [],
2544
- joins: [],
2545
- groupBy: [],
2546
- orderBy: []
2547
- }, undefined, "transaction", "releaseSavepoint");
2548
- const createTable = (target, options2 = {}) => {
2549
- assertTableTarget(target, "createTable");
2550
- const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2551
- return ctx.makePlan({
2552
- selection: {},
2553
- required: [],
2554
- available: {},
2555
- dialect: target[TypeId].dialect
2556
- }, {
2557
- kind: "createTable",
2558
- select: {},
2559
- target: {
2560
- kind: "from",
2561
- tableName: sourceName,
2562
- baseTableName: sourceBaseName,
2563
- source: target
2564
- },
2565
- ddl: {
2566
- kind: "createTable",
2567
- ifNotExists: options2.ifNotExists ?? false
2568
- },
2569
- where: [],
2570
- having: [],
2571
- joins: [],
2572
- groupBy: [],
2573
- orderBy: []
2574
- }, undefined, "ddl", "createTable");
2575
- };
2576
- const dropTable = (target, options2 = {}) => {
2577
- assertTableTarget(target, "dropTable");
2578
- const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2579
- return ctx.makePlan({
2580
- selection: {},
2581
- required: [],
2582
- available: {},
2583
- dialect: target[TypeId].dialect
2584
- }, {
2585
- kind: "dropTable",
2586
- select: {},
2587
- target: {
2588
- kind: "from",
2589
- tableName: sourceName,
2590
- baseTableName: sourceBaseName,
2591
- source: target
2592
- },
2593
- ddl: {
2594
- kind: "dropTable",
2595
- ifExists: options2.ifExists ?? false
2596
- },
2597
- where: [],
2598
- having: [],
2599
- joins: [],
2600
- groupBy: [],
2601
- orderBy: []
2602
- }, undefined, "ddl", "dropTable");
2603
- };
2604
- const createIndex = (target, columns, options2 = {}) => {
2605
- assertTableTarget(target, "createIndex");
2606
- const normalizedColumns = ctx.normalizeColumnList(columns);
2607
- validateIndexColumns(target, normalizedColumns);
2608
- const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2609
- return ctx.makePlan({
2610
- selection: {},
2611
- required: [],
2612
- available: {},
2613
- dialect: target[TypeId].dialect
2614
- }, {
2615
- kind: "createIndex",
2616
- select: {},
2617
- target: {
2618
- kind: "from",
2619
- tableName: sourceName,
2620
- baseTableName: sourceBaseName,
2621
- source: target
2622
- },
2623
- ddl: {
2624
- kind: "createIndex",
2625
- name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options2.unique ?? false),
2626
- columns: normalizedColumns,
2627
- unique: options2.unique ?? false,
2628
- ifNotExists: options2.ifNotExists ?? false
2629
- },
2630
- where: [],
2631
- having: [],
2632
- joins: [],
2633
- groupBy: [],
2634
- orderBy: []
2635
- }, undefined, "ddl", "createIndex");
2636
- };
2637
- const dropIndex = (target, columns, options2 = {}) => {
2638
- assertTableTarget(target, "dropIndex");
2639
- const normalizedColumns = ctx.normalizeColumnList(columns);
2640
- validateIndexColumns(target, normalizedColumns);
2641
- const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
2642
- return ctx.makePlan({
2643
- selection: {},
2644
- required: [],
2645
- available: {},
2646
- dialect: target[TypeId].dialect
2647
- }, {
2648
- kind: "dropIndex",
2649
- select: {},
2650
- target: {
2651
- kind: "from",
2652
- tableName: sourceName,
2653
- baseTableName: sourceBaseName,
2654
- source: target
2655
- },
2656
- ddl: {
2657
- kind: "dropIndex",
2658
- name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
2659
- ifExists: options2.ifExists ?? false
2660
- },
2661
- where: [],
2662
- having: [],
2663
- joins: [],
2664
- groupBy: [],
2665
- orderBy: []
2666
- }, undefined, "ddl", "dropIndex");
2667
- };
2668
- return {
2669
- transaction,
2670
- commit,
2671
- rollback,
2672
- savepoint,
2673
- rollbackTo,
2674
- releaseSavepoint,
2675
- createTable,
2676
- dropTable,
2677
- createIndex,
2678
- dropIndex
2475
+ }, undefined, "write", "merge");
2476
+ };
2477
+ return {
2478
+ insert,
2479
+ attachInsertSource,
2480
+ onConflict,
2481
+ update,
2482
+ upsert,
2483
+ delete_,
2484
+ truncate,
2485
+ merge: merge2
2679
2486
  };
2680
2487
  };
2681
2488
 
@@ -2799,6 +2606,12 @@ var isPlainRecord = (value) => {
2799
2606
  return prototype === Object.prototype || prototype === null;
2800
2607
  };
2801
2608
  var pad = (value, width = 2) => value.toString().padStart(width, "0");
2609
+ var validDate = (value) => {
2610
+ if (Number.isNaN(value.getTime())) {
2611
+ throw new Error("Expected a valid Date value");
2612
+ }
2613
+ return value;
2614
+ };
2802
2615
  var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
2803
2616
  var formatLocalTime = (value) => {
2804
2617
  const milliseconds = value.getUTCMilliseconds();
@@ -2886,7 +2699,7 @@ var normalizeDecimalString = (value) => {
2886
2699
  };
2887
2700
  var normalizeLocalDate = (value) => {
2888
2701
  if (value instanceof Date) {
2889
- return formatLocalDate(value);
2702
+ return formatLocalDate(validDate(value));
2890
2703
  }
2891
2704
  const raw = expectString(value, "local date").trim();
2892
2705
  if (isValidLocalDateString(raw)) {
@@ -2903,7 +2716,7 @@ var normalizeLocalDate = (value) => {
2903
2716
  };
2904
2717
  var normalizeLocalTime = (value) => {
2905
2718
  if (value instanceof Date) {
2906
- return formatLocalTime(value);
2719
+ return formatLocalTime(validDate(value));
2907
2720
  }
2908
2721
  const raw = expectString(value, "local time").trim();
2909
2722
  if (isValidLocalTimeString(raw)) {
@@ -2913,7 +2726,7 @@ var normalizeLocalTime = (value) => {
2913
2726
  };
2914
2727
  var normalizeOffsetTime = (value) => {
2915
2728
  if (value instanceof Date) {
2916
- return `${formatLocalTime(value)}Z`;
2729
+ return `${formatLocalTime(validDate(value))}Z`;
2917
2730
  }
2918
2731
  const raw = expectString(value, "offset time").trim();
2919
2732
  if (isValidOffsetTimeString(raw)) {
@@ -2923,7 +2736,7 @@ var normalizeOffsetTime = (value) => {
2923
2736
  };
2924
2737
  var normalizeLocalDateTime = (value) => {
2925
2738
  if (value instanceof Date) {
2926
- return formatLocalDateTime(value);
2739
+ return formatLocalDateTime(validDate(value));
2927
2740
  }
2928
2741
  const raw = expectString(value, "local datetime").trim();
2929
2742
  const canonicalLocalDateTime = raw.replace(" ", "T");
@@ -2941,7 +2754,7 @@ var normalizeLocalDateTime = (value) => {
2941
2754
  };
2942
2755
  var normalizeInstant = (value) => {
2943
2756
  if (value instanceof Date) {
2944
- return value.toISOString();
2757
+ return validDate(value).toISOString();
2945
2758
  }
2946
2759
  const raw = expectString(value, "instant").trim();
2947
2760
  if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
@@ -3157,16 +2970,16 @@ var isJsonDbType = (dbType) => {
3157
2970
  const variant = dbType.variant;
3158
2971
  return variant === "json" || variant === "jsonb";
3159
2972
  };
3160
- var schemaAccepts = (schema2, value) => schema2 !== undefined && Schema4.is(schema2)(value);
3161
- var encodeWithSchema = (schema2, value) => {
3162
- if (schema2 === undefined) {
2973
+ var schemaAccepts = (schema, value) => schema !== undefined && Schema4.is(schema)(value);
2974
+ var encodeWithSchema = (schema, value) => {
2975
+ if (schema === undefined) {
3163
2976
  return { value, encoded: false };
3164
2977
  }
3165
- if (!Schema4.is(schema2)(value)) {
2978
+ if (!Schema4.is(schema)(value)) {
3166
2979
  return { value, encoded: false };
3167
2980
  }
3168
2981
  return {
3169
- value: Schema4.encodeUnknownSync(schema2)(value),
2982
+ value: Schema4.encodeUnknownSync(schema)(value),
3170
2983
  encoded: true
3171
2984
  };
3172
2985
  };
@@ -3262,12 +3075,12 @@ var renderJsonSelectSql = (sql, context) => {
3262
3075
  };
3263
3076
 
3264
3077
  // src/internal/projection-alias.ts
3265
- var TypeId8 = Symbol.for("effect-qb/ProjectionAlias");
3078
+ var TypeId9 = Symbol.for("effect-qb/ProjectionAlias");
3266
3079
 
3267
3080
  // src/internal/projections.ts
3268
3081
  var aliasFromPath = (path2) => path2.join("__");
3269
3082
  var isExpression = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
3270
- var projectionAliasOf = (expression) => (TypeId8 in expression) ? expression[TypeId8].alias : undefined;
3083
+ var projectionAliasOf = (expression) => (TypeId9 in expression) ? expression[TypeId9].alias : undefined;
3271
3084
  var pathKeyOf = (path2) => JSON.stringify(path2);
3272
3085
  var formatProjectionPath = (path2) => path2.join(".");
3273
3086
  var isPrefixPath = (left, right) => left.length < right.length && left.every((segment, index3) => segment === right[index3]);
@@ -3329,7 +3142,7 @@ var subqueryPlanGroupingKey = (plan) => {
3329
3142
  };
3330
3143
  var literalGroupingKey = (value) => {
3331
3144
  if (value instanceof Date) {
3332
- return `date:${value.toISOString()}`;
3145
+ return Number.isNaN(value.getTime()) ? "date:invalid" : `date:${value.toISOString()}`;
3333
3146
  }
3334
3147
  if (value === null) {
3335
3148
  return "null";
@@ -3347,7 +3160,27 @@ var literalGroupingKey = (value) => {
3347
3160
  };
3348
3161
  var isExpression2 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3349
3162
  var expressionGroupingKey = (value) => isExpression2(value) ? groupingKeyOfExpression(value) : "missing";
3163
+ var requiredExpressionGroupingKey = (_functionName, value) => groupingKeyOfExpression(value);
3164
+ var requiredBinaryExpressionGroupingKey = (_functionName, left, right) => `${groupingKeyOfExpression(left)},${groupingKeyOfExpression(right)}`;
3165
+ var functionCallArgsGroupingKey = (args) => args.map(groupingKeyOfExpression).join(",");
3166
+ var variadicGroupingKey = (_functionName, values) => values.map(groupingKeyOfExpression).join(",");
3167
+ var castTargetGroupingKey = (target) => {
3168
+ const typed = target;
3169
+ return `${typed?.dialect}:${typed?.kind}`;
3170
+ };
3350
3171
  var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
3172
+ var functionCallNameGroupingKey = (name) => escapeGroupingText(name);
3173
+ var quantifiedComparisonGroupingName = (kind) => kind === "comparisonAny" ? "compareAny" : "compareAll";
3174
+ var caseGroupingKey = (branches, fallback) => {
3175
+ const typedBranches = branches;
3176
+ return `case(${typedBranches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(fallback)})`;
3177
+ };
3178
+ var collationGroupingKey = (collation) => {
3179
+ if (Array.isArray(collation)) {
3180
+ return collation.map((part) => escapeGroupingText(String(part))).join(",");
3181
+ }
3182
+ return escapeGroupingText(String(collation));
3183
+ };
3351
3184
  var jsonSegmentGroupingKey = (segment) => {
3352
3185
  if (segment !== null && typeof segment === "object" && "kind" in segment) {
3353
3186
  switch (segment.kind) {
@@ -3373,8 +3206,16 @@ var jsonSegmentGroupingKey = (segment) => {
3373
3206
  }
3374
3207
  return "unknown";
3375
3208
  };
3376
- var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
3377
- var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
3209
+ var jsonPathGroupingKey = (segments) => {
3210
+ if (segments === undefined) {
3211
+ return "";
3212
+ }
3213
+ if (!Array.isArray(segments)) {
3214
+ return "unknown";
3215
+ }
3216
+ return segments.map(jsonSegmentGroupingKey).join(",");
3217
+ };
3218
+ var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId8 in value);
3378
3219
  var jsonOpaquePathGroupingKey = (value) => {
3379
3220
  if (isJsonPath(value)) {
3380
3221
  return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
@@ -3387,7 +3228,16 @@ var jsonOpaquePathGroupingKey = (value) => {
3387
3228
  }
3388
3229
  return "jsonpath:unknown";
3389
3230
  };
3390
- var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
3231
+ var jsonKeysGroupingKey = (keys) => {
3232
+ if (!Array.isArray(keys) || keys.length === 0) {
3233
+ return "";
3234
+ }
3235
+ return keys.map((key2) => escapeGroupingText(String(key2))).join(",");
3236
+ };
3237
+ var jsonBuildObjectGroupingKey = (entries) => {
3238
+ return entries.map((entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`).join("|");
3239
+ };
3240
+ var jsonBuildArrayGroupingKey = (values) => values.map(groupingKeyOfExpression).join(",");
3391
3241
  var groupingKeyOfExpression = (expression) => {
3392
3242
  const ast = expression[TypeId3];
3393
3243
  switch (ast.kind) {
@@ -3396,11 +3246,11 @@ var groupingKeyOfExpression = (expression) => {
3396
3246
  case "literal":
3397
3247
  return `literal:${literalGroupingKey(ast.value)}`;
3398
3248
  case "cast":
3399
- return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
3249
+ return `cast(${requiredExpressionGroupingKey("cast", ast.value)} as ${castTargetGroupingKey(ast.target)})`;
3400
3250
  case "collate":
3401
- return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
3251
+ return `collate(${requiredExpressionGroupingKey("collate", ast.value)},${collationGroupingKey(ast.collation)})`;
3402
3252
  case "function":
3403
- return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
3253
+ return `function(${functionCallNameGroupingKey(ast.name)},${functionCallArgsGroupingKey(ast.args)})`;
3404
3254
  case "isNull":
3405
3255
  case "isNotNull":
3406
3256
  case "not":
@@ -3409,7 +3259,7 @@ var groupingKeyOfExpression = (expression) => {
3409
3259
  case "count":
3410
3260
  case "max":
3411
3261
  case "min":
3412
- return `${ast.kind}(${groupingKeyOfExpression(ast.value)})`;
3262
+ return `${ast.kind}(${requiredExpressionGroupingKey(ast.kind, ast.value)})`;
3413
3263
  case "eq":
3414
3264
  case "neq":
3415
3265
  case "lt":
@@ -3427,7 +3277,7 @@ var groupingKeyOfExpression = (expression) => {
3427
3277
  case "contains":
3428
3278
  case "containedBy":
3429
3279
  case "overlaps":
3430
- return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
3280
+ return `${ast.kind}(${requiredBinaryExpressionGroupingKey(ast.kind, ast.left, ast.right)})`;
3431
3281
  case "and":
3432
3282
  case "or":
3433
3283
  case "coalesce":
@@ -3435,18 +3285,18 @@ var groupingKeyOfExpression = (expression) => {
3435
3285
  case "in":
3436
3286
  case "notIn":
3437
3287
  case "between":
3438
- return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
3288
+ return `${ast.kind}(${variadicGroupingKey(ast.kind, ast.values)})`;
3439
3289
  case "case":
3440
- return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
3290
+ return caseGroupingKey(ast.branches, ast.else);
3441
3291
  case "exists":
3442
3292
  return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
3443
3293
  case "scalarSubquery":
3444
3294
  return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
3445
3295
  case "inSubquery":
3446
- return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3296
+ return `inSubquery(${requiredExpressionGroupingKey("inSubquery", ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3447
3297
  case "comparisonAny":
3448
3298
  case "comparisonAll":
3449
- return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3299
+ return `${ast.kind}(${ast.operator},${requiredExpressionGroupingKey(quantifiedComparisonGroupingName(ast.kind), ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
3450
3300
  case "jsonGet":
3451
3301
  case "jsonPath":
3452
3302
  case "jsonAccess":
@@ -3460,7 +3310,7 @@ var groupingKeyOfExpression = (expression) => {
3460
3310
  case "jsonKeyExists":
3461
3311
  case "jsonHasAnyKeys":
3462
3312
  case "jsonHasAllKeys":
3463
- return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
3313
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonKeysGroupingKey(ast.keys)})`;
3464
3314
  case "jsonConcat":
3465
3315
  case "jsonMerge":
3466
3316
  return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
@@ -3476,9 +3326,9 @@ var groupingKeyOfExpression = (expression) => {
3476
3326
  case "jsonPathMatch":
3477
3327
  return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
3478
3328
  case "jsonBuildObject":
3479
- return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
3329
+ return `json(${ast.kind},${jsonBuildObjectGroupingKey(ast.entries)})`;
3480
3330
  case "jsonBuildArray":
3481
- return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
3331
+ return `json(${ast.kind},${jsonBuildArrayGroupingKey(ast.values)})`;
3482
3332
  case "jsonToJson":
3483
3333
  case "jsonToJsonb":
3484
3334
  case "jsonTypeOf":
@@ -3487,7 +3337,7 @@ var groupingKeyOfExpression = (expression) => {
3487
3337
  case "jsonStripNulls":
3488
3338
  return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
3489
3339
  default:
3490
- throw new Error("Unsupported expression for grouping key generation");
3340
+ return `unknown:${typeof ast === "object" && ast !== null && "kind" in ast ? String(ast.kind) : "ast"}`;
3491
3341
  }
3492
3342
  };
3493
3343
  var dedupeGroupedExpressions = (values) => {
@@ -3502,51 +3352,20 @@ var dedupeGroupedExpressions = (values) => {
3502
3352
  });
3503
3353
  };
3504
3354
 
3505
- // src/internal/aggregation-validation.ts
3506
- var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
3507
- var selectionHasAggregate = (selection) => {
3508
- if (isExpression3(selection)) {
3509
- return selection[TypeId2].kind === "aggregate";
3510
- }
3511
- return Object.values(selection).some((value) => selectionHasAggregate(value));
3512
- };
3513
- var isGroupedSelectionValid = (selection, groupedExpressions) => {
3514
- if (isExpression3(selection)) {
3515
- const aggregation = selection[TypeId2].kind;
3516
- if (aggregation === "aggregate") {
3517
- return true;
3518
- }
3519
- if (aggregation === "window") {
3520
- return false;
3521
- }
3522
- if (Object.keys(selection[TypeId2].dependencies).length === 0) {
3523
- return true;
3524
- }
3525
- return groupedExpressions.has(groupingKeyOfExpression(selection));
3526
- }
3527
- return Object.values(selection).every((value) => isGroupedSelectionValid(value, groupedExpressions));
3528
- };
3529
- var validateAggregationSelection = (selection, grouped) => {
3530
- const groupedExpressions = new Set(grouped.map(groupingKeyOfExpression));
3531
- const hasAggregate = selectionHasAggregate(selection);
3532
- const isValid = hasAggregate || grouped.length > 0 ? isGroupedSelectionValid(selection, groupedExpressions) : true;
3533
- if (!isValid) {
3534
- throw new Error("Invalid grouped selection: scalar expressions must be covered by groupBy(...) when aggregates are present");
3535
- }
3536
- };
3537
-
3538
- // src/postgres/internal/sql-expression-renderer.ts
3355
+ // src/internal/dialect-renderers/postgres.ts
3539
3356
  var renderDbType = (dialect, dbType) => {
3540
- if (dialect.name === "mysql" && dbType.dialect === "mysql" && dbType.kind === "uuid") {
3541
- return "char(36)";
3357
+ if (dialect.name === "postgres" && dbType.kind === "blob") {
3358
+ return "bytea";
3542
3359
  }
3543
- return dbType.kind;
3360
+ return renderDbTypeName(dbType.kind);
3544
3361
  };
3362
+ var isArrayDbType = (dbType) => ("element" in dbType);
3545
3363
  var renderCastType = (dialect, dbType) => {
3364
+ const kind = dbType?.kind;
3546
3365
  if (dialect.name !== "mysql") {
3547
- return dbType.kind;
3366
+ return renderDbTypeName(kind);
3548
3367
  }
3549
- switch (dbType.kind) {
3368
+ switch (kind) {
3550
3369
  case "text":
3551
3370
  return "char";
3552
3371
  case "uuid":
@@ -3561,7 +3380,85 @@ var renderCastType = (dialect, dbType) => {
3561
3380
  case "json":
3562
3381
  return "json";
3563
3382
  default:
3564
- return dbType.kind;
3383
+ return renderDbTypeName(kind);
3384
+ }
3385
+ };
3386
+ var casingForTable = (table, state) => merge(state.casing, table[TypeId6].casing);
3387
+ var casedTableName = (table, state) => {
3388
+ const tableState = table[TypeId6];
3389
+ return applyCategory(casingForTable(table, state), "tables", tableState.baseName);
3390
+ };
3391
+ var casedSchemaName = (table, state) => {
3392
+ const schemaName = table[TypeId6].schemaName;
3393
+ return schemaName === undefined ? undefined : applyCategory(casingForTable(table, state), "schemas", schemaName);
3394
+ };
3395
+ var casedColumnName = (columnName, state, tableName) => {
3396
+ if (tableName !== undefined) {
3397
+ const mapped = state.sourceNames?.get(tableName)?.columns.get(columnName);
3398
+ if (mapped !== undefined) {
3399
+ return mapped;
3400
+ }
3401
+ }
3402
+ return applyCategory(state.casing, "columns", columnName);
3403
+ };
3404
+ var casedTableReferenceName = (tableName, state) => state.sourceNames?.get(tableName)?.tableName ?? applyCategory(state.casing, "tables", tableName);
3405
+ var quoteColumn = (columnName, state, dialect, tableName) => dialect.quoteIdentifier(casedColumnName(columnName, state, tableName));
3406
+ var stateWithTableCasing = (state, source) => typeof source === "object" && source !== null && (TypeId6 in source) ? { ...state, casing: casingForTable(source, state) } : state;
3407
+ var referenceCasing = (reference, state) => merge(state.casing, reference.casing);
3408
+ var renderReferenceTable = (reference, state, dialect) => {
3409
+ const casing = referenceCasing(reference, state);
3410
+ const tableName = applyCategory(casing, "tables", reference.tableName);
3411
+ const schemaName = reference.schemaName === undefined ? undefined : applyCategory(casing, "schemas", reference.schemaName);
3412
+ return dialect.renderTableReference(tableName, tableName, schemaName);
3413
+ };
3414
+ var quoteReferenceColumn = (columnName, reference, state, dialect) => dialect.quoteIdentifier(applyCategory(referenceCasing(reference, state), "columns", columnName));
3415
+ var registerSourceReference = (source, tableName, state) => {
3416
+ if (typeof source !== "object" || source === null) {
3417
+ return;
3418
+ }
3419
+ if (TypeId6 in source) {
3420
+ const table = source;
3421
+ const tableState = table[TypeId6];
3422
+ const casing = casingForTable(table, state);
3423
+ const renderedTableName = tableState.kind === "alias" ? tableName : applyCategory(casing, "tables", tableState.baseName);
3424
+ const columns = new Map(Object.keys(tableState.fields).map((columnName) => [
3425
+ columnName,
3426
+ applyCategory(casing, "columns", columnName)
3427
+ ]));
3428
+ state.sourceNames?.set(tableName, {
3429
+ tableName: renderedTableName,
3430
+ columns
3431
+ });
3432
+ return;
3433
+ }
3434
+ if ("columns" in source && typeof source.columns === "object" && source.columns !== null) {
3435
+ state.sourceNames?.set(tableName, {
3436
+ tableName,
3437
+ columns: new Map(Object.keys(source.columns).map((columnName) => [columnName, columnName]))
3438
+ });
3439
+ }
3440
+ };
3441
+ var registerQuerySources = (ast, state) => {
3442
+ if (ast.from !== undefined) {
3443
+ registerSourceReference(ast.from.source, ast.from.tableName, state);
3444
+ }
3445
+ for (const source of ast.fromSources ?? []) {
3446
+ registerSourceReference(source.source, source.tableName, state);
3447
+ }
3448
+ for (const join of ast.joins) {
3449
+ registerSourceReference(join.source, join.tableName, state);
3450
+ }
3451
+ if (ast.into !== undefined) {
3452
+ registerSourceReference(ast.into.source, ast.into.tableName, state);
3453
+ }
3454
+ if (ast.target !== undefined) {
3455
+ registerSourceReference(ast.target.source, ast.target.tableName, state);
3456
+ }
3457
+ for (const target of ast.targets ?? []) {
3458
+ registerSourceReference(target.source, target.tableName, state);
3459
+ }
3460
+ if (ast.using !== undefined) {
3461
+ registerSourceReference(ast.using.source, ast.using.tableName, state);
3565
3462
  }
3566
3463
  };
3567
3464
  var renderPostgresDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
@@ -3599,22 +3496,29 @@ var renderDdlExpression = (expression, state, dialect) => {
3599
3496
  if (isSchemaExpression(expression)) {
3600
3497
  return render(expression);
3601
3498
  }
3602
- return renderExpression(expression, state, {
3499
+ return renderExpression2(expression, state, {
3603
3500
  ...dialect,
3604
3501
  renderLiteral: renderPostgresDdlLiteral
3605
3502
  });
3606
3503
  };
3607
- var renderColumnDefinition = (dialect, state, columnName, column) => {
3504
+ var renderColumnDefinition = (dialect, state, columnName, column, tableName, casing) => {
3505
+ const expressionState = { ...state, casing, rowLocalColumns: true };
3506
+ if (dialect.name !== "postgres" && isArrayDbType(column.metadata.dbType)) {
3507
+ throw new Error(`Unsupported ${dialect.name} array column options`);
3508
+ }
3608
3509
  const clauses = [
3609
- dialect.quoteIdentifier(columnName),
3610
- column.metadata.ddlType ?? renderDbType(dialect, column.metadata.dbType)
3510
+ quoteColumn(columnName, state, dialect, tableName),
3511
+ column.metadata.ddlType === undefined ? renderDbType(dialect, column.metadata.dbType) : renderDbTypeName(column.metadata.ddlType)
3611
3512
  ];
3612
3513
  if (column.metadata.identity) {
3514
+ if (dialect.name !== "postgres") {
3515
+ throw new Error(`Unsupported ${dialect.name} identity column options`);
3516
+ }
3613
3517
  clauses.push(`generated ${column.metadata.identity.generation === "byDefault" ? "by default" : "always"} as identity`);
3614
3518
  } else if (column.metadata.generatedValue) {
3615
- clauses.push(`generated always as (${renderDdlExpression(column.metadata.generatedValue, state, dialect)}) stored`);
3519
+ clauses.push(`generated always as (${renderDdlExpression(column.metadata.generatedValue, expressionState, dialect)}) stored`);
3616
3520
  } else if (column.metadata.defaultValue) {
3617
- clauses.push(`default ${renderDdlExpression(column.metadata.defaultValue, state, dialect)}`);
3521
+ clauses.push(`default ${renderDdlExpression(column.metadata.defaultValue, expressionState, dialect)}`);
3618
3522
  }
3619
3523
  if (!column.metadata.nullable) {
3620
3524
  clauses.push("not null");
@@ -3622,24 +3526,47 @@ var renderColumnDefinition = (dialect, state, columnName, column) => {
3622
3526
  return clauses.join(" ");
3623
3527
  };
3624
3528
  var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
3529
+ const normalizedIfNotExists = normalizeStatementFlag(ifNotExists);
3530
+ if (dialect.name !== "postgres" && normalizedIfNotExists) {
3531
+ throw new Error(`Unsupported ${dialect.name} create table options`);
3532
+ }
3625
3533
  const table = targetSource.source;
3626
- const fields = table[TypeId4].fields;
3627
- const definitions = Object.entries(fields).map(([columnName, column]) => renderColumnDefinition(dialect, state, columnName, column));
3628
- for (const option2 of table[OptionsSymbol]) {
3534
+ const tableCasing = casingForTable(table, state);
3535
+ const fields = table[TypeId6].fields;
3536
+ const definitions = Object.entries(fields).map(([columnName, column]) => renderColumnDefinition(dialect, state, columnName, column, targetSource.tableName, tableCasing));
3537
+ const options2 = table[OptionsSymbol];
3538
+ const tableOptions = Array.isArray(options2) ? options2 : [options2];
3539
+ validateOptions(table[TypeId6].name, fields, tableOptions);
3540
+ for (const option2 of tableOptions) {
3541
+ if (typeof option2 !== "object" || option2 === null || !("kind" in option2)) {
3542
+ continue;
3543
+ }
3629
3544
  switch (option2.kind) {
3630
3545
  case "primaryKey":
3631
- definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}primary key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3546
+ if (dialect.name !== "postgres" && (option2.deferrable || option2.initiallyDeferred)) {
3547
+ throw new Error(`Unsupported ${dialect.name} primary key constraint options`);
3548
+ }
3549
+ definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(applyCategory(tableCasing, "constraints", option2.name))} ` : ""}primary key (${option2.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3632
3550
  break;
3633
3551
  case "unique":
3634
- definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}unique${option2.nullsNotDistinct ? " nulls not distinct" : ""} (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3552
+ if (dialect.name !== "postgres" && (option2.nullsNotDistinct || option2.deferrable || option2.initiallyDeferred)) {
3553
+ throw new Error(`Unsupported ${dialect.name} unique constraint options`);
3554
+ }
3555
+ definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(applyCategory(tableCasing, "constraints", option2.name))} ` : ""}unique${option2.nullsNotDistinct ? " nulls not distinct" : ""} (${option2.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3635
3556
  break;
3636
3557
  case "foreignKey": {
3637
- const reference = option2.references();
3638
- definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3558
+ if (dialect.name !== "postgres" && (option2.deferrable || option2.initiallyDeferred)) {
3559
+ throw new Error(`Unsupported ${dialect.name} foreign key constraint options`);
3560
+ }
3561
+ const reference = typeof option2.references === "function" ? option2.references() : option2.references;
3562
+ definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(applyCategory(tableCasing, "constraints", option2.name))} ` : ""}foreign key (${option2.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ")}) references ${renderReferenceTable(reference, state, dialect)} (${reference.columns.map((column) => quoteReferenceColumn(column, reference, state, dialect)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
3639
3563
  break;
3640
3564
  }
3641
3565
  case "check":
3642
- definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
3566
+ if (dialect.name !== "postgres" && option2.noInherit) {
3567
+ throw new Error(`Unsupported ${dialect.name} check constraint options`);
3568
+ }
3569
+ definitions.push(`constraint ${dialect.quoteIdentifier(applyCategory(tableCasing, "constraints", option2.name))} check (${renderDdlExpression(option2.predicate, { ...state, casing: tableCasing, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
3643
3570
  break;
3644
3571
  case "index":
3645
3572
  break;
@@ -3647,21 +3574,40 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
3647
3574
  throw new Error("Unsupported table option kind");
3648
3575
  }
3649
3576
  }
3650
- return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
3577
+ return `create table${normalizedIfNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
3651
3578
  };
3652
3579
  var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
3653
- const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
3654
- return `create${ddl.unique ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`;
3580
+ const unique2 = normalizeStatementFlag(ddl.unique);
3581
+ const ifNotExists = normalizeStatementFlag(ddl.ifNotExists);
3582
+ const name = normalizeStatementIdentifier("createIndex", "option 'name'", ddl.name);
3583
+ if (dialect.name !== "postgres" && ifNotExists) {
3584
+ throw new Error(`Unsupported ${dialect.name} create index options`);
3585
+ }
3586
+ const maybeIfNotExists = dialect.name === "postgres" && ifNotExists ? " if not exists" : "";
3587
+ const table = targetSource.source;
3588
+ const tableCasing = casingForTable(table, state);
3589
+ return `create${unique2 ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(applyCategory(tableCasing, "indexes", name))} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ")})`;
3655
3590
  };
3656
3591
  var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
3592
+ const ifExists = normalizeStatementFlag(ddl.ifExists);
3593
+ const name = normalizeStatementIdentifier("dropIndex", "option 'name'", ddl.name);
3594
+ if (dialect.name !== "postgres" && ifExists) {
3595
+ throw new Error(`Unsupported ${dialect.name} drop index options`);
3596
+ }
3657
3597
  if (dialect.name === "postgres") {
3658
- const schemaName = typeof targetSource.source === "object" && targetSource.source !== null && TypeId4 in targetSource.source ? targetSource.source[TypeId4].schemaName : undefined;
3659
- const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(ddl.name) : `${dialect.quoteIdentifier(schemaName)}.${dialect.quoteIdentifier(ddl.name)}`;
3660
- return `drop index${ddl.ifExists ? " if exists" : ""} ${indexName}`;
3598
+ const table2 = typeof targetSource.source === "object" && targetSource.source !== null && TypeId6 in targetSource.source ? targetSource.source : undefined;
3599
+ const schemaName = table2?.[TypeId6].schemaName;
3600
+ const tableCasing2 = table2 === undefined ? state.casing : casingForTable(table2, state);
3601
+ const renderedSchemaName = table2 === undefined ? schemaName : casedSchemaName(table2, state);
3602
+ const renderedIndexName = applyCategory(tableCasing2, "indexes", name);
3603
+ const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(renderedIndexName) : `${dialect.quoteIdentifier(renderedSchemaName ?? schemaName)}.${dialect.quoteIdentifier(renderedIndexName)}`;
3604
+ return `drop index${ifExists ? " if exists" : ""} ${indexName}`;
3661
3605
  }
3662
- return `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
3606
+ const table = targetSource.source;
3607
+ const tableCasing = casingForTable(table, state);
3608
+ return `drop index ${dialect.quoteIdentifier(applyCategory(tableCasing, "indexes", name))} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
3663
3609
  };
3664
- var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3610
+ var isExpression3 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
3665
3611
  var isJsonDbType2 = (dbType) => {
3666
3612
  if (dbType.kind === "jsonb" || dbType.kind === "json") {
3667
3613
  return true;
@@ -3672,7 +3618,13 @@ var isJsonDbType2 = (dbType) => {
3672
3618
  const variant = dbType.variant;
3673
3619
  return variant === "json" || variant === "jsonb";
3674
3620
  };
3675
- var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId2].dbType);
3621
+ var isJsonExpression = (value) => isExpression3(value) && isJsonDbType2(value[TypeId2].dbType);
3622
+ var expectValueExpression = (_functionName, value) => value;
3623
+ var expectBinaryExpressions = (_functionName, left, right) => [left, right];
3624
+ var renderBinaryExpression = (functionName, operator, left, right, state, dialect) => {
3625
+ const [leftExpression, rightExpression] = expectBinaryExpressions(functionName, left, right);
3626
+ return `(${renderExpression2(leftExpression, state, dialect)} ${operator} ${renderExpression2(rightExpression, state, dialect)})`;
3627
+ };
3676
3628
  var postgresRangeSubtypeByKind = {
3677
3629
  int4range: "int4",
3678
3630
  int8range: "int8",
@@ -3713,14 +3665,53 @@ var unsupportedJsonFeature = (dialect, feature) => {
3713
3665
  throw error;
3714
3666
  };
3715
3667
  var extractJsonBase = (node) => node.value ?? node.base ?? node.input ?? node.left ?? node.target;
3716
- var isJsonPathValue = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
3668
+ var isJsonPathValue = (value) => value !== null && typeof value === "object" && (TypeId8 in value);
3669
+ var isOptionalJsonPathNumber = (value) => value === undefined || typeof value === "number" && Number.isFinite(value);
3670
+ var isJsonPathSegment = (segment) => {
3671
+ if (typeof segment === "string") {
3672
+ return true;
3673
+ }
3674
+ if (typeof segment === "number") {
3675
+ return Number.isFinite(segment);
3676
+ }
3677
+ if (segment === null || typeof segment !== "object" || !("kind" in segment)) {
3678
+ return false;
3679
+ }
3680
+ switch (segment.kind) {
3681
+ case "key":
3682
+ return typeof segment.key === "string";
3683
+ case "index": {
3684
+ const index3 = segment.index;
3685
+ return typeof index3 === "number" && Number.isFinite(index3);
3686
+ }
3687
+ case "wildcard":
3688
+ case "descend":
3689
+ return true;
3690
+ case "slice":
3691
+ return isOptionalJsonPathNumber(segment.start) && isOptionalJsonPathNumber(segment.end);
3692
+ default:
3693
+ return false;
3694
+ }
3695
+ };
3696
+ var validateJsonPathSegments = (segments) => {
3697
+ if (!Array.isArray(segments)) {
3698
+ throw new Error("JSON path expressions require a segment array");
3699
+ }
3700
+ if (segments.some((segment) => !isJsonPathSegment(segment))) {
3701
+ throw new Error("JSON path segments require string, number, or path segment objects");
3702
+ }
3703
+ return segments;
3704
+ };
3717
3705
  var extractJsonPathSegments = (node) => {
3718
3706
  const path2 = node.path ?? node.segments ?? node.keys;
3719
3707
  if (isJsonPathValue(path2)) {
3720
- return path2.segments;
3708
+ return validateJsonPathSegments(path2.segments);
3721
3709
  }
3722
3710
  if (Array.isArray(path2)) {
3723
- return path2;
3711
+ return validateJsonPathSegments(path2);
3712
+ }
3713
+ if (node.segments !== undefined) {
3714
+ return validateJsonPathSegments(node.segments);
3724
3715
  }
3725
3716
  if ("key" in node) {
3726
3717
  return [key(String(node.key))];
@@ -3739,10 +3730,11 @@ var extractJsonPathSegments = (node) => {
3739
3730
  return [];
3740
3731
  }
3741
3732
  if ("right" in node && isJsonPathValue(node.right)) {
3742
- return node.right.segments;
3733
+ return validateJsonPathSegments(node.right.segments);
3743
3734
  }
3744
3735
  return [];
3745
3736
  };
3737
+ var extractJsonKeys = (node, segments) => Array.isArray(node.keys) ? node.keys : segments.map((segment) => typeof segment === "object" && segment !== null && segment.kind === "key" ? segment.key : segment);
3746
3738
  var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
3747
3739
  var renderJsonPathSegment = (segment) => {
3748
3740
  const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
@@ -3803,10 +3795,10 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
3803
3795
  }
3804
3796
  };
3805
3797
  var renderPostgresJsonValue = (value, state, dialect) => {
3806
- if (!isExpression4(value)) {
3798
+ if (!isExpression3(value)) {
3807
3799
  throw new Error("Expected a JSON expression");
3808
3800
  }
3809
- const rendered = renderExpression(value, state, dialect);
3801
+ const rendered = renderExpression2(value, state, dialect);
3810
3802
  const ast = value[TypeId3];
3811
3803
  if (ast.kind === "literal") {
3812
3804
  return `cast(${rendered} as jsonb)`;
@@ -3820,7 +3812,7 @@ var expressionDriverContext = (expression, state, dialect) => ({
3820
3812
  runtimeSchema: expression[TypeId2].runtimeSchema,
3821
3813
  driverValueMapping: expression[TypeId2].driverValueMapping
3822
3814
  });
3823
- var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
3815
+ var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression2(expression, state, dialect), expressionDriverContext(expression, state, dialect));
3824
3816
  var encodeArrayValues = (values, column, state, dialect) => values.map((value) => {
3825
3817
  if (value === null && column.metadata.nullable) {
3826
3818
  return null;
@@ -3842,44 +3834,52 @@ var renderJsonOpaquePath = (value, state, dialect) => {
3842
3834
  return dialect.renderLiteral(renderJsonPathStringLiteral(value.segments), state);
3843
3835
  }
3844
3836
  if (typeof value === "string") {
3837
+ if (value.trim().length === 0) {
3838
+ throw new Error("SQL/JSON path input must be a non-empty string");
3839
+ }
3845
3840
  return dialect.renderLiteral(value, state);
3846
3841
  }
3847
- if (isExpression4(value)) {
3848
- return renderExpression(value, state, dialect);
3842
+ if (isExpression3(value)) {
3843
+ const ast = value[TypeId3];
3844
+ if (ast.kind === "literal" && typeof ast.value === "string" && ast.value.trim().length === 0) {
3845
+ throw new Error("SQL/JSON path input must be a non-empty string");
3846
+ }
3847
+ return renderExpression2(value, state, dialect);
3849
3848
  }
3850
3849
  throw new Error("Unsupported SQL/JSON path input");
3851
3850
  };
3851
+ var renderFunctionName = (name) => {
3852
+ return name;
3853
+ };
3854
+ var renderExtractField = (field) => {
3855
+ const ast = field[TypeId3];
3856
+ return ast.value;
3857
+ };
3852
3858
  var renderFunctionCall = (name, args, state, dialect) => {
3853
- if (name === "array") {
3854
- return `ARRAY[${args.map((arg) => renderExpression(arg, state, dialect)).join(", ")}]`;
3855
- }
3856
- if (name === "extract" && args.length === 2) {
3857
- const field = args[0];
3858
- const source = args[1];
3859
- if (field === undefined) {
3860
- throw new Error("Unsupported SQL extract expression");
3861
- }
3862
- if (source === undefined) {
3863
- throw new Error("Unsupported SQL extract expression");
3864
- }
3865
- const fieldRuntime = isExpression4(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
3866
- const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
3867
- return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
3868
- }
3869
- const renderedArgs = args.map((arg) => renderExpression(arg, state, dialect)).join(", ");
3870
- if (args.length === 0) {
3871
- switch (name) {
3859
+ const functionName = renderFunctionName(name);
3860
+ const functionArgs = args;
3861
+ if (functionName === "array") {
3862
+ return `ARRAY[${functionArgs.map((arg) => renderExpression2(arg, state, dialect)).join(", ")}]`;
3863
+ }
3864
+ if (functionName === "extract") {
3865
+ const field = functionArgs[0];
3866
+ const source = functionArgs[1];
3867
+ return `extract(${renderExtractField(field)} from ${renderExpression2(source, state, dialect)})`;
3868
+ }
3869
+ const renderedArgs = functionArgs.map((arg) => renderExpression2(arg, state, dialect)).join(", ");
3870
+ if (functionArgs.length === 0) {
3871
+ switch (functionName) {
3872
3872
  case "current_date":
3873
3873
  case "current_time":
3874
3874
  case "current_timestamp":
3875
3875
  case "localtime":
3876
3876
  case "localtimestamp":
3877
- return name;
3877
+ return functionName;
3878
3878
  default:
3879
- return `${name}()`;
3879
+ return `${functionName}()`;
3880
3880
  }
3881
3881
  }
3882
- return `${name}(${renderedArgs})`;
3882
+ return `${functionName}(${renderedArgs})`;
3883
3883
  };
3884
3884
  var renderJsonExpression = (expression, ast, state, dialect) => {
3885
3885
  const kind = typeof ast.kind === "string" ? ast.kind : undefined;
@@ -3900,10 +3900,10 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
3900
3900
  case "jsonPathText":
3901
3901
  case "jsonAccessText":
3902
3902
  case "jsonTraverseText": {
3903
- if (!isExpression4(base) || segments.length === 0) {
3903
+ if (!isExpression3(base) || segments.length === 0) {
3904
3904
  return;
3905
3905
  }
3906
- const baseSql = renderExpression(base, state, dialect);
3906
+ const baseSql = renderExpression2(base, state, dialect);
3907
3907
  const textMode = kind.endsWith("Text") || ast.text === true || ast.asText === true;
3908
3908
  if (dialect.name === "postgres") {
3909
3909
  if (exact) {
@@ -3923,45 +3923,49 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
3923
3923
  case "jsonKeyExists":
3924
3924
  case "jsonHasAnyKeys":
3925
3925
  case "jsonHasAllKeys": {
3926
- if (!isExpression4(base)) {
3926
+ if (!isExpression3(base)) {
3927
3927
  return;
3928
3928
  }
3929
- const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
3930
- const keys = segments;
3929
+ const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression2(base, state, dialect);
3930
+ const keys = extractJsonKeys(ast, segments);
3931
3931
  if (keys.length === 0) {
3932
3932
  return;
3933
3933
  }
3934
+ if (keys.some((key2) => typeof key2 !== "string" || key2.length === 0)) {
3935
+ throw new Error("json key predicates require string keys");
3936
+ }
3937
+ const keyNames = keys;
3934
3938
  if (dialect.name === "postgres") {
3935
3939
  if (kind === "jsonHasAnyKeys") {
3936
- return `(${baseSql} ?| array[${keys.map((key2) => renderPostgresTextLiteral(String(key2), state, dialect)).join(", ")}])`;
3940
+ return `(${baseSql} ?| array[${keyNames.map((key2) => renderPostgresTextLiteral(key2, state, dialect)).join(", ")}])`;
3937
3941
  }
3938
3942
  if (kind === "jsonHasAllKeys") {
3939
- return `(${baseSql} ?& array[${keys.map((key2) => renderPostgresTextLiteral(String(key2), state, dialect)).join(", ")}])`;
3943
+ return `(${baseSql} ?& array[${keyNames.map((key2) => renderPostgresTextLiteral(key2, state, dialect)).join(", ")}])`;
3940
3944
  }
3941
- return `(${baseSql} ? ${renderPostgresTextLiteral(String(keys[0]), state, dialect)})`;
3945
+ return `(${baseSql} ? ${renderPostgresTextLiteral(keyNames[0], state, dialect)})`;
3942
3946
  }
3943
3947
  if (dialect.name === "mysql") {
3944
3948
  const mode = kind === "jsonHasAllKeys" ? "all" : "one";
3945
- const paths = keys.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ");
3949
+ const paths = keyNames.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ");
3946
3950
  return `json_contains_path(${baseSql}, ${dialect.renderLiteral(mode, state)}, ${paths})`;
3947
3951
  }
3948
3952
  return;
3949
3953
  }
3950
3954
  case "jsonConcat":
3951
3955
  case "jsonMerge": {
3952
- if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
3956
+ if (!isExpression3(ast.left) || !isExpression3(ast.right)) {
3953
3957
  return;
3954
3958
  }
3955
3959
  if (dialect.name === "postgres") {
3956
3960
  return `(${renderPostgresJsonValue(ast.left, state, dialect)} || ${renderPostgresJsonValue(ast.right, state, dialect)})`;
3957
3961
  }
3958
3962
  if (dialect.name === "mysql") {
3959
- return `json_merge_preserve(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
3963
+ return `json_merge_preserve(${renderExpression2(ast.left, state, dialect)}, ${renderExpression2(ast.right, state, dialect)})`;
3960
3964
  }
3961
3965
  return;
3962
3966
  }
3963
3967
  case "jsonBuildObject": {
3964
- const entries = Array.isArray(ast.entries) ? ast.entries : [];
3968
+ const entries = ast.entries;
3965
3969
  const renderedEntries = entries.flatMap((entry) => [
3966
3970
  dialect.renderLiteral(entry.key, state),
3967
3971
  renderJsonInputExpression(entry.value, state, dialect)
@@ -3975,7 +3979,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
3975
3979
  return;
3976
3980
  }
3977
3981
  case "jsonBuildArray": {
3978
- const values = Array.isArray(ast.values) ? ast.values : [];
3982
+ const values = ast.values;
3979
3983
  const renderedValues = values.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ");
3980
3984
  if (dialect.name === "postgres") {
3981
3985
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`;
@@ -3986,81 +3990,81 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
3986
3990
  return;
3987
3991
  }
3988
3992
  case "jsonToJson":
3989
- if (!isExpression4(base)) {
3993
+ if (!isExpression3(base)) {
3990
3994
  return;
3991
3995
  }
3992
3996
  if (dialect.name === "postgres") {
3993
3997
  return `to_json(${renderJsonInputExpression(base, state, dialect)})`;
3994
3998
  }
3995
3999
  if (dialect.name === "mysql") {
3996
- return `cast(${renderExpression(base, state, dialect)} as json)`;
4000
+ return `cast(${renderExpression2(base, state, dialect)} as json)`;
3997
4001
  }
3998
4002
  return;
3999
4003
  case "jsonToJsonb":
4000
- if (!isExpression4(base)) {
4004
+ if (!isExpression3(base)) {
4001
4005
  return;
4002
4006
  }
4003
4007
  if (dialect.name === "postgres") {
4004
4008
  return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`;
4005
4009
  }
4006
4010
  if (dialect.name === "mysql") {
4007
- return `cast(${renderExpression(base, state, dialect)} as json)`;
4011
+ return `cast(${renderExpression2(base, state, dialect)} as json)`;
4008
4012
  }
4009
4013
  return;
4010
4014
  case "jsonTypeOf":
4011
- if (!isExpression4(base)) {
4015
+ if (!isExpression3(base)) {
4012
4016
  return;
4013
4017
  }
4014
4018
  if (dialect.name === "postgres") {
4015
- const baseSql = renderExpression(base, state, dialect);
4019
+ const baseSql = renderExpression2(base, state, dialect);
4016
4020
  return `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof(${baseSql})`;
4017
4021
  }
4018
4022
  if (dialect.name === "mysql") {
4019
- return `json_type(${renderExpression(base, state, dialect)})`;
4023
+ return `json_type(${renderExpression2(base, state, dialect)})`;
4020
4024
  }
4021
4025
  return;
4022
4026
  case "jsonLength":
4023
- if (!isExpression4(base)) {
4027
+ if (!isExpression3(base)) {
4024
4028
  return;
4025
4029
  }
4026
4030
  if (dialect.name === "postgres") {
4027
- const baseSql = renderExpression(base, state, dialect);
4031
+ const baseSql = renderExpression2(base, state, dialect);
4028
4032
  const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
4029
4033
  const arrayLength = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_array_length`;
4030
4034
  const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
4031
4035
  return `(case when ${typeOf}(${baseSql}) = 'array' then ${arrayLength}(${baseSql}) when ${typeOf}(${baseSql}) = 'object' then (select count(*)::int from ${objectKeys}(${baseSql})) else null end)`;
4032
4036
  }
4033
4037
  if (dialect.name === "mysql") {
4034
- return `json_length(${renderExpression(base, state, dialect)})`;
4038
+ return `json_length(${renderExpression2(base, state, dialect)})`;
4035
4039
  }
4036
4040
  return;
4037
4041
  case "jsonKeys":
4038
- if (!isExpression4(base)) {
4042
+ if (!isExpression3(base)) {
4039
4043
  return;
4040
4044
  }
4041
4045
  if (dialect.name === "postgres") {
4042
- const baseSql = renderExpression(base, state, dialect);
4046
+ const baseSql = renderExpression2(base, state, dialect);
4043
4047
  const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
4044
4048
  const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
4045
4049
  return `(case when ${typeOf}(${baseSql}) = 'object' then to_json(array(select ${objectKeys}(${baseSql}))) else null end)`;
4046
4050
  }
4047
4051
  if (dialect.name === "mysql") {
4048
- return `json_keys(${renderExpression(base, state, dialect)})`;
4052
+ return `json_keys(${renderExpression2(base, state, dialect)})`;
4049
4053
  }
4050
4054
  return;
4051
4055
  case "jsonStripNulls":
4052
- if (!isExpression4(base)) {
4056
+ if (!isExpression3(base)) {
4053
4057
  return;
4054
4058
  }
4055
4059
  if (dialect.name === "postgres") {
4056
- return `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_strip_nulls(${renderExpression(base, state, dialect)})`;
4060
+ return `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_strip_nulls(${renderExpression2(base, state, dialect)})`;
4057
4061
  }
4058
4062
  unsupportedJsonFeature(dialect, "jsonStripNulls");
4059
4063
  return;
4060
4064
  case "jsonDelete":
4061
4065
  case "jsonDeletePath":
4062
4066
  case "jsonRemove": {
4063
- if (!isExpression4(base) || segments.length === 0) {
4067
+ if (!isExpression3(base) || segments.length === 0) {
4064
4068
  return;
4065
4069
  }
4066
4070
  if (dialect.name === "postgres") {
@@ -4072,17 +4076,17 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
4072
4076
  return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
4073
4077
  }
4074
4078
  if (dialect.name === "mysql") {
4075
- return `json_remove(${renderExpression(base, state, dialect)}, ${segments.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ")})`;
4079
+ return `json_remove(${renderExpression2(base, state, dialect)}, ${segments.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ")})`;
4076
4080
  }
4077
4081
  return;
4078
4082
  }
4079
4083
  case "jsonSet":
4080
4084
  case "jsonInsert": {
4081
- if (!isExpression4(base) || segments.length === 0) {
4085
+ if (!isExpression3(base) || segments.length === 0) {
4082
4086
  return;
4083
4087
  }
4084
4088
  const nextValue = extractJsonValue(ast);
4085
- if (!isExpression4(nextValue)) {
4089
+ if (!isExpression3(nextValue)) {
4086
4090
  return;
4087
4091
  }
4088
4092
  const createMissing = ast.createMissing === true;
@@ -4094,12 +4098,12 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
4094
4098
  }
4095
4099
  if (dialect.name === "mysql") {
4096
4100
  const functionName = kind === "jsonInsert" ? "json_insert" : "json_set";
4097
- return `${functionName}(${renderExpression(base, state, dialect)}, ${renderMySqlJsonPath(segments, state, dialect)}, ${renderExpression(nextValue, state, dialect)})`;
4101
+ return `${functionName}(${renderExpression2(base, state, dialect)}, ${renderMySqlJsonPath(segments, state, dialect)}, ${renderExpression2(nextValue, state, dialect)})`;
4098
4102
  }
4099
4103
  return;
4100
4104
  }
4101
4105
  case "jsonPathExists": {
4102
- if (!isExpression4(base)) {
4106
+ if (!isExpression3(base)) {
4103
4107
  return;
4104
4108
  }
4105
4109
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -4110,12 +4114,12 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
4110
4114
  return `(${renderPostgresJsonValue(base, state, dialect)} @? ${renderJsonOpaquePath(path2, state, dialect)})`;
4111
4115
  }
4112
4116
  if (dialect.name === "mysql") {
4113
- return `json_contains_path(${renderExpression(base, state, dialect)}, ${dialect.renderLiteral("one", state)}, ${renderJsonOpaquePath(path2, state, dialect)})`;
4117
+ return `json_contains_path(${renderExpression2(base, state, dialect)}, ${dialect.renderLiteral("one", state)}, ${renderJsonOpaquePath(path2, state, dialect)})`;
4114
4118
  }
4115
4119
  return;
4116
4120
  }
4117
4121
  case "jsonPathMatch": {
4118
- if (!isExpression4(base)) {
4122
+ if (!isExpression3(base)) {
4119
4123
  return;
4120
4124
  }
4121
4125
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -4134,19 +4138,14 @@ var selectionProjections = (selection) => flattenSelection(selection).map(({ pat
4134
4138
  path: path2,
4135
4139
  alias: alias2
4136
4140
  }));
4137
- var renderMutationAssignment = (entry, state, dialect) => {
4138
- const column = entry.tableName && dialect.name === "mysql" ? `${dialect.quoteIdentifier(entry.tableName)}.${dialect.quoteIdentifier(entry.columnName)}` : dialect.quoteIdentifier(entry.columnName);
4139
- return `${column} = ${renderExpression(entry.value, state, dialect)}`;
4141
+ var renderMutationAssignment = (entry, state, dialect, targetTableName) => {
4142
+ const column = entry.tableName && dialect.name === "mysql" ? `${dialect.quoteIdentifier(casedTableReferenceName(entry.tableName, state))}.${quoteColumn(entry.columnName, state, dialect, entry.tableName)}` : quoteColumn(entry.columnName, state, dialect, targetTableName);
4143
+ return `${column} = ${renderExpression2(entry.value, state, dialect)}`;
4140
4144
  };
4141
4145
  var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) => renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)).join(", ");
4142
4146
  var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
4143
- var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
4147
+ var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression2(join.on, state, dialect)]);
4144
4148
  var renderDeleteTargets = (targets, dialect) => targets.map((target) => dialect.quoteIdentifier(target.tableName)).join(", ");
4145
- var assertMergeActionKind = (kind, allowed) => {
4146
- if (typeof kind !== "string" || !allowed.includes(kind)) {
4147
- throw new Error("Unsupported merge action kind");
4148
- }
4149
- };
4150
4149
  var renderMysqlMutationLock = (lock, statement) => {
4151
4150
  if (!lock) {
4152
4151
  return "";
@@ -4170,7 +4169,7 @@ var renderTransactionClause = (clause, dialect) => {
4170
4169
  if (isolationLevel) {
4171
4170
  modes.push(isolationLevel);
4172
4171
  }
4173
- if (clause.readOnly === true) {
4172
+ if (normalizeStatementFlag(clause.readOnly)) {
4174
4173
  modes.push("read only");
4175
4174
  }
4176
4175
  return modes.length > 0 ? `start transaction ${modes.join(", ")}` : "start transaction";
@@ -4180,24 +4179,18 @@ var renderTransactionClause = (clause, dialect) => {
4180
4179
  case "rollback":
4181
4180
  return "rollback";
4182
4181
  case "savepoint":
4183
- return `savepoint ${dialect.quoteIdentifier(clause.name)}`;
4182
+ return `savepoint ${dialect.quoteIdentifier(normalizeStatementIdentifier("savepoint", "name", clause.name))}`;
4184
4183
  case "rollbackTo":
4185
- return `rollback to savepoint ${dialect.quoteIdentifier(clause.name)}`;
4184
+ return `rollback to savepoint ${dialect.quoteIdentifier(normalizeStatementIdentifier("rollbackTo", "name", clause.name))}`;
4186
4185
  case "releaseSavepoint":
4187
- return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
4186
+ return `release savepoint ${dialect.quoteIdentifier(normalizeStatementIdentifier("releaseSavepoint", "name", clause.name))}`;
4188
4187
  }
4189
- throw new Error("Unsupported transaction statement kind");
4188
+ return "start transaction";
4190
4189
  };
4191
- var renderSelectionList = (selection, state, dialect, validateAggregation) => {
4192
- if (validateAggregation) {
4193
- validateAggregationSelection(selection, []);
4194
- }
4190
+ var renderSelectionList = (selection, state, dialect) => {
4195
4191
  const flattened = flattenSelection(selection);
4196
- if (dialect.name === "mysql" && flattened.length === 0) {
4197
- throw new Error("mysql select statements require at least one selected expression");
4198
- }
4199
4192
  const projections = selectionProjections(selection);
4200
- const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
4193
+ const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression2(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
4201
4194
  return {
4202
4195
  sql,
4203
4196
  projections
@@ -4206,120 +4199,78 @@ var renderSelectionList = (selection, state, dialect, validateAggregation) => {
4206
4199
  var nestedRenderState = (state) => ({
4207
4200
  params: state.params,
4208
4201
  valueMappings: state.valueMappings,
4202
+ casing: state.casing,
4209
4203
  ctes: [],
4210
4204
  cteNames: new Set(state.cteNames),
4211
- cteSources: new Map(state.cteSources)
4205
+ cteSources: new Map(state.cteSources),
4206
+ sourceNames: new Map(state.sourceNames)
4212
4207
  });
4213
- var assertMatchingSetProjections = (left, right) => {
4214
- const leftKeys = left.map((projection) => JSON.stringify(projection.path));
4215
- const rightKeys = right.map((projection) => JSON.stringify(projection.path));
4216
- if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index3) => key2 !== rightKeys[index3])) {
4217
- throw new Error("set operator operands must have matching result rows");
4208
+ var assertSupportedMutationReturning = (dialect, selection) => {
4209
+ if (dialect.name === "standard" && Object.keys(selection).length > 0) {
4210
+ throw new Error("Unsupported standard returning");
4218
4211
  }
4219
4212
  };
4220
- var assertNoGroupedMutationClauses = (ast, statement) => {
4221
- if (ast.groupBy.length > 0) {
4222
- throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4223
- }
4224
- if (ast.having.length > 0) {
4225
- throw new Error(`having(...) is not supported for ${statement} statements`);
4226
- }
4227
- };
4228
- var assertNoInsertQueryClauses = (ast) => {
4229
- if (ast.where.length > 0) {
4230
- throw new Error("where(...) is not supported for insert statements");
4231
- }
4232
- if (ast.joins.length > 0) {
4233
- throw new Error("join(...) is not supported for insert statements");
4234
- }
4235
- if (ast.orderBy.length > 0) {
4236
- throw new Error("orderBy(...) is not supported for insert statements");
4237
- }
4238
- if (ast.limit) {
4239
- throw new Error("limit(...) is not supported for insert statements");
4240
- }
4241
- if (ast.offset) {
4242
- throw new Error("offset(...) is not supported for insert statements");
4243
- }
4244
- if (ast.lock) {
4245
- throw new Error("lock(...) is not supported for insert statements");
4246
- }
4247
- };
4248
- var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
4249
- if (ast.distinct) {
4250
- throw new Error(`distinct(...) is not supported for ${statement} statements`);
4251
- }
4252
- if (ast.where.length > 0) {
4253
- throw new Error(`where(...) is not supported for ${statement} statements`);
4254
- }
4255
- if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
4256
- throw new Error(`from(...) is not supported for ${statement} statements`);
4257
- }
4258
- if (ast.joins.length > 0) {
4259
- throw new Error(`join(...) is not supported for ${statement} statements`);
4260
- }
4261
- if (ast.groupBy.length > 0) {
4262
- throw new Error(`groupBy(...) is not supported for ${statement} statements`);
4263
- }
4264
- if (ast.having.length > 0) {
4265
- throw new Error(`having(...) is not supported for ${statement} statements`);
4266
- }
4267
- if (ast.orderBy.length > 0) {
4268
- throw new Error(`orderBy(...) is not supported for ${statement} statements`);
4269
- }
4270
- if (ast.limit) {
4271
- throw new Error(`limit(...) is not supported for ${statement} statements`);
4272
- }
4273
- if (ast.offset) {
4274
- throw new Error(`offset(...) is not supported for ${statement} statements`);
4275
- }
4276
- if (ast.lock) {
4277
- throw new Error(`lock(...) is not supported for ${statement} statements`);
4213
+ var validateDistinctOnOrdering = (distinctOn, orderBy) => {
4214
+ if (distinctOn === undefined || distinctOn.length === 0 || orderBy.length === 0) {
4215
+ return;
4278
4216
  }
4279
- if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
4280
- throw new Error(`returning(...) is not supported for ${statement} statements`);
4217
+ const remainingDistinctKeys = new Set(distinctOn.map(groupingKeyOfExpression));
4218
+ for (const order of orderBy) {
4219
+ const key2 = groupingKeyOfExpression(order.value);
4220
+ if (remainingDistinctKeys.has(key2)) {
4221
+ remainingDistinctKeys.delete(key2);
4222
+ continue;
4223
+ }
4224
+ if (remainingDistinctKeys.size > 0) {
4225
+ throw new Error("distinctOn(...) expressions must match the leftmost orderBy(...) expressions");
4226
+ }
4227
+ return;
4281
4228
  }
4282
4229
  };
4283
- var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4230
+ var renderQueryAst2 = (ast, state, dialect, options2 = {}) => {
4231
+ registerQuerySources(ast, state);
4284
4232
  let sql = "";
4285
4233
  let projections = [];
4286
4234
  switch (ast.kind) {
4287
4235
  case "select": {
4288
- validateAggregationSelection(ast.select, ast.groupBy);
4289
- const rendered = renderSelectionList(ast.select, state, dialect, false);
4236
+ validateDistinctOnOrdering(ast.distinctOn, ast.orderBy);
4237
+ const rendered = renderSelectionList(ast.select, state, dialect);
4290
4238
  projections = rendered.projections;
4291
4239
  const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
4292
4240
  const clauses = [
4293
- ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
4241
+ ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression2(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
4294
4242
  ];
4295
4243
  if (ast.from) {
4296
4244
  clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
4297
4245
  }
4298
4246
  for (const join of ast.joins) {
4247
+ if (dialect.name === "standard" && join.kind === "full") {
4248
+ throw new Error("Unsupported standard full join");
4249
+ }
4299
4250
  const source = renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect);
4300
- clauses.push(join.kind === "cross" ? `cross join ${source}` : `${join.kind} join ${source} on ${renderExpression(join.on, state, dialect)}`);
4251
+ clauses.push(join.kind === "cross" ? `cross join ${source}` : `${join.kind} join ${source} on ${renderExpression2(join.on, state, dialect)}`);
4301
4252
  }
4302
4253
  if (ast.where.length > 0) {
4303
- clauses.push(`where ${ast.where.map((entry) => renderExpression(entry.predicate, state, dialect)).join(" and ")}`);
4254
+ clauses.push(`where ${ast.where.map((entry) => renderExpression2(entry.predicate, state, dialect)).join(" and ")}`);
4304
4255
  }
4305
4256
  if (ast.groupBy.length > 0) {
4306
- clauses.push(`group by ${ast.groupBy.map((value) => renderExpression(value, state, dialect)).join(", ")}`);
4257
+ clauses.push(`group by ${ast.groupBy.map((value) => renderExpression2(value, state, dialect)).join(", ")}`);
4307
4258
  }
4308
4259
  if (ast.having.length > 0) {
4309
- clauses.push(`having ${ast.having.map((entry) => renderExpression(entry.predicate, state, dialect)).join(" and ")}`);
4260
+ clauses.push(`having ${ast.having.map((entry) => renderExpression2(entry.predicate, state, dialect)).join(" and ")}`);
4310
4261
  }
4311
4262
  if (ast.orderBy.length > 0) {
4312
- clauses.push(`order by ${ast.orderBy.map((entry) => `${renderExpression(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`);
4263
+ clauses.push(`order by ${ast.orderBy.map((entry) => `${renderExpression2(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`);
4313
4264
  }
4314
4265
  if (ast.limit) {
4315
- clauses.push(`limit ${renderExpression(ast.limit, state, dialect)}`);
4266
+ clauses.push(`limit ${renderExpression2(ast.limit, state, dialect)}`);
4316
4267
  }
4317
4268
  if (ast.offset) {
4318
- clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
4269
+ clauses.push(`offset ${renderExpression2(ast.offset, state, dialect)}`);
4319
4270
  }
4320
4271
  if (ast.lock) {
4321
- if (ast.lock.nowait && ast.lock.skipLocked) {
4322
- throw new Error("lock(...) cannot specify both nowait and skipLocked");
4272
+ if (dialect.name === "standard") {
4273
+ throw new Error("Unsupported standard row locking");
4323
4274
  }
4324
4275
  clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
4325
4276
  }
@@ -4328,15 +4279,15 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4328
4279
  }
4329
4280
  case "set": {
4330
4281
  const setAst = ast;
4331
- assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
4332
- const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
4282
+ const base = renderQueryAst2(getAst(setAst.setBase), state, dialect);
4333
4283
  projections = selectionProjections(setAst.select);
4334
- assertMatchingSetProjections(projections, base.projections);
4335
4284
  sql = [
4336
4285
  `(${base.sql})`,
4337
4286
  ...(setAst.setOperations ?? []).map((entry) => {
4338
- const rendered = renderQueryAst(getAst(entry.query), state, dialect);
4339
- assertMatchingSetProjections(projections, rendered.projections);
4287
+ const rendered = renderQueryAst2(getAst(entry.query), state, dialect);
4288
+ if (dialect.name === "standard" && entry.all && entry.kind !== "union") {
4289
+ throw new Error("Unsupported standard set operator all variant");
4290
+ }
4340
4291
  return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
4341
4292
  })
4342
4293
  ].join(" ");
@@ -4344,61 +4295,60 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4344
4295
  }
4345
4296
  case "insert": {
4346
4297
  const insertAst = ast;
4347
- if (insertAst.distinct) {
4348
- throw new Error("distinct(...) is not supported for insert statements");
4349
- }
4350
- assertNoGroupedMutationClauses(insertAst, "insert");
4351
- assertNoInsertQueryClauses(insertAst);
4352
4298
  const targetSource = insertAst.into;
4353
4299
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4354
- const insertSource = expectInsertSourceKind(insertAst.insertSource);
4300
+ const targetCasingState = stateWithTableCasing(state, targetSource.source);
4301
+ const insertSource = insertAst.insertSource;
4355
4302
  const conflict = expectConflictClause(insertAst.conflict);
4356
4303
  sql = `insert into ${target}`;
4357
4304
  if (insertSource?.kind === "values") {
4358
- const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4359
- const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
4305
+ const columns = insertSource.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ");
4306
+ const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression2(entry.value, targetCasingState, dialect)).join(", ")})`).join(", ");
4360
4307
  sql += ` (${columns}) values ${rows}`;
4361
4308
  } else if (insertSource?.kind === "query") {
4362
- const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4363
- const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
4309
+ const columns = insertSource.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ");
4310
+ const renderedQuery = renderQueryAst2(getAst(insertSource.query), state, dialect);
4364
4311
  sql += ` (${columns}) ${renderedQuery.sql}`;
4365
4312
  } else if (insertSource?.kind === "unnest") {
4366
- const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
4313
+ const columns = insertSource.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ");
4367
4314
  if (dialect.name === "postgres") {
4368
4315
  const table = targetSource.source;
4369
- const fields = table[TypeId4].fields;
4316
+ const fields = table[TypeId6].fields;
4370
4317
  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(", ");
4371
4318
  sql += ` (${columns}) select * from unnest(${rendered})`;
4372
4319
  } else {
4373
4320
  const rowCount = insertSource.values[0]?.values.length ?? 0;
4374
- const rows = Array.from({ length: rowCount }, (_, index3) => `(${insertSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
4321
+ const rows = Array.from({ length: rowCount }, (_, index3) => `(${insertSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId6].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
4375
4322
  sql += ` (${columns}) values ${rows}`;
4376
4323
  }
4377
4324
  } else {
4378
- const columns = (insertAst.values ?? []).map((entry) => dialect.quoteIdentifier(entry.columnName)).join(", ");
4379
- const values = (insertAst.values ?? []).map((entry) => renderExpression(entry.value, state, dialect)).join(", ");
4380
- if ((insertAst.values ?? []).length > 0) {
4325
+ const insertValues = insertAst.values ?? [];
4326
+ const columns = insertValues.map((entry) => quoteColumn(entry.columnName, state, dialect, targetSource.tableName)).join(", ");
4327
+ const values = insertValues.map((entry) => renderExpression2(entry.value, targetCasingState, dialect)).join(", ");
4328
+ if (insertValues.length > 0) {
4381
4329
  sql += ` (${columns}) values (${values})`;
4382
4330
  } else {
4383
4331
  sql += " default values";
4384
4332
  }
4385
4333
  }
4386
4334
  if (conflict) {
4387
- if (conflict.action === "doNothing" && conflict.where) {
4388
- throw new Error("conflict action predicates require update assignments");
4335
+ if (dialect.name === "standard") {
4336
+ throw new Error("Unsupported standard insert conflict");
4389
4337
  }
4390
- const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
4338
+ const conflictValueState = { ...targetCasingState, allowExcluded: true };
4339
+ const updateValues = (conflict.values ?? []).map((entry) => `${quoteColumn(entry.columnName, state, dialect, targetSource.tableName)} = ${renderExpression2(entry.value, conflictValueState, dialect)}`).join(", ");
4391
4340
  if (dialect.name === "postgres") {
4392
- const targetSql = conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(conflict.target.name)}` : conflict.target?.kind === "columns" ? ` on conflict (${conflict.target.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${conflict.target.where ? ` where ${renderExpression(conflict.target.where, state, dialect)}` : ""}` : " on conflict";
4341
+ const targetSql = conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(applyCategory(targetCasingState.casing, "constraints", conflict.target.name))}` : conflict.target?.kind === "columns" ? ` on conflict (${conflict.target.columns.map((column) => quoteColumn(column, state, dialect, targetSource.tableName)).join(", ")})${conflict.target.where ? ` where ${renderExpression2(conflict.target.where, targetCasingState, dialect)}` : ""}` : " on conflict";
4393
4342
  sql += targetSql;
4394
- sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
4343
+ sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression2(conflict.where, conflictValueState, dialect)}` : ""}`;
4395
4344
  } else if (conflict.action === "doNothing") {
4396
4345
  sql = sql.replace(/^insert/, "insert ignore");
4397
4346
  } else {
4398
4347
  sql += ` on duplicate key update ${updateValues}`;
4399
4348
  }
4400
4349
  }
4401
- const returning = renderSelectionList(insertAst.select, state, dialect, false);
4350
+ assertSupportedMutationReturning(dialect, insertAst.select);
4351
+ const returning = renderSelectionList(insertAst.select, state, dialect);
4402
4352
  projections = returning.projections;
4403
4353
  if (returning.sql.length > 0) {
4404
4354
  sql += ` returning ${returning.sql}`;
@@ -4407,34 +4357,18 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4407
4357
  }
4408
4358
  case "update": {
4409
4359
  const updateAst = ast;
4410
- if (updateAst.distinct) {
4411
- throw new Error("distinct(...) is not supported for update statements");
4412
- }
4413
- assertNoGroupedMutationClauses(updateAst, "update");
4414
- if (updateAst.orderBy.length > 0) {
4415
- throw new Error("orderBy(...) is not supported for update statements");
4416
- }
4417
- if (updateAst.limit) {
4418
- throw new Error("limit(...) is not supported for update statements");
4419
- }
4420
- if (updateAst.offset) {
4421
- throw new Error("offset(...) is not supported for update statements");
4422
- }
4423
- if (updateAst.lock) {
4424
- throw new Error("lock(...) is not supported for update statements");
4425
- }
4426
4360
  const targetSource = updateAst.target;
4427
4361
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4428
4362
  const targets = updateAst.targets ?? [targetSource];
4429
4363
  const fromSources = updateAst.fromSources ?? [];
4430
- if ((updateAst.set ?? []).length === 0) {
4431
- throw new Error("update statements require at least one assignment");
4364
+ if (dialect.name === "standard" && (targets.length > 1 || fromSources.length > 0 || updateAst.joins.length > 0)) {
4365
+ throw new Error("Unsupported standard joined mutation");
4432
4366
  }
4433
- const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
4367
+ const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect, targetSource.tableName)).join(", ");
4434
4368
  if (dialect.name === "mysql") {
4435
4369
  const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
4436
4370
  const extraSources = renderFromSources(fromSources, state, dialect);
4437
- const joinSources = updateAst.joins.map((join) => join.kind === "cross" ? `cross join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)}` : `${join.kind} join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)} on ${renderExpression(join.on, state, dialect)}`).join(" ");
4371
+ const joinSources = updateAst.joins.map((join) => join.kind === "cross" ? `cross join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)}` : `${join.kind} join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)} on ${renderExpression2(join.on, state, dialect)}`).join(" ");
4438
4372
  const targetList = [
4439
4373
  ...targets.map((entry) => renderSourceReference(entry.source, entry.tableName, entry.baseTableName, state, dialect)),
4440
4374
  ...extraSources.length > 0 ? [extraSources] : []
@@ -4452,18 +4386,19 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4452
4386
  }
4453
4387
  const whereParts = [
4454
4388
  ...dialect.name === "postgres" ? renderJoinPredicatesForMutation(updateAst.joins, state, dialect) : [],
4455
- ...updateAst.where.map((entry) => renderExpression(entry.predicate, state, dialect))
4389
+ ...updateAst.where.map((entry) => renderExpression2(entry.predicate, state, dialect))
4456
4390
  ];
4457
4391
  if (whereParts.length > 0) {
4458
4392
  sql += ` where ${whereParts.join(" and ")}`;
4459
4393
  }
4460
4394
  if (dialect.name === "mysql" && updateAst.orderBy.length > 0) {
4461
- sql += ` order by ${updateAst.orderBy.map((entry) => `${renderExpression(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`;
4395
+ sql += ` order by ${updateAst.orderBy.map((entry) => `${renderExpression2(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`;
4462
4396
  }
4463
4397
  if (dialect.name === "mysql" && updateAst.limit) {
4464
- sql += ` limit ${renderExpression(updateAst.limit, state, dialect)}`;
4398
+ sql += ` limit ${renderExpression2(updateAst.limit, state, dialect)}`;
4465
4399
  }
4466
- const returning = renderSelectionList(updateAst.select, state, dialect, false);
4400
+ assertSupportedMutationReturning(dialect, updateAst.select);
4401
+ const returning = renderSelectionList(updateAst.select, state, dialect);
4467
4402
  projections = returning.projections;
4468
4403
  if (returning.sql.length > 0) {
4469
4404
  sql += ` returning ${returning.sql}`;
@@ -4472,31 +4407,18 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4472
4407
  }
4473
4408
  case "delete": {
4474
4409
  const deleteAst = ast;
4475
- if (deleteAst.distinct) {
4476
- throw new Error("distinct(...) is not supported for delete statements");
4477
- }
4478
- assertNoGroupedMutationClauses(deleteAst, "delete");
4479
- if (deleteAst.orderBy.length > 0 && dialect.name === "postgres") {
4480
- throw new Error("orderBy(...) is not supported for delete statements");
4481
- }
4482
- if (deleteAst.limit && dialect.name === "postgres") {
4483
- throw new Error("limit(...) is not supported for delete statements");
4484
- }
4485
- if (deleteAst.offset) {
4486
- throw new Error("offset(...) is not supported for delete statements");
4487
- }
4488
- if (deleteAst.lock) {
4489
- throw new Error("lock(...) is not supported for delete statements");
4490
- }
4491
4410
  const targetSource = deleteAst.target;
4492
4411
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
4493
4412
  const targets = deleteAst.targets ?? [targetSource];
4413
+ if (dialect.name === "standard" && (targets.length > 1 || deleteAst.joins.length > 0)) {
4414
+ throw new Error("Unsupported standard joined mutation");
4415
+ }
4494
4416
  if (dialect.name === "mysql") {
4495
4417
  const modifiers = renderMysqlMutationLock(deleteAst.lock, "delete");
4496
4418
  const hasJoinedSources = deleteAst.joins.length > 0 || targets.length > 1;
4497
4419
  const targetList = renderDeleteTargets(targets, dialect);
4498
4420
  const fromSources = targets.map((entry) => renderSourceReference(entry.source, entry.tableName, entry.baseTableName, state, dialect)).join(", ");
4499
- const joinSources = deleteAst.joins.map((join) => join.kind === "cross" ? `cross join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)}` : `${join.kind} join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)} on ${renderExpression(join.on, state, dialect)}`).join(" ");
4421
+ const joinSources = deleteAst.joins.map((join) => join.kind === "cross" ? `cross join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)}` : `${join.kind} join ${renderSourceReference(join.source, join.tableName, join.baseTableName, state, dialect)} on ${renderExpression2(join.on, state, dialect)}`).join(" ");
4500
4422
  sql = hasJoinedSources ? `delete${modifiers} ${targetList} from ${fromSources}${joinSources.length > 0 ? ` ${joinSources}` : ""}` : `delete${modifiers} from ${fromSources}`;
4501
4423
  } else {
4502
4424
  sql = `delete from ${target}`;
@@ -4506,18 +4428,19 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4506
4428
  }
4507
4429
  const whereParts = [
4508
4430
  ...dialect.name === "postgres" ? renderJoinPredicatesForMutation(deleteAst.joins, state, dialect) : [],
4509
- ...deleteAst.where.map((entry) => renderExpression(entry.predicate, state, dialect))
4431
+ ...deleteAst.where.map((entry) => renderExpression2(entry.predicate, state, dialect))
4510
4432
  ];
4511
4433
  if (whereParts.length > 0) {
4512
4434
  sql += ` where ${whereParts.join(" and ")}`;
4513
4435
  }
4514
4436
  if (dialect.name === "mysql" && deleteAst.orderBy.length > 0) {
4515
- sql += ` order by ${deleteAst.orderBy.map((entry) => `${renderExpression(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`;
4437
+ sql += ` order by ${deleteAst.orderBy.map((entry) => `${renderExpression2(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`;
4516
4438
  }
4517
4439
  if (dialect.name === "mysql" && deleteAst.limit) {
4518
- sql += ` limit ${renderExpression(deleteAst.limit, state, dialect)}`;
4440
+ sql += ` limit ${renderExpression2(deleteAst.limit, state, dialect)}`;
4519
4441
  }
4520
- const returning = renderSelectionList(deleteAst.select, state, dialect, false);
4442
+ assertSupportedMutationReturning(dialect, deleteAst.select);
4443
+ const returning = renderSelectionList(deleteAst.select, state, dialect);
4521
4444
  projections = returning.projections;
4522
4445
  if (returning.sql.length > 0) {
4523
4446
  sql += ` returning ${returning.sql}`;
@@ -4526,14 +4449,18 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4526
4449
  }
4527
4450
  case "truncate": {
4528
4451
  const truncateAst = ast;
4529
- assertNoStatementQueryClauses(truncateAst, "truncate");
4452
+ if (dialect.name === "standard") {
4453
+ throw new Error("Unsupported standard truncate statement");
4454
+ }
4530
4455
  const truncate = expectTruncateClause(truncateAst.truncate);
4531
4456
  const targetSource = truncateAst.target;
4457
+ const restartIdentity = truncate.restartIdentity;
4458
+ const cascade = truncate.cascade;
4532
4459
  sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
4533
- if (truncate.restartIdentity) {
4460
+ if (restartIdentity) {
4534
4461
  sql += " restart identity";
4535
4462
  }
4536
- if (truncate.cascade) {
4463
+ if (cascade) {
4537
4464
  sql += " cascade";
4538
4465
  }
4539
4466
  break;
@@ -4545,42 +4472,27 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4545
4472
  const mergeAst = ast;
4546
4473
  const targetSource = mergeAst.target;
4547
4474
  const usingSource = mergeAst.using;
4548
- const merge = mergeAst.merge;
4549
- if (merge.kind !== "merge") {
4550
- throw new Error("Unsupported merge statement kind");
4551
- }
4552
- if (Object.keys(mergeAst.select).length > 0) {
4553
- throw new Error("returning(...) is not supported for merge statements");
4554
- }
4555
- if (!merge.whenMatched && !merge.whenNotMatched) {
4556
- throw new Error("merge statements require at least one action");
4557
- }
4558
- sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression(merge.on, state, dialect)}`;
4559
- if (merge.whenMatched) {
4560
- assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
4475
+ const merge2 = mergeAst.merge;
4476
+ sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression2(merge2.on, state, dialect)}`;
4477
+ if (merge2.whenMatched) {
4478
+ const matchedKind = merge2.whenMatched.kind === "delete" ? "delete" : "update";
4561
4479
  sql += " when matched";
4562
- if (merge.whenMatched.predicate) {
4563
- sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
4480
+ if (merge2.whenMatched.predicate) {
4481
+ sql += ` and ${renderExpression2(merge2.whenMatched.predicate, state, dialect)}`;
4564
4482
  }
4565
- if (merge.whenMatched.kind === "delete") {
4483
+ if (matchedKind === "delete") {
4566
4484
  sql += " then delete";
4567
4485
  } else {
4568
- if (merge.whenMatched.values.length === 0) {
4569
- throw new Error("merge update actions require at least one assignment");
4570
- }
4571
- sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
4486
+ const matchedUpdate = merge2.whenMatched;
4487
+ sql += ` then update set ${matchedUpdate.values.map((entry) => `${quoteColumn(entry.columnName, state, dialect, targetSource.tableName)} = ${renderExpression2(entry.value, state, dialect)}`).join(", ")}`;
4572
4488
  }
4573
4489
  }
4574
- if (merge.whenNotMatched) {
4575
- assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
4490
+ if (merge2.whenNotMatched) {
4576
4491
  sql += " when not matched";
4577
- if (merge.whenNotMatched.predicate) {
4578
- sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
4579
- }
4580
- if (merge.whenNotMatched.values.length === 0) {
4581
- throw new Error("merge insert actions require at least one value");
4492
+ if (merge2.whenNotMatched.predicate) {
4493
+ sql += ` and ${renderExpression2(merge2.whenNotMatched.predicate, state, dialect)}`;
4582
4494
  }
4583
- sql += ` then insert (${merge.whenNotMatched.values.map((entry) => dialect.quoteIdentifier(entry.columnName)).join(", ")}) values (${merge.whenNotMatched.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`;
4495
+ sql += ` then insert (${merge2.whenNotMatched.values.map((entry) => quoteColumn(entry.columnName, state, dialect, targetSource.tableName)).join(", ")}) values (${merge2.whenNotMatched.values.map((entry) => renderExpression2(entry.value, state, dialect)).join(", ")})`;
4584
4496
  }
4585
4497
  break;
4586
4498
  }
@@ -4590,38 +4502,41 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4590
4502
  case "savepoint":
4591
4503
  case "rollbackTo":
4592
4504
  case "releaseSavepoint": {
4593
- assertNoStatementQueryClauses(ast, ast.kind);
4594
4505
  sql = renderTransactionClause(ast.transaction, dialect);
4595
4506
  break;
4596
4507
  }
4597
4508
  case "createTable": {
4598
4509
  const createTableAst = ast;
4599
- assertNoStatementQueryClauses(createTableAst, "createTable");
4600
4510
  const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
4601
4511
  sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
4602
4512
  break;
4603
4513
  }
4604
4514
  case "dropTable": {
4605
4515
  const dropTableAst = ast;
4606
- assertNoStatementQueryClauses(dropTableAst, "dropTable");
4607
4516
  const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
4608
- sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
4517
+ const ifExists = normalizeStatementFlag(ddl.ifExists);
4518
+ if (dialect.name !== "postgres" && ifExists) {
4519
+ throw new Error(`Unsupported ${dialect.name} drop table options`);
4520
+ }
4521
+ sql = `drop table${ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
4609
4522
  break;
4610
4523
  }
4611
4524
  case "createIndex": {
4612
4525
  const createIndexAst = ast;
4613
- assertNoStatementQueryClauses(createIndexAst, "createIndex");
4614
4526
  sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
4615
4527
  break;
4616
4528
  }
4617
4529
  case "dropIndex": {
4618
4530
  const dropIndexAst = ast;
4619
- assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
4620
4531
  sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
4621
4532
  break;
4622
4533
  }
4623
- default:
4624
- throw new Error("Unsupported query statement kind");
4534
+ default: {
4535
+ if (ast.transaction !== undefined) {
4536
+ sql = renderTransactionClause(ast.transaction, dialect);
4537
+ }
4538
+ break;
4539
+ }
4625
4540
  }
4626
4541
  if (state.ctes.length === 0 || options2.emitCtes === false) {
4627
4542
  return {
@@ -4636,7 +4551,7 @@ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
4636
4551
  };
4637
4552
  var renderSourceReference = (source, tableName, baseTableName, state, dialect) => {
4638
4553
  const renderSelectRows = (rows, columnNames) => {
4639
- const renderedRows = rows.map((row) => `select ${columnNames.map((columnName) => `${renderExpression(row[columnName], state, dialect)} as ${dialect.quoteIdentifier(columnName)}`).join(", ")}`);
4554
+ const renderedRows = rows.map((row) => `select ${columnNames.map((columnName) => `${renderExpression2(row[columnName], state, dialect)} as ${dialect.quoteIdentifier(columnName)}`).join(", ")}`);
4640
4555
  return `(${renderedRows.join(" union all ")}) as ${dialect.quoteIdentifier(tableName)}(${columnNames.map((columnName) => dialect.quoteIdentifier(columnName)).join(", ")})`;
4641
4556
  };
4642
4557
  const renderUnnestRows = (arrays, columnNames) => {
@@ -4653,7 +4568,7 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
4653
4568
  if (!state.cteNames.has(cte.name)) {
4654
4569
  state.cteNames.add(cte.name);
4655
4570
  state.cteSources.set(cte.name, cte.plan);
4656
- const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
4571
+ const rendered = renderQueryAst2(getAst(cte.plan), state, dialect, { emitCtes: false });
4657
4572
  state.ctes.push({
4658
4573
  name: cte.name,
4659
4574
  sql: rendered.sql,
@@ -4665,11 +4580,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
4665
4580
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
4666
4581
  const derived = source;
4667
4582
  if (!state.cteNames.has(derived.name)) {}
4668
- return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
4583
+ return `(${renderQueryAst2(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
4669
4584
  }
4670
4585
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
4671
4586
  const lateral = source;
4672
- return `lateral (${renderQueryAst(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
4587
+ if (dialect.name === "standard") {
4588
+ throw new Error("Unsupported standard lateral source");
4589
+ }
4590
+ return `lateral (${renderQueryAst2(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
4673
4591
  }
4674
4592
  if (typeof source === "object" && source !== null && source.kind === "values") {
4675
4593
  const values = source;
@@ -4684,168 +4602,219 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
4684
4602
  if (dialect.name !== "postgres") {
4685
4603
  throw new Error("Unsupported table function source for SQL rendering");
4686
4604
  }
4605
+ const functionName = renderFunctionName(tableFunction.functionName);
4687
4606
  const columnNames = Object.keys(tableFunction.columns);
4688
- return `${tableFunction.functionName}(${tableFunction.args.map((arg) => renderExpression(arg, state, dialect)).join(", ")}) as ${dialect.quoteIdentifier(tableFunction.name)}(${columnNames.map((columnName) => dialect.quoteIdentifier(columnName)).join(", ")})`;
4607
+ return `${functionName}(${tableFunction.args.map((arg) => renderExpression2(arg, state, dialect)).join(", ")}) as ${dialect.quoteIdentifier(tableFunction.name)}(${columnNames.map((columnName) => dialect.quoteIdentifier(columnName)).join(", ")})`;
4689
4608
  }
4690
- const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
4691
- return dialect.renderTableReference(tableName, baseTableName, schemaName);
4609
+ const schemaName = typeof source === "object" && source !== null && TypeId6 in source ? casedSchemaName(source, state) : undefined;
4610
+ if (typeof source === "object" && source !== null && TypeId6 in source) {
4611
+ const table = source;
4612
+ const renderedBaseName = casedTableName(table, state);
4613
+ const renderedTableName = table[TypeId6].kind === "alias" ? tableName : renderedBaseName;
4614
+ return dialect.renderTableReference(renderedTableName, renderedBaseName, schemaName);
4615
+ }
4616
+ return dialect.renderTableReference(applyCategory(state.casing, "tables", tableName), applyCategory(state.casing, "tables", baseTableName), schemaName);
4692
4617
  };
4693
4618
  var renderSubqueryExpressionPlan = (plan, state, dialect) => {
4694
4619
  const statement = getQueryState(plan).statement;
4695
4620
  if (statement !== "select" && statement !== "set") {
4696
4621
  throw new Error("subquery expressions only accept select-like query plans");
4697
4622
  }
4698
- return renderQueryAst(getAst(plan), state, dialect).sql;
4623
+ return renderQueryAst2(getAst(plan), state, dialect).sql;
4699
4624
  };
4700
- var renderExpression = (expression, state, dialect) => {
4625
+ var renderExpression2 = (expression, state, dialect) => {
4701
4626
  const rawAst = expression[TypeId3];
4702
4627
  const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
4703
4628
  if (jsonSql !== undefined) {
4704
4629
  return jsonSql;
4705
4630
  }
4706
4631
  const ast = rawAst;
4707
- const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
4632
+ const renderComparisonOperator = (operator) => ({
4633
+ eq: "=",
4634
+ neq: "<>",
4635
+ lt: "<",
4636
+ lte: "<=",
4637
+ gt: ">",
4638
+ gte: ">="
4639
+ })[operator];
4640
+ const renderCollation = (collation) => {
4641
+ return collation.map((segment) => dialect.quoteIdentifier(segment)).join(".");
4642
+ };
4708
4643
  switch (ast.kind) {
4709
4644
  case "column":
4710
- return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
4645
+ return state.rowLocalColumns || ast.tableName.length === 0 ? quoteColumn(ast.columnName, state, dialect, ast.tableName) : `${dialect.quoteIdentifier(casedTableReferenceName(ast.tableName, state))}.${quoteColumn(ast.columnName, state, dialect, ast.tableName)}`;
4711
4646
  case "literal":
4712
4647
  if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
4713
4648
  throw new Error("Expected a finite numeric value");
4714
4649
  }
4715
4650
  return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
4716
4651
  case "excluded":
4717
- return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
4652
+ if (state.allowExcluded !== true) {
4653
+ throw new Error("excluded(...) is only supported inside insert conflict handlers");
4654
+ }
4655
+ return dialect.name === "mysql" ? `values(${quoteColumn(ast.columnName, state, dialect)})` : `excluded.${quoteColumn(ast.columnName, state, dialect)}`;
4718
4656
  case "cast":
4719
- return `cast(${renderExpression(ast.value, state, dialect)} as ${renderCastType(dialect, ast.target)})`;
4657
+ return `cast(${renderExpression2(expectValueExpression("cast", ast.value), state, dialect)} as ${renderCastType(dialect, ast.target)})`;
4720
4658
  case "collate":
4721
- return `(${renderExpression(ast.value, state, dialect)} collate ${ast.collation.map((segment) => dialect.quoteIdentifier(segment)).join(".")})`;
4659
+ return `(${renderExpression2(expectValueExpression("collate", ast.value), state, dialect)} collate ${renderCollation(ast.collation)})`;
4722
4660
  case "function":
4723
- return renderFunctionCall(ast.name, Array.isArray(ast.args) ? ast.args : [], state, dialect);
4661
+ return renderFunctionCall(ast.name, ast.args, state, dialect);
4724
4662
  case "eq":
4725
- return `(${renderExpression(ast.left, state, dialect)} = ${renderExpression(ast.right, state, dialect)})`;
4663
+ return renderBinaryExpression("eq", "=", ast.left, ast.right, state, dialect);
4726
4664
  case "neq":
4727
- return `(${renderExpression(ast.left, state, dialect)} <> ${renderExpression(ast.right, state, dialect)})`;
4665
+ return renderBinaryExpression("neq", "<>", ast.left, ast.right, state, dialect);
4728
4666
  case "lt":
4729
- return `(${renderExpression(ast.left, state, dialect)} < ${renderExpression(ast.right, state, dialect)})`;
4667
+ return renderBinaryExpression("lt", "<", ast.left, ast.right, state, dialect);
4730
4668
  case "lte":
4731
- return `(${renderExpression(ast.left, state, dialect)} <= ${renderExpression(ast.right, state, dialect)})`;
4669
+ return renderBinaryExpression("lte", "<=", ast.left, ast.right, state, dialect);
4732
4670
  case "gt":
4733
- return `(${renderExpression(ast.left, state, dialect)} > ${renderExpression(ast.right, state, dialect)})`;
4671
+ return renderBinaryExpression("gt", ">", ast.left, ast.right, state, dialect);
4734
4672
  case "gte":
4735
- return `(${renderExpression(ast.left, state, dialect)} >= ${renderExpression(ast.right, state, dialect)})`;
4673
+ return renderBinaryExpression("gte", ">=", ast.left, ast.right, state, dialect);
4736
4674
  case "like":
4737
- return `(${renderExpression(ast.left, state, dialect)} like ${renderExpression(ast.right, state, dialect)})`;
4738
- case "ilike":
4739
- return dialect.name === "postgres" ? `(${renderExpression(ast.left, state, dialect)} ilike ${renderExpression(ast.right, state, dialect)})` : `(lower(${renderExpression(ast.left, state, dialect)}) like lower(${renderExpression(ast.right, state, dialect)}))`;
4740
- case "regexMatch":
4741
- return dialect.name === "postgres" ? `(${renderExpression(ast.left, state, dialect)} ~ ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} regexp ${renderExpression(ast.right, state, dialect)})`;
4742
- case "regexIMatch":
4743
- return dialect.name === "postgres" ? `(${renderExpression(ast.left, state, dialect)} ~* ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} regexp ${renderExpression(ast.right, state, dialect)})`;
4744
- case "regexNotMatch":
4745
- return dialect.name === "postgres" ? `(${renderExpression(ast.left, state, dialect)} !~ ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} not regexp ${renderExpression(ast.right, state, dialect)})`;
4746
- case "regexNotIMatch":
4747
- return dialect.name === "postgres" ? `(${renderExpression(ast.left, state, dialect)} !~* ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} not regexp ${renderExpression(ast.right, state, dialect)})`;
4748
- case "isDistinctFrom":
4749
- return dialect.name === "mysql" ? `(not (${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)}))` : `(${renderExpression(ast.left, state, dialect)} is distinct from ${renderExpression(ast.right, state, dialect)})`;
4750
- case "isNotDistinctFrom":
4751
- return dialect.name === "mysql" ? `(${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} is not distinct from ${renderExpression(ast.right, state, dialect)})`;
4752
- case "contains":
4675
+ return renderBinaryExpression("like", "like", ast.left, ast.right, state, dialect);
4676
+ case "ilike": {
4677
+ const [left, right] = expectBinaryExpressions("ilike", ast.left, ast.right);
4678
+ return dialect.name === "postgres" ? `(${renderExpression2(left, state, dialect)} ilike ${renderExpression2(right, state, dialect)})` : `(lower(${renderExpression2(left, state, dialect)}) like lower(${renderExpression2(right, state, dialect)}))`;
4679
+ }
4680
+ case "regexMatch": {
4681
+ const [left, right] = expectBinaryExpressions("regexMatch", ast.left, ast.right);
4682
+ if (dialect.name === "standard") {
4683
+ throw new Error("Unsupported standard regular-expression predicates");
4684
+ }
4685
+ return dialect.name === "postgres" ? `(${renderExpression2(left, state, dialect)} ~ ${renderExpression2(right, state, dialect)})` : `(${renderExpression2(left, state, dialect)} regexp ${renderExpression2(right, state, dialect)})`;
4686
+ }
4687
+ case "regexIMatch": {
4688
+ const [left, right] = expectBinaryExpressions("regexIMatch", ast.left, ast.right);
4689
+ if (dialect.name === "standard") {
4690
+ throw new Error("Unsupported standard regular-expression predicates");
4691
+ }
4692
+ return dialect.name === "postgres" ? `(${renderExpression2(left, state, dialect)} ~* ${renderExpression2(right, state, dialect)})` : `(${renderExpression2(left, state, dialect)} regexp ${renderExpression2(right, state, dialect)})`;
4693
+ }
4694
+ case "regexNotMatch": {
4695
+ const [left, right] = expectBinaryExpressions("regexNotMatch", ast.left, ast.right);
4696
+ if (dialect.name === "standard") {
4697
+ throw new Error("Unsupported standard regular-expression predicates");
4698
+ }
4699
+ return dialect.name === "postgres" ? `(${renderExpression2(left, state, dialect)} !~ ${renderExpression2(right, state, dialect)})` : `(${renderExpression2(left, state, dialect)} not regexp ${renderExpression2(right, state, dialect)})`;
4700
+ }
4701
+ case "regexNotIMatch": {
4702
+ const [left, right] = expectBinaryExpressions("regexNotIMatch", ast.left, ast.right);
4703
+ if (dialect.name === "standard") {
4704
+ throw new Error("Unsupported standard regular-expression predicates");
4705
+ }
4706
+ return dialect.name === "postgres" ? `(${renderExpression2(left, state, dialect)} !~* ${renderExpression2(right, state, dialect)})` : `(${renderExpression2(left, state, dialect)} not regexp ${renderExpression2(right, state, dialect)})`;
4707
+ }
4708
+ case "isDistinctFrom": {
4709
+ const [left, right] = expectBinaryExpressions("isDistinctFrom", ast.left, ast.right);
4710
+ return dialect.name === "mysql" ? `(not (${renderExpression2(left, state, dialect)} <=> ${renderExpression2(right, state, dialect)}))` : `(${renderExpression2(left, state, dialect)} is distinct from ${renderExpression2(right, state, dialect)})`;
4711
+ }
4712
+ case "isNotDistinctFrom": {
4713
+ const [left, right] = expectBinaryExpressions("isNotDistinctFrom", ast.left, ast.right);
4714
+ return dialect.name === "mysql" ? `(${renderExpression2(left, state, dialect)} <=> ${renderExpression2(right, state, dialect)})` : `(${renderExpression2(left, state, dialect)} is not distinct from ${renderExpression2(right, state, dialect)})`;
4715
+ }
4716
+ case "contains": {
4717
+ const [leftExpression, rightExpression] = expectBinaryExpressions("contains", ast.left, ast.right);
4753
4718
  if (dialect.name === "postgres") {
4754
- assertCompatiblePostgresRangeOperands(ast.left, ast.right);
4755
- const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
4756
- const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
4719
+ assertCompatiblePostgresRangeOperands(leftExpression, rightExpression);
4720
+ const left = isJsonExpression(leftExpression) ? renderPostgresJsonValue(leftExpression, state, dialect) : renderExpression2(leftExpression, state, dialect);
4721
+ const right = isJsonExpression(rightExpression) ? renderPostgresJsonValue(rightExpression, state, dialect) : renderExpression2(rightExpression, state, dialect);
4757
4722
  return `(${left} @> ${right})`;
4758
4723
  }
4759
- if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
4760
- return `json_contains(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
4724
+ if (dialect.name === "mysql" && isJsonExpression(leftExpression) && isJsonExpression(rightExpression)) {
4725
+ return `json_contains(${renderExpression2(leftExpression, state, dialect)}, ${renderExpression2(rightExpression, state, dialect)})`;
4761
4726
  }
4762
4727
  throw new Error("Unsupported container operator for SQL rendering");
4763
- case "containedBy":
4728
+ }
4729
+ case "containedBy": {
4730
+ const [leftExpression, rightExpression] = expectBinaryExpressions("containedBy", ast.left, ast.right);
4764
4731
  if (dialect.name === "postgres") {
4765
- assertCompatiblePostgresRangeOperands(ast.left, ast.right);
4766
- const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
4767
- const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
4732
+ assertCompatiblePostgresRangeOperands(leftExpression, rightExpression);
4733
+ const left = isJsonExpression(leftExpression) ? renderPostgresJsonValue(leftExpression, state, dialect) : renderExpression2(leftExpression, state, dialect);
4734
+ const right = isJsonExpression(rightExpression) ? renderPostgresJsonValue(rightExpression, state, dialect) : renderExpression2(rightExpression, state, dialect);
4768
4735
  return `(${left} <@ ${right})`;
4769
4736
  }
4770
- if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
4771
- return `json_contains(${renderExpression(ast.right, state, dialect)}, ${renderExpression(ast.left, state, dialect)})`;
4737
+ if (dialect.name === "mysql" && isJsonExpression(leftExpression) && isJsonExpression(rightExpression)) {
4738
+ return `json_contains(${renderExpression2(rightExpression, state, dialect)}, ${renderExpression2(leftExpression, state, dialect)})`;
4772
4739
  }
4773
4740
  throw new Error("Unsupported container operator for SQL rendering");
4774
- case "overlaps":
4741
+ }
4742
+ case "overlaps": {
4743
+ const [leftExpression, rightExpression] = expectBinaryExpressions("overlaps", ast.left, ast.right);
4775
4744
  if (dialect.name === "postgres") {
4776
- assertCompatiblePostgresRangeOperands(ast.left, ast.right);
4777
- const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
4778
- const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
4745
+ assertCompatiblePostgresRangeOperands(leftExpression, rightExpression);
4746
+ const left = isJsonExpression(leftExpression) ? renderPostgresJsonValue(leftExpression, state, dialect) : renderExpression2(leftExpression, state, dialect);
4747
+ const right = isJsonExpression(rightExpression) ? renderPostgresJsonValue(rightExpression, state, dialect) : renderExpression2(rightExpression, state, dialect);
4779
4748
  return `(${left} && ${right})`;
4780
4749
  }
4781
- if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
4782
- return `json_overlaps(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
4750
+ if (dialect.name === "mysql" && isJsonExpression(leftExpression) && isJsonExpression(rightExpression)) {
4751
+ return `json_overlaps(${renderExpression2(leftExpression, state, dialect)}, ${renderExpression2(rightExpression, state, dialect)})`;
4783
4752
  }
4784
4753
  throw new Error("Unsupported container operator for SQL rendering");
4754
+ }
4785
4755
  case "isNull":
4786
- return `(${renderExpression(ast.value, state, dialect)} is null)`;
4756
+ return `(${renderExpression2(expectValueExpression("isNull", ast.value), state, dialect)} is null)`;
4787
4757
  case "isNotNull":
4788
- return `(${renderExpression(ast.value, state, dialect)} is not null)`;
4758
+ return `(${renderExpression2(expectValueExpression("isNotNull", ast.value), state, dialect)} is not null)`;
4789
4759
  case "not":
4790
- return `(not ${renderExpression(ast.value, state, dialect)})`;
4760
+ return `(not ${renderExpression2(expectValueExpression("not", ast.value), state, dialect)})`;
4791
4761
  case "upper":
4792
- return `upper(${renderExpression(ast.value, state, dialect)})`;
4762
+ return `upper(${renderExpression2(expectValueExpression("upper", ast.value), state, dialect)})`;
4793
4763
  case "lower":
4794
- return `lower(${renderExpression(ast.value, state, dialect)})`;
4764
+ return `lower(${renderExpression2(expectValueExpression("lower", ast.value), state, dialect)})`;
4795
4765
  case "count":
4796
- return `count(${renderExpression(ast.value, state, dialect)})`;
4766
+ return `count(${renderExpression2(expectValueExpression("count", ast.value), state, dialect)})`;
4797
4767
  case "max":
4798
- return `max(${renderExpression(ast.value, state, dialect)})`;
4768
+ return `max(${renderExpression2(expectValueExpression("max", ast.value), state, dialect)})`;
4799
4769
  case "min":
4800
- return `min(${renderExpression(ast.value, state, dialect)})`;
4770
+ return `min(${renderExpression2(expectValueExpression("min", ast.value), state, dialect)})`;
4801
4771
  case "and":
4802
- if (ast.values.length === 0) {
4803
- throw new Error("and(...) requires at least one predicate");
4804
- }
4805
- return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
4772
+ return `(${ast.values.map((value) => renderExpression2(value, state, dialect)).join(" and ")})`;
4806
4773
  case "or":
4807
- if (ast.values.length === 0) {
4808
- throw new Error("or(...) requires at least one predicate");
4809
- }
4810
- return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
4774
+ return `(${ast.values.map((value) => renderExpression2(value, state, dialect)).join(" or ")})`;
4811
4775
  case "coalesce":
4812
- return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
4776
+ return `coalesce(${ast.values.map((value) => renderExpression2(value, state, dialect)).join(", ")})`;
4813
4777
  case "in":
4814
- if (ast.values.length < 2) {
4815
- throw new Error("in(...) requires at least one candidate value");
4816
- }
4817
- return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
4778
+ return `(${renderExpression2(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression2(value, state, dialect)).join(", ")}))`;
4818
4779
  case "notIn":
4819
- if (ast.values.length < 2) {
4820
- throw new Error("notIn(...) requires at least one candidate value");
4821
- }
4822
- return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
4780
+ return `(${renderExpression2(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression2(value, state, dialect)).join(", ")}))`;
4823
4781
  case "between":
4824
- return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
4782
+ return `(${renderExpression2(ast.values[0], state, dialect)} between ${renderExpression2(ast.values[1], state, dialect)} and ${renderExpression2(ast.values[2], state, dialect)})`;
4825
4783
  case "concat":
4826
- return dialect.renderConcat(ast.values.map((value) => renderExpression(value, state, dialect)));
4784
+ return dialect.renderConcat(ast.values.map((value) => renderExpression2(value, state, dialect)));
4827
4785
  case "case":
4828
- return `case ${ast.branches.map((branch) => `when ${renderExpression(branch.when, state, dialect)} then ${renderExpression(branch.then, state, dialect)}`).join(" ")} else ${renderExpression(ast.else, state, dialect)} end`;
4786
+ return `case ${ast.branches.map((branch) => `when ${renderExpression2(branch.when, state, dialect)} then ${renderExpression2(branch.then, state, dialect)}`).join(" ")} else ${renderExpression2(ast.else, state, dialect)} end`;
4829
4787
  case "exists":
4830
4788
  return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
4831
4789
  case "scalarSubquery":
4832
4790
  return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
4833
4791
  case "inSubquery":
4834
- return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4835
- case "comparisonAny":
4836
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4837
- case "comparisonAll":
4838
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4839
- case "window": {
4840
- if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
4841
- break;
4792
+ return `(${renderExpression2(expectValueExpression("inSubquery", ast.left), state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4793
+ case "comparisonAny": {
4794
+ const left = expectValueExpression("compareAny", ast.left);
4795
+ const operator = renderComparisonOperator(ast.operator);
4796
+ if (dialect.name === "standard") {
4797
+ throw new Error("Unsupported standard quantified comparison");
4798
+ }
4799
+ return `(${renderExpression2(left, state, dialect)} ${operator} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4800
+ }
4801
+ case "comparisonAll": {
4802
+ const left = expectValueExpression("compareAll", ast.left);
4803
+ const operator = renderComparisonOperator(ast.operator);
4804
+ if (dialect.name === "standard") {
4805
+ throw new Error("Unsupported standard quantified comparison");
4842
4806
  }
4807
+ return `(${renderExpression2(left, state, dialect)} ${operator} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
4808
+ }
4809
+ case "window": {
4810
+ const partitionBy = ast.partitionBy;
4811
+ const orderBy = ast.orderBy;
4843
4812
  const clauses = [];
4844
- if (ast.partitionBy.length > 0) {
4845
- clauses.push(`partition by ${ast.partitionBy.map((value) => renderExpression(value, state, dialect)).join(", ")}`);
4813
+ if (partitionBy.length > 0) {
4814
+ clauses.push(`partition by ${partitionBy.map((value) => renderExpression2(value, state, dialect)).join(", ")}`);
4846
4815
  }
4847
- if (ast.orderBy.length > 0) {
4848
- clauses.push(`order by ${ast.orderBy.map((entry) => `${renderExpression(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`);
4816
+ if (orderBy.length > 0) {
4817
+ clauses.push(`order by ${orderBy.map((entry) => `${renderExpression2(entry.value, state, dialect)} ${entry.direction}`).join(", ")}`);
4849
4818
  }
4850
4819
  const specification = clauses.join(" ");
4851
4820
  switch (ast.function) {
@@ -4856,7 +4825,7 @@ var renderExpression = (expression, state, dialect) => {
4856
4825
  case "denseRank":
4857
4826
  return `dense_rank() over (${specification})`;
4858
4827
  case "over":
4859
- return `${renderExpression(ast.value, state, dialect)} over (${specification})`;
4828
+ return `${renderExpression2(ast.value, state, dialect)} over (${specification})`;
4860
4829
  }
4861
4830
  break;
4862
4831
  }
@@ -4864,12 +4833,41 @@ var renderExpression = (expression, state, dialect) => {
4864
4833
  throw new Error("Unsupported expression for SQL rendering");
4865
4834
  };
4866
4835
 
4867
- // src/postgres/internal/schema-ddl.ts
4868
- import { parse as parse2, toSql as toSql2 } from "pgsql-ast-parser";
4836
+ // src/standard/dialect.ts
4837
+ var quoteIdentifier = quoteDoubleQuotedIdentifier;
4838
+ var renderLiteral = (value, state, context = {}) => {
4839
+ const driverValue = toDriverValue(value, {
4840
+ dialect: "standard",
4841
+ valueMappings: state.valueMappings,
4842
+ ...context
4843
+ });
4844
+ if (driverValue === null) {
4845
+ return "null";
4846
+ }
4847
+ if (typeof driverValue === "boolean") {
4848
+ return driverValue ? "true" : "false";
4849
+ }
4850
+ state.params.push(driverValue);
4851
+ return "?";
4852
+ };
4853
+ var standardDialect = {
4854
+ name: "standard",
4855
+ quoteIdentifier,
4856
+ renderLiteral,
4857
+ renderTableReference(tableName, baseTableName, schemaName) {
4858
+ const renderedBase = schemaName && schemaName !== "public" ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}` : quoteIdentifier(baseTableName);
4859
+ return tableName === baseTableName ? renderedBase : `${renderedBase} as ${quoteIdentifier(tableName)}`;
4860
+ },
4861
+ renderConcat(values) {
4862
+ return `(${values.join(" || ")})`;
4863
+ },
4864
+ renderQueryAst: renderQueryAst2,
4865
+ renderExpression: renderExpression2
4866
+ };
4869
4867
 
4870
4868
  // src/postgres/internal/dialect.ts
4871
- var quoteIdentifier = (value) => `"${value.replaceAll('"', '""')}"`;
4872
- var renderLiteral = (value, state, context = {}) => {
4869
+ var quoteIdentifier2 = quoteDoubleQuotedIdentifier;
4870
+ var renderLiteral2 = (value, state, context = {}) => {
4873
4871
  const driverValue = toDriverValue(value, {
4874
4872
  dialect: "postgres",
4875
4873
  valueMappings: state.valueMappings,
@@ -4885,16 +4883,19 @@ var renderLiteral = (value, state, context = {}) => {
4885
4883
  return `$${state.params.length}`;
4886
4884
  };
4887
4885
  var postgresDialect = {
4886
+ ...standardDialect,
4888
4887
  name: "postgres",
4889
- quoteIdentifier,
4890
- renderLiteral,
4888
+ quoteIdentifier: quoteIdentifier2,
4889
+ renderLiteral: renderLiteral2,
4891
4890
  renderTableReference(tableName, baseTableName, schemaName) {
4892
- const renderedBase = schemaName ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}` : quoteIdentifier(baseTableName);
4893
- return tableName === baseTableName ? renderedBase : `${renderedBase} as ${quoteIdentifier(tableName)}`;
4891
+ const renderedBase = schemaName && schemaName !== "public" ? `${quoteIdentifier2(schemaName)}.${quoteIdentifier2(baseTableName)}` : quoteIdentifier2(baseTableName);
4892
+ return tableName === baseTableName ? renderedBase : `${renderedBase} as ${quoteIdentifier2(tableName)}`;
4894
4893
  },
4895
4894
  renderConcat(values) {
4896
4895
  return `(${values.join(" || ")})`;
4897
- }
4896
+ },
4897
+ renderQueryAst: renderQueryAst2,
4898
+ renderExpression: renderExpression2
4898
4899
  };
4899
4900
 
4900
4901
  // src/postgres/internal/schema-ddl.ts
@@ -4912,17 +4913,22 @@ var inlineLiteralDialect = {
4912
4913
  return String(value);
4913
4914
  }
4914
4915
  if (value instanceof Date) {
4916
+ if (Number.isNaN(value.getTime())) {
4917
+ throw new Error("Expected a valid Date value");
4918
+ }
4915
4919
  return escapeString(value.toISOString());
4916
4920
  }
4917
4921
  return escapeString(String(value));
4918
4922
  }
4919
4923
  };
4920
- var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
4924
+ var makeExpressionState = (state = {}) => ({
4925
+ ...state,
4921
4926
  params: [],
4922
4927
  ctes: [],
4923
4928
  cteNames: new Set,
4924
4929
  cteSources: new Map
4925
- }, inlineLiteralDialect);
4930
+ });
4931
+ var renderDdlExpressionSql = (expression, state) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, makeExpressionState(state), inlineLiteralDialect);
4926
4932
  var stripRedundantOuterParens = (value) => {
4927
4933
  let current = value.trim();
4928
4934
  while (current.startsWith("(") && current.endsWith(")")) {
@@ -4962,8 +4968,8 @@ var stripRedundantOuterParens = (value) => {
4962
4968
  return current;
4963
4969
  };
4964
4970
  var canonicalizeDdlExpressionSql = (value) => stripRedundantOuterParens(value.trim().replace(/\s+/g, " ").replace(/"[^"]+"\./g, "").replace(/"([A-Za-z_][A-Za-z0-9_]*)"/g, "$1").replace(/\bCOLLATE\b/g, "collate").replace(/cast\(((?:'(?:[^']|'')*'|"[^"]+"|[a-zA-Z_][a-zA-Z0-9_]*|\([^()]+\))) as ([^)]+)\)/gi, (_, expression, target) => `${expression}::${target.trim()}`));
4965
- var normalizeDdlExpressionSql = (expression) => {
4966
- const rendered = renderDdlExpressionSql(expression);
4971
+ var normalizeDdlExpressionSql = (expression, state) => {
4972
+ const rendered = renderDdlExpressionSql(expression, state);
4967
4973
  try {
4968
4974
  return canonicalizeDdlExpressionSql(toSql2.expr(parse2(rendered, "expr")));
4969
4975
  } catch {
@@ -4977,8 +4983,8 @@ import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
4977
4983
  var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
4978
4984
  var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
4979
4985
  var safeUnquotedIdentifier = /^[a-z_][a-z0-9_$]*$/;
4980
- var quoteIdentifier2 = (value) => `"${value.replaceAll('"', '""')}"`;
4981
- var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier2(value);
4986
+ var quoteIdentifier3 = (value) => `"${value.replaceAll('"', '""')}"`;
4987
+ var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier3(value);
4982
4988
  var renderQualifiedTypeName = (name, schemaName) => schemaName === undefined || schemaName === "public" ? renderIdentifier(name) : `${renderIdentifier(schemaName)}.${renderIdentifier(name)}`;
4983
4989
  var EnumProto = {
4984
4990
  pipe() {
@@ -4995,7 +5001,11 @@ var EnumProto = {
4995
5001
  };
4996
5002
  },
4997
5003
  column() {
4998
- const values = this.values.map((value) => Schema6.Literal(value));
5004
+ const [first, ...rest] = this.values;
5005
+ const values = [
5006
+ Schema6.Literal(first),
5007
+ ...rest.map((value) => Schema6.Literal(value))
5008
+ ];
4999
5009
  return makeColumnDefinition(values.length === 1 ? values[0] : Schema6.Union(...values), {
5000
5010
  dbType: this.type(),
5001
5011
  nullable: false,
@@ -5049,17 +5059,123 @@ function sequence(name, schemaName) {
5049
5059
  var isSequenceDefinition = (value) => typeof value === "object" && value !== null && (SequenceTypeId in value);
5050
5060
 
5051
5061
  // src/postgres/internal/schema-model.ts
5052
- var isTableDefinition = (value) => value !== null && (typeof value === "object" || typeof value === "function") && (TypeId4 in value);
5062
+ var isTableDefinition = (value) => value !== null && (typeof value === "object" || typeof value === "function") && (TypeId6 in value);
5053
5063
  var isEnumDefinition = (value) => typeof value === "object" && value !== null && (EnumTypeId in value);
5064
+ var applyCasing = (casing, category, name) => applyCategory(casing, category, name);
5065
+ var mapColumnList = (columns, casing) => !Array.isArray(columns) ? columns : columns.length === 0 ? columns : [
5066
+ mapCasedValue(columns[0], casing, "columns"),
5067
+ ...columns.slice(1).map((column) => mapCasedValue(column, casing, "columns"))
5068
+ ];
5069
+ var expressionStateForTable = (state, tableName, columns, casing) => ({
5070
+ casing,
5071
+ rowLocalColumns: true,
5072
+ sourceNames: new Map([
5073
+ [state.name, { tableName, columns }],
5074
+ [state.baseName, { tableName, columns }]
5075
+ ])
5076
+ });
5077
+ var mapDdlExpression = (expression, state) => fromSql(normalizeDdlExpressionSql(expression, state));
5078
+ function mapOptionName(name, casing, category) {
5079
+ return typeof name === "string" ? applyCasing(casing, category, name) : name;
5080
+ }
5081
+ function mapCasedValue(value, casing, category) {
5082
+ return typeof value === "string" ? applyCasing(casing, category, value) : value;
5083
+ }
5084
+ var isDdlExpressionLike = (value) => typeof value === "object" && value !== null && ((TypeId2 in value) || (TypeId4 in value));
5085
+ function mapIndexKey(key2, casing, expressionState) {
5086
+ if (typeof key2 !== "object" || key2 === null || !("kind" in key2)) {
5087
+ return key2;
5088
+ }
5089
+ const kind = key2.kind;
5090
+ if (kind === "column") {
5091
+ const column = key2.column;
5092
+ return typeof column === "string" ? {
5093
+ ...key2,
5094
+ column: applyCasing(casing, "columns", column)
5095
+ } : key2;
5096
+ }
5097
+ if (kind === "expression") {
5098
+ const expression = key2.expression;
5099
+ return isDdlExpressionLike(expression) ? {
5100
+ ...key2,
5101
+ expression: mapDdlExpression(expression, expressionState)
5102
+ } : key2;
5103
+ }
5104
+ return key2;
5105
+ }
5106
+ var mapOption = (option2, casing, expressionState) => {
5107
+ switch (option2.kind) {
5108
+ case "index":
5109
+ return {
5110
+ ...option2,
5111
+ columns: option2.columns === undefined ? undefined : mapColumnList(option2.columns, casing),
5112
+ name: option2.name === undefined ? undefined : mapOptionName(option2.name, casing, "indexes"),
5113
+ include: option2.include === undefined ? undefined : Array.isArray(option2.include) ? option2.include.map((column) => mapCasedValue(column, casing, "columns")) : option2.include,
5114
+ predicate: option2.predicate === undefined ? undefined : isDdlExpressionLike(option2.predicate) ? mapDdlExpression(option2.predicate, expressionState) : option2.predicate,
5115
+ keys: option2.keys === undefined ? undefined : Array.isArray(option2.keys) ? option2.keys.length === 0 ? option2.keys : [
5116
+ mapIndexKey(option2.keys[0], casing, expressionState),
5117
+ ...option2.keys.slice(1).map((key2) => mapIndexKey(key2, casing, expressionState))
5118
+ ] : option2.keys
5119
+ };
5120
+ case "primaryKey":
5121
+ return {
5122
+ ...option2,
5123
+ columns: mapColumnList(option2.columns, casing),
5124
+ name: option2.name === undefined ? undefined : mapOptionName(option2.name, casing, "constraints")
5125
+ };
5126
+ case "unique":
5127
+ return {
5128
+ ...option2,
5129
+ columns: mapColumnList(option2.columns, casing),
5130
+ name: option2.name === undefined ? undefined : mapOptionName(option2.name, casing, "constraints")
5131
+ };
5132
+ case "foreignKey":
5133
+ return {
5134
+ ...option2,
5135
+ columns: mapColumnList(option2.columns, casing),
5136
+ name: option2.name === undefined ? undefined : mapOptionName(option2.name, casing, "constraints"),
5137
+ references: () => {
5138
+ const reference = typeof option2.references === "function" ? option2.references() : option2.references;
5139
+ if (typeof reference !== "object" || reference === null) {
5140
+ return reference;
5141
+ }
5142
+ const referenceCasing2 = reference.casing;
5143
+ return {
5144
+ ...reference,
5145
+ tableName: mapCasedValue(reference.tableName, referenceCasing2, "tables"),
5146
+ schemaName: reference.schemaName === undefined ? undefined : mapCasedValue(reference.schemaName, referenceCasing2, "schemas"),
5147
+ columns: mapColumnList(reference.columns, referenceCasing2),
5148
+ knownColumns: reference.knownColumns === undefined ? undefined : Array.isArray(reference.knownColumns) ? reference.knownColumns.map((column) => mapCasedValue(column, referenceCasing2, "columns")) : reference.knownColumns
5149
+ };
5150
+ }
5151
+ };
5152
+ case "check":
5153
+ return {
5154
+ ...option2,
5155
+ name: mapOptionName(option2.name, casing, "constraints"),
5156
+ predicate: isDdlExpressionLike(option2.predicate) ? mapDdlExpression(option2.predicate, expressionState) : option2.predicate
5157
+ };
5158
+ default:
5159
+ return option2;
5160
+ }
5161
+ };
5054
5162
  var toTableModel = (table) => {
5055
- const state = table[TypeId4];
5163
+ const state = table[TypeId6];
5164
+ const casing = state.casing;
5165
+ const tableName = applyCasing(casing, "tables", state.baseName);
5166
+ const schemaName = state.schemaName === undefined ? undefined : applyCasing(casing, "schemas", state.schemaName);
5056
5167
  const fields = state.fields;
5168
+ const options2 = table[OptionsSymbol];
5169
+ const normalizedOptions = Array.isArray(options2) ? options2 : [options2];
5170
+ validateOptions(state.name, fields, normalizedOptions);
5171
+ const columnNames = new Map(Object.keys(fields).map((name) => [name, applyCasing(casing, "columns", name)]));
5172
+ const expressionState = expressionStateForTable(state, tableName, columnNames, casing);
5057
5173
  const columns = Object.entries(fields).map(([name, column]) => {
5058
5174
  const metadata = column.metadata;
5059
5175
  const enumDefinition = metadata.enum;
5060
5176
  const ddlType = metadata.ddlType ?? metadata.dbType.kind;
5061
5177
  return {
5062
- name,
5178
+ name: columnNames.get(name) ?? name,
5063
5179
  ddlType,
5064
5180
  dbTypeKind: enumDefinition?.name ?? column.metadata.dbType.kind,
5065
5181
  typeKind: enumDefinition === undefined ? undefined : "e",
@@ -5067,18 +5183,18 @@ var toTableModel = (table) => {
5067
5183
  nullable: column.metadata.nullable,
5068
5184
  hasDefault: column.metadata.hasDefault,
5069
5185
  generated: column.metadata.generated,
5070
- defaultSql: column.metadata.defaultValue === undefined ? undefined : normalizeDdlExpressionSql(column.metadata.defaultValue),
5071
- generatedSql: column.metadata.generatedValue === undefined ? undefined : normalizeDdlExpressionSql(column.metadata.generatedValue),
5186
+ defaultSql: column.metadata.defaultValue === undefined ? undefined : normalizeDdlExpressionSql(column.metadata.defaultValue, expressionState),
5187
+ generatedSql: column.metadata.generatedValue === undefined ? undefined : normalizeDdlExpressionSql(column.metadata.generatedValue, expressionState),
5072
5188
  identity: column.metadata.identity,
5073
5189
  column
5074
5190
  };
5075
5191
  });
5076
5192
  return {
5077
5193
  kind: "table",
5078
- schemaName: state.schemaName,
5079
- name: state.baseName,
5194
+ schemaName,
5195
+ name: tableName,
5080
5196
  columns,
5081
- options: table[OptionsSymbol],
5197
+ options: normalizedOptions.map((option2) => typeof option2 === "object" && option2 !== null && ("kind" in option2) ? mapOption(option2, casing, expressionState) : option2),
5082
5198
  table
5083
5199
  };
5084
5200
  };
@@ -5089,7 +5205,7 @@ var toEnumModel = (definition) => ({
5089
5205
  values: [...definition.values]
5090
5206
  });
5091
5207
  var enumModelsOfTable = (table) => {
5092
- const state = table[TypeId4];
5208
+ const state = table[TypeId6];
5093
5209
  const fields = state.fields;
5094
5210
  return Object.values(fields).flatMap((column) => column.metadata.enum === undefined ? [] : [
5095
5211
  {