effect-qb 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/mysql.js +1957 -595
  2. package/dist/postgres/metadata.js +2507 -182
  3. package/dist/postgres.js +9587 -8201
  4. package/dist/sqlite.js +8360 -0
  5. package/package.json +7 -2
  6. package/src/internal/column-state.ts +7 -0
  7. package/src/internal/column.ts +22 -0
  8. package/src/internal/derived-table.ts +29 -3
  9. package/src/internal/dialect.ts +14 -1
  10. package/src/internal/dsl-mutation-runtime.ts +173 -4
  11. package/src/internal/dsl-plan-runtime.ts +165 -20
  12. package/src/internal/dsl-query-runtime.ts +60 -6
  13. package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
  14. package/src/internal/executor.ts +62 -13
  15. package/src/internal/expression-ast.ts +3 -2
  16. package/src/internal/grouping-key.ts +141 -1
  17. package/src/internal/implication-runtime.ts +2 -1
  18. package/src/internal/json/types.ts +155 -40
  19. package/src/internal/predicate/analysis.ts +103 -1
  20. package/src/internal/predicate/atom.ts +7 -0
  21. package/src/internal/predicate/context.ts +170 -17
  22. package/src/internal/predicate/key.ts +64 -2
  23. package/src/internal/predicate/normalize.ts +115 -34
  24. package/src/internal/predicate/runtime.ts +144 -13
  25. package/src/internal/query.ts +563 -103
  26. package/src/internal/renderer.ts +39 -2
  27. package/src/internal/runtime/driver-value-mapping.ts +244 -0
  28. package/src/internal/runtime/normalize.ts +62 -38
  29. package/src/internal/runtime/schema.ts +5 -3
  30. package/src/internal/runtime/value.ts +153 -30
  31. package/src/internal/scalar.ts +11 -0
  32. package/src/internal/table-options.ts +108 -1
  33. package/src/internal/table.ts +87 -29
  34. package/src/mysql/column.ts +19 -2
  35. package/src/mysql/datatypes/index.ts +21 -0
  36. package/src/mysql/errors/catalog.ts +5 -5
  37. package/src/mysql/errors/normalize.ts +2 -2
  38. package/src/mysql/executor.ts +20 -5
  39. package/src/mysql/internal/dialect.ts +12 -6
  40. package/src/mysql/internal/dsl.ts +995 -263
  41. package/src/mysql/internal/renderer.ts +13 -3
  42. package/src/mysql/internal/sql-expression-renderer.ts +530 -128
  43. package/src/mysql/query.ts +9 -2
  44. package/src/mysql/renderer.ts +7 -2
  45. package/src/mysql/table.ts +38 -12
  46. package/src/postgres/cast.ts +22 -7
  47. package/src/postgres/column.ts +5 -2
  48. package/src/postgres/errors/normalize.ts +2 -2
  49. package/src/postgres/executor.ts +68 -10
  50. package/src/postgres/function/core.ts +19 -1
  51. package/src/postgres/internal/dialect.ts +12 -6
  52. package/src/postgres/internal/dsl.ts +958 -288
  53. package/src/postgres/internal/renderer.ts +13 -3
  54. package/src/postgres/internal/schema-ddl.ts +2 -1
  55. package/src/postgres/internal/schema-model.ts +6 -3
  56. package/src/postgres/internal/sql-expression-renderer.ts +477 -96
  57. package/src/postgres/json.ts +57 -17
  58. package/src/postgres/query.ts +9 -2
  59. package/src/postgres/renderer.ts +7 -2
  60. package/src/postgres/schema-management.ts +91 -4
  61. package/src/postgres/schema.ts +1 -1
  62. package/src/postgres/table.ts +189 -53
  63. package/src/postgres/type.ts +4 -0
  64. package/src/sqlite/column.ts +128 -0
  65. package/src/sqlite/datatypes/index.ts +79 -0
  66. package/src/sqlite/datatypes/spec.ts +98 -0
  67. package/src/sqlite/errors/catalog.ts +103 -0
  68. package/src/sqlite/errors/fields.ts +19 -0
  69. package/src/sqlite/errors/index.ts +19 -0
  70. package/src/sqlite/errors/normalize.ts +229 -0
  71. package/src/sqlite/errors/requirements.ts +71 -0
  72. package/src/sqlite/errors/types.ts +29 -0
  73. package/src/sqlite/executor.ts +227 -0
  74. package/src/sqlite/function/aggregate.ts +2 -0
  75. package/src/sqlite/function/core.ts +2 -0
  76. package/src/sqlite/function/index.ts +19 -0
  77. package/src/sqlite/function/string.ts +2 -0
  78. package/src/sqlite/function/temporal.ts +100 -0
  79. package/src/sqlite/function/window.ts +2 -0
  80. package/src/sqlite/internal/dialect.ts +37 -0
  81. package/src/sqlite/internal/dsl.ts +6926 -0
  82. package/src/sqlite/internal/renderer.ts +47 -0
  83. package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
  84. package/src/sqlite/json.ts +2 -0
  85. package/src/sqlite/query.ts +196 -0
  86. package/src/sqlite/renderer.ts +24 -0
  87. package/src/sqlite/table.ts +183 -0
  88. package/src/sqlite.ts +22 -0
package/dist/mysql.js CHANGED
@@ -24,6 +24,7 @@ __export(exports_column, {
24
24
  json: () => json,
25
25
  int: () => int,
26
26
  generated: () => generated2,
27
+ driverValueMapping: () => driverValueMapping2,
27
28
  default: () => default_2,
28
29
  datetime: () => datetime,
29
30
  date: () => date,
@@ -76,6 +77,7 @@ var makeColumnDefinition = (schema, metadata) => {
76
77
  runtime: undefined,
77
78
  dbType: metadata.dbType,
78
79
  runtimeSchema: schema,
80
+ driverValueMapping: metadata.driverValueMapping,
79
81
  nullability: metadata.nullable ? "maybe" : "never",
80
82
  dialect: metadata.dbType.dialect,
81
83
  kind: "scalar",
@@ -95,6 +97,7 @@ var makeColumnDefinition = (schema, metadata) => {
95
97
  defaultValue: metadata.defaultValue,
96
98
  generatedValue: metadata.generatedValue,
97
99
  ddlType: metadata.ddlType,
100
+ driverValueMapping: metadata.driverValueMapping,
98
101
  identity: metadata.identity,
99
102
  enum: metadata.enum
100
103
  };
@@ -111,6 +114,7 @@ var remapColumnDefinition = (column, options = {}) => {
111
114
  runtime: undefined,
112
115
  dbType: metadata.dbType,
113
116
  runtimeSchema: schema,
117
+ driverValueMapping: metadata.driverValueMapping,
114
118
  nullability: metadata.nullable ? "maybe" : "never",
115
119
  dialect: metadata.dbType.dialect
116
120
  };
@@ -129,6 +133,7 @@ var remapColumnDefinition = (column, options = {}) => {
129
133
  defaultValue: metadata.defaultValue,
130
134
  generatedValue: metadata.generatedValue,
131
135
  ddlType: metadata.ddlType,
136
+ driverValueMapping: metadata.driverValueMapping,
132
137
  identity: metadata.identity,
133
138
  enum: metadata.enum
134
139
  };
@@ -150,6 +155,7 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
150
155
  runtime: undefined,
151
156
  dbType: column.metadata.dbType,
152
157
  runtimeSchema: schema,
158
+ driverValueMapping: column.metadata.driverValueMapping,
153
159
  nullability: column.metadata.nullable ? "maybe" : "never",
154
160
  dialect: column.metadata.dbType.dialect,
155
161
  kind: "scalar",
@@ -238,6 +244,10 @@ var ddlType = (sqlType) => (column) => mapColumn(column, {
238
244
  ...column.metadata,
239
245
  ddlType: sqlType
240
246
  });
247
+ var driverValueMapping = (mapping) => (column) => mapColumn(column, {
248
+ ...column.metadata,
249
+ driverValueMapping: mapping
250
+ });
241
251
  var array = (options) => (column) => remapColumnDefinition(column, {
242
252
  schema: Schema2.Array(options?.nullableElements ? Schema2.NullOr(column.schema) : column.schema),
243
253
  metadata: {
@@ -302,19 +312,109 @@ var references = (target) => foreignKey(target);
302
312
  // src/internal/runtime/value.ts
303
313
  import * as Schema3 from "effect/Schema";
304
314
  var brandString = (pattern2, brand5) => Schema3.String.pipe(Schema3.pattern(pattern2), Schema3.brand(brand5));
305
- var LocalDateStringSchema = brandString(/^\d{4}-\d{2}-\d{2}$/, "LocalDateString");
306
- var LocalTimeStringSchema = brandString(/^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/, "LocalTimeString");
307
- var OffsetTimeStringSchema = brandString(/^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/, "OffsetTimeString");
308
- var LocalDateTimeStringSchema = brandString(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?$/, "LocalDateTimeString");
309
- var InstantStringSchema = brandString(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/, "InstantString");
315
+ var localDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
316
+ var isValidLocalDateString = (value) => {
317
+ const match = localDatePattern.exec(value);
318
+ if (match === null) {
319
+ return false;
320
+ }
321
+ const year = Number(match[1]);
322
+ const month = Number(match[2]);
323
+ const day = Number(match[3]);
324
+ const parsed = new Date(Date.UTC(year, month - 1, day));
325
+ parsed.setUTCFullYear(year);
326
+ return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
327
+ };
328
+ var localTimePattern = /^(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
329
+ var isValidLocalTimeString = (value) => {
330
+ const match = localTimePattern.exec(value);
331
+ if (match === null) {
332
+ return false;
333
+ }
334
+ const hour = Number(match[1]);
335
+ const minute = Number(match[2]);
336
+ const second = Number(match[3]);
337
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
338
+ };
339
+ var offsetPattern = /^(?:Z|[+-](\d{2}):(\d{2}))$/;
340
+ var isValidOffset = (value) => {
341
+ const match = offsetPattern.exec(value);
342
+ if (match === null) {
343
+ return false;
344
+ }
345
+ if (value === "Z") {
346
+ return true;
347
+ }
348
+ const hour = Number(match[1]);
349
+ const minute = Number(match[2]);
350
+ return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59;
351
+ };
352
+ var offsetTimePattern = /^(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
353
+ var isValidOffsetTimeString = (value) => {
354
+ const match = offsetTimePattern.exec(value);
355
+ return match !== null && isValidLocalTimeString(match[1]) && isValidOffset(match[2]);
356
+ };
357
+ var localDateTimePattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
358
+ var isValidLocalDateTimeString = (value) => {
359
+ const match = localDateTimePattern.exec(value);
360
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]);
361
+ };
362
+ var instantPattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
363
+ var isValidInstantString = (value) => {
364
+ const match = instantPattern.exec(value);
365
+ return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]) && isValidOffset(match[3]);
366
+ };
367
+ var LocalDateStringSchema = Schema3.String.pipe(Schema3.pattern(localDatePattern), Schema3.filter(isValidLocalDateString), Schema3.brand("LocalDateString"));
368
+ var LocalTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localTimePattern), Schema3.filter(isValidLocalTimeString), Schema3.brand("LocalTimeString"));
369
+ var OffsetTimeStringSchema = Schema3.String.pipe(Schema3.pattern(offsetTimePattern), Schema3.filter(isValidOffsetTimeString), Schema3.brand("OffsetTimeString"));
370
+ var LocalDateTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localDateTimePattern), Schema3.filter(isValidLocalDateTimeString), Schema3.brand("LocalDateTimeString"));
371
+ var InstantStringSchema = Schema3.String.pipe(Schema3.pattern(instantPattern), Schema3.filter(isValidInstantString), Schema3.brand("InstantString"));
310
372
  var YearStringSchema = brandString(/^\d{4}$/, "YearString");
311
- var BigIntStringSchema = brandString(/^-?\d+$/, "BigIntString");
312
- var DecimalStringSchema = brandString(/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/, "DecimalString");
313
- var JsonValueSchema = Schema3.suspend(() => Schema3.Union(Schema3.String, Schema3.Number, Schema3.Boolean, Schema3.Null, Schema3.Array(JsonValueSchema), Schema3.Record({
373
+ var canonicalizeBigIntString = (input) => {
374
+ const trimmed = input.trim();
375
+ if (!/^-?\d+$/.test(trimmed)) {
376
+ throw new Error("Expected an integer-like bigint value");
377
+ }
378
+ return BigInt(trimmed).toString();
379
+ };
380
+ var isCanonicalBigIntString = (value) => {
381
+ try {
382
+ return canonicalizeBigIntString(value) === value;
383
+ } catch {
384
+ return false;
385
+ }
386
+ };
387
+ var canonicalizeDecimalString = (input) => {
388
+ const trimmed = input.trim();
389
+ const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
390
+ if (match === null) {
391
+ throw new Error("Expected a decimal string");
392
+ }
393
+ const sign = match[1] === "-" ? "-" : "";
394
+ const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
395
+ const fraction = (match[3] ?? "").replace(/0+$/, "");
396
+ if (fraction.length === 0) {
397
+ if (integer === "0") {
398
+ return "0";
399
+ }
400
+ return `${sign}${integer}`;
401
+ }
402
+ return `${sign}${integer}.${fraction}`;
403
+ };
404
+ var isCanonicalDecimalString = (value) => {
405
+ try {
406
+ return canonicalizeDecimalString(value) === value;
407
+ } catch {
408
+ return false;
409
+ }
410
+ };
411
+ var BigIntStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalBigIntString), Schema3.brand("BigIntString"));
412
+ var DecimalStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalDecimalString), Schema3.brand("DecimalString"));
413
+ var JsonValueSchema = Schema3.suspend(() => Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null, Schema3.Array(JsonValueSchema), Schema3.Record({
314
414
  key: Schema3.String,
315
415
  value: JsonValueSchema
316
416
  })));
317
- var JsonPrimitiveSchema = Schema3.Union(Schema3.String, Schema3.Number, Schema3.Boolean, Schema3.Null);
417
+ var JsonPrimitiveSchema = Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null);
318
418
 
319
419
  // src/mysql/datatypes/index.ts
320
420
  var exports_datatypes = {};
@@ -532,6 +632,12 @@ var mysqlDatatypeModule = {
532
632
  for (const kind of Object.keys(mysqlDatatypeKinds)) {
533
633
  mysqlDatatypeModule[kind] = () => withMetadata(kind);
534
634
  }
635
+ mysqlDatatypeModule.json = () => ({
636
+ ...withMetadata("json"),
637
+ driverValueMapping: {
638
+ toDriver: (value) => value !== null && typeof value === "object" ? JSON.stringify(value) : value
639
+ }
640
+ });
535
641
  var mysqlDatatypes = mysqlDatatypeModule;
536
642
 
537
643
  // src/mysql/column.ts
@@ -600,6 +706,7 @@ var primaryKey2 = primaryKey;
600
706
  var unique2 = unique;
601
707
  var default_2 = default_;
602
708
  var generated2 = generated;
709
+ var driverValueMapping2 = driverValueMapping;
603
710
  var references2 = references;
604
711
  var schema2 = schema;
605
712
  // src/mysql/errors/index.ts
@@ -52227,10 +52334,8 @@ var mysqlErrorCatalogByNumber = {
52227
52334
  "MY-015152": [mysqlErrorCatalogBySymbol["ER_AUDIT_LOG_JSON_INVALID_FILTER_CANNOT_BE_USED"]],
52228
52335
  "MY-015153": [mysqlErrorCatalogBySymbol["ER_WARN_AUDIT_LOG_FILTER_RECOVERY_LOGGING_DISABLED_LOG"]]
52229
52336
  };
52230
- var mysqlSymbolPattern = /^(?:[A-Z][A-Z0-9_]*|MY-\d+)$/;
52231
- var mysqlNumberPattern = /^(?:\d+|MY-\d+)$/;
52232
- var isMysqlErrorSymbol = (value) => mysqlSymbolPattern.test(value);
52233
- var isMysqlErrorNumber = (value) => mysqlNumberPattern.test(value);
52337
+ var isMysqlErrorSymbol = (value) => (value in mysqlErrorCatalogBySymbol);
52338
+ var isMysqlErrorNumber = (value) => (value in mysqlErrorCatalogByNumber);
52234
52339
  var getMysqlErrorDescriptor = (symbol) => mysqlErrorCatalogBySymbol[symbol];
52235
52340
  var findMysqlErrorDescriptorsByNumber = (value) => mysqlErrorCatalogByNumber[value];
52236
52341
  var findMysqlErrorDescriptorsByNumberLoose = (value) => mysqlErrorCatalogByNumber[String(value)];
@@ -109602,8 +109707,8 @@ var asNumber = (value) => {
109602
109707
  if (typeof value === "number" && Number.isFinite(value)) {
109603
109708
  return value;
109604
109709
  }
109605
- if (typeof value === "string" && value.trim() !== "") {
109606
- const parsed = Number(value);
109710
+ if (typeof value === "string" && /^[+-]?\d+$/.test(value.trim())) {
109711
+ const parsed = Number(value.trim());
109607
109712
  return Number.isFinite(parsed) ? parsed : undefined;
109608
109713
  }
109609
109714
  return;
@@ -109786,6 +109891,27 @@ var TypeId3 = Symbol.for("effect-qb/Plan");
109786
109891
  import { pipeArguments as pipeArguments2 } from "effect/Pipeable";
109787
109892
 
109788
109893
  // src/internal/table-options.ts
109894
+ var referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault";
109895
+ var renderReferentialAction = (action) => {
109896
+ switch (action) {
109897
+ case "noAction":
109898
+ return "no action";
109899
+ case "restrict":
109900
+ return "restrict";
109901
+ case "cascade":
109902
+ return "cascade";
109903
+ case "setNull":
109904
+ return "set null";
109905
+ case "setDefault":
109906
+ return "set default";
109907
+ }
109908
+ throw new Error(referentialActionError);
109909
+ };
109910
+ var validateReferentialAction = (action) => {
109911
+ if (action !== undefined) {
109912
+ renderReferentialAction(action);
109913
+ }
109914
+ };
109789
109915
  var normalizeColumnList = (columns) => {
109790
109916
  const normalized = Array.isArray(columns) ? [...columns] : [columns];
109791
109917
  if (normalized.length === 0) {
@@ -109813,6 +109939,8 @@ var collectInlineOptions = (fields2) => {
109813
109939
  });
109814
109940
  }
109815
109941
  if (column.metadata.references) {
109942
+ validateReferentialAction(column.metadata.references.onUpdate);
109943
+ validateReferentialAction(column.metadata.references.onDelete);
109816
109944
  const local = [columnName];
109817
109945
  options.push({
109818
109946
  kind: "foreignKey",
@@ -109889,6 +110017,8 @@ var validateOptions = (tableName, fields2, options) => {
109889
110017
  }
109890
110018
  }
109891
110019
  if (option.kind === "foreignKey") {
110020
+ validateReferentialAction(option.onUpdate);
110021
+ validateReferentialAction(option.onDelete);
109892
110022
  const reference = option.references();
109893
110023
  if (reference.columns.length !== columns.length) {
109894
110024
  throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
@@ -109913,7 +110043,7 @@ var validateOptions = (tableName, fields2, options) => {
109913
110043
  throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
109914
110044
  }
109915
110045
  }
109916
- if (option.columns === undefined && (option.keys === undefined || option.keys.length === 0)) {
110046
+ if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
109917
110047
  throw new Error(`Index on table '${tableName}' requires at least one column or key`);
109918
110048
  }
109919
110049
  }
@@ -110127,10 +110257,13 @@ function make2(name, fields2, schemaName) {
110127
110257
  const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
110128
110258
  return makeTable(name, fields2, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
110129
110259
  }
110130
- var schema3 = (schemaName) => ({
110131
- schemaName,
110132
- table: (name, fields2, ...options2) => applyDeclaredOptions(makeTable(name, fields2, [], name, "schema", schemaName, "explicit"), options2)
110133
- });
110260
+ var schema3 = (schemaName) => {
110261
+ const table = (name, fields2, ...options2) => applyDeclaredOptions(makeTable(name, fields2, [], name, "schema", schemaName, "explicit"), options2);
110262
+ return {
110263
+ schemaName,
110264
+ table
110265
+ };
110266
+ };
110134
110267
  var alias = (table, aliasName) => {
110135
110268
  const state = table[TypeId4];
110136
110269
  const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
@@ -110254,6 +110387,309 @@ var check = (name, predicate) => makeOption({
110254
110387
  predicate
110255
110388
  });
110256
110389
 
110390
+ // src/internal/runtime/normalize.ts
110391
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
110392
+ var isPlainRecord = (value) => {
110393
+ if (!isRecord2(value)) {
110394
+ return false;
110395
+ }
110396
+ const prototype = Object.getPrototypeOf(value);
110397
+ return prototype === Object.prototype || prototype === null;
110398
+ };
110399
+ var pad = (value, width = 2) => value.toString().padStart(width, "0");
110400
+ var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
110401
+ var formatLocalTime = (value) => {
110402
+ const milliseconds = value.getUTCMilliseconds();
110403
+ const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
110404
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
110405
+ };
110406
+ var formatLocalDateTime = (value) => {
110407
+ const milliseconds = value.getUTCMilliseconds();
110408
+ const base = `${formatLocalDate(value)}T${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
110409
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
110410
+ };
110411
+ var runtimeTagOfBaseDbType = (dbType) => {
110412
+ return dbType.runtime;
110413
+ };
110414
+ var expectString = (value, label) => {
110415
+ if (typeof value === "string") {
110416
+ return value;
110417
+ }
110418
+ throw new Error(`Expected ${label} as string`);
110419
+ };
110420
+ var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
110421
+ var normalizeNumber = (value) => {
110422
+ if (typeof value === "number" && Number.isFinite(value)) {
110423
+ return value;
110424
+ }
110425
+ if (typeof value === "string") {
110426
+ const trimmed = value.trim();
110427
+ const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
110428
+ if (Number.isFinite(parsed)) {
110429
+ return parsed;
110430
+ }
110431
+ }
110432
+ if (typeof value === "bigint" && Number.isSafeInteger(Number(value))) {
110433
+ return Number(value);
110434
+ }
110435
+ throw new Error("Expected a finite numeric value");
110436
+ };
110437
+ var normalizeBoolean = (value) => {
110438
+ if (typeof value === "boolean") {
110439
+ return value;
110440
+ }
110441
+ if (typeof value === "number") {
110442
+ if (value === 1) {
110443
+ return true;
110444
+ }
110445
+ if (value === 0) {
110446
+ return false;
110447
+ }
110448
+ }
110449
+ if (typeof value === "string") {
110450
+ const normalized = value.trim().toLowerCase();
110451
+ if (normalized === "true" || normalized === "t" || normalized === "1") {
110452
+ return true;
110453
+ }
110454
+ if (normalized === "false" || normalized === "f" || normalized === "0") {
110455
+ return false;
110456
+ }
110457
+ }
110458
+ throw new Error("Expected a boolean-like value");
110459
+ };
110460
+ var normalizeBigIntString = (value) => {
110461
+ if (typeof value === "bigint") {
110462
+ return value.toString();
110463
+ }
110464
+ if (typeof value === "number" && Number.isSafeInteger(value)) {
110465
+ return BigInt(value).toString();
110466
+ }
110467
+ if (typeof value === "string") {
110468
+ return canonicalizeBigIntString(value);
110469
+ }
110470
+ throw new Error("Expected an integer-like bigint value");
110471
+ };
110472
+ var normalizeDecimalString = (value) => {
110473
+ if (typeof value === "string") {
110474
+ return canonicalizeDecimalString(value);
110475
+ }
110476
+ if (typeof value === "number" && Number.isFinite(value)) {
110477
+ const rendered = String(value);
110478
+ if (/[eE]/.test(rendered)) {
110479
+ throw new Error("Scientific notation is not a supported decimal runtime");
110480
+ }
110481
+ return canonicalizeDecimalString(rendered);
110482
+ }
110483
+ throw new Error("Expected a decimal-like value");
110484
+ };
110485
+ var normalizeLocalDate = (value) => {
110486
+ if (value instanceof Date) {
110487
+ return formatLocalDate(value);
110488
+ }
110489
+ const raw = expectString(value, "local date").trim();
110490
+ if (isValidLocalDateString(raw)) {
110491
+ return raw;
110492
+ }
110493
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
110494
+ if (isValidInstantString(canonicalInstant)) {
110495
+ const parsed = new Date(canonicalInstant);
110496
+ if (!Number.isNaN(parsed.getTime())) {
110497
+ return formatLocalDate(parsed);
110498
+ }
110499
+ }
110500
+ throw new Error("Expected a local-date value");
110501
+ };
110502
+ var normalizeLocalTime = (value) => {
110503
+ if (value instanceof Date) {
110504
+ return formatLocalTime(value);
110505
+ }
110506
+ const raw = expectString(value, "local time").trim();
110507
+ if (isValidLocalTimeString(raw)) {
110508
+ return raw;
110509
+ }
110510
+ throw new Error("Expected a local-time value");
110511
+ };
110512
+ var normalizeOffsetTime = (value) => {
110513
+ if (value instanceof Date) {
110514
+ return `${formatLocalTime(value)}Z`;
110515
+ }
110516
+ const raw = expectString(value, "offset time").trim();
110517
+ if (isValidOffsetTimeString(raw)) {
110518
+ return raw;
110519
+ }
110520
+ throw new Error("Expected an offset-time value");
110521
+ };
110522
+ var normalizeLocalDateTime = (value) => {
110523
+ if (value instanceof Date) {
110524
+ return formatLocalDateTime(value);
110525
+ }
110526
+ const raw = expectString(value, "local datetime").trim();
110527
+ const canonicalLocalDateTime = raw.replace(" ", "T");
110528
+ if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
110529
+ return canonicalLocalDateTime;
110530
+ }
110531
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
110532
+ if (isValidInstantString(canonicalInstant)) {
110533
+ const parsed = new Date(canonicalInstant);
110534
+ if (!Number.isNaN(parsed.getTime())) {
110535
+ return formatLocalDateTime(parsed);
110536
+ }
110537
+ }
110538
+ throw new Error("Expected a local-datetime value");
110539
+ };
110540
+ var normalizeInstant = (value) => {
110541
+ if (value instanceof Date) {
110542
+ return value.toISOString();
110543
+ }
110544
+ const raw = expectString(value, "instant").trim();
110545
+ if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
110546
+ throw new Error("Instant values require a timezone offset");
110547
+ }
110548
+ const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
110549
+ if (!isValidInstantString(canonicalInstant)) {
110550
+ throw new Error("Expected an ISO instant value");
110551
+ }
110552
+ const parsed = new Date(canonicalInstant);
110553
+ if (Number.isNaN(parsed.getTime())) {
110554
+ throw new Error("Expected an ISO instant value");
110555
+ }
110556
+ return parsed.toISOString();
110557
+ };
110558
+ var normalizeYear = (value) => {
110559
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 9999) {
110560
+ return pad(value, 4);
110561
+ }
110562
+ const raw = expectString(value, "year").trim();
110563
+ if (/^\d{4}$/.test(raw)) {
110564
+ return raw;
110565
+ }
110566
+ throw new Error("Expected a four-digit year");
110567
+ };
110568
+ var normalizeBytes = (value) => {
110569
+ if (value instanceof Uint8Array) {
110570
+ return new Uint8Array(value);
110571
+ }
110572
+ const BufferConstructor = globalThis.Buffer;
110573
+ if (BufferConstructor !== undefined && value instanceof BufferConstructor) {
110574
+ return new Uint8Array(value);
110575
+ }
110576
+ throw new Error("Expected a byte array value");
110577
+ };
110578
+ var isJsonValue = (value) => {
110579
+ if (value === null) {
110580
+ return true;
110581
+ }
110582
+ switch (typeof value) {
110583
+ case "string":
110584
+ case "boolean":
110585
+ return true;
110586
+ case "number":
110587
+ return Number.isFinite(value);
110588
+ case "object":
110589
+ if (Array.isArray(value)) {
110590
+ return value.every(isJsonValue);
110591
+ }
110592
+ return isPlainRecord(value) && Object.values(value).every(isJsonValue);
110593
+ default:
110594
+ return false;
110595
+ }
110596
+ };
110597
+ var normalizeJson = (value) => {
110598
+ if (typeof value === "string") {
110599
+ try {
110600
+ const parsed = JSON.parse(value);
110601
+ if (isJsonValue(parsed)) {
110602
+ return parsed;
110603
+ }
110604
+ throw new Error("Parsed JSON value is not a valid JSON runtime");
110605
+ } catch (error) {
110606
+ if (error instanceof SyntaxError) {
110607
+ return value;
110608
+ }
110609
+ throw error;
110610
+ }
110611
+ }
110612
+ if (isJsonValue(value)) {
110613
+ return value;
110614
+ }
110615
+ throw new Error("Expected a JSON value");
110616
+ };
110617
+ var normalizeDbValue = (dbType, value) => {
110618
+ if (value === null) {
110619
+ return null;
110620
+ }
110621
+ if ("base" in dbType) {
110622
+ return normalizeDbValue(dbType.base, value);
110623
+ }
110624
+ if ("element" in dbType) {
110625
+ if (!Array.isArray(value)) {
110626
+ throw new Error("Expected an array value");
110627
+ }
110628
+ return value.map((entry) => normalizeDbValue(dbType.element, entry));
110629
+ }
110630
+ if ("fields" in dbType) {
110631
+ if (!isRecord2(value)) {
110632
+ throw new Error("Expected a record value");
110633
+ }
110634
+ const normalized = {};
110635
+ for (const [key, fieldDbType] of Object.entries(dbType.fields)) {
110636
+ if (key in value) {
110637
+ normalized[key] = normalizeDbValue(fieldDbType, value[key]);
110638
+ }
110639
+ }
110640
+ return normalized;
110641
+ }
110642
+ if ("variant" in dbType && dbType.variant === "json") {
110643
+ return normalizeJson(value);
110644
+ }
110645
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
110646
+ return expectString(value, "text");
110647
+ }
110648
+ switch (runtimeTagOfBaseDbType(dbType)) {
110649
+ case "string":
110650
+ return expectString(value, "text");
110651
+ case "number":
110652
+ return normalizeNumber(value);
110653
+ case "bigintString":
110654
+ return normalizeBigIntString(value);
110655
+ case "boolean":
110656
+ return normalizeBoolean(value);
110657
+ case "json":
110658
+ return normalizeJson(value);
110659
+ case "localDate":
110660
+ return normalizeLocalDate(value);
110661
+ case "localTime":
110662
+ return normalizeLocalTime(value);
110663
+ case "offsetTime":
110664
+ return normalizeOffsetTime(value);
110665
+ case "localDateTime":
110666
+ return normalizeLocalDateTime(value);
110667
+ case "instant":
110668
+ return normalizeInstant(value);
110669
+ case "year":
110670
+ return normalizeYear(value);
110671
+ case "decimalString":
110672
+ return normalizeDecimalString(value);
110673
+ case "bytes":
110674
+ return normalizeBytes(value);
110675
+ case "array":
110676
+ if (!Array.isArray(value)) {
110677
+ throw new Error("Expected an array value");
110678
+ }
110679
+ return value;
110680
+ case "record":
110681
+ if (!isRecord2(value)) {
110682
+ throw new Error("Expected a record value");
110683
+ }
110684
+ return value;
110685
+ case "null":
110686
+ return null;
110687
+ case "unknown":
110688
+ case undefined:
110689
+ return value;
110690
+ }
110691
+ };
110692
+
110257
110693
  // src/internal/query.ts
110258
110694
  import { pipeArguments as pipeArguments3 } from "effect/Pipeable";
110259
110695
 
@@ -110274,6 +110710,7 @@ var emptyContext = () => ({
110274
110710
  nullKeys: new Set,
110275
110711
  eqLiterals: new Map,
110276
110712
  neqLiterals: new Map,
110713
+ literalSets: new Map,
110277
110714
  sourceNames: new Set,
110278
110715
  contradiction: false,
110279
110716
  unknown: false
@@ -110283,12 +110720,24 @@ var cloneContext = (context) => ({
110283
110720
  nullKeys: new Set(context.nullKeys),
110284
110721
  eqLiterals: new Map(context.eqLiterals),
110285
110722
  neqLiterals: new Map(Array.from(context.neqLiterals.entries(), ([key, values]) => [key, new Set(values)])),
110723
+ literalSets: new Map(Array.from(context.literalSets.entries(), ([key, values]) => [key, new Set(values)])),
110286
110724
  sourceNames: new Set(context.sourceNames),
110287
110725
  contradiction: context.contradiction,
110288
110726
  unknown: context.unknown
110289
110727
  });
110290
110728
  var freezeContext = (context) => context;
110291
- var sourceNameOfKey = (key) => key.split(".", 1)[0] ?? key;
110729
+ var columnPredicateKey = (tableName, columnName) => JSON.stringify([tableName, columnName]);
110730
+ var columnPredicateKeyParts = (key) => {
110731
+ const jsonSeparator = key.indexOf("#json:");
110732
+ const columnKey = jsonSeparator === -1 ? key : key.slice(0, jsonSeparator);
110733
+ try {
110734
+ const parsed = JSON.parse(columnKey);
110735
+ return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : undefined;
110736
+ } catch {
110737
+ return;
110738
+ }
110739
+ };
110740
+ var sourceNameOfKey = (key) => columnPredicateKeyParts(key)?.[0] ?? key.split(".", 1)[0] ?? key;
110292
110741
  var addSourceName = (context, key) => {
110293
110742
  context.sourceNames.add(sourceNameOfKey(key));
110294
110743
  };
@@ -110316,7 +110765,12 @@ var addEqLiteral = (context, key, value) => {
110316
110765
  if (neqValues?.has(value)) {
110317
110766
  context.contradiction = true;
110318
110767
  }
110768
+ const existingSet = context.literalSets.get(key);
110769
+ if (existingSet !== undefined && !existingSet.has(value)) {
110770
+ context.contradiction = true;
110771
+ }
110319
110772
  context.eqLiterals.set(key, value);
110773
+ context.literalSets.set(key, new Set([value]));
110320
110774
  };
110321
110775
  var addNeqLiteral = (context, key, value) => {
110322
110776
  addNonNull(context, key);
@@ -110327,6 +110781,18 @@ var addNeqLiteral = (context, key, value) => {
110327
110781
  values.add(value);
110328
110782
  context.neqLiterals.set(key, values);
110329
110783
  };
110784
+ var addLiteralSet = (context, key, values) => {
110785
+ addNonNull(context, key);
110786
+ const existingEq = context.eqLiterals.get(key);
110787
+ if (existingEq !== undefined && !values.has(existingEq)) {
110788
+ context.contradiction = true;
110789
+ }
110790
+ const existing = context.literalSets.get(key);
110791
+ context.literalSets.set(key, existing === undefined ? new Set(values) : new Set(Array.from(existing).filter((value) => values.has(value))));
110792
+ if (context.literalSets.get(key)?.size === 0) {
110793
+ context.contradiction = true;
110794
+ }
110795
+ };
110330
110796
  var applyEqColumn = (context, left, right) => {
110331
110797
  const leftValue = context.eqLiterals.get(left);
110332
110798
  const rightValue = context.eqLiterals.get(right);
@@ -110366,6 +110832,9 @@ var applyAtom = (context, atom) => {
110366
110832
  case "neq-literal":
110367
110833
  addNeqLiteral(context, atom.key, atom.value);
110368
110834
  return;
110835
+ case "literal-set":
110836
+ addLiteralSet(context, atom.key, new Set(atom.values));
110837
+ return;
110369
110838
  case "eq-column":
110370
110839
  applyEqColumn(context, atom.left, atom.right);
110371
110840
  return;
@@ -110388,6 +110857,9 @@ var applyNegativeAtom = (context, atom) => {
110388
110857
  case "neq-literal":
110389
110858
  addEqLiteral(context, atom.key, atom.value);
110390
110859
  return;
110860
+ case "literal-set":
110861
+ addNonNull(context, atom.key);
110862
+ return;
110391
110863
  case "eq-column":
110392
110864
  addNonNull(context, atom.left);
110393
110865
  addNonNull(context, atom.right);
@@ -110420,6 +110892,17 @@ var intersectNeqLiterals = (left, right) => {
110420
110892
  }
110421
110893
  return result;
110422
110894
  };
110895
+ var unionLiteralSets = (left, right) => {
110896
+ const result = new Map;
110897
+ for (const [key, leftValues] of left) {
110898
+ const rightValues = right.get(key);
110899
+ if (rightValues === undefined) {
110900
+ continue;
110901
+ }
110902
+ result.set(key, new Set([...leftValues, ...rightValues]));
110903
+ }
110904
+ return result;
110905
+ };
110423
110906
  var intersectContexts = (left, right) => {
110424
110907
  if (left.contradiction) {
110425
110908
  return cloneContext(right);
@@ -110432,6 +110915,7 @@ var intersectContexts = (left, right) => {
110432
110915
  nullKeys: new Set(Array.from(left.nullKeys).filter((key) => right.nullKeys.has(key))),
110433
110916
  eqLiterals: intersectEqLiterals(left.eqLiterals, right.eqLiterals),
110434
110917
  neqLiterals: intersectNeqLiterals(left.neqLiterals, right.neqLiterals),
110918
+ literalSets: unionLiteralSets(left.literalSets, right.literalSets),
110435
110919
  sourceNames: new Set(Array.from(left.sourceNames).filter((name) => right.sourceNames.has(name))),
110436
110920
  contradiction: false,
110437
110921
  unknown: left.unknown || right.unknown
@@ -110503,7 +110987,47 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
110503
110987
  var astOf = (value) => value[TypeId2];
110504
110988
  var columnKeyOfExpression = (value) => {
110505
110989
  const ast = astOf(value);
110506
- return ast.kind === "column" ? `${ast.tableName}.${ast.columnName}` : undefined;
110990
+ return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
110991
+ };
110992
+ var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
110993
+ var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
110994
+ var jsonPathPredicateKeyOfExpression = (value) => {
110995
+ const ast = astOf(value);
110996
+ switch (ast.kind) {
110997
+ case "jsonGetText":
110998
+ case "jsonPathText":
110999
+ case "jsonAccessText":
111000
+ case "jsonTraverseText": {
111001
+ const jsonAst = ast;
111002
+ const segments = jsonAst.segments;
111003
+ if (segments.length === 0 || segments.length > 8) {
111004
+ return;
111005
+ }
111006
+ const path = [];
111007
+ for (const segment of segments) {
111008
+ if (typeof segment !== "object" || segment === null || segment.kind !== "key") {
111009
+ return;
111010
+ }
111011
+ path.push(segment.key);
111012
+ }
111013
+ if (path.length === 0) {
111014
+ return;
111015
+ }
111016
+ const baseKey = columnKeyOfExpression(jsonAst.base);
111017
+ return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
111018
+ }
111019
+ default:
111020
+ return;
111021
+ }
111022
+ };
111023
+ var predicateKeyOfExpression = (value) => columnKeyOfExpression(value) ?? castPredicateKeyOfExpression(value) ?? jsonPathPredicateKeyOfExpression(value);
111024
+ var castPredicateKeyOfExpression = (value) => {
111025
+ const ast = astOf(value);
111026
+ if (ast.kind !== "cast") {
111027
+ return;
111028
+ }
111029
+ const source = ast.value;
111030
+ return sameDbType(source[TypeId].dbType, ast.target) ? predicateKeyOfExpression(source) : undefined;
110507
111031
  };
110508
111032
  var valueKeyOfLiteral = (value) => {
110509
111033
  if (typeof value === "string") {
@@ -110524,7 +111048,7 @@ var valueKeyOfLiteral = (value) => {
110524
111048
  return "unknown";
110525
111049
  };
110526
111050
  var nonNullFactsOfExpression = (value) => {
110527
- const key = columnKeyOfExpression(value);
111051
+ const key = predicateKeyOfExpression(value);
110528
111052
  return key === undefined ? undefined : atomFormula({ kind: "is-not-null", key });
110529
111053
  };
110530
111054
  var combineFacts = (left, right) => {
@@ -110537,8 +111061,8 @@ var combineFacts = (left, right) => {
110537
111061
  return andFormula(left, right);
110538
111062
  };
110539
111063
  var formulaOfEq = (left, right) => {
110540
- const leftKey = columnKeyOfExpression(left);
110541
- const rightKey = columnKeyOfExpression(right);
111064
+ const leftKey = predicateKeyOfExpression(left);
111065
+ const rightKey = predicateKeyOfExpression(right);
110542
111066
  const leftAst = astOf(left);
110543
111067
  const rightAst = astOf(right);
110544
111068
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -110585,8 +111109,8 @@ var formulaOfEq = (left, right) => {
110585
111109
  });
110586
111110
  };
110587
111111
  var formulaOfNeq = (left, right) => {
110588
- const leftKey = columnKeyOfExpression(left);
110589
- const rightKey = columnKeyOfExpression(right);
111112
+ const leftKey = predicateKeyOfExpression(left);
111113
+ const rightKey = predicateKeyOfExpression(right);
110590
111114
  const leftAst = astOf(left);
110591
111115
  const rightAst = astOf(right);
110592
111116
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -110629,8 +111153,8 @@ var formulaOfNeq = (left, right) => {
110629
111153
  return combineFacts(nonNullFactsOfExpression(left), nonNullFactsOfExpression(right));
110630
111154
  };
110631
111155
  var formulaOfIsNotDistinctFrom = (left, right) => {
110632
- const leftKey = columnKeyOfExpression(left);
110633
- const rightKey = columnKeyOfExpression(right);
111156
+ const leftKey = predicateKeyOfExpression(left);
111157
+ const rightKey = predicateKeyOfExpression(right);
110634
111158
  const leftAst = astOf(left);
110635
111159
  const rightAst = astOf(right);
110636
111160
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -110736,11 +111260,11 @@ var formulaOfExpression = (value) => {
110736
111260
  }
110737
111261
  return unknownTag("literal:non-boolean");
110738
111262
  case "isNull": {
110739
- const key = columnKeyOfExpression(ast.value);
111263
+ const key = predicateKeyOfExpression(ast.value);
110740
111264
  return key === undefined ? unknownTag("isNull:unsupported") : atomFormula({ kind: "is-null", key });
110741
111265
  }
110742
111266
  case "isNotNull": {
110743
- const key = columnKeyOfExpression(ast.value);
111267
+ const key = predicateKeyOfExpression(ast.value);
110744
111268
  return key === undefined ? unknownTag("isNotNull:unsupported") : atomFormula({ kind: "is-not-null", key });
110745
111269
  }
110746
111270
  case "not":
@@ -110759,7 +111283,15 @@ var formulaOfExpression = (value) => {
110759
111283
  return anyFormula(ast.values.map((value2) => formulaOfExpression(value2)));
110760
111284
  case "in": {
110761
111285
  const [left, ...rest] = ast.values;
110762
- return left === undefined ? falseFormula() : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
111286
+ if (left === undefined) {
111287
+ return falseFormula();
111288
+ }
111289
+ const key = predicateKeyOfExpression(left);
111290
+ const literalValues = rest.map((entry) => {
111291
+ const entryAst = astOf(entry);
111292
+ return entryAst.kind === "literal" && entryAst.value !== null ? valueKeyOfLiteral(entryAst.value) : undefined;
111293
+ });
111294
+ return key !== undefined && literalValues.every((entry) => entry !== undefined) ? atomFormula({ kind: "literal-set", key, values: literalValues }) : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
110763
111295
  }
110764
111296
  case "notIn": {
110765
111297
  const [left, ...rest] = ast.values;
@@ -110823,6 +111355,7 @@ var makeExpression = (state, ast) => {
110823
111355
  runtime: state.runtime,
110824
111356
  dbType: state.dbType,
110825
111357
  runtimeSchema: state.runtimeSchema,
111358
+ driverValueMapping: state.driverValueMapping,
110826
111359
  nullability: state.nullability,
110827
111360
  dialect: state.dialect,
110828
111361
  kind: state.kind ?? "scalar",
@@ -110831,7 +111364,7 @@ var makeExpression = (state, ast) => {
110831
111364
  expression[TypeId2] = ast;
110832
111365
  return expression;
110833
111366
  };
110834
- var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState) => {
111367
+ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState, _facts) => {
110835
111368
  const plan = Object.create(PlanProto);
110836
111369
  Object.defineProperty(plan, "pipe", {
110837
111370
  configurable: true,
@@ -110847,6 +111380,7 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
110847
111380
  availableNames: undefined,
110848
111381
  grouped: undefined,
110849
111382
  assumptions: _assumptions ?? trueFormula(),
111383
+ facts: _facts ?? undefined,
110850
111384
  capabilities: undefined,
110851
111385
  statement: _statement ?? "select",
110852
111386
  target: _target ?? undefined,
@@ -110896,7 +111430,7 @@ var collectPresenceWitnesses = (selection, output) => {
110896
111430
  const expression = selection;
110897
111431
  const ast = expression[TypeId2];
110898
111432
  if (ast.kind === "column" && expression[TypeId].nullability === "never") {
110899
- output.add(`${ast.tableName}.${ast.columnName}`);
111433
+ output.add(columnPredicateKey(ast.tableName, ast.columnName));
110900
111434
  }
110901
111435
  return;
110902
111436
  }
@@ -111045,6 +111579,20 @@ var path = (...segments) => ({
111045
111579
  });
111046
111580
 
111047
111581
  // src/internal/grouping-key.ts
111582
+ var subqueryPlanIds = new WeakMap;
111583
+ var nextSubqueryPlanId = 0;
111584
+ var subqueryPlanGroupingKey = (plan) => {
111585
+ if (plan === null || typeof plan !== "object") {
111586
+ return "unknown";
111587
+ }
111588
+ const existing = subqueryPlanIds.get(plan);
111589
+ if (existing !== undefined) {
111590
+ return existing;
111591
+ }
111592
+ const next = `${nextSubqueryPlanId++}`;
111593
+ subqueryPlanIds.set(plan, next);
111594
+ return next;
111595
+ };
111048
111596
  var literalGroupingKey = (value) => {
111049
111597
  if (value instanceof Date) {
111050
111598
  return `date:${value.toISOString()}`;
@@ -111063,15 +111611,62 @@ var literalGroupingKey = (value) => {
111063
111611
  return `literal:${JSON.stringify(value)}`;
111064
111612
  }
111065
111613
  };
111614
+ var isExpression = (value) => value !== null && typeof value === "object" && (TypeId in value);
111615
+ var expressionGroupingKey = (value) => isExpression(value) ? groupingKeyOfExpression(value) : "missing";
111616
+ var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
111617
+ var jsonSegmentGroupingKey = (segment) => {
111618
+ if (segment !== null && typeof segment === "object" && "kind" in segment) {
111619
+ switch (segment.kind) {
111620
+ case "key":
111621
+ return `key:${escapeGroupingText(segment.key)}`;
111622
+ case "index":
111623
+ return `index:${segment.index}`;
111624
+ case "wildcard":
111625
+ return "wildcard";
111626
+ case "slice": {
111627
+ const slice2 = segment;
111628
+ return `slice:${slice2.start ?? ""}:${slice2.end ?? ""}`;
111629
+ }
111630
+ case "descend":
111631
+ return "descend";
111632
+ }
111633
+ }
111634
+ if (typeof segment === "string") {
111635
+ return `key:${escapeGroupingText(segment)}`;
111636
+ }
111637
+ if (typeof segment === "number") {
111638
+ return `index:${segment}`;
111639
+ }
111640
+ return "unknown";
111641
+ };
111642
+ var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
111643
+ var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId6 in value);
111644
+ var jsonOpaquePathGroupingKey = (value) => {
111645
+ if (isJsonPath(value)) {
111646
+ return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
111647
+ }
111648
+ if (typeof value === "string") {
111649
+ return `jsonpath:${escapeGroupingText(value)}`;
111650
+ }
111651
+ if (isExpression(value)) {
111652
+ return `jsonpath:${groupingKeyOfExpression(value)}`;
111653
+ }
111654
+ return "jsonpath:unknown";
111655
+ };
111656
+ var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
111066
111657
  var groupingKeyOfExpression = (expression) => {
111067
111658
  const ast = expression[TypeId2];
111068
111659
  switch (ast.kind) {
111069
111660
  case "column":
111070
- return `column:${ast.tableName}.${ast.columnName}`;
111661
+ return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
111071
111662
  case "literal":
111072
111663
  return `literal:${literalGroupingKey(ast.value)}`;
111073
111664
  case "cast":
111074
111665
  return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
111666
+ case "collate":
111667
+ return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
111668
+ case "function":
111669
+ return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
111075
111670
  case "isNull":
111076
111671
  case "isNotNull":
111077
111672
  case "not":
@@ -111089,8 +111684,15 @@ var groupingKeyOfExpression = (expression) => {
111089
111684
  case "gte":
111090
111685
  case "like":
111091
111686
  case "ilike":
111687
+ case "regexMatch":
111688
+ case "regexIMatch":
111689
+ case "regexNotMatch":
111690
+ case "regexNotIMatch":
111092
111691
  case "isDistinctFrom":
111093
111692
  case "isNotDistinctFrom":
111693
+ case "contains":
111694
+ case "containedBy":
111695
+ case "overlaps":
111094
111696
  return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
111095
111697
  case "and":
111096
111698
  case "or":
@@ -111102,6 +111704,54 @@ var groupingKeyOfExpression = (expression) => {
111102
111704
  return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
111103
111705
  case "case":
111104
111706
  return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
111707
+ case "exists":
111708
+ return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
111709
+ case "scalarSubquery":
111710
+ return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
111711
+ case "inSubquery":
111712
+ return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
111713
+ case "comparisonAny":
111714
+ case "comparisonAll":
111715
+ return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
111716
+ case "jsonGet":
111717
+ case "jsonPath":
111718
+ case "jsonAccess":
111719
+ case "jsonTraverse":
111720
+ case "jsonGetText":
111721
+ case "jsonPathText":
111722
+ case "jsonAccessText":
111723
+ case "jsonTraverseText":
111724
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonPathGroupingKey(ast.segments)})`;
111725
+ case "jsonHasKey":
111726
+ case "jsonKeyExists":
111727
+ case "jsonHasAnyKeys":
111728
+ case "jsonHasAllKeys":
111729
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
111730
+ case "jsonConcat":
111731
+ case "jsonMerge":
111732
+ return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
111733
+ case "jsonDelete":
111734
+ case "jsonDeletePath":
111735
+ case "jsonRemove":
111736
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(undefined)},${jsonPathGroupingKey(ast.segments)})`;
111737
+ case "jsonSet":
111738
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.newValue)},${jsonPathGroupingKey(ast.segments)})`;
111739
+ case "jsonInsert":
111740
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.insert)},${jsonPathGroupingKey(ast.segments)})`;
111741
+ case "jsonPathExists":
111742
+ case "jsonPathMatch":
111743
+ return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
111744
+ case "jsonBuildObject":
111745
+ return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
111746
+ case "jsonBuildArray":
111747
+ return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
111748
+ case "jsonToJson":
111749
+ case "jsonToJsonb":
111750
+ case "jsonTypeOf":
111751
+ case "jsonLength":
111752
+ case "jsonKeys":
111753
+ case "jsonStripNulls":
111754
+ return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
111105
111755
  default:
111106
111756
  throw new Error("Unsupported expression for grouping key generation");
111107
111757
  }
@@ -111119,8 +111769,112 @@ var dedupeGroupedExpressions = (values) => {
111119
111769
  };
111120
111770
 
111121
111771
  // src/internal/dsl-mutation-runtime.ts
111772
+ var expectInsertSourceKind = (source) => {
111773
+ if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
111774
+ throw new Error("Unsupported insert source kind");
111775
+ }
111776
+ return source;
111777
+ };
111778
+ var expectConflictClause = (conflict) => {
111779
+ if (conflict === undefined) {
111780
+ return conflict;
111781
+ }
111782
+ if (conflict.kind !== "conflict") {
111783
+ throw new Error("Unsupported conflict clause kind");
111784
+ }
111785
+ if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
111786
+ throw new Error("Unsupported conflict action");
111787
+ }
111788
+ if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
111789
+ throw new Error("Unsupported conflict target kind");
111790
+ }
111791
+ return conflict;
111792
+ };
111122
111793
  var makeDslMutationRuntime = (ctx) => {
111794
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
111795
+ const isRecord3 = (value) => typeof value === "object" && value !== null;
111796
+ const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId3 in target);
111797
+ const hasColumnRecord = (value) => isRecord3(value.columns);
111798
+ const isAliasedSource = (source) => {
111799
+ if (!isRecord3(source)) {
111800
+ return false;
111801
+ }
111802
+ if (isTableTarget(source)) {
111803
+ return true;
111804
+ }
111805
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
111806
+ return false;
111807
+ }
111808
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
111809
+ return false;
111810
+ }
111811
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
111812
+ return false;
111813
+ }
111814
+ switch (source.kind) {
111815
+ case "derived":
111816
+ case "cte":
111817
+ case "lateral":
111818
+ return isRecord3(source.plan) && TypeId3 in source.plan && hasColumnRecord(source);
111819
+ case "values":
111820
+ return Array.isArray(source.rows) && hasColumnRecord(source);
111821
+ case "unnest":
111822
+ return isRecord3(source.arrays) && hasColumnRecord(source);
111823
+ case "tableFunction":
111824
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
111825
+ }
111826
+ return false;
111827
+ };
111828
+ const assertMutationTarget = (target, apiName) => {
111829
+ if (!isTableTarget(target)) {
111830
+ throw new Error(`${apiName}(...) requires table targets`);
111831
+ }
111832
+ };
111833
+ const assertAliasedSource = (source, apiName) => {
111834
+ if (!isAliasedSource(source)) {
111835
+ throw new Error(`${apiName}(...) requires an aliased source`);
111836
+ }
111837
+ };
111838
+ const assertMutationTargets = (target, apiName, options2 = {}) => {
111839
+ const targets = Array.isArray(target) ? target : [target];
111840
+ if (targets.length === 0) {
111841
+ throw new Error(`${apiName}(...) requires at least one table target`);
111842
+ }
111843
+ if (Array.isArray(target) && targets.length === 1) {
111844
+ throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
111845
+ }
111846
+ for (const entry of targets) {
111847
+ assertMutationTarget(entry, apiName);
111848
+ }
111849
+ if (targets.length > 1 && options2.allowMultiple !== true) {
111850
+ throw new Error(`${apiName}(...) requires a single table target`);
111851
+ }
111852
+ if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
111853
+ throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
111854
+ }
111855
+ };
111856
+ const assertUniqueTargetNames = (targets) => {
111857
+ const seen = new Set;
111858
+ for (const target of targets) {
111859
+ if (seen.has(target.tableName)) {
111860
+ throw new Error(`mutation target source names must be unique: ${target.tableName}`);
111861
+ }
111862
+ seen.add(target.tableName);
111863
+ }
111864
+ };
111865
+ const assertInsertSelectSource = (sourcePlan, selection) => {
111866
+ const statement = ctx.getQueryState(sourcePlan).statement;
111867
+ if (statement !== "select" && statement !== "set") {
111868
+ throw new Error("insert sources only accept select-like query plans");
111869
+ }
111870
+ for (const value of Object.values(selection)) {
111871
+ if (value === null || typeof value !== "object" || !(TypeId in value)) {
111872
+ throw new Error("insert sources require a flat selection object");
111873
+ }
111874
+ }
111875
+ };
111123
111876
  const insert = (target, values) => {
111877
+ assertMutationTargets(target, "insert");
111124
111878
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
111125
111879
  const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
111126
111880
  const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId].dependencies));
@@ -111196,10 +111950,11 @@ var makeDslMutationRuntime = (ctx) => {
111196
111950
  }
111197
111951
  const sourcePlan = source;
111198
111952
  const selection = sourcePlan[TypeId3].selection;
111953
+ assertInsertSelectSource(sourcePlan, selection);
111199
111954
  const columns = ctx.normalizeInsertSelectColumns(selection);
111200
111955
  return ctx.makePlan({
111201
111956
  selection: current.selection,
111202
- required: ctx.currentRequiredList(sourcePlan[TypeId3].required).filter((name) => name !== sourceName),
111957
+ required: ctx.currentRequiredList(sourcePlan[TypeId3].required),
111203
111958
  available: current.available,
111204
111959
  dialect: current.dialect
111205
111960
  }, {
@@ -111216,14 +111971,22 @@ var makeDslMutationRuntime = (ctx) => {
111216
111971
  const current = plan[TypeId3];
111217
111972
  const currentAst = ctx.getAst(plan);
111218
111973
  const currentQuery = ctx.getQueryState(plan);
111974
+ if (currentQuery.statement !== "insert") {
111975
+ throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
111976
+ }
111219
111977
  const insertTarget = currentAst.into.source;
111220
111978
  const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
111221
111979
  const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
111980
+ if (options2.update !== undefined && updateAssignments.length === 0) {
111981
+ throw new Error("conflict update assignments require at least one assignment");
111982
+ }
111222
111983
  const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
111984
+ const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
111223
111985
  const required = [
111224
111986
  ...ctx.currentRequiredList(current.required),
111225
111987
  ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId].dependencies)),
111226
- ...updateWhere ? Object.keys(updateWhere[TypeId].dependencies) : []
111988
+ ...updateWhere ? Object.keys(updateWhere[TypeId].dependencies) : [],
111989
+ ...targetWhere ? Object.keys(targetWhere[TypeId].dependencies) : []
111227
111990
  ].filter((name, index4, list) => !(name in current.available) && list.indexOf(name) === index4);
111228
111991
  return ctx.makePlan({
111229
111992
  selection: current.selection,
@@ -111242,7 +112005,9 @@ var makeDslMutationRuntime = (ctx) => {
111242
112005
  }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
111243
112006
  };
111244
112007
  const update = (target, values) => {
112008
+ assertMutationTargets(target, "update", { allowMultiple: true });
111245
112009
  const targets = ctx.mutationTargetClauses(target);
112010
+ assertUniqueTargetNames(targets);
111246
112011
  const primaryTarget = targets[0];
111247
112012
  const assignments = ctx.buildMutationAssignments(target, values);
111248
112013
  const targetNames = new Set(targets.map((entry) => entry.tableName));
@@ -111266,9 +112031,13 @@ var makeDslMutationRuntime = (ctx) => {
111266
112031
  }, undefined, "write", "update");
111267
112032
  };
111268
112033
  const upsert = (target, values, conflictColumns, updateValues) => {
112034
+ assertMutationTargets(target, "upsert");
111269
112035
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
111270
112036
  const assignments = ctx.buildMutationAssignments(target, values);
111271
112037
  const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
112038
+ if (updateValues !== undefined && updateAssignments.length === 0) {
112039
+ throw new Error("upsert update assignments require at least one assignment");
112040
+ }
111272
112041
  const required = [
111273
112042
  ...assignments.flatMap((entry) => Object.keys(entry.value[TypeId].dependencies)),
111274
112043
  ...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId].dependencies))
@@ -111298,7 +112067,7 @@ var makeDslMutationRuntime = (ctx) => {
111298
112067
  kind: "conflict",
111299
112068
  target: {
111300
112069
  kind: "columns",
111301
- columns: ctx.normalizeColumnList(conflictColumns)
112070
+ columns: ctx.normalizeConflictColumns(target, conflictColumns)
111302
112071
  },
111303
112072
  action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
111304
112073
  values: updateAssignments.length > 0 ? updateAssignments : undefined
@@ -111311,7 +112080,9 @@ var makeDslMutationRuntime = (ctx) => {
111311
112080
  }, undefined, "write", "insert", target, "ready");
111312
112081
  };
111313
112082
  const delete_ = (target) => {
112083
+ assertMutationTargets(target, "delete", { allowMultiple: true });
111314
112084
  const targets = ctx.mutationTargetClauses(target);
112085
+ assertUniqueTargetNames(targets);
111315
112086
  const primaryTarget = targets[0];
111316
112087
  return ctx.makePlan({
111317
112088
  selection: {},
@@ -111331,6 +112102,7 @@ var makeDslMutationRuntime = (ctx) => {
111331
112102
  }, undefined, "write", "delete");
111332
112103
  };
111333
112104
  const truncate = (target, options2 = {}) => {
112105
+ assertMutationTargets(target, "truncate");
111334
112106
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
111335
112107
  return ctx.makePlan({
111336
112108
  selection: {},
@@ -111359,8 +112131,13 @@ var makeDslMutationRuntime = (ctx) => {
111359
112131
  }, undefined, "write", "truncate");
111360
112132
  };
111361
112133
  const merge = (target, source, on, options2 = {}) => {
112134
+ assertMutationTargets(target, "merge");
112135
+ assertAliasedSource(source, "merge");
111362
112136
  const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
111363
112137
  const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
112138
+ if (targetName === usingName) {
112139
+ throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
112140
+ }
111364
112141
  const onExpression = ctx.toDialectExpression(on);
111365
112142
  const matched = options2.whenMatched;
111366
112143
  const notMatched = options2.whenNotMatched;
@@ -111446,8 +112223,98 @@ var makeDslMutationRuntime = (ctx) => {
111446
112223
  };
111447
112224
 
111448
112225
  // src/internal/dsl-plan-runtime.ts
112226
+ var renderSelectLockMode = (mode) => {
112227
+ switch (mode) {
112228
+ case "update":
112229
+ return "for update";
112230
+ case "share":
112231
+ return "for share";
112232
+ }
112233
+ throw new Error("lock(...) mode must be update or share for select statements");
112234
+ };
112235
+ var renderMysqlMutationLockMode = (mode, statement) => {
112236
+ switch (mode) {
112237
+ case "lowPriority":
112238
+ return " low_priority";
112239
+ case "ignore":
112240
+ return " ignore";
112241
+ case "quick":
112242
+ if (statement === "delete") {
112243
+ return " quick";
112244
+ }
112245
+ break;
112246
+ }
112247
+ 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");
112248
+ };
111449
112249
  var makeDslPlanRuntime = (ctx) => {
112250
+ const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
112251
+ const isRecord3 = (value) => typeof value === "object" && value !== null;
112252
+ const isPlan = (value) => isRecord3(value) && (TypeId3 in value);
112253
+ const hasColumnRecord = (value) => isRecord3(value.columns);
112254
+ const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
112255
+ const isAliasedSource = (source) => {
112256
+ if (!isRecord3(source)) {
112257
+ return false;
112258
+ }
112259
+ if (TypeId4 in source) {
112260
+ return true;
112261
+ }
112262
+ if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
112263
+ return false;
112264
+ }
112265
+ if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
112266
+ return false;
112267
+ }
112268
+ if (typeof source.name !== "string" || typeof source.baseName !== "string") {
112269
+ return false;
112270
+ }
112271
+ switch (source.kind) {
112272
+ case "derived":
112273
+ case "cte":
112274
+ case "lateral":
112275
+ return isPlan(source.plan) && hasColumnRecord(source);
112276
+ case "values":
112277
+ return Array.isArray(source.rows) && hasColumnRecord(source);
112278
+ case "unnest":
112279
+ return isRecord3(source.arrays) && hasColumnRecord(source);
112280
+ case "tableFunction":
112281
+ return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
112282
+ }
112283
+ return false;
112284
+ };
112285
+ const assertAliasedSource = (source, message) => {
112286
+ if (!isAliasedSource(source)) {
112287
+ throw new Error(message);
112288
+ }
112289
+ };
112290
+ const assertPlanComplete = (plan) => {
112291
+ const required = ctx.currentRequiredList(plan[TypeId3].required);
112292
+ if (required.length > 0) {
112293
+ throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
112294
+ }
112295
+ };
112296
+ const assertSourceNameAvailable = (available, sourceName) => {
112297
+ if (sourceName in available) {
112298
+ throw new Error(`query source name is already in scope: ${sourceName}`);
112299
+ }
112300
+ };
112301
+ const assertSelectHasBaseSourceForJoin = (statement, available) => {
112302
+ if (statement === "select" && Object.keys(available).length === 0) {
112303
+ throw new Error("select joins require a from(...) source before joining");
112304
+ }
112305
+ };
112306
+ const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
112307
+ const assertSetOperandStatement = (plan) => {
112308
+ const statement = ctx.getQueryState(plan).statement;
112309
+ if (statement !== "select" && statement !== "set") {
112310
+ throw new Error("set operator operands only accept select-like query plans");
112311
+ }
112312
+ };
111450
112313
  const buildSetOperation = (kind, all, left, right) => {
112314
+ assertSetOperandStatement(left);
112315
+ assertSetOperandStatement(right);
112316
+ assertPlanComplete(left);
112317
+ assertPlanComplete(right);
111451
112318
  const leftState = left[TypeId3];
111452
112319
  const leftAst = ctx.getAst(left);
111453
112320
  const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
@@ -111502,25 +112369,29 @@ var makeDslPlanRuntime = (ctx) => {
111502
112369
  if (currentQuery.statement === "insert") {
111503
112370
  return ctx.attachInsertSource(plan, source);
111504
112371
  }
111505
- if (typeof source !== "object" || source === null || "kind" in source && source.kind === "values" && !("name" in source) || !(TypeId4 in source) && !(("name" in source) && ("baseName" in source))) {
111506
- throw new Error("from(...) requires an aliased source in select/update statements");
112372
+ assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
112373
+ if (currentQuery.statement === "select" && currentAst.from !== undefined) {
112374
+ throw new Error("select statements accept only one from(...) source; use joins for additional sources");
111507
112375
  }
111508
112376
  const sourceLike = source;
111509
112377
  const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
111510
112378
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
112379
+ const sourceRequired = sourceRequiredList(sourceLike);
112380
+ assertSourceNameAvailable(current.available, sourceName);
111511
112381
  if (currentQuery.statement === "select") {
112382
+ const nextAvailable = {
112383
+ [sourceName]: {
112384
+ name: sourceName,
112385
+ mode: "required",
112386
+ baseName: sourceBaseName,
112387
+ _presentFormula: ctx.trueFormula(),
112388
+ _presenceWitnesses: presenceWitnesses
112389
+ }
112390
+ };
111512
112391
  return ctx.makePlan({
111513
112392
  selection: current.selection,
111514
- required: ctx.currentRequiredList(current.required).filter((name) => name !== sourceName),
111515
- available: {
111516
- [sourceName]: {
111517
- name: sourceName,
111518
- mode: "required",
111519
- baseName: sourceBaseName,
111520
- _presentFormula: ctx.trueFormula(),
111521
- _presenceWitnesses: presenceWitnesses
111522
- }
111523
- },
112393
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index4, values) => !(name in nextAvailable) && values.indexOf(name) === index4),
112394
+ available: nextAvailable,
111524
112395
  dialect: current.dialect
111525
112396
  }, {
111526
112397
  ...currentAst,
@@ -111545,7 +112416,7 @@ var makeDslPlanRuntime = (ctx) => {
111545
112416
  };
111546
112417
  return ctx.makePlan({
111547
112418
  selection: current.selection,
111548
- required: ctx.currentRequiredList(current.required).filter((name) => !(name in nextAvailable)),
112419
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index4, values) => !(name in nextAvailable) && values.indexOf(name) === index4),
111549
112420
  available: nextAvailable,
111550
112421
  dialect: current.dialect
111551
112422
  }, {
@@ -111586,8 +112457,16 @@ var makeDslPlanRuntime = (ctx) => {
111586
112457
  const current = plan[TypeId3];
111587
112458
  const currentAst = ctx.getAst(plan);
111588
112459
  const currentQuery = ctx.getQueryState(plan);
112460
+ if (supportsJoinSources(currentQuery.statement)) {
112461
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
112462
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
112463
+ }
111589
112464
  const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
111590
112465
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
112466
+ const sourceRequired = sourceRequiredList(table);
112467
+ if (supportsJoinSources(currentQuery.statement)) {
112468
+ assertSourceNameAvailable(current.available, sourceName);
112469
+ }
111591
112470
  const nextAvailable = {
111592
112471
  ...current.available,
111593
112472
  [sourceName]: {
@@ -111600,7 +112479,7 @@ var makeDslPlanRuntime = (ctx) => {
111600
112479
  };
111601
112480
  return ctx.makePlan({
111602
112481
  selection: current.selection,
111603
- required: ctx.currentRequiredList(current.required).filter((name) => !(name in nextAvailable)),
112482
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index4, values) => !(name in nextAvailable) && values.indexOf(name) === index4),
111604
112483
  available: nextAvailable,
111605
112484
  dialect: current.dialect ?? table[TypeId3]?.dialect ?? table.dialect
111606
112485
  }, {
@@ -111619,8 +112498,16 @@ var makeDslPlanRuntime = (ctx) => {
111619
112498
  const currentQuery = ctx.getQueryState(plan);
111620
112499
  const onExpression = ctx.toDialectExpression(on);
111621
112500
  const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
112501
+ if (supportsJoinSources(currentQuery.statement)) {
112502
+ assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
112503
+ assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
112504
+ }
111622
112505
  const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
111623
112506
  const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
112507
+ const sourceRequired = sourceRequiredList(table);
112508
+ if (supportsJoinSources(currentQuery.statement)) {
112509
+ assertSourceNameAvailable(current.available, sourceName);
112510
+ }
111624
112511
  const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
111625
112512
  name: source.name,
111626
112513
  mode: "optional",
@@ -111640,7 +112527,7 @@ var makeDslPlanRuntime = (ctx) => {
111640
112527
  };
111641
112528
  return ctx.makePlan({
111642
112529
  selection: current.selection,
111643
- required: [...ctx.currentRequiredList(current.required), ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index4, values) => !(name in nextAvailable) && values.indexOf(name) === index4),
112530
+ required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index4, values) => !(name in nextAvailable) && values.indexOf(name) === index4),
111644
112531
  available: nextAvailable,
111645
112532
  dialect: current.dialect ?? table.dialect ?? onExpression[TypeId].dialect
111646
112533
  }, {
@@ -111655,6 +112542,9 @@ var makeDslPlanRuntime = (ctx) => {
111655
112542
  }, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
111656
112543
  };
111657
112544
  const orderBy = (value, direction = "asc") => (plan) => {
112545
+ if (direction !== "asc" && direction !== "desc") {
112546
+ throw new Error("orderBy(...) direction must be asc or desc");
112547
+ }
111658
112548
  const current = plan[TypeId3];
111659
112549
  const currentAst = ctx.getAst(plan);
111660
112550
  const currentQuery = ctx.getQueryState(plan);
@@ -111678,6 +112568,15 @@ var makeDslPlanRuntime = (ctx) => {
111678
112568
  const current = plan[TypeId3];
111679
112569
  const currentAst = ctx.getAst(plan);
111680
112570
  const currentQuery = ctx.getQueryState(plan);
112571
+ if (currentQuery.statement === "select") {
112572
+ renderSelectLockMode(mode);
112573
+ }
112574
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
112575
+ renderMysqlMutationLockMode(mode, "update");
112576
+ }
112577
+ if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
112578
+ renderMysqlMutationLockMode(mode, "delete");
112579
+ }
111681
112580
  return ctx.makePlan({
111682
112581
  selection: current.selection,
111683
112582
  required: current.required,
@@ -111754,18 +112653,96 @@ var makeDslPlanRuntime = (ctx) => {
111754
112653
  };
111755
112654
  };
111756
112655
 
112656
+ // src/internal/projection-alias.ts
112657
+ var TypeId7 = Symbol.for("effect-qb/ProjectionAlias");
112658
+
112659
+ // src/internal/projections.ts
112660
+ var aliasFromPath = (path2) => path2.join("__");
112661
+ var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId in value);
112662
+ var projectionAliasOf = (expression) => (TypeId7 in expression) ? expression[TypeId7].alias : undefined;
112663
+ var pathKeyOf = (path2) => JSON.stringify(path2);
112664
+ var formatProjectionPath = (path2) => path2.join(".");
112665
+ var isPrefixPath = (left, right) => left.length < right.length && left.every((segment, index4) => segment === right[index4]);
112666
+ var flattenSelection = (selection, path2 = []) => {
112667
+ const fields2 = [];
112668
+ for (const [key2, value] of Object.entries(selection)) {
112669
+ const nextPath = [...path2, key2];
112670
+ if (isExpression2(value)) {
112671
+ fields2.push({
112672
+ path: nextPath,
112673
+ expression: value,
112674
+ alias: projectionAliasOf(value) ?? aliasFromPath(nextPath)
112675
+ });
112676
+ continue;
112677
+ }
112678
+ fields2.push(...flattenSelection(value, nextPath));
112679
+ }
112680
+ return fields2;
112681
+ };
112682
+ var validateProjections = (projections) => {
112683
+ const seen = new Set;
112684
+ const pathKeys = new Set;
112685
+ for (const projection of projections) {
112686
+ if (seen.has(projection.alias)) {
112687
+ throw new Error(`Duplicate projection alias: ${projection.alias}`);
112688
+ }
112689
+ seen.add(projection.alias);
112690
+ const pathKey = pathKeyOf(projection.path);
112691
+ if (pathKeys.has(pathKey)) {
112692
+ throw new Error(`Duplicate projection path: ${formatProjectionPath(projection.path)}`);
112693
+ }
112694
+ pathKeys.add(pathKey);
112695
+ }
112696
+ for (let index4 = 0;index4 < projections.length; index4++) {
112697
+ const current = projections[index4];
112698
+ for (let compareIndex = index4 + 1;compareIndex < projections.length; compareIndex++) {
112699
+ const other = projections[compareIndex];
112700
+ if (isPrefixPath(current.path, other.path) || isPrefixPath(other.path, current.path)) {
112701
+ throw new Error(`Conflicting projection paths: ${formatProjectionPath(current.path)} conflicts with ${formatProjectionPath(other.path)}`);
112702
+ }
112703
+ }
112704
+ }
112705
+ };
112706
+
111757
112707
  // src/internal/dsl-query-runtime.ts
111758
112708
  var makeDslQueryRuntime = (ctx) => {
112709
+ const assertSelectionObject = (apiName, selection) => {
112710
+ if (selection === null || typeof selection !== "object" || Array.isArray(selection) || TypeId in selection) {
112711
+ throw new Error(`${apiName}(...) expects a projection object`);
112712
+ }
112713
+ };
112714
+ const assertSelectionTree = (apiName, selection) => {
112715
+ const visit = (value, isRoot) => {
112716
+ if (value !== null && typeof value === "object" && TypeId in value) {
112717
+ return;
112718
+ }
112719
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
112720
+ throw new Error(`${apiName}(...) selection leaves must be expressions`);
112721
+ }
112722
+ const nested = Object.values(value);
112723
+ if (!isRoot && nested.length === 0) {
112724
+ throw new Error(`${apiName}(...) projection objects cannot contain empty nested selections`);
112725
+ }
112726
+ for (const item of nested) {
112727
+ visit(item, false);
112728
+ }
112729
+ };
112730
+ visit(selection, true);
112731
+ };
111759
112732
  const values = (rows) => {
111760
112733
  if (rows.length === 0) {
111761
112734
  throw new Error("values(...) requires at least one row");
111762
112735
  }
111763
112736
  const normalizedRows = rows.map((row) => ctx.normalizeValuesRow(row));
111764
112737
  const columnNames = Object.keys(normalizedRows[0]);
112738
+ if (columnNames.length === 0) {
112739
+ throw new Error("values(...) rows must specify at least one column");
112740
+ }
112741
+ const columnNameSet = new Set(columnNames);
111765
112742
  for (const row of normalizedRows) {
111766
112743
  const rowKeys = Object.keys(row);
111767
- if (rowKeys.length !== columnNames.length || !rowKeys.every((key2, index4) => key2 === columnNames[index4])) {
111768
- throw new Error("values(...) rows must project the same columns in the same order");
112744
+ if (rowKeys.length !== columnNames.length || !rowKeys.every((key2) => columnNameSet.has(key2))) {
112745
+ throw new Error("values(...) rows must project the same columns");
111769
112746
  }
111770
112747
  }
111771
112748
  return Object.assign(Object.create(ctx.ValuesInputProto), {
@@ -111824,21 +112801,28 @@ var makeDslQueryRuntime = (ctx) => {
111824
112801
  };
111825
112802
  return Object.assign(source, columns);
111826
112803
  };
111827
- const select = (selection) => ctx.makePlan({
111828
- selection,
111829
- required: ctx.extractRequiredRuntime(selection),
111830
- available: {},
111831
- dialect: ctx.profile.dialect
111832
- }, {
111833
- kind: "select",
111834
- select: selection,
111835
- where: [],
111836
- having: [],
111837
- joins: [],
111838
- groupBy: [],
111839
- orderBy: []
111840
- }, undefined, "read", "select");
112804
+ const select = (selection = {}) => {
112805
+ assertSelectionObject("select", selection);
112806
+ assertSelectionTree("select", selection);
112807
+ return ctx.makePlan({
112808
+ selection,
112809
+ required: ctx.extractRequiredRuntime(selection),
112810
+ available: {},
112811
+ dialect: ctx.profile.dialect
112812
+ }, {
112813
+ kind: "select",
112814
+ select: selection,
112815
+ where: [],
112816
+ having: [],
112817
+ joins: [],
112818
+ groupBy: [],
112819
+ orderBy: []
112820
+ }, undefined, "read", "select");
112821
+ };
111841
112822
  const groupBy = (...values2) => (plan) => {
112823
+ if (values2.length === 0) {
112824
+ throw new Error("groupBy(...) requires at least one expression");
112825
+ }
111842
112826
  const current = plan[TypeId3];
111843
112827
  const currentAst = ctx.getAst(plan);
111844
112828
  const currentQuery = ctx.getQueryState(plan);
@@ -111853,19 +112837,29 @@ var makeDslQueryRuntime = (ctx) => {
111853
112837
  groupBy: ctx.dedupeGroupedExpressions([...currentAst.groupBy, ...values2])
111854
112838
  }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
111855
112839
  };
111856
- const returning = (selection) => (plan) => {
111857
- const current = plan[TypeId3];
111858
- const currentAst = ctx.getAst(plan);
111859
- const currentQuery = ctx.getQueryState(plan);
111860
- return ctx.makePlan({
111861
- selection,
111862
- required: [...ctx.currentRequiredList(current.required), ...ctx.extractRequiredRuntime(selection)].filter((name, index4, list) => !(name in current.available) && list.indexOf(name) === index4),
111863
- available: current.available,
111864
- dialect: current.dialect
111865
- }, {
111866
- ...currentAst,
111867
- select: selection
111868
- }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
112840
+ const returning = (selection) => {
112841
+ assertSelectionObject("returning", selection);
112842
+ assertSelectionTree("returning", selection);
112843
+ if (flattenSelection(selection).length === 0) {
112844
+ throw new Error("returning(...) requires at least one selected expression");
112845
+ }
112846
+ return (plan) => {
112847
+ const current = plan[TypeId3];
112848
+ const currentAst = ctx.getAst(plan);
112849
+ const currentQuery = ctx.getQueryState(plan);
112850
+ if (currentQuery.statement !== "insert" && currentQuery.statement !== "update" && currentQuery.statement !== "delete") {
112851
+ throw new Error(`returning(...) is not supported for ${currentQuery.statement} statements`);
112852
+ }
112853
+ return ctx.makePlan({
112854
+ selection,
112855
+ required: [...ctx.currentRequiredList(current.required), ...ctx.extractRequiredRuntime(selection)].filter((name, index4, list) => !(name in current.available) && list.indexOf(name) === index4),
112856
+ available: current.available,
112857
+ dialect: current.dialect
112858
+ }, {
112859
+ ...currentAst,
112860
+ select: selection
112861
+ }, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
112862
+ };
111869
112863
  };
111870
112864
  return {
111871
112865
  values,
@@ -111878,26 +112872,71 @@ var makeDslQueryRuntime = (ctx) => {
111878
112872
  };
111879
112873
 
111880
112874
  // src/internal/dsl-transaction-ddl-runtime.ts
112875
+ var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
112876
+ var renderTransactionIsolationLevel = (isolationLevel) => {
112877
+ if (isolationLevel === undefined) {
112878
+ return "";
112879
+ }
112880
+ if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
112881
+ throw new Error("Unsupported transaction isolation level");
112882
+ }
112883
+ return `isolation level ${isolationLevel}`;
112884
+ };
112885
+ var expectDdlClauseKind = (ddl, kind) => {
112886
+ if (ddl === undefined || ddl.kind !== kind) {
112887
+ throw new Error("Unsupported DDL statement kind");
112888
+ }
112889
+ return ddl;
112890
+ };
112891
+ var expectTruncateClause = (truncate) => {
112892
+ if (truncate === undefined || truncate.kind !== "truncate") {
112893
+ throw new Error("Unsupported truncate statement kind");
112894
+ }
112895
+ return truncate;
112896
+ };
112897
+ var validateIsolationLevel = (isolationLevel) => {
112898
+ renderTransactionIsolationLevel(isolationLevel);
112899
+ };
111881
112900
  var makeDslTransactionDdlRuntime = (ctx) => {
111882
- const transaction = (options2 = {}) => ctx.makePlan({
111883
- selection: {},
111884
- required: [],
111885
- available: {},
111886
- dialect: ctx.profile.dialect
111887
- }, {
111888
- kind: "transaction",
111889
- select: {},
111890
- transaction: {
112901
+ const isRecord3 = (value) => typeof value === "object" && value !== null;
112902
+ const assertTableTarget = (target, apiName) => {
112903
+ if (!isRecord3(target) || !(TypeId4 in target) || !(TypeId3 in target)) {
112904
+ throw new Error(`${apiName}(...) requires a table target`);
112905
+ }
112906
+ };
112907
+ const validateIndexColumns = (target, columns) => {
112908
+ const fields2 = target[TypeId4]?.fields;
112909
+ if (fields2 === undefined) {
112910
+ return;
112911
+ }
112912
+ for (const columnName of columns) {
112913
+ if (!(columnName in fields2)) {
112914
+ throw new Error(`effect-qb: unknown index column '${columnName}'`);
112915
+ }
112916
+ }
112917
+ };
112918
+ const transaction = (options2 = {}) => {
112919
+ validateIsolationLevel(options2.isolationLevel);
112920
+ return ctx.makePlan({
112921
+ selection: {},
112922
+ required: [],
112923
+ available: {},
112924
+ dialect: ctx.profile.dialect
112925
+ }, {
111891
112926
  kind: "transaction",
111892
- isolationLevel: options2.isolationLevel,
111893
- readOnly: options2.readOnly
111894
- },
111895
- where: [],
111896
- having: [],
111897
- joins: [],
111898
- groupBy: [],
111899
- orderBy: []
111900
- }, undefined, "transaction", "transaction");
112927
+ select: {},
112928
+ transaction: {
112929
+ kind: "transaction",
112930
+ isolationLevel: options2.isolationLevel,
112931
+ readOnly: options2.readOnly
112932
+ },
112933
+ where: [],
112934
+ having: [],
112935
+ joins: [],
112936
+ groupBy: [],
112937
+ orderBy: []
112938
+ }, undefined, "transaction", "transaction");
112939
+ };
111901
112940
  const commit = () => ctx.makePlan({
111902
112941
  selection: {},
111903
112942
  required: [],
@@ -111987,6 +113026,7 @@ var makeDslTransactionDdlRuntime = (ctx) => {
111987
113026
  orderBy: []
111988
113027
  }, undefined, "transaction", "releaseSavepoint");
111989
113028
  const createTable = (target, options2 = {}) => {
113029
+ assertTableTarget(target, "createTable");
111990
113030
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
111991
113031
  return ctx.makePlan({
111992
113032
  selection: {},
@@ -112014,6 +113054,7 @@ var makeDslTransactionDdlRuntime = (ctx) => {
112014
113054
  }, undefined, "ddl", "createTable");
112015
113055
  };
112016
113056
  const dropTable = (target, options2 = {}) => {
113057
+ assertTableTarget(target, "dropTable");
112017
113058
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
112018
113059
  return ctx.makePlan({
112019
113060
  selection: {},
@@ -112041,7 +113082,9 @@ var makeDslTransactionDdlRuntime = (ctx) => {
112041
113082
  }, undefined, "ddl", "dropTable");
112042
113083
  };
112043
113084
  const createIndex = (target, columns, options2 = {}) => {
113085
+ assertTableTarget(target, "createIndex");
112044
113086
  const normalizedColumns = ctx.normalizeColumnList(columns);
113087
+ validateIndexColumns(target, normalizedColumns);
112045
113088
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
112046
113089
  return ctx.makePlan({
112047
113090
  selection: {},
@@ -112072,7 +113115,9 @@ var makeDslTransactionDdlRuntime = (ctx) => {
112072
113115
  }, undefined, "ddl", "createIndex");
112073
113116
  };
112074
113117
  const dropIndex = (target, columns, options2 = {}) => {
113118
+ assertTableTarget(target, "dropIndex");
112075
113119
  const normalizedColumns = ctx.normalizeColumnList(columns);
113120
+ validateIndexColumns(target, normalizedColumns);
112076
113121
  const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
112077
113122
  return ctx.makePlan({
112078
113123
  selection: {},
@@ -112116,59 +113161,6 @@ var makeDslTransactionDdlRuntime = (ctx) => {
112116
113161
 
112117
113162
  // src/internal/derived-table.ts
112118
113163
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
112119
-
112120
- // src/internal/projection-alias.ts
112121
- var TypeId7 = Symbol.for("effect-qb/ProjectionAlias");
112122
-
112123
- // src/internal/projections.ts
112124
- var aliasFromPath = (path2) => path2.join("__");
112125
- var isExpression = (value) => typeof value === "object" && value !== null && (TypeId in value);
112126
- var projectionAliasOf = (expression) => (TypeId7 in expression) ? expression[TypeId7].alias : undefined;
112127
- var pathKeyOf = (path2) => JSON.stringify(path2);
112128
- var formatProjectionPath = (path2) => path2.join(".");
112129
- var isPrefixPath = (left, right) => left.length < right.length && left.every((segment, index4) => segment === right[index4]);
112130
- var flattenSelection = (selection, path2 = []) => {
112131
- const fields2 = [];
112132
- for (const [key2, value] of Object.entries(selection)) {
112133
- const nextPath = [...path2, key2];
112134
- if (isExpression(value)) {
112135
- fields2.push({
112136
- path: nextPath,
112137
- expression: value,
112138
- alias: projectionAliasOf(value) ?? aliasFromPath(nextPath)
112139
- });
112140
- continue;
112141
- }
112142
- fields2.push(...flattenSelection(value, nextPath));
112143
- }
112144
- return fields2;
112145
- };
112146
- var validateProjections = (projections) => {
112147
- const seen = new Set;
112148
- const pathKeys = new Set;
112149
- for (const projection of projections) {
112150
- if (seen.has(projection.alias)) {
112151
- throw new Error(`Duplicate projection alias: ${projection.alias}`);
112152
- }
112153
- seen.add(projection.alias);
112154
- const pathKey = pathKeyOf(projection.path);
112155
- if (pathKeys.has(pathKey)) {
112156
- throw new Error(`Duplicate projection path: ${formatProjectionPath(projection.path)}`);
112157
- }
112158
- pathKeys.add(pathKey);
112159
- }
112160
- for (let index4 = 0;index4 < projections.length; index4++) {
112161
- const current = projections[index4];
112162
- for (let compareIndex = index4 + 1;compareIndex < projections.length; compareIndex++) {
112163
- const other = projections[compareIndex];
112164
- if (isPrefixPath(current.path, other.path) || isPrefixPath(other.path, current.path)) {
112165
- throw new Error(`Conflicting projection paths: ${formatProjectionPath(current.path)} conflicts with ${formatProjectionPath(other.path)}`);
112166
- }
112167
- }
112168
- }
112169
- };
112170
-
112171
- // src/internal/derived-table.ts
112172
113164
  var DerivedProto = {
112173
113165
  pipe() {
112174
113166
  return pipeArguments4(this, arguments);
@@ -112200,10 +113192,24 @@ var setPath = (target, path2, value) => {
112200
113192
  current[path2[path2.length - 1]] = value;
112201
113193
  };
112202
113194
  var pathAlias = (path2) => path2.join("__");
113195
+ var assertSourceComplete = (plan) => {
113196
+ const required = currentRequiredList(plan[TypeId3].required);
113197
+ if (required.length > 0) {
113198
+ throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
113199
+ }
113200
+ };
113201
+ var assertInlineSourceStatement = (plan) => {
113202
+ const statement = getQueryState(plan).statement;
113203
+ if (statement !== "select" && statement !== "set") {
113204
+ throw new Error("inline derived sources only accept select-like query plans");
113205
+ }
113206
+ };
112203
113207
  var reboundedColumns = (plan, alias2) => {
112204
113208
  const ast = getAst(plan);
112205
113209
  const selection = {};
112206
- for (const projection of flattenSelection(ast.select)) {
113210
+ const projections = flattenSelection(ast.select);
113211
+ validateProjections(projections);
113212
+ for (const projection of projections) {
112207
113213
  const expectedAlias = pathAlias(projection.path);
112208
113214
  if (projection.alias !== expectedAlias) {
112209
113215
  throw new Error(`Derived subqueries currently require path-based output aliases; expected '${expectedAlias}' for path '${projection.path.join(".")}'`);
@@ -112228,6 +113234,8 @@ var reboundedColumns = (plan, alias2) => {
112228
113234
  return selection;
112229
113235
  };
112230
113236
  var makeDerivedSource = (plan, alias2) => {
113237
+ assertInlineSourceStatement(plan);
113238
+ assertSourceComplete(plan);
112231
113239
  const columns = reboundedColumns(plan, alias2);
112232
113240
  const derived = attachPipe3(Object.create(DerivedProto));
112233
113241
  Object.assign(derived, columns);
@@ -112241,6 +113249,7 @@ var makeDerivedSource = (plan, alias2) => {
112241
113249
  return derived;
112242
113250
  };
112243
113251
  var makeCteSource = (plan, alias2, recursive = false) => {
113252
+ assertSourceComplete(plan);
112244
113253
  const columns = reboundedColumns(plan, alias2);
112245
113254
  const cte = attachPipe3(Object.create(DerivedProto));
112246
113255
  Object.assign(cte, columns);
@@ -112255,6 +113264,7 @@ var makeCteSource = (plan, alias2, recursive = false) => {
112255
113264
  return cte;
112256
113265
  };
112257
113266
  var makeLateralSource = (plan, alias2) => {
113267
+ assertInlineSourceStatement(plan);
112258
113268
  const columns = reboundedColumns(plan, alias2);
112259
113269
  const lateral = attachPipe3(Object.create(DerivedProto));
112260
113270
  Object.assign(lateral, columns);
@@ -112263,7 +113273,7 @@ var makeLateralSource = (plan, alias2) => {
112263
113273
  lateral.baseName = alias2;
112264
113274
  lateral.dialect = plan[TypeId3].dialect;
112265
113275
  lateral.plan = plan;
112266
- lateral.required = undefined;
113276
+ lateral.required = currentRequiredList(plan[TypeId3].required);
112267
113277
  lateral.columns = columns;
112268
113278
  return lateral;
112269
113279
  };
@@ -112326,6 +113336,34 @@ var toDialectExpression = (value) => {
112326
113336
  }
112327
113337
  return literal(value);
112328
113338
  };
113339
+ var retargetLiteralExpression = (value, target) => {
113340
+ const ast = value[TypeId2];
113341
+ if (ast.kind !== "literal") {
113342
+ return value;
113343
+ }
113344
+ const targetState = target[TypeId];
113345
+ return makeExpression({
113346
+ runtime: value[TypeId].runtime,
113347
+ dbType: targetState.dbType,
113348
+ runtimeSchema: targetState.runtimeSchema,
113349
+ driverValueMapping: targetState.driverValueMapping,
113350
+ nullability: value[TypeId].nullability,
113351
+ dialect: targetState.dialect,
113352
+ kind: "scalar",
113353
+ dependencies: {}
113354
+ }, ast);
113355
+ };
113356
+ var alignBinaryPredicateExpressions = (left, right) => {
113357
+ const leftAst = left[TypeId2];
113358
+ const rightAst = right[TypeId2];
113359
+ if (leftAst.kind === "literal" && rightAst.kind !== "literal") {
113360
+ return [retargetLiteralExpression(left, right), right];
113361
+ }
113362
+ if (rightAst.kind === "literal" && leftAst.kind !== "literal") {
113363
+ return [left, retargetLiteralExpression(right, left)];
113364
+ }
113365
+ return [left, right];
113366
+ };
112329
113367
  var toDialectStringExpression = (value) => typeof value === "string" ? literal(value) : value;
112330
113368
  var toDialectNumericExpression = (value) => typeof value === "number" ? literal(value) : value;
112331
113369
  var flattenVariadicBooleanExpressions = (kind, values) => {
@@ -112379,10 +113417,16 @@ var extractRequiredFromDialectInputRuntime = (value) => {
112379
113417
  };
112380
113418
  var normalizeWindowSpec = (spec) => {
112381
113419
  const partitionBy = [...spec?.partitionBy ?? []];
112382
- const orderBy = (spec?.orderBy ?? []).map((term) => ({
112383
- value: term.value,
112384
- direction: term.direction ?? "asc"
112385
- }));
113420
+ const orderBy = (spec?.orderBy ?? []).map((term) => {
113421
+ const direction = term.direction ?? "asc";
113422
+ if (direction !== "asc" && direction !== "desc") {
113423
+ throw new Error("window order direction must be asc or desc");
113424
+ }
113425
+ return {
113426
+ value: term.value,
113427
+ direction
113428
+ };
113429
+ });
112386
113430
  return {
112387
113431
  partitionBy,
112388
113432
  orderBy
@@ -112394,8 +113438,7 @@ var extractRequiredFromDialectNumericInputRuntime = (value) => {
112394
113438
  return Object.keys(expression[TypeId].dependencies);
112395
113439
  };
112396
113440
  var buildBinaryPredicate = (left, right, kind, nullability = "maybe") => {
112397
- const leftExpression = toDialectExpression(left);
112398
- const rightExpression = toDialectExpression(right);
113441
+ const [leftExpression, rightExpression] = alignBinaryPredicateExpressions(toDialectExpression(left), toDialectExpression(right));
112399
113442
  return makeExpression({
112400
113443
  runtime: true,
112401
113444
  dbType: profile.boolDb,
@@ -112411,16 +113454,18 @@ var buildBinaryPredicate = (left, right, kind, nullability = "maybe") => {
112411
113454
  };
112412
113455
  var buildVariadicPredicate = (values, kind) => {
112413
113456
  const expressions = values.map((value) => toDialectExpression(value));
113457
+ const [head, ...tail] = expressions;
113458
+ const alignedExpressions = head !== undefined && (kind === "in" || kind === "notIn" || kind === "between") ? [head, ...tail.map((value) => retargetLiteralExpression(value, head))] : expressions;
112414
113459
  return makeExpression({
112415
113460
  runtime: true,
112416
113461
  dbType: profile.boolDb,
112417
113462
  nullability: "maybe",
112418
- dialect: expressions.find((value) => value[TypeId].dialect !== undefined)?.[TypeId].dialect ?? profile.dialect,
113463
+ dialect: alignedExpressions.find((value) => value[TypeId].dialect !== undefined)?.[TypeId].dialect ?? profile.dialect,
112419
113464
  kind: "scalar",
112420
- dependencies: mergeManyDependencies(expressions)
113465
+ dependencies: mergeManyDependencies(alignedExpressions)
112421
113466
  }, {
112422
113467
  kind,
112423
- values: expressions
113468
+ values: alignedExpressions
112424
113469
  });
112425
113470
  };
112426
113471
  var eq = (...args) => {
@@ -112541,6 +113586,7 @@ var cast = (value, target) => {
112541
113586
  runtime: undefined,
112542
113587
  dbType: target,
112543
113588
  runtimeSchema: undefined,
113589
+ driverValueMapping: target.driverValueMapping,
112544
113590
  nullability: expression[TypeId].nullability,
112545
113591
  dialect: expression[TypeId].dialect,
112546
113592
  kind: expression[TypeId].kind,
@@ -112590,6 +113636,10 @@ var custom2 = (kind) => ({
112590
113636
  dialect: profile.dialect,
112591
113637
  kind
112592
113638
  });
113639
+ var driverValueMapping3 = (dbType, mapping) => ({
113640
+ ...dbType,
113641
+ driverValueMapping: mapping
113642
+ });
112593
113643
  var type = {
112594
113644
  ...profile.type,
112595
113645
  array: array2,
@@ -112599,7 +113649,8 @@ var type = {
112599
113649
  domain,
112600
113650
  enum: enum_,
112601
113651
  set,
112602
- custom: custom2
113652
+ custom: custom2,
113653
+ driverValueMapping: driverValueMapping3
112603
113654
  };
112604
113655
  var makeJsonDb = (kind) => ({
112605
113656
  dialect: profile.dialect,
@@ -113112,6 +114163,8 @@ var scalar = (plan) => {
113112
114163
  return makeExpression({
113113
114164
  runtime: undefined,
113114
114165
  dbType: expression[TypeId].dbType,
114166
+ runtimeSchema: expression[TypeId].runtimeSchema,
114167
+ driverValueMapping: expression[TypeId].driverValueMapping,
113115
114168
  nullability: "maybe",
113116
114169
  dialect: profile.dialect,
113117
114170
  kind: "scalar",
@@ -113340,6 +114393,7 @@ var excluded = (value) => {
113340
114393
  runtime: undefined,
113341
114394
  dbType: value[TypeId].dbType,
113342
114395
  runtimeSchema: value[TypeId].runtimeSchema,
114396
+ driverValueMapping: value[TypeId].driverValueMapping,
113343
114397
  nullability: value[TypeId].nullability,
113344
114398
  dialect: profile.dialect,
113345
114399
  kind: "scalar",
@@ -113350,19 +114404,52 @@ var excluded = (value) => {
113350
114404
  });
113351
114405
  };
113352
114406
  var toMutationValueExpression = (value, column2) => {
114407
+ const columnState = column2[TypeId];
114408
+ const normalizeMutationValue = (candidate) => {
114409
+ if (candidate === null && columnState.nullability !== "never") {
114410
+ return null;
114411
+ }
114412
+ const runtimeSchemaAccepts = columnState.runtimeSchema !== undefined && Schema6.is(columnState.runtimeSchema)(candidate);
114413
+ if (runtimeSchemaAccepts) {
114414
+ return candidate;
114415
+ }
114416
+ const normalized = normalizeDbValue(columnState.dbType, candidate);
114417
+ return columnState.runtimeSchema === undefined ? normalized : Schema6.decodeUnknownSync(columnState.runtimeSchema)(normalized);
114418
+ };
113353
114419
  if (value !== null && typeof value === "object" && TypeId in value) {
113354
- return value;
114420
+ const expression = value;
114421
+ const ast = expression[TypeId2];
114422
+ if (ast.kind === "literal") {
114423
+ const normalizedValue2 = normalizeMutationValue(ast.value);
114424
+ return makeExpression({
114425
+ runtime: normalizedValue2,
114426
+ dbType: columnState.dbType,
114427
+ runtimeSchema: columnState.runtimeSchema,
114428
+ driverValueMapping: columnState.driverValueMapping,
114429
+ nullability: normalizedValue2 === null ? "always" : "never",
114430
+ dialect: columnState.dialect,
114431
+ kind: "scalar",
114432
+ dependencies: {}
114433
+ }, {
114434
+ kind: "literal",
114435
+ value: normalizedValue2
114436
+ });
114437
+ }
114438
+ return retargetLiteralExpression(value, column2);
113355
114439
  }
114440
+ const normalizedValue = normalizeMutationValue(value);
113356
114441
  return makeExpression({
113357
- runtime: value,
113358
- dbType: column2[TypeId].dbType,
113359
- nullability: value === null ? "always" : "never",
113360
- dialect: column2[TypeId].dialect,
114442
+ runtime: normalizedValue,
114443
+ dbType: columnState.dbType,
114444
+ runtimeSchema: columnState.runtimeSchema,
114445
+ driverValueMapping: columnState.driverValueMapping,
114446
+ nullability: normalizedValue === null ? "always" : "never",
114447
+ dialect: columnState.dialect,
113361
114448
  kind: "scalar",
113362
114449
  dependencies: {}
113363
114450
  }, {
113364
114451
  kind: "literal",
113365
- value
114452
+ value: normalizedValue
113366
114453
  });
113367
114454
  };
113368
114455
  var renderQuantifiedComparisonAst = (left, plan, operator, quantifier) => ({
@@ -113397,6 +114484,7 @@ var makeColumnReferenceSelection = (alias2, selection) => {
113397
114484
  runtime: undefined,
113398
114485
  dbType: state.dbType,
113399
114486
  runtimeSchema: state.runtimeSchema,
114487
+ driverValueMapping: state.driverValueMapping,
113400
114488
  nullability: state.nullability,
113401
114489
  dialect: state.dialect,
113402
114490
  kind: "scalar",
@@ -113424,7 +114512,12 @@ var makeAliasedValuesSource = (rows, selection, alias2) => {
113424
114512
  return Object.assign(source, columns);
113425
114513
  };
113426
114514
  var normalizeValuesRow = (row) => Object.fromEntries(Object.entries(row).map(([key2, value]) => [key2, toDialectExpression(value)]));
113427
- var normalizeUnnestColumns = (columns) => Object.fromEntries(Object.entries(columns).map(([key2, values]) => [key2, values.map((value) => toDialectExpression(value))]));
114515
+ var normalizeUnnestColumns = (columns) => Object.fromEntries(Object.entries(columns).map(([key2, values]) => {
114516
+ if (!Array.isArray(values)) {
114517
+ throw new Error("unnest(...) expects every value to be an array");
114518
+ }
114519
+ return [key2, values.map((value) => toDialectExpression(value))];
114520
+ }));
113428
114521
  var normalizeMutationTargets = (target) => Array.isArray(target) ? target : [target];
113429
114522
  var mutationTargetClauses = (target) => normalizeMutationTargets(target).map((table) => {
113430
114523
  const { sourceName, sourceBaseName } = targetSourceDetails(table);
@@ -113446,13 +114539,20 @@ var mutationAvailableSources = (target, mode = "required") => Object.fromEntries
113446
114539
  }
113447
114540
  ];
113448
114541
  }));
114542
+ var getMutationColumn = (columns, columnName) => {
114543
+ const column2 = columns[columnName];
114544
+ if (column2 === undefined || column2 === null || typeof column2 !== "object" || !(TypeId in column2)) {
114545
+ throw new Error("effect-qb: unknown mutation column");
114546
+ }
114547
+ return column2;
114548
+ };
113449
114549
  var buildMutationAssignments = (target, values) => {
113450
114550
  const targets = normalizeMutationTargets(target);
113451
114551
  if (targets.length === 1 && !Array.isArray(target)) {
113452
114552
  const columns = target;
113453
114553
  return Object.entries(values).map(([columnName, value]) => ({
113454
114554
  columnName,
113455
- value: toMutationValueExpression(value, columns[columnName])
114555
+ value: toMutationValueExpression(value, getMutationColumn(columns, columnName))
113456
114556
  }));
113457
114557
  }
113458
114558
  const valueMap = values;
@@ -113463,7 +114563,7 @@ var buildMutationAssignments = (target, values) => {
113463
114563
  return Object.entries(scopedValues).map(([columnName, value]) => ({
113464
114564
  tableName: targetName,
113465
114565
  columnName,
113466
- value: toMutationValueExpression(value, columns[columnName])
114566
+ value: toMutationValueExpression(value, getMutationColumn(columns, columnName))
113467
114567
  }));
113468
114568
  });
113469
114569
  };
@@ -113526,25 +114626,22 @@ var normalizeInsertUnnestValues = (target, values) => {
113526
114626
  values: normalized
113527
114627
  };
113528
114628
  };
114629
+ var normalizeConflictColumns = (target, columnsInput) => {
114630
+ const columns = normalizeColumnList(columnsInput);
114631
+ const knownColumns = new Set(Object.keys(target[TypeId4].fields));
114632
+ if (columns.some((columnName) => !knownColumns.has(columnName))) {
114633
+ throw new Error("effect-qb: unknown conflict target column");
114634
+ }
114635
+ return columns;
114636
+ };
113529
114637
  var buildConflictTarget = (target, input) => {
113530
- if (Array.isArray(input)) {
114638
+ if (typeof input === "string" || Array.isArray(input)) {
113531
114639
  return {
113532
114640
  kind: "columns",
113533
- columns: normalizeColumnList(input)
114641
+ columns: normalizeConflictColumns(target, input)
113534
114642
  };
113535
114643
  }
113536
- if (!Array.isArray(input) && "constraint" in input) {
113537
- return {
113538
- kind: "constraint",
113539
- name: input.constraint
113540
- };
113541
- }
113542
- const columnTarget = input;
113543
- return {
113544
- kind: "columns",
113545
- columns: normalizeColumnList(columnTarget.columns),
113546
- where: columnTarget.where === undefined ? undefined : toDialectExpression(columnTarget.where)
113547
- };
114644
+ throw new Error("Unsupported mysql conflict target");
113548
114645
  };
113549
114646
  var defaultIndexName = (tableName, columns, unique4) => `${tableName}_${columns.join("_")}_${unique4 ? "uniq" : "idx"}`;
113550
114647
  function as(valueOrAlias, alias2) {
@@ -113657,6 +114754,7 @@ var distinctOn = {
113657
114754
  __effect_qb_hint__: "Use postgres.Query.distinctOn(...) or regular distinct()/grouping logic"
113658
114755
  };
113659
114756
  var mutationRuntime = makeDslMutationRuntime({
114757
+ profile,
113660
114758
  makePlan,
113661
114759
  getAst,
113662
114760
  getQueryState,
@@ -113669,7 +114767,7 @@ var mutationRuntime = makeDslMutationRuntime({
113669
114767
  buildConflictTarget,
113670
114768
  mutationTargetClauses,
113671
114769
  mutationAvailableSources,
113672
- normalizeColumnList,
114770
+ normalizeConflictColumns,
113673
114771
  targetSourceDetails,
113674
114772
  sourceDetails
113675
114773
  });
@@ -113680,7 +114778,7 @@ var update = (target, values2) => mutationRuntime.update(target, values2);
113680
114778
  var upsert = (target, values2, conflictColumns, updateValues) => mutationRuntime.upsert(target, values2, conflictColumns, updateValues);
113681
114779
  var delete_ = (target) => mutationRuntime.delete_(target);
113682
114780
  var truncate = (target, options2 = {}) => mutationRuntime.truncate(target, options2);
113683
- var merge = (target, source, on, options2 = {}) => mutationRuntime.merge(target, source, on, options2);
114781
+ var merge = (target, source, on, options2) => mutationRuntime.merge(target, source, on, options2);
113684
114782
  var {
113685
114783
  transaction,
113686
114784
  commit,
@@ -113785,315 +114883,195 @@ import * as Stream2 from "effect/Stream";
113785
114883
  import * as Chunk from "effect/Chunk";
113786
114884
  import * as Effect from "effect/Effect";
113787
114885
  import * as Option from "effect/Option";
113788
- import * as Schema8 from "effect/Schema";
114886
+ import * as Schema9 from "effect/Schema";
113789
114887
  import * as SqlClient from "@effect/sql/SqlClient";
113790
114888
  import * as Stream from "effect/Stream";
113791
114889
 
113792
- // src/internal/runtime/normalize.ts
113793
- var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
113794
- var pad = (value, width = 2) => value.toString().padStart(width, "0");
113795
- var formatLocalDate = (value) => `${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
113796
- var formatLocalTime = (value) => {
113797
- const milliseconds = value.getUTCMilliseconds();
113798
- const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
113799
- return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
113800
- };
113801
- var formatLocalDateTime = (value) => {
113802
- const milliseconds = value.getUTCMilliseconds();
113803
- const base = `${formatLocalDate(value)}T${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
113804
- return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
113805
- };
113806
- var runtimeTagOfBaseDbType = (dbType) => {
113807
- return dbType.runtime;
113808
- };
113809
- var expectString = (value, label) => {
113810
- if (typeof value === "string") {
113811
- return value;
113812
- }
113813
- throw new Error(`Expected ${label} as string`);
113814
- };
113815
- var normalizeNumber = (value) => {
113816
- if (typeof value === "number" && Number.isFinite(value)) {
113817
- return value;
114890
+ // src/internal/runtime/driver-value-mapping.ts
114891
+ import * as Schema7 from "effect/Schema";
114892
+ var runtimeTagOfDbType = (dbType) => {
114893
+ if (dbType === undefined) {
114894
+ return;
113818
114895
  }
113819
- if (typeof value === "string" && value.trim() !== "") {
113820
- const parsed = Number(value);
113821
- if (Number.isFinite(parsed)) {
113822
- return parsed;
113823
- }
114896
+ if ("base" in dbType) {
114897
+ return runtimeTagOfDbType(dbType.base);
113824
114898
  }
113825
- if (typeof value === "bigint" && Number.isSafeInteger(Number(value))) {
113826
- return Number(value);
114899
+ if ("element" in dbType) {
114900
+ return "array";
113827
114901
  }
113828
- throw new Error("Expected a finite numeric value");
113829
- };
113830
- var normalizeBoolean = (value) => {
113831
- if (typeof value === "boolean") {
113832
- return value;
114902
+ if ("fields" in dbType) {
114903
+ return "record";
113833
114904
  }
113834
- if (typeof value === "number") {
113835
- if (value === 1) {
113836
- return true;
113837
- }
113838
- if (value === 0) {
113839
- return false;
113840
- }
114905
+ if ("variant" in dbType && dbType.variant === "json") {
114906
+ return "json";
113841
114907
  }
113842
- if (typeof value === "string") {
113843
- const normalized = value.trim().toLowerCase();
113844
- if (normalized === "true" || normalized === "t" || normalized === "1") {
113845
- return true;
113846
- }
113847
- if (normalized === "false" || normalized === "f" || normalized === "0") {
113848
- return false;
113849
- }
114908
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
114909
+ return "string";
113850
114910
  }
113851
- throw new Error("Expected a boolean-like value");
114911
+ return dbType.runtime;
113852
114912
  };
113853
- var normalizeBigIntString = (value) => {
113854
- if (typeof value === "bigint") {
113855
- return value.toString();
113856
- }
113857
- if (typeof value === "number" && Number.isSafeInteger(value)) {
113858
- return BigInt(value).toString();
114913
+ var familyOfDbType = (dbType) => {
114914
+ if (dbType === undefined) {
114915
+ return;
113859
114916
  }
113860
- if (typeof value === "string" && /^-?\d+$/.test(value.trim())) {
113861
- return BigInt(value.trim()).toString();
114917
+ if ("base" in dbType) {
114918
+ return familyOfDbType(dbType.base);
113862
114919
  }
113863
- throw new Error("Expected an integer-like bigint value");
114920
+ return dbType.family;
113864
114921
  };
113865
- var canonicalizeDecimalString = (input) => {
113866
- const trimmed = input.trim();
113867
- const match2 = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
113868
- if (match2 === null) {
113869
- throw new Error("Expected a decimal string");
113870
- }
113871
- const sign = match2[1] === "-" ? "-" : "";
113872
- const integer = match2[2].replace(/^0+(?=\d)/, "") || "0";
113873
- const fraction = (match2[3] ?? "").replace(/0+$/, "");
113874
- if (fraction.length === 0) {
113875
- return `${sign}${integer}`;
113876
- }
113877
- return `${sign}${integer}.${fraction}`;
114922
+ var mappingCandidates = (context) => {
114923
+ const dbType = context.dbType;
114924
+ const runtimeTag = runtimeTagOfDbType(dbType);
114925
+ const family = familyOfDbType(dbType);
114926
+ return [
114927
+ context.driverValueMapping,
114928
+ dbType?.driverValueMapping,
114929
+ dbType === undefined ? undefined : context.valueMappings?.[dbType.kind],
114930
+ family === undefined ? undefined : context.valueMappings?.[family],
114931
+ runtimeTag === undefined ? undefined : context.valueMappings?.[runtimeTag]
114932
+ ];
113878
114933
  };
113879
- var normalizeDecimalString = (value) => {
113880
- if (typeof value === "string") {
113881
- return canonicalizeDecimalString(value);
113882
- }
113883
- if (typeof value === "number" && Number.isFinite(value)) {
113884
- const rendered = String(value);
113885
- if (/[eE]/.test(rendered)) {
113886
- throw new Error("Scientific notation is not a supported decimal runtime");
114934
+ var findMapping = (context, key2) => {
114935
+ for (const candidate of mappingCandidates(context)) {
114936
+ const value = candidate?.[key2];
114937
+ if (value !== undefined) {
114938
+ return value;
113887
114939
  }
113888
- return canonicalizeDecimalString(rendered);
113889
114940
  }
113890
- throw new Error("Expected a decimal-like value");
114941
+ return;
113891
114942
  };
113892
- var normalizeLocalDate = (value) => {
113893
- if (value instanceof Date) {
113894
- return formatLocalDate(value);
114943
+ var isJsonDbType = (dbType) => {
114944
+ if (dbType === undefined) {
114945
+ return false;
113895
114946
  }
113896
- const raw = expectString(value, "local date").trim();
113897
- if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
113898
- return raw;
113899
- }
113900
- const parsed = new Date(raw);
113901
- if (!Number.isNaN(parsed.getTime())) {
113902
- return formatLocalDate(parsed);
113903
- }
113904
- throw new Error("Expected a local-date value");
113905
- };
113906
- var normalizeLocalTime = (value) => {
113907
- if (value instanceof Date) {
113908
- return formatLocalTime(value);
114947
+ if ("base" in dbType) {
114948
+ return isJsonDbType(dbType.base);
113909
114949
  }
113910
- const raw = expectString(value, "local time").trim();
113911
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
113912
- return raw;
114950
+ if (!("variant" in dbType)) {
114951
+ return false;
113913
114952
  }
113914
- throw new Error("Expected a local-time value");
114953
+ const variant = dbType.variant;
114954
+ return variant === "json" || variant === "jsonb";
113915
114955
  };
113916
- var normalizeOffsetTime = (value) => {
113917
- if (value instanceof Date) {
113918
- return `${formatLocalTime(value)}Z`;
114956
+ var schemaAccepts = (schema4, value) => schema4 !== undefined && Schema7.is(schema4)(value);
114957
+ var encodeWithSchema = (schema4, value) => {
114958
+ if (schema4 === undefined) {
114959
+ return { value, encoded: false };
113919
114960
  }
113920
- const raw = expectString(value, "offset time").trim();
113921
- if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
113922
- return raw;
114961
+ if (!Schema7.is(schema4)(value)) {
114962
+ return { value, encoded: false };
113923
114963
  }
113924
- throw new Error("Expected an offset-time value");
114964
+ return {
114965
+ value: Schema7.encodeUnknownSync(schema4)(value),
114966
+ encoded: true
114967
+ };
113925
114968
  };
113926
- var normalizeLocalDateTime = (value) => {
113927
- if (value instanceof Date) {
113928
- return formatLocalDateTime(value);
113929
- }
113930
- const raw = expectString(value, "local datetime").trim();
113931
- if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
113932
- return raw.replace(" ", "T");
114969
+ var normalizeJsonDriverString = (value, context) => {
114970
+ if (!isJsonDbType(context.dbType) || context.runtimeSchema === undefined) {
114971
+ return;
113933
114972
  }
113934
- if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
113935
- const parsed = new Date(raw);
113936
- if (!Number.isNaN(parsed.getTime())) {
113937
- return formatLocalDateTime(parsed);
114973
+ try {
114974
+ const parsed = JSON.parse(value);
114975
+ if (value.trimStart().startsWith('"') && schemaAccepts(context.runtimeSchema, parsed)) {
114976
+ return parsed;
114977
+ }
114978
+ if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
114979
+ return value;
114980
+ }
114981
+ } catch (error) {
114982
+ if (error instanceof SyntaxError && schemaAccepts(context.runtimeSchema, value)) {
114983
+ return value;
114984
+ }
114985
+ if (!(error instanceof SyntaxError)) {
114986
+ throw error;
113938
114987
  }
113939
114988
  }
113940
- throw new Error("Expected a local-datetime value");
113941
- };
113942
- var normalizeInstant = (value) => {
113943
- if (value instanceof Date) {
113944
- return value.toISOString();
113945
- }
113946
- const raw = expectString(value, "instant").trim();
113947
- if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
113948
- throw new Error("Instant values require a timezone offset");
113949
- }
113950
- const parsed = new Date(raw);
113951
- if (Number.isNaN(parsed.getTime())) {
113952
- throw new Error("Expected an ISO instant value");
113953
- }
113954
- return parsed.toISOString();
113955
- };
113956
- var normalizeYear = (value) => {
113957
- if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 9999) {
113958
- return pad(value, 4);
113959
- }
113960
- const raw = expectString(value, "year").trim();
113961
- if (/^\d{4}$/.test(raw)) {
113962
- return raw;
113963
- }
113964
- throw new Error("Expected a four-digit year");
113965
- };
113966
- var normalizeBytes = (value) => {
113967
- if (value instanceof Uint8Array) {
113968
- return new Uint8Array(value);
113969
- }
113970
- const BufferConstructor = globalThis.Buffer;
113971
- if (BufferConstructor !== undefined && value instanceof BufferConstructor) {
113972
- return new Uint8Array(value);
113973
- }
113974
- throw new Error("Expected a byte array value");
114989
+ return;
113975
114990
  };
113976
- var isJsonValue = (value) => {
114991
+ var toDriverValue = (value, context) => {
113977
114992
  if (value === null) {
113978
- return true;
114993
+ return null;
113979
114994
  }
113980
- switch (typeof value) {
113981
- case "string":
113982
- case "number":
113983
- case "boolean":
113984
- return true;
113985
- case "object":
113986
- if (Array.isArray(value)) {
113987
- return value.every(isJsonValue);
113988
- }
113989
- return isRecord2(value) && Object.values(value).every(isJsonValue);
113990
- default:
113991
- return false;
114995
+ if (value instanceof Date && Number.isNaN(value.getTime())) {
114996
+ throw new Error("Expected a valid Date value");
113992
114997
  }
113993
- };
113994
- var normalizeJson = (value) => {
113995
- if (typeof value === "string") {
113996
- const parsed = JSON.parse(value);
113997
- if (isJsonValue(parsed)) {
113998
- return parsed;
113999
- }
114000
- throw new Error("Parsed JSON value is not a valid JSON runtime");
114998
+ const dbType = context.dbType;
114999
+ const encoded = encodeWithSchema(context.runtimeSchema, value);
115000
+ let current = encoded.value;
115001
+ const custom3 = findMapping(context, "toDriver");
115002
+ if (custom3 !== undefined && dbType !== undefined) {
115003
+ return custom3(current, dbType);
114001
115004
  }
114002
- if (isJsonValue(value)) {
114003
- return value;
115005
+ if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
115006
+ return current;
114004
115007
  }
114005
- throw new Error("Expected a JSON value");
115008
+ return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
114006
115009
  };
114007
- var normalizeDbValue = (dbType, value) => {
115010
+ var fromDriverValue = (value, context) => {
114008
115011
  if (value === null) {
114009
115012
  return null;
114010
115013
  }
114011
- if ("base" in dbType) {
114012
- return normalizeDbValue(dbType.base, value);
114013
- }
114014
- if ("element" in dbType) {
114015
- if (!Array.isArray(value)) {
114016
- throw new Error("Expected an array value");
114017
- }
114018
- return value.map((entry) => normalizeDbValue(dbType.element, entry));
115014
+ const dbType = context.dbType;
115015
+ const custom3 = findMapping(context, "fromDriver");
115016
+ if (custom3 !== undefined && dbType !== undefined) {
115017
+ return custom3(value, dbType);
114019
115018
  }
114020
- if ("fields" in dbType) {
114021
- if (!isRecord2(value)) {
114022
- throw new Error("Expected a record value");
114023
- }
114024
- const normalized = {};
114025
- for (const [key2, fieldDbType] of Object.entries(dbType.fields)) {
114026
- if (key2 in value) {
114027
- normalized[key2] = normalizeDbValue(fieldDbType, value[key2]);
114028
- }
115019
+ if (typeof value === "string") {
115020
+ const normalizedJsonString = normalizeJsonDriverString(value, context);
115021
+ if (normalizedJsonString !== undefined) {
115022
+ return normalizedJsonString;
114029
115023
  }
114030
- return normalized;
114031
- }
114032
- if ("variant" in dbType && dbType.variant === "json") {
114033
- return normalizeJson(value);
114034
- }
114035
- if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
114036
- return expectString(value, "text");
114037
115024
  }
114038
- switch (runtimeTagOfBaseDbType(dbType)) {
114039
- case "string":
114040
- return expectString(value, "text");
114041
- case "number":
114042
- return normalizeNumber(value);
115025
+ return dbType === undefined ? value : normalizeDbValue(dbType, value);
115026
+ };
115027
+ var textCast = (sql) => `(${sql})::text`;
115028
+ var postgresJsonSql = (sql, dbType) => {
115029
+ const runtimeTag = runtimeTagOfDbType(dbType);
115030
+ switch (runtimeTag) {
114043
115031
  case "bigintString":
114044
- return normalizeBigIntString(value);
114045
- case "boolean":
114046
- return normalizeBoolean(value);
114047
- case "json":
114048
- return normalizeJson(value);
115032
+ case "decimalString":
114049
115033
  case "localDate":
114050
- return normalizeLocalDate(value);
114051
115034
  case "localTime":
114052
- return normalizeLocalTime(value);
114053
115035
  case "offsetTime":
114054
- return normalizeOffsetTime(value);
114055
115036
  case "localDateTime":
114056
- return normalizeLocalDateTime(value);
114057
115037
  case "instant":
114058
- return normalizeInstant(value);
114059
115038
  case "year":
114060
- return normalizeYear(value);
114061
- case "decimalString":
114062
- return normalizeDecimalString(value);
115039
+ return textCast(sql);
114063
115040
  case "bytes":
114064
- return normalizeBytes(value);
114065
- case "array":
114066
- if (!Array.isArray(value)) {
114067
- throw new Error("Expected an array value");
114068
- }
114069
- return value;
114070
- case "record":
114071
- if (!isRecord2(value)) {
114072
- throw new Error("Expected a record value");
114073
- }
114074
- return value;
114075
- case "null":
114076
- return null;
114077
- case "unknown":
114078
- case undefined:
114079
- return value;
115041
+ return `encode(${sql}, 'base64')`;
115042
+ default:
115043
+ return sql;
115044
+ }
115045
+ };
115046
+ var renderSelectSql = (sql, context) => {
115047
+ const dbType = context.dbType;
115048
+ const custom3 = findMapping(context, "selectSql");
115049
+ return custom3 !== undefined && dbType !== undefined ? custom3(sql, dbType) : sql;
115050
+ };
115051
+ var renderJsonSelectSql = (sql, context) => {
115052
+ const dbType = context.dbType;
115053
+ const custom3 = findMapping(context, "jsonSelectSql");
115054
+ if (custom3 !== undefined && dbType !== undefined) {
115055
+ return custom3(sql, dbType);
114080
115056
  }
115057
+ return context.dialect === "postgres" && dbType !== undefined ? postgresJsonSql(sql, dbType) : sql;
114081
115058
  };
114082
115059
 
114083
115060
  // src/internal/runtime/schema.ts
114084
- import * as Schema7 from "effect/Schema";
115061
+ import * as Schema8 from "effect/Schema";
114085
115062
  import * as SchemaAST from "effect/SchemaAST";
114086
115063
  var schemaCache = new WeakMap;
115064
+ var FiniteNumberSchema = Schema8.Number.pipe(Schema8.finite());
114087
115065
  var runtimeSchemaForTag = (tag) => {
114088
115066
  switch (tag) {
114089
115067
  case "string":
114090
- return Schema7.String;
115068
+ return Schema8.String;
114091
115069
  case "number":
114092
- return Schema7.Number;
115070
+ return FiniteNumberSchema;
114093
115071
  case "bigintString":
114094
115072
  return BigIntStringSchema;
114095
115073
  case "boolean":
114096
- return Schema7.Boolean;
115074
+ return Schema8.Boolean;
114097
115075
  case "json":
114098
115076
  return JsonValueSchema;
114099
115077
  case "localDate":
@@ -114111,16 +115089,16 @@ var runtimeSchemaForTag = (tag) => {
114111
115089
  case "decimalString":
114112
115090
  return DecimalStringSchema;
114113
115091
  case "bytes":
114114
- return Schema7.Uint8ArrayFromSelf;
115092
+ return Schema8.Uint8ArrayFromSelf;
114115
115093
  case "array":
114116
- return Schema7.Array(Schema7.Unknown);
115094
+ return Schema8.Array(Schema8.Unknown);
114117
115095
  case "record":
114118
- return Schema7.Record({
114119
- key: Schema7.String,
114120
- value: Schema7.Unknown
115096
+ return Schema8.Record({
115097
+ key: Schema8.String,
115098
+ value: Schema8.Unknown
114121
115099
  });
114122
115100
  case "null":
114123
- return Schema7.Null;
115101
+ return Schema8.Null;
114124
115102
  case "unknown":
114125
115103
  return;
114126
115104
  }
@@ -114133,22 +115111,22 @@ var runtimeSchemaForDbType = (dbType) => {
114133
115111
  return runtimeSchemaForDbType(dbType.base);
114134
115112
  }
114135
115113
  if ("element" in dbType) {
114136
- return Schema7.Array(runtimeSchemaForDbType(dbType.element) ?? Schema7.Unknown);
115114
+ return Schema8.Array(runtimeSchemaForDbType(dbType.element) ?? Schema8.Unknown);
114137
115115
  }
114138
115116
  if ("fields" in dbType) {
114139
- const fields2 = Object.fromEntries(Object.entries(dbType.fields).map(([key2, field]) => [key2, runtimeSchemaForDbType(field) ?? Schema7.Unknown]));
114140
- return Schema7.Struct(fields2);
115117
+ const fields2 = Object.fromEntries(Object.entries(dbType.fields).map(([key2, field]) => [key2, runtimeSchemaForDbType(field) ?? Schema8.Unknown]));
115118
+ return Schema8.Struct(fields2);
114141
115119
  }
114142
115120
  if ("variant" in dbType && dbType.variant === "json") {
114143
115121
  return JsonValueSchema;
114144
115122
  }
114145
115123
  if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
114146
- return Schema7.String;
115124
+ return Schema8.String;
114147
115125
  }
114148
115126
  const runtimeTag = runtimeTagOfBaseDbType2(dbType);
114149
115127
  return runtimeTag === undefined ? undefined : runtimeSchemaForTag(runtimeTag);
114150
115128
  };
114151
- var makeSchemaFromAst = (ast) => Schema7.make(ast);
115129
+ var makeSchemaFromAst = (ast) => Schema8.make(ast);
114152
115130
  var unionAst = (asts) => {
114153
115131
  if (asts.length === 0) {
114154
115132
  return;
@@ -114246,7 +115224,7 @@ var unionSchemas = (schemas) => {
114246
115224
  if (resolved.length === 1) {
114247
115225
  return resolved[0];
114248
115226
  }
114249
- return Schema7.Union(...resolved);
115227
+ return Schema8.Union(...resolved);
114250
115228
  };
114251
115229
  var firstSelectedExpression = (plan) => {
114252
115230
  const selection = getAst(plan).select;
@@ -114281,9 +115259,9 @@ var jsonCompatibleSchema = (schema4) => {
114281
115259
  };
114282
115260
  var buildStructSchema = (entries, context) => {
114283
115261
  const fields2 = Object.fromEntries(entries.map((entry) => [entry.key, expressionRuntimeSchema(entry.value, context) ?? JsonValueSchema]));
114284
- return Schema7.Struct(fields2);
115262
+ return Schema8.Struct(fields2);
114285
115263
  };
114286
- var buildTupleSchema = (values2, context) => Schema7.Tuple(...values2.map((value) => expressionRuntimeSchema(value, context) ?? JsonValueSchema));
115264
+ var buildTupleSchema = (values2, context) => Schema8.Tuple(...values2.map((value) => expressionRuntimeSchema(value, context) ?? JsonValueSchema));
114287
115265
  var deriveCaseSchema = (ast, context) => {
114288
115266
  if (context === undefined) {
114289
115267
  return unionSchemas([
@@ -114323,10 +115301,10 @@ var deriveRuntimeSchema = (expression, context) => {
114323
115301
  return state.runtimeSchema;
114324
115302
  case "literal":
114325
115303
  if (ast.value === null) {
114326
- return Schema7.Null;
115304
+ return Schema8.Null;
114327
115305
  }
114328
115306
  if (typeof ast.value === "string" || typeof ast.value === "number" || typeof ast.value === "boolean") {
114329
- return Schema7.Literal(ast.value);
115307
+ return Schema8.Literal(ast.value);
114330
115308
  }
114331
115309
  return runtimeSchemaForDbType(state.dbType);
114332
115310
  case "cast":
@@ -114362,7 +115340,7 @@ var deriveRuntimeSchema = (expression, context) => {
114362
115340
  case "jsonHasAllKeys":
114363
115341
  case "jsonPathExists":
114364
115342
  case "jsonPathMatch":
114365
- return Schema7.Boolean;
115343
+ return Schema8.Boolean;
114366
115344
  case "upper":
114367
115345
  case "lower":
114368
115346
  case "concat":
@@ -114371,10 +115349,10 @@ var deriveRuntimeSchema = (expression, context) => {
114371
115349
  case "jsonAccessText":
114372
115350
  case "jsonTraverseText":
114373
115351
  case "jsonTypeOf":
114374
- return Schema7.String;
115352
+ return Schema8.String;
114375
115353
  case "count":
114376
115354
  case "jsonLength":
114377
- return Schema7.Number;
115355
+ return FiniteNumberSchema;
114378
115356
  case "max":
114379
115357
  case "min":
114380
115358
  return expressionRuntimeSchema(ast.value, context);
@@ -114387,7 +115365,7 @@ var deriveRuntimeSchema = (expression, context) => {
114387
115365
  return selection === undefined ? undefined : expressionRuntimeSchema(selection, context);
114388
115366
  }
114389
115367
  case "window":
114390
- return ast.function === "over" && ast.value !== undefined ? expressionRuntimeSchema(ast.value, context) : Schema7.Number;
115368
+ return ast.function === "over" && ast.value !== undefined ? expressionRuntimeSchema(ast.value, context) : FiniteNumberSchema;
114391
115369
  case "jsonGet":
114392
115370
  case "jsonPath":
114393
115371
  case "jsonAccess":
@@ -114419,7 +115397,7 @@ var deriveRuntimeSchema = (expression, context) => {
114419
115397
  case "jsonToJsonb":
114420
115398
  return jsonCompatibleSchema(expressionRuntimeSchema(ast.value, context));
114421
115399
  case "jsonKeys":
114422
- return Schema7.Array(Schema7.String);
115400
+ return Schema8.Array(Schema8.String);
114423
115401
  }
114424
115402
  };
114425
115403
  var expressionRuntimeSchema = (expression, context) => {
@@ -114509,7 +115487,7 @@ var effectiveRuntimeNullability = (expression, scope) => {
114509
115487
  return "always";
114510
115488
  }
114511
115489
  if (ast.kind === "column") {
114512
- const key2 = `${ast.tableName}.${ast.columnName}`;
115490
+ const key2 = columnPredicateKey(ast.tableName, ast.columnName);
114513
115491
  if (scope.absentSourceNames.has(ast.tableName) || scope.nullKeys.has(key2)) {
114514
115492
  return "always";
114515
115493
  }
@@ -114522,18 +115500,35 @@ var effectiveRuntimeNullability = (expression, scope) => {
114522
115500
  }
114523
115501
  return hasOptionalSourceDependency(expression, scope) ? "maybe" : nullability;
114524
115502
  };
114525
- var decodeProjectionValue = (rendered, projection, expression, raw, scope, driverMode) => {
115503
+ var dbTypeAllowsTopLevelJsonNull = (dbType) => {
115504
+ if ("base" in dbType) {
115505
+ return dbTypeAllowsTopLevelJsonNull(dbType.base);
115506
+ }
115507
+ return "variant" in dbType && dbType.variant === "json" || dbType.runtime === "json";
115508
+ };
115509
+ var schemaAcceptsNull = (schema4) => schema4 !== undefined && Schema9.is(schema4)(null);
115510
+ var decodeProjectionValue = (rendered, projection, expression, raw, scope, driverMode, valueMappings) => {
114526
115511
  let normalized = raw;
114527
115512
  if (driverMode === "raw") {
114528
115513
  try {
114529
- normalized = normalizeDbValue(expression[TypeId].dbType, raw);
115514
+ normalized = fromDriverValue(raw, {
115515
+ dialect: rendered.dialect,
115516
+ dbType: expression[TypeId].dbType,
115517
+ runtimeSchema: expression[TypeId].runtimeSchema,
115518
+ driverValueMapping: expression[TypeId].driverValueMapping,
115519
+ valueMappings
115520
+ });
114530
115521
  } catch (cause) {
114531
115522
  throw makeRowDecodeError(rendered, projection, expression, raw, "normalize", cause);
114532
115523
  }
114533
115524
  }
114534
115525
  const nullability = effectiveRuntimeNullability(expression, scope);
115526
+ const schema4 = expressionRuntimeSchema(expression, { assumptions: scope.assumptions });
114535
115527
  if (normalized === null) {
114536
115528
  if (nullability === "never") {
115529
+ if (dbTypeAllowsTopLevelJsonNull(expression[TypeId].dbType) && schemaAcceptsNull(schema4)) {
115530
+ return null;
115531
+ }
114537
115532
  throw makeRowDecodeError(rendered, projection, expression, raw, "schema", new Error("Received null for a non-null projection"), normalized);
114538
115533
  }
114539
115534
  return null;
@@ -114541,35 +115536,38 @@ var decodeProjectionValue = (rendered, projection, expression, raw, scope, drive
114541
115536
  if (nullability === "always") {
114542
115537
  throw makeRowDecodeError(rendered, projection, expression, raw, "schema", new Error("Received non-null for an always-null projection"), normalized);
114543
115538
  }
114544
- const schema4 = expressionRuntimeSchema(expression, { assumptions: scope.assumptions });
115539
+ if (dbTypeAllowsTopLevelJsonNull(expression[TypeId].dbType) && !isJsonValue(normalized)) {
115540
+ throw makeRowDecodeError(rendered, projection, expression, raw, "schema", new Error("Expected a JSON value"), normalized);
115541
+ }
114545
115542
  if (schema4 === undefined) {
114546
115543
  return normalized;
114547
115544
  }
114548
- if (Schema8.is(schema4)(normalized)) {
115545
+ if (Schema9.is(schema4)(normalized)) {
114549
115546
  return normalized;
114550
115547
  }
114551
115548
  try {
114552
- return Schema8.decodeUnknownSync(schema4)(normalized);
115549
+ return Schema9.decodeUnknownSync(schema4)(normalized);
114553
115550
  } catch (cause) {
114554
115551
  throw makeRowDecodeError(rendered, projection, expression, raw, "schema", cause, normalized);
114555
115552
  }
114556
115553
  };
114557
115554
  var makeRowDecoder = (rendered, plan, options2 = {}) => {
114558
115555
  const projections = flattenSelection(getAst(plan).select);
114559
- const byAlias = new Map(projections.map((projection) => [projection.alias, projection.expression]));
115556
+ const byPath = new Map(projections.map((projection) => [JSON.stringify(projection.path), projection.expression]));
114560
115557
  const driverMode = options2.driverMode ?? "raw";
115558
+ const valueMappings = options2.valueMappings ?? rendered.valueMappings;
114561
115559
  const scope = resolveImplicationScope(plan[TypeId3].available, getQueryState(plan).assumptions);
114562
115560
  return (row) => {
114563
115561
  const decoded = {};
114564
115562
  for (const projection of rendered.projections) {
114565
- if (!(projection.alias in row)) {
114566
- continue;
114567
- }
114568
- const expression = byAlias.get(projection.alias);
115563
+ const expression = byPath.get(JSON.stringify(projection.path));
114569
115564
  if (expression === undefined) {
114570
- continue;
115565
+ throw new Error(`Rendered projection path '${projection.path.join(".")}' does not exist in the query selection`);
114571
115566
  }
114572
- setPath2(decoded, projection.path, decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode));
115567
+ if (!(projection.alias in row)) {
115568
+ throw makeRowDecodeError(rendered, projection, expression, undefined, "schema", new Error(`Missing required projection alias '${projection.alias}'`));
115569
+ }
115570
+ setPath2(decoded, projection.path, decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode, valueMappings));
114573
115571
  }
114574
115572
  return decoded;
114575
115573
  };
@@ -114614,6 +115612,23 @@ var withSavepoint = (effect) => Effect.flatMap(SqlClient.SqlClient, (sql) => sql
114614
115612
 
114615
115613
  // src/internal/renderer.ts
114616
115614
  var TypeId8 = Symbol.for("effect-qb/Renderer");
115615
+ var projectionPathKey = (path2) => JSON.stringify(path2);
115616
+ var formatProjectionPath2 = (path2) => path2.join(".");
115617
+ var validateProjectionPathsMatchSelection = (plan, projections) => {
115618
+ const expected = flattenSelection(getAst(plan).select);
115619
+ const expectedPaths = new Set(expected.map((projection) => projectionPathKey(projection.path)));
115620
+ const actualPaths = new Set(projections.map((projection) => projectionPathKey(projection.path)));
115621
+ for (const projection of projections) {
115622
+ if (!expectedPaths.has(projectionPathKey(projection.path))) {
115623
+ throw new Error(`Projection path ${formatProjectionPath2(projection.path)} does not exist in the query selection`);
115624
+ }
115625
+ }
115626
+ for (const projection of expected) {
115627
+ if (!actualPaths.has(projectionPathKey(projection.path))) {
115628
+ throw new Error(`Projection path ${formatProjectionPath2(projection.path)} is missing from rendered projections`);
115629
+ }
115630
+ }
115631
+ };
114617
115632
  function make5(dialect, render) {
114618
115633
  if (typeof render !== "function") {
114619
115634
  throw new Error(`Renderer.make requires an explicit render implementation for dialect: ${dialect}`);
@@ -114621,13 +115636,23 @@ function make5(dialect, render) {
114621
115636
  return {
114622
115637
  dialect,
114623
115638
  render(plan) {
115639
+ const required = currentRequiredList(plan[TypeId3].required);
115640
+ if (required.length > 0) {
115641
+ throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
115642
+ }
115643
+ const planDialect = plan[TypeId3].dialect;
115644
+ if (planDialect !== dialect) {
115645
+ throw new Error("effect-qb: plan dialect is not compatible with the target renderer or executor");
115646
+ }
114624
115647
  const rendered = render(plan);
114625
115648
  const projections = rendered.projections ?? [];
114626
115649
  validateProjections(projections);
115650
+ validateProjectionPathsMatchSelection(plan, projections);
114627
115651
  return {
114628
115652
  sql: rendered.sql,
114629
115653
  params: rendered.params ?? [],
114630
115654
  projections,
115655
+ valueMappings: rendered.valueMappings,
114631
115656
  dialect,
114632
115657
  [TypeId8]: {
114633
115658
  row: undefined,
@@ -114640,14 +115665,19 @@ function make5(dialect, render) {
114640
115665
 
114641
115666
  // src/mysql/internal/dialect.ts
114642
115667
  var quoteIdentifier = (value) => `\`${value.replaceAll("`", "``")}\``;
114643
- var renderLiteral = (value, state) => {
114644
- if (value === null) {
115668
+ var renderLiteral = (value, state, context = {}) => {
115669
+ const driverValue = toDriverValue(value, {
115670
+ dialect: "mysql",
115671
+ valueMappings: state.valueMappings,
115672
+ ...context
115673
+ });
115674
+ if (driverValue === null) {
114645
115675
  return "null";
114646
115676
  }
114647
- if (typeof value === "boolean") {
114648
- return value ? "true" : "false";
115677
+ if (typeof driverValue === "boolean") {
115678
+ return driverValue ? "true" : "false";
114649
115679
  }
114650
- state.params.push(value);
115680
+ state.params.push(driverValue);
114651
115681
  return "?";
114652
115682
  };
114653
115683
  var mysqlDialect = {
@@ -114663,16 +115693,19 @@ var mysqlDialect = {
114663
115693
  }
114664
115694
  };
114665
115695
 
115696
+ // src/mysql/internal/sql-expression-renderer.ts
115697
+ import * as Schema10 from "effect/Schema";
115698
+
114666
115699
  // src/internal/aggregation-validation.ts
114667
- var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId in value);
115700
+ var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId in value);
114668
115701
  var selectionHasAggregate = (selection) => {
114669
- if (isExpression2(selection)) {
115702
+ if (isExpression3(selection)) {
114670
115703
  return selection[TypeId].kind === "aggregate";
114671
115704
  }
114672
115705
  return Object.values(selection).some((value) => selectionHasAggregate(value));
114673
115706
  };
114674
115707
  var isGroupedSelectionValid = (selection, groupedExpressions) => {
114675
- if (isExpression2(selection)) {
115708
+ if (isExpression3(selection)) {
114676
115709
  const aggregation = selection[TypeId].kind;
114677
115710
  if (aggregation === "aggregate") {
114678
115711
  return true;
@@ -114777,7 +115810,46 @@ var renderCastType = (dialect, dbType) => {
114777
115810
  return dbType.kind;
114778
115811
  }
114779
115812
  };
114780
- var renderDdlExpression = (expression, state, dialect) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, state, dialect);
115813
+ var renderMysqlDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
115814
+ var renderMysqlDdlBytes = (value) => `x'${Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("")}'`;
115815
+ var renderMysqlDdlLiteral = (value, state, context = {}) => {
115816
+ const driverValue = toDriverValue(value, {
115817
+ dialect: "mysql",
115818
+ valueMappings: state.valueMappings,
115819
+ ...context
115820
+ });
115821
+ if (driverValue === null) {
115822
+ return "null";
115823
+ }
115824
+ switch (typeof driverValue) {
115825
+ case "boolean":
115826
+ return driverValue ? "true" : "false";
115827
+ case "number":
115828
+ if (!Number.isFinite(driverValue)) {
115829
+ throw new Error("Expected a finite numeric value");
115830
+ }
115831
+ return String(driverValue);
115832
+ case "bigint":
115833
+ return driverValue.toString();
115834
+ case "string":
115835
+ return renderMysqlDdlString(driverValue);
115836
+ case "object":
115837
+ if (driverValue instanceof Uint8Array) {
115838
+ return renderMysqlDdlBytes(driverValue);
115839
+ }
115840
+ break;
115841
+ }
115842
+ throw new Error("Unsupported mysql DDL literal value");
115843
+ };
115844
+ var renderDdlExpression = (expression, state, dialect) => {
115845
+ if (isSchemaExpression(expression)) {
115846
+ return render(expression);
115847
+ }
115848
+ return renderExpression(expression, state, {
115849
+ ...dialect,
115850
+ renderLiteral: renderMysqlDdlLiteral
115851
+ });
115852
+ };
114781
115853
  var renderMysqlMutationLimit = (expression, state, dialect) => {
114782
115854
  const ast = expression[TypeId2];
114783
115855
  if (ast.kind === "literal" && typeof ast.value === "number" && Number.isInteger(ast.value) && ast.value >= 0) {
@@ -114812,30 +115884,52 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
114812
115884
  definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}primary key (${option2.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
114813
115885
  break;
114814
115886
  case "unique":
115887
+ if (option2.nullsNotDistinct || option2.deferrable || option2.initiallyDeferred) {
115888
+ throw new Error("Unsupported mysql unique constraint options");
115889
+ }
114815
115890
  definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}unique${option2.nullsNotDistinct ? " nulls not distinct" : ""} (${option2.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
114816
115891
  break;
114817
115892
  case "foreignKey": {
114818
115893
  const reference = option2.references();
114819
- definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})${option2.onDelete ? ` on delete ${option2.onDelete.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option2.onUpdate ? ` on update ${option2.onUpdate.replace(/[A-Z]/g, (value) => ` ${value.toLowerCase()}`).trim()}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
115894
+ definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
114820
115895
  break;
114821
115896
  }
114822
115897
  case "check":
114823
- definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, state, dialect)})${option2.noInherit ? " no inherit" : ""}`);
115898
+ definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
114824
115899
  break;
114825
115900
  case "index":
114826
115901
  break;
115902
+ default:
115903
+ throw new Error("Unsupported table option kind");
114827
115904
  }
114828
115905
  }
114829
115906
  return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
114830
115907
  };
114831
115908
  var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
115909
+ if (ddl.ifNotExists) {
115910
+ throw new Error("Unsupported mysql create index options");
115911
+ }
114832
115912
  const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
114833
115913
  return `create${ddl.unique ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})`;
114834
115914
  };
114835
- var renderDropIndexSql = (targetSource, ddl, state, dialect) => dialect.name === "postgres" ? `drop index${ddl.ifExists ? " if exists" : ""} ${dialect.quoteIdentifier(ddl.name)}` : `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
114836
- var isExpression3 = (value) => value !== null && typeof value === "object" && (TypeId in value);
114837
- var isJsonDbType = (dbType) => dbType.kind === "jsonb" || dbType.kind === "json" || ("variant" in dbType) && dbType.variant === "json";
114838
- var isJsonExpression = (value) => isExpression3(value) && isJsonDbType(value[TypeId].dbType);
115915
+ var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
115916
+ if (ddl.ifExists) {
115917
+ throw new Error("Unsupported mysql drop index options");
115918
+ }
115919
+ return dialect.name === "postgres" ? `drop index${ddl.ifExists ? " if exists" : ""} ${dialect.quoteIdentifier(ddl.name)}` : `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
115920
+ };
115921
+ var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId in value);
115922
+ var isJsonDbType2 = (dbType) => {
115923
+ if (dbType.kind === "jsonb" || dbType.kind === "json") {
115924
+ return true;
115925
+ }
115926
+ if (!("variant" in dbType)) {
115927
+ return false;
115928
+ }
115929
+ const variant = dbType.variant;
115930
+ return variant === "json" || variant === "jsonb";
115931
+ };
115932
+ var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId].dbType);
114839
115933
  var unsupportedJsonFeature = (dialect, feature) => {
114840
115934
  const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
114841
115935
  Object.assign(error, {
@@ -114878,15 +115972,16 @@ var extractJsonPathSegments = (node) => {
114878
115972
  };
114879
115973
  var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
114880
115974
  var renderJsonPathSegment = (segment) => {
115975
+ const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
114881
115976
  if (typeof segment === "string") {
114882
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment) ? `.${segment}` : `."${segment.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
115977
+ return renderKey(segment);
114883
115978
  }
114884
115979
  if (typeof segment === "number") {
114885
115980
  return `[${segment}]`;
114886
115981
  }
114887
115982
  switch (segment.kind) {
114888
115983
  case "key":
114889
- return /^[A-Za-z_][A-Za-z0-9_]*$/.test(segment.key) ? `.${segment.key}` : `."${segment.key.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
115984
+ return renderKey(segment.key);
114890
115985
  case "index":
114891
115986
  return `[${segment.index}]`;
114892
115987
  case "wildcard":
@@ -114899,14 +115994,45 @@ var renderJsonPathSegment = (segment) => {
114899
115994
  throw new Error("Unsupported JSON path segment");
114900
115995
  }
114901
115996
  };
114902
- var renderJsonPathStringLiteral = (segments) => {
115997
+ var renderMySqlJsonIndex = (index4) => index4 >= 0 ? String(index4) : index4 === -1 ? "last" : `last-${Math.abs(index4) - 1}`;
115998
+ var renderMySqlJsonPathSegment = (segment) => {
115999
+ if (typeof segment === "number") {
116000
+ return `[${renderMySqlJsonIndex(segment)}]`;
116001
+ }
116002
+ if (typeof segment === "object" && segment !== null && segment.kind === "index") {
116003
+ return `[${renderMySqlJsonIndex(segment.index)}]`;
116004
+ }
116005
+ if (typeof segment === "object" && segment !== null && segment.kind === "slice") {
116006
+ return `[${renderMySqlJsonIndex(segment.start ?? 0)} to ${segment.end === undefined ? "last" : renderMySqlJsonIndex(segment.end)}]`;
116007
+ }
116008
+ if (typeof segment === "object" && segment !== null && segment.kind === "descend") {
116009
+ return "**";
116010
+ }
116011
+ return renderJsonPathSegment(segment);
116012
+ };
116013
+ var renderJsonPathStringLiteral = (segments, renderSegment = renderJsonPathSegment) => {
114903
116014
  let path2 = "$";
114904
116015
  for (const segment of segments) {
114905
- path2 += renderJsonPathSegment(segment);
116016
+ path2 += renderSegment(segment);
114906
116017
  }
114907
116018
  return path2;
114908
116019
  };
114909
- var renderMySqlJsonPath = (segments, state, dialect) => dialect.renderLiteral(renderJsonPathStringLiteral(segments), state);
116020
+ var renderMySqlJsonPath = (segments, state, dialect) => dialect.renderLiteral(renderJsonPathStringLiteral(segments, renderMySqlJsonPathSegment), state);
116021
+ var isJsonArrayIndexSegment = (segment) => typeof segment === "number" || typeof segment === "object" && segment !== null && segment.kind === "index";
116022
+ var renderMySqlJsonInsertPath = (segments, insertAfter, state, dialect) => {
116023
+ if (!insertAfter || segments.length === 0) {
116024
+ return renderMySqlJsonPath(segments, state, dialect);
116025
+ }
116026
+ const last = segments[segments.length - 1];
116027
+ const nextSegments = segments.slice(0, -1);
116028
+ if (typeof last === "number") {
116029
+ return renderMySqlJsonPath([...nextSegments, last + 1], state, dialect);
116030
+ }
116031
+ if (typeof last === "object" && last !== null && last.kind === "index") {
116032
+ return renderMySqlJsonPath([...nextSegments, { ...last, index: last.index + 1 }], state, dialect);
116033
+ }
116034
+ return renderMySqlJsonPath(segments, state, dialect);
116035
+ };
114910
116036
  var renderPostgresJsonPathArray = (segments, state, dialect) => `array[${segments.map((segment) => {
114911
116037
  if (typeof segment === "string") {
114912
116038
  return dialect.renderLiteral(segment, state);
@@ -114935,21 +116061,61 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
114935
116061
  }
114936
116062
  };
114937
116063
  var renderPostgresJsonValue = (value, state, dialect) => {
114938
- if (!isExpression3(value)) {
116064
+ if (!isExpression4(value)) {
114939
116065
  throw new Error("Expected a JSON expression");
114940
116066
  }
114941
116067
  const rendered = renderExpression(value, state, dialect);
114942
116068
  return value[TypeId].dbType.kind === "jsonb" ? rendered : `cast(${rendered} as jsonb)`;
114943
116069
  };
116070
+ var expressionDriverContext = (expression, state, dialect) => ({
116071
+ dialect: dialect.name,
116072
+ valueMappings: state.valueMappings,
116073
+ dbType: expression[TypeId].dbType,
116074
+ runtimeSchema: expression[TypeId].runtimeSchema,
116075
+ driverValueMapping: expression[TypeId].driverValueMapping
116076
+ });
116077
+ var renderMySqlStructuredJsonLiteral = (expression, state) => {
116078
+ const ast = expression[TypeId2];
116079
+ if (ast.kind !== "literal" || ast.value === null || typeof ast.value !== "object") {
116080
+ return;
116081
+ }
116082
+ state.params.push(JSON.stringify(ast.value));
116083
+ return "cast(? as json)";
116084
+ };
116085
+ var renderJsonInputExpression = (expression, state, dialect) => {
116086
+ if (dialect.name === "mysql") {
116087
+ const jsonLiteral = renderMySqlStructuredJsonLiteral(expression, state);
116088
+ if (jsonLiteral !== undefined) {
116089
+ return jsonLiteral;
116090
+ }
116091
+ }
116092
+ return renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
116093
+ };
116094
+ var encodeArrayValues = (values2, column2, state, dialect) => values2.map((value) => {
116095
+ if (value === null && column2.metadata.nullable) {
116096
+ return null;
116097
+ }
116098
+ const runtimeSchemaAccepts = column2.schema !== undefined && Schema10.is(column2.schema)(value);
116099
+ const normalizedValue = runtimeSchemaAccepts ? value : normalizeDbValue(column2.metadata.dbType, value);
116100
+ const encodedValue = column2.schema === undefined || runtimeSchemaAccepts ? normalizedValue : Schema10.decodeUnknownSync(column2.schema)(normalizedValue);
116101
+ return toDriverValue(encodedValue, {
116102
+ dialect: dialect.name,
116103
+ valueMappings: state.valueMappings,
116104
+ dbType: column2.metadata.dbType,
116105
+ runtimeSchema: column2.schema,
116106
+ driverValueMapping: column2.metadata.driverValueMapping
116107
+ });
116108
+ });
114944
116109
  var renderPostgresJsonKind = (value) => value[TypeId].dbType.kind === "jsonb" ? "jsonb" : "json";
114945
116110
  var renderJsonOpaquePath = (value, state, dialect) => {
114946
116111
  if (isJsonPathValue2(value)) {
114947
- return dialect.renderLiteral(renderJsonPathStringLiteral(value.segments), state);
116112
+ const renderSegment = dialect.name === "mysql" ? renderMySqlJsonPathSegment : renderJsonPathSegment;
116113
+ return dialect.renderLiteral(renderJsonPathStringLiteral(value.segments, renderSegment), state);
114948
116114
  }
114949
116115
  if (typeof value === "string") {
114950
116116
  return dialect.renderLiteral(value, state);
114951
116117
  }
114952
- if (isExpression3(value)) {
116118
+ if (isExpression4(value)) {
114953
116119
  return renderExpression(value, state, dialect);
114954
116120
  }
114955
116121
  throw new Error("Unsupported SQL/JSON path input");
@@ -114967,7 +116133,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
114967
116133
  if (source === undefined) {
114968
116134
  throw new Error("Unsupported SQL extract expression");
114969
116135
  }
114970
- const fieldRuntime = isExpression3(field) && field[TypeId].dbType.kind === "text" && typeof field[TypeId].runtime === "string" ? field[TypeId].runtime : undefined;
116136
+ const fieldRuntime = isExpression4(field) && field[TypeId].dbType.kind === "text" && typeof field[TypeId].runtime === "string" ? field[TypeId].runtime : undefined;
114971
116137
  const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
114972
116138
  return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
114973
116139
  }
@@ -115005,7 +116171,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115005
116171
  case "jsonPathText":
115006
116172
  case "jsonAccessText":
115007
116173
  case "jsonTraverseText": {
115008
- if (!isExpression3(base) || segments.length === 0) {
116174
+ if (!isExpression4(base) || segments.length === 0) {
115009
116175
  return;
115010
116176
  }
115011
116177
  const baseSql = renderExpression(base, state, dialect);
@@ -115028,7 +116194,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115028
116194
  case "jsonKeyExists":
115029
116195
  case "jsonHasAnyKeys":
115030
116196
  case "jsonHasAllKeys": {
115031
- if (!isExpression3(base)) {
116197
+ if (!isExpression4(base)) {
115032
116198
  return;
115033
116199
  }
115034
116200
  const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
@@ -115047,21 +116213,22 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115047
116213
  }
115048
116214
  if (dialect.name === "mysql") {
115049
116215
  const mode = kind === "jsonHasAllKeys" ? "all" : "one";
116216
+ const modeSql = dialect.renderLiteral(mode, state);
115050
116217
  const paths = keys.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ");
115051
- return `json_contains_path(${baseSql}, ${dialect.renderLiteral(mode, state)}, ${paths})`;
116218
+ return `json_contains_path(${baseSql}, ${modeSql}, ${paths})`;
115052
116219
  }
115053
116220
  return;
115054
116221
  }
115055
116222
  case "jsonConcat":
115056
116223
  case "jsonMerge": {
115057
- if (!isExpression3(ast.left) || !isExpression3(ast.right)) {
116224
+ if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
115058
116225
  return;
115059
116226
  }
115060
116227
  if (dialect.name === "postgres") {
115061
116228
  return `(${renderPostgresJsonValue(ast.left, state, dialect)} || ${renderPostgresJsonValue(ast.right, state, dialect)})`;
115062
116229
  }
115063
116230
  if (dialect.name === "mysql") {
115064
- return `json_merge_preserve(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
116231
+ return `json_merge_preserve(${renderJsonInputExpression(ast.left, state, dialect)}, ${renderJsonInputExpression(ast.right, state, dialect)})`;
115065
116232
  }
115066
116233
  return;
115067
116234
  }
@@ -115069,7 +116236,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115069
116236
  const entries = Array.isArray(ast.entries) ? ast.entries : [];
115070
116237
  const renderedEntries = entries.flatMap((entry) => [
115071
116238
  dialect.renderLiteral(entry.key, state),
115072
- renderExpression(entry.value, state, dialect)
116239
+ renderJsonInputExpression(entry.value, state, dialect)
115073
116240
  ]);
115074
116241
  if (dialect.name === "postgres") {
115075
116242
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`;
@@ -115081,7 +116248,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115081
116248
  }
115082
116249
  case "jsonBuildArray": {
115083
116250
  const values2 = Array.isArray(ast.values) ? ast.values : [];
115084
- const renderedValues = values2.map((value) => renderExpression(value, state, dialect)).join(", ");
116251
+ const renderedValues = values2.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ");
115085
116252
  if (dialect.name === "postgres") {
115086
116253
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`;
115087
116254
  }
@@ -115091,29 +116258,29 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115091
116258
  return;
115092
116259
  }
115093
116260
  case "jsonToJson":
115094
- if (!isExpression3(base)) {
116261
+ if (!isExpression4(base)) {
115095
116262
  return;
115096
116263
  }
115097
116264
  if (dialect.name === "postgres") {
115098
- return `to_json(${renderExpression(base, state, dialect)})`;
116265
+ return `to_json(${renderJsonInputExpression(base, state, dialect)})`;
115099
116266
  }
115100
116267
  if (dialect.name === "mysql") {
115101
- return `cast(${renderExpression(base, state, dialect)} as json)`;
116268
+ return renderMySqlStructuredJsonLiteral(base, state) ?? `cast(${renderExpression(base, state, dialect)} as json)`;
115102
116269
  }
115103
116270
  return;
115104
116271
  case "jsonToJsonb":
115105
- if (!isExpression3(base)) {
116272
+ if (!isExpression4(base)) {
115106
116273
  return;
115107
116274
  }
115108
116275
  if (dialect.name === "postgres") {
115109
- return `to_jsonb(${renderExpression(base, state, dialect)})`;
116276
+ return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`;
115110
116277
  }
115111
116278
  if (dialect.name === "mysql") {
115112
- return `cast(${renderExpression(base, state, dialect)} as json)`;
116279
+ return renderMySqlStructuredJsonLiteral(base, state) ?? `cast(${renderExpression(base, state, dialect)} as json)`;
115113
116280
  }
115114
116281
  return;
115115
116282
  case "jsonTypeOf":
115116
- if (!isExpression3(base)) {
116283
+ if (!isExpression4(base)) {
115117
116284
  return;
115118
116285
  }
115119
116286
  if (dialect.name === "postgres") {
@@ -115125,7 +116292,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115125
116292
  }
115126
116293
  return;
115127
116294
  case "jsonLength":
115128
- if (!isExpression3(base)) {
116295
+ if (!isExpression4(base)) {
115129
116296
  return;
115130
116297
  }
115131
116298
  if (dialect.name === "postgres") {
@@ -115140,7 +116307,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115140
116307
  }
115141
116308
  return;
115142
116309
  case "jsonKeys":
115143
- if (!isExpression3(base)) {
116310
+ if (!isExpression4(base)) {
115144
116311
  return;
115145
116312
  }
115146
116313
  if (dialect.name === "postgres") {
@@ -115154,7 +116321,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115154
116321
  }
115155
116322
  return;
115156
116323
  case "jsonStripNulls":
115157
- if (!isExpression3(base)) {
116324
+ if (!isExpression4(base)) {
115158
116325
  return;
115159
116326
  }
115160
116327
  if (dialect.name === "postgres") {
@@ -115165,7 +116332,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115165
116332
  case "jsonDelete":
115166
116333
  case "jsonDeletePath":
115167
116334
  case "jsonRemove": {
115168
- if (!isExpression3(base) || segments.length === 0) {
116335
+ if (!isExpression4(base) || segments.length === 0) {
115169
116336
  return;
115170
116337
  }
115171
116338
  if (dialect.name === "postgres") {
@@ -115177,17 +116344,17 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115177
116344
  return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
115178
116345
  }
115179
116346
  if (dialect.name === "mysql") {
115180
- return `json_remove(${renderExpression(base, state, dialect)}, ${segments.map((segment) => renderMySqlJsonPath([segment], state, dialect)).join(", ")})`;
116347
+ return `json_remove(${renderExpression(base, state, dialect)}, ${renderMySqlJsonPath(segments, state, dialect)})`;
115181
116348
  }
115182
116349
  return;
115183
116350
  }
115184
116351
  case "jsonSet":
115185
116352
  case "jsonInsert": {
115186
- if (!isExpression3(base) || segments.length === 0) {
116353
+ if (!isExpression4(base) || segments.length === 0) {
115187
116354
  return;
115188
116355
  }
115189
116356
  const nextValue = extractJsonValue(ast);
115190
- if (!isExpression3(nextValue)) {
116357
+ if (!isExpression4(nextValue)) {
115191
116358
  return;
115192
116359
  }
115193
116360
  const createMissing = ast.createMissing === true;
@@ -115198,13 +116365,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115198
116365
  return `${functionName}(${renderPostgresJsonValue(base, state, dialect)}, ${renderPostgresJsonPathArray(segments, state, dialect)}, ${renderPostgresJsonValue(nextValue, state, dialect)}${extra})`;
115199
116366
  }
115200
116367
  if (dialect.name === "mysql") {
115201
- const functionName = kind === "jsonInsert" ? "json_insert" : "json_set";
115202
- return `${functionName}(${renderExpression(base, state, dialect)}, ${renderMySqlJsonPath(segments, state, dialect)}, ${renderExpression(nextValue, state, dialect)})`;
116368
+ const renderedBase = renderExpression(base, state, dialect);
116369
+ if (kind === "jsonInsert" && isJsonArrayIndexSegment(segments[segments.length - 1])) {
116370
+ const renderedPath2 = renderMySqlJsonInsertPath(segments, insertAfter, state, dialect);
116371
+ const renderedValue2 = renderJsonInputExpression(nextValue, state, dialect);
116372
+ return `json_array_insert(${renderedBase}, ${renderedPath2}, ${renderedValue2})`;
116373
+ }
116374
+ const functionName = kind === "jsonInsert" ? "json_insert" : createMissing ? "json_set" : "json_replace";
116375
+ const renderedPath = renderMySqlJsonPath(segments, state, dialect);
116376
+ const renderedValue = renderJsonInputExpression(nextValue, state, dialect);
116377
+ return `${functionName}(${renderedBase}, ${renderedPath}, ${renderedValue})`;
115203
116378
  }
115204
116379
  return;
115205
116380
  }
115206
116381
  case "jsonPathExists": {
115207
- if (!isExpression3(base)) {
116382
+ if (!isExpression4(base)) {
115208
116383
  return;
115209
116384
  }
115210
116385
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -115220,7 +116395,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
115220
116395
  return;
115221
116396
  }
115222
116397
  case "jsonPathMatch": {
115223
- if (!isExpression3(base)) {
116398
+ if (!isExpression4(base)) {
115224
116399
  return;
115225
116400
  }
115226
116401
  const path2 = ast.path ?? ast.query ?? ast.right;
@@ -115251,23 +116426,15 @@ var renderMysqlMutationLock = (lock2, statement) => {
115251
116426
  if (!lock2) {
115252
116427
  return "";
115253
116428
  }
115254
- switch (lock2.mode) {
115255
- case "lowPriority":
115256
- return " low_priority";
115257
- case "ignore":
115258
- return " ignore";
115259
- case "quick":
115260
- return statement === "delete" ? " quick" : "";
115261
- default:
115262
- return "";
115263
- }
116429
+ return renderMysqlMutationLockMode(lock2.mode, statement);
115264
116430
  };
115265
116431
  var renderTransactionClause = (clause, dialect) => {
115266
116432
  switch (clause.kind) {
115267
116433
  case "transaction": {
115268
116434
  const modes = [];
115269
- if (clause.isolationLevel) {
115270
- modes.push(`isolation level ${clause.isolationLevel}`);
116435
+ const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
116436
+ if (isolationLevel) {
116437
+ modes.push(isolationLevel);
115271
116438
  }
115272
116439
  if (clause.readOnly === true) {
115273
116440
  modes.push("read only");
@@ -115285,21 +116452,101 @@ var renderTransactionClause = (clause, dialect) => {
115285
116452
  case "releaseSavepoint":
115286
116453
  return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
115287
116454
  }
115288
- return "";
116455
+ throw new Error("Unsupported transaction statement kind");
115289
116456
  };
115290
116457
  var renderSelectionList = (selection, state, dialect, validateAggregation) => {
115291
116458
  if (validateAggregation) {
115292
116459
  validateAggregationSelection(selection, []);
115293
116460
  }
115294
116461
  const flattened = flattenSelection(selection);
116462
+ if (dialect.name === "mysql" && flattened.length === 0) {
116463
+ throw new Error("mysql select statements require at least one selected expression");
116464
+ }
115295
116465
  const projections = selectionProjections(selection);
115296
- const sql = flattened.map(({ expression, alias: alias2 }) => `${renderExpression(expression, state, dialect)} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
116466
+ const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
115297
116467
  return {
115298
116468
  sql,
115299
116469
  projections
115300
116470
  };
115301
116471
  };
115302
- var renderQueryAst = (ast, state, dialect) => {
116472
+ var nestedRenderState = (state) => ({
116473
+ params: state.params,
116474
+ valueMappings: state.valueMappings,
116475
+ ctes: [],
116476
+ cteNames: new Set(state.cteNames),
116477
+ cteSources: new Map(state.cteSources)
116478
+ });
116479
+ var assertMatchingSetProjections = (left, right) => {
116480
+ const leftKeys = left.map((projection) => JSON.stringify(projection.path));
116481
+ const rightKeys = right.map((projection) => JSON.stringify(projection.path));
116482
+ if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index4) => key2 !== rightKeys[index4])) {
116483
+ throw new Error("set operator operands must have matching result rows");
116484
+ }
116485
+ };
116486
+ var assertNoGroupedMutationClauses = (ast, statement) => {
116487
+ if (ast.groupBy.length > 0) {
116488
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
116489
+ }
116490
+ if (ast.having.length > 0) {
116491
+ throw new Error(`having(...) is not supported for ${statement} statements`);
116492
+ }
116493
+ };
116494
+ var assertNoInsertQueryClauses = (ast) => {
116495
+ if (ast.where.length > 0) {
116496
+ throw new Error("where(...) is not supported for insert statements");
116497
+ }
116498
+ if (ast.joins.length > 0) {
116499
+ throw new Error("join(...) is not supported for insert statements");
116500
+ }
116501
+ if (ast.orderBy.length > 0) {
116502
+ throw new Error("orderBy(...) is not supported for insert statements");
116503
+ }
116504
+ if (ast.limit) {
116505
+ throw new Error("limit(...) is not supported for insert statements");
116506
+ }
116507
+ if (ast.offset) {
116508
+ throw new Error("offset(...) is not supported for insert statements");
116509
+ }
116510
+ if (ast.lock) {
116511
+ throw new Error("lock(...) is not supported for insert statements");
116512
+ }
116513
+ };
116514
+ var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
116515
+ if (ast.distinct) {
116516
+ throw new Error(`distinct(...) is not supported for ${statement} statements`);
116517
+ }
116518
+ if (ast.where.length > 0) {
116519
+ throw new Error(`where(...) is not supported for ${statement} statements`);
116520
+ }
116521
+ if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
116522
+ throw new Error(`from(...) is not supported for ${statement} statements`);
116523
+ }
116524
+ if (ast.joins.length > 0) {
116525
+ throw new Error(`join(...) is not supported for ${statement} statements`);
116526
+ }
116527
+ if (ast.groupBy.length > 0) {
116528
+ throw new Error(`groupBy(...) is not supported for ${statement} statements`);
116529
+ }
116530
+ if (ast.having.length > 0) {
116531
+ throw new Error(`having(...) is not supported for ${statement} statements`);
116532
+ }
116533
+ if (ast.orderBy.length > 0) {
116534
+ throw new Error(`orderBy(...) is not supported for ${statement} statements`);
116535
+ }
116536
+ if (ast.limit) {
116537
+ throw new Error(`limit(...) is not supported for ${statement} statements`);
116538
+ }
116539
+ if (ast.offset) {
116540
+ throw new Error(`offset(...) is not supported for ${statement} statements`);
116541
+ }
116542
+ if (ast.lock) {
116543
+ throw new Error(`lock(...) is not supported for ${statement} statements`);
116544
+ }
116545
+ if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
116546
+ throw new Error(`returning(...) is not supported for ${statement} statements`);
116547
+ }
116548
+ };
116549
+ var renderQueryAst = (ast, state, dialect, options2 = {}) => {
115303
116550
  let sql = "";
115304
116551
  let projections = [];
115305
116552
  switch (ast.kind) {
@@ -115307,13 +116554,17 @@ var renderQueryAst = (ast, state, dialect) => {
115307
116554
  validateAggregationSelection(ast.select, ast.groupBy);
115308
116555
  const rendered = renderSelectionList(ast.select, state, dialect, false);
115309
116556
  projections = rendered.projections;
116557
+ const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
115310
116558
  const clauses = [
115311
- ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")}) ${rendered.sql}` : `select${ast.distinct ? " distinct" : ""} ${rendered.sql}`
116559
+ ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
115312
116560
  ];
115313
116561
  if (ast.from) {
115314
116562
  clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
115315
116563
  }
115316
116564
  for (const join2 of ast.joins) {
116565
+ if (dialect.name === "mysql" && join2.kind === "full") {
116566
+ throw new Error("Unsupported mysql full join");
116567
+ }
115317
116568
  const source = renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect);
115318
116569
  clauses.push(join2.kind === "cross" ? `cross join ${source}` : `${join2.kind} join ${source} on ${renderExpression(join2.on, state, dialect)}`);
115319
116570
  }
@@ -115336,19 +116587,25 @@ var renderQueryAst = (ast, state, dialect) => {
115336
116587
  clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
115337
116588
  }
115338
116589
  if (ast.lock) {
115339
- clauses.push(`${ast.lock.mode === "update" ? "for update" : "for share"}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
116590
+ if (ast.lock.nowait && ast.lock.skipLocked) {
116591
+ throw new Error("lock(...) cannot specify both nowait and skipLocked");
116592
+ }
116593
+ clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
115340
116594
  }
115341
116595
  sql = clauses.join(" ");
115342
116596
  break;
115343
116597
  }
115344
116598
  case "set": {
115345
116599
  const setAst = ast;
116600
+ assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
115346
116601
  const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
115347
116602
  projections = selectionProjections(setAst.select);
116603
+ assertMatchingSetProjections(projections, base.projections);
115348
116604
  sql = [
115349
116605
  `(${base.sql})`,
115350
116606
  ...(setAst.setOperations ?? []).map((entry) => {
115351
116607
  const rendered = renderQueryAst(getAst(entry.query), state, dialect);
116608
+ assertMatchingSetProjections(projections, rendered.projections);
115352
116609
  return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
115353
116610
  })
115354
116611
  ].join(" ");
@@ -115356,28 +116613,40 @@ var renderQueryAst = (ast, state, dialect) => {
115356
116613
  }
115357
116614
  case "insert": {
115358
116615
  const insertAst = ast;
116616
+ if (insertAst.distinct) {
116617
+ throw new Error("distinct(...) is not supported for insert statements");
116618
+ }
116619
+ assertNoGroupedMutationClauses(insertAst, "insert");
116620
+ assertNoInsertQueryClauses(insertAst);
115359
116621
  const targetSource = insertAst.into;
115360
116622
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
116623
+ const insertSource = expectInsertSourceKind(insertAst.insertSource);
116624
+ const conflict = expectConflictClause(insertAst.conflict);
115361
116625
  sql = `insert into ${target}`;
115362
- if (insertAst.insertSource?.kind === "values") {
115363
- const columns = insertAst.insertSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
115364
- const rows = insertAst.insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
116626
+ if (insertSource?.kind === "values") {
116627
+ const columns = insertSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
116628
+ const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
115365
116629
  sql += ` (${columns}) values ${rows}`;
115366
- } else if (insertAst.insertSource?.kind === "query") {
115367
- const columns = insertAst.insertSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
115368
- const renderedQuery = renderQueryAst(getAst(insertAst.insertSource.query), state, dialect);
116630
+ } else if (insertSource?.kind === "query") {
116631
+ const columns = insertSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
116632
+ const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
115369
116633
  sql += ` (${columns}) ${renderedQuery.sql}`;
115370
- } else if (insertAst.insertSource?.kind === "unnest") {
115371
- const unnestSource = insertAst.insertSource;
115372
- const columns = unnestSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
116634
+ } else if (insertSource?.kind === "unnest") {
116635
+ const columns = insertSource.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ");
115373
116636
  if (dialect.name === "postgres") {
115374
116637
  const table = targetSource.source;
115375
116638
  const fields2 = table[TypeId4].fields;
115376
- const rendered = unnestSource.values.map((entry) => `cast(${dialect.renderLiteral(entry.values, state)} as ${renderCastType(dialect, fields2[entry.columnName].metadata.dbType)}[])`).join(", ");
116639
+ const rendered = insertSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields2[entry.columnName], state, dialect), state)} as ${renderCastType(dialect, fields2[entry.columnName].metadata.dbType)}[])`).join(", ");
115377
116640
  sql += ` (${columns}) select * from unnest(${rendered})`;
115378
116641
  } else {
115379
- const rowCount = unnestSource.values[0]?.values.length ?? 0;
115380
- const rows = Array.from({ length: rowCount }, (_, index4) => `(${unnestSource.values.map((entry) => dialect.renderLiteral(entry.values[index4], state)).join(", ")})`).join(", ");
116642
+ const table = targetSource.source;
116643
+ const fields2 = table[TypeId4].fields;
116644
+ const encodedValues = insertSource.values.map((entry) => ({
116645
+ columnName: entry.columnName,
116646
+ values: encodeArrayValues(entry.values, fields2[entry.columnName], state, dialect)
116647
+ }));
116648
+ const rowCount = encodedValues[0]?.values.length ?? 0;
116649
+ const rows = Array.from({ length: rowCount }, (_, index4) => `(${encodedValues.map((entry) => dialect.renderLiteral(entry.values[index4], state)).join(", ")})`).join(", ");
115381
116650
  sql += ` (${columns}) values ${rows}`;
115382
116651
  }
115383
116652
  } else {
@@ -115386,22 +116655,29 @@ var renderQueryAst = (ast, state, dialect) => {
115386
116655
  if ((insertAst.values ?? []).length > 0) {
115387
116656
  sql += ` (${columns}) values (${values2})`;
115388
116657
  } else {
115389
- sql += " default values";
116658
+ sql += " () values ()";
115390
116659
  }
115391
116660
  }
115392
- if (insertAst.conflict) {
115393
- const updateValues = (insertAst.conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
116661
+ if (conflict) {
116662
+ if (conflict.where) {
116663
+ throw new Error("Unsupported mysql conflict action predicates");
116664
+ }
116665
+ const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
115394
116666
  if (dialect.name === "postgres") {
115395
- const targetSql = insertAst.conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(insertAst.conflict.target.name)}` : insertAst.conflict.target?.kind === "columns" ? ` on conflict (${insertAst.conflict.target.columns.map((column2) => dialect.quoteIdentifier(column2)).join(", ")})${insertAst.conflict.target.where ? ` where ${renderExpression(insertAst.conflict.target.where, state, dialect)}` : ""}` : " on conflict";
116667
+ 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((column2) => dialect.quoteIdentifier(column2)).join(", ")})${conflict.target.where ? ` where ${renderExpression(conflict.target.where, state, dialect)}` : ""}` : " on conflict";
115396
116668
  sql += targetSql;
115397
- sql += insertAst.conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${insertAst.conflict.where ? ` where ${renderExpression(insertAst.conflict.where, state, dialect)}` : ""}`;
115398
- } else if (insertAst.conflict.action === "doNothing") {
116669
+ sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
116670
+ } else if (conflict.action === "doNothing") {
115399
116671
  sql = sql.replace(/^insert/, "insert ignore");
115400
116672
  } else {
115401
116673
  sql += ` on duplicate key update ${updateValues}`;
115402
116674
  }
115403
116675
  }
115404
- const returning2 = renderSelectionList(insertAst.select, state, dialect, false);
116676
+ const hasReturning = Object.keys(insertAst.select).length > 0;
116677
+ const returning2 = hasReturning ? renderSelectionList(insertAst.select, state, dialect, false) : { sql: "", projections: [] };
116678
+ if (dialect.name === "mysql" && returning2.sql.length > 0) {
116679
+ throw new Error("Unsupported mysql returning");
116680
+ }
115405
116681
  projections = returning2.projections;
115406
116682
  if (returning2.sql.length > 0) {
115407
116683
  sql += ` returning ${returning2.sql}`;
@@ -115410,15 +116686,27 @@ var renderQueryAst = (ast, state, dialect) => {
115410
116686
  }
115411
116687
  case "update": {
115412
116688
  const updateAst = ast;
116689
+ if (updateAst.distinct) {
116690
+ throw new Error("distinct(...) is not supported for update statements");
116691
+ }
116692
+ assertNoGroupedMutationClauses(updateAst, "update");
116693
+ if (updateAst.offset) {
116694
+ throw new Error("offset(...) is not supported for update statements");
116695
+ }
115413
116696
  const targetSource = updateAst.target;
115414
116697
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
115415
116698
  const targets = updateAst.targets ?? [targetSource];
115416
116699
  const fromSources = updateAst.fromSources ?? [];
116700
+ if ((updateAst.set ?? []).length === 0) {
116701
+ throw new Error("update statements require at least one assignment");
116702
+ }
115417
116703
  const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
115418
116704
  if (dialect.name === "mysql") {
115419
116705
  const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
115420
116706
  const extraSources = renderFromSources(fromSources, state, dialect);
115421
- const joinSources = updateAst.joins.map((join2) => join2.kind === "cross" ? `cross join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)}` : `${join2.kind} join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)} on ${renderExpression(join2.on, state, dialect)}`).join(" ");
116707
+ const joinSources = updateAst.joins.map((join2) => join2.kind === "full" ? (() => {
116708
+ throw new Error("Unsupported mysql full join");
116709
+ })() : join2.kind === "cross" ? `cross join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)}` : `${join2.kind} join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)} on ${renderExpression(join2.on, state, dialect)}`).join(" ");
115422
116710
  const targetList = [
115423
116711
  ...targets.map((entry) => renderSourceReference(entry.source, entry.tableName, entry.baseTableName, state, dialect)),
115424
116712
  ...extraSources.length > 0 ? [extraSources] : []
@@ -115447,7 +116735,11 @@ var renderQueryAst = (ast, state, dialect) => {
115447
116735
  if (dialect.name === "mysql" && updateAst.limit) {
115448
116736
  sql += ` limit ${renderMysqlMutationLimit(updateAst.limit, state, dialect)}`;
115449
116737
  }
115450
- const returning2 = renderSelectionList(updateAst.select, state, dialect, false);
116738
+ const hasReturning = Object.keys(updateAst.select).length > 0;
116739
+ const returning2 = hasReturning ? renderSelectionList(updateAst.select, state, dialect, false) : { sql: "", projections: [] };
116740
+ if (dialect.name === "mysql" && returning2.sql.length > 0) {
116741
+ throw new Error("Unsupported mysql returning");
116742
+ }
115451
116743
  projections = returning2.projections;
115452
116744
  if (returning2.sql.length > 0) {
115453
116745
  sql += ` returning ${returning2.sql}`;
@@ -115456,6 +116748,13 @@ var renderQueryAst = (ast, state, dialect) => {
115456
116748
  }
115457
116749
  case "delete": {
115458
116750
  const deleteAst = ast;
116751
+ if (deleteAst.distinct) {
116752
+ throw new Error("distinct(...) is not supported for delete statements");
116753
+ }
116754
+ assertNoGroupedMutationClauses(deleteAst, "delete");
116755
+ if (deleteAst.offset) {
116756
+ throw new Error("offset(...) is not supported for delete statements");
116757
+ }
115459
116758
  const targetSource = deleteAst.target;
115460
116759
  const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
115461
116760
  const targets = deleteAst.targets ?? [targetSource];
@@ -115464,7 +116763,9 @@ var renderQueryAst = (ast, state, dialect) => {
115464
116763
  const hasJoinedSources = deleteAst.joins.length > 0 || targets.length > 1;
115465
116764
  const targetList = renderDeleteTargets(targets, dialect);
115466
116765
  const fromSources = targets.map((entry) => renderSourceReference(entry.source, entry.tableName, entry.baseTableName, state, dialect)).join(", ");
115467
- const joinSources = deleteAst.joins.map((join2) => join2.kind === "cross" ? `cross join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)}` : `${join2.kind} join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)} on ${renderExpression(join2.on, state, dialect)}`).join(" ");
116766
+ const joinSources = deleteAst.joins.map((join2) => join2.kind === "full" ? (() => {
116767
+ throw new Error("Unsupported mysql full join");
116768
+ })() : join2.kind === "cross" ? `cross join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)}` : `${join2.kind} join ${renderSourceReference(join2.source, join2.tableName, join2.baseTableName, state, dialect)} on ${renderExpression(join2.on, state, dialect)}`).join(" ");
115468
116769
  sql = hasJoinedSources ? `delete${modifiers} ${targetList} from ${fromSources}${joinSources.length > 0 ? ` ${joinSources}` : ""}` : `delete${modifiers} from ${fromSources}`;
115469
116770
  } else {
115470
116771
  sql = `delete from ${target}`;
@@ -115485,7 +116786,11 @@ var renderQueryAst = (ast, state, dialect) => {
115485
116786
  if (dialect.name === "mysql" && deleteAst.limit) {
115486
116787
  sql += ` limit ${renderMysqlMutationLimit(deleteAst.limit, state, dialect)}`;
115487
116788
  }
115488
- const returning2 = renderSelectionList(deleteAst.select, state, dialect, false);
116789
+ const hasReturning = Object.keys(deleteAst.select).length > 0;
116790
+ const returning2 = hasReturning ? renderSelectionList(deleteAst.select, state, dialect, false) : { sql: "", projections: [] };
116791
+ if (dialect.name === "mysql" && returning2.sql.length > 0) {
116792
+ throw new Error("Unsupported mysql returning");
116793
+ }
115489
116794
  projections = returning2.projections;
115490
116795
  if (returning2.sql.length > 0) {
115491
116796
  sql += ` returning ${returning2.sql}`;
@@ -115494,12 +116799,17 @@ var renderQueryAst = (ast, state, dialect) => {
115494
116799
  }
115495
116800
  case "truncate": {
115496
116801
  const truncateAst = ast;
116802
+ assertNoStatementQueryClauses(truncateAst, "truncate");
116803
+ const truncate2 = expectTruncateClause(truncateAst.truncate);
115497
116804
  const targetSource = truncateAst.target;
116805
+ if (dialect.name === "mysql" && (truncate2.restartIdentity || truncate2.cascade)) {
116806
+ throw new Error("Unsupported mysql truncate options");
116807
+ }
115498
116808
  sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
115499
- if (truncateAst.truncate?.restartIdentity) {
116809
+ if (truncate2.restartIdentity) {
115500
116810
  sql += " restart identity";
115501
116811
  }
115502
- if (truncateAst.truncate?.cascade) {
116812
+ if (truncate2.cascade) {
115503
116813
  sql += " cascade";
115504
116814
  }
115505
116815
  break;
@@ -115512,6 +116822,9 @@ var renderQueryAst = (ast, state, dialect) => {
115512
116822
  const targetSource = mergeAst.target;
115513
116823
  const usingSource = mergeAst.using;
115514
116824
  const merge2 = mergeAst.merge;
116825
+ if (Object.keys(mergeAst.select).length > 0) {
116826
+ throw new Error("returning(...) is not supported for merge statements");
116827
+ }
115515
116828
  sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression(merge2.on, state, dialect)}`;
115516
116829
  if (merge2.whenMatched) {
115517
116830
  sql += " when matched";
@@ -115539,32 +116852,40 @@ var renderQueryAst = (ast, state, dialect) => {
115539
116852
  case "savepoint":
115540
116853
  case "rollbackTo":
115541
116854
  case "releaseSavepoint": {
116855
+ assertNoStatementQueryClauses(ast, ast.kind);
115542
116856
  sql = renderTransactionClause(ast.transaction, dialect);
115543
116857
  break;
115544
116858
  }
115545
116859
  case "createTable": {
115546
116860
  const createTableAst = ast;
115547
- sql = renderCreateTableSql(createTableAst.target, state, dialect, createTableAst.ddl?.kind === "createTable" && createTableAst.ddl.ifNotExists);
116861
+ assertNoStatementQueryClauses(createTableAst, "createTable");
116862
+ const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
116863
+ sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
115548
116864
  break;
115549
116865
  }
115550
116866
  case "dropTable": {
115551
116867
  const dropTableAst = ast;
115552
- const ifExists = dropTableAst.ddl?.kind === "dropTable" && dropTableAst.ddl.ifExists;
115553
- sql = `drop table${ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
116868
+ assertNoStatementQueryClauses(dropTableAst, "dropTable");
116869
+ const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
116870
+ sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
115554
116871
  break;
115555
116872
  }
115556
116873
  case "createIndex": {
115557
116874
  const createIndexAst = ast;
115558
- sql = renderCreateIndexSql(createIndexAst.target, createIndexAst.ddl, state, dialect);
116875
+ assertNoStatementQueryClauses(createIndexAst, "createIndex");
116876
+ sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
115559
116877
  break;
115560
116878
  }
115561
116879
  case "dropIndex": {
115562
116880
  const dropIndexAst = ast;
115563
- sql = renderDropIndexSql(dropIndexAst.target, dropIndexAst.ddl, state, dialect);
116881
+ assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
116882
+ sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
115564
116883
  break;
115565
116884
  }
116885
+ default:
116886
+ throw new Error("Unsupported query statement kind");
115566
116887
  }
115567
- if (state.ctes.length === 0) {
116888
+ if (state.ctes.length === 0 || options2.emitCtes === false) {
115568
116889
  return {
115569
116890
  sql,
115570
116891
  projections
@@ -115587,9 +116908,22 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
115587
116908
  };
115588
116909
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
115589
116910
  const cte = source;
116911
+ const registeredCteSource = state.cteSources.get(cte.name);
116912
+ if (registeredCteSource !== undefined && registeredCteSource !== cte.plan) {
116913
+ throw new Error(`common table expression name is already registered with a different plan: ${cte.name}`);
116914
+ }
115590
116915
  if (!state.cteNames.has(cte.name)) {
115591
116916
  state.cteNames.add(cte.name);
115592
- const rendered = renderQueryAst(getAst(cte.plan), state, dialect);
116917
+ state.cteSources.set(cte.name, cte.plan);
116918
+ const statement = getQueryState(cte.plan).statement;
116919
+ if (statement !== "select" && statement !== "set") {
116920
+ const cteAst = getAst(cte.plan);
116921
+ if (Object.keys(cteAst.select ?? {}).length > 0) {
116922
+ throw new Error("Unsupported mysql returning");
116923
+ }
116924
+ throw new Error("Unsupported mysql data-modifying cte");
116925
+ }
116926
+ const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
115593
116927
  state.ctes.push({
115594
116928
  name: cte.name,
115595
116929
  sql: rendered.sql,
@@ -115601,11 +116935,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
115601
116935
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
115602
116936
  const derived = source;
115603
116937
  if (!state.cteNames.has(derived.name)) {}
115604
- return `(${renderQueryAst(getAst(derived.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
116938
+ return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
115605
116939
  }
115606
116940
  if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
115607
116941
  const lateral2 = source;
115608
- return `lateral (${renderQueryAst(getAst(lateral2.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(lateral2.name)}`;
116942
+ return `lateral (${renderQueryAst(getAst(lateral2.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral2.name)}`;
115609
116943
  }
115610
116944
  if (typeof source === "object" && source !== null && source.kind === "values") {
115611
116945
  const values2 = source;
@@ -115626,6 +116960,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
115626
116960
  const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
115627
116961
  return dialect.renderTableReference(tableName, baseTableName, schemaName);
115628
116962
  };
116963
+ var renderSubqueryExpressionPlan = (plan, state, dialect) => {
116964
+ const statement = getQueryState(plan).statement;
116965
+ if (statement !== "select" && statement !== "set") {
116966
+ throw new Error("subquery expressions only accept select-like query plans");
116967
+ }
116968
+ return renderQueryAst(getAst(plan), state, dialect).sql;
116969
+ };
115629
116970
  var renderExpression = (expression, state, dialect) => {
115630
116971
  const rawAst = expression[TypeId2];
115631
116972
  const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
@@ -115636,9 +116977,12 @@ var renderExpression = (expression, state, dialect) => {
115636
116977
  const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
115637
116978
  switch (ast.kind) {
115638
116979
  case "column":
115639
- return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
116980
+ return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
115640
116981
  case "literal":
115641
- return dialect.renderLiteral(ast.value, state);
116982
+ if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
116983
+ throw new Error("Expected a finite numeric value");
116984
+ }
116985
+ return dialect.renderLiteral(ast.value, state, expression[TypeId]);
115642
116986
  case "excluded":
115643
116987
  return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
115644
116988
  case "cast":
@@ -115680,7 +117024,7 @@ var renderExpression = (expression, state, dialect) => {
115680
117024
  return `(${left} @> ${right})`;
115681
117025
  }
115682
117026
  if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
115683
- return `json_contains(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
117027
+ return `json_contains(${renderJsonInputExpression(ast.left, state, dialect)}, ${renderJsonInputExpression(ast.right, state, dialect)})`;
115684
117028
  }
115685
117029
  throw new Error("Unsupported container operator for SQL rendering");
115686
117030
  case "containedBy":
@@ -115690,7 +117034,7 @@ var renderExpression = (expression, state, dialect) => {
115690
117034
  return `(${left} <@ ${right})`;
115691
117035
  }
115692
117036
  if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
115693
- return `json_contains(${renderExpression(ast.right, state, dialect)}, ${renderExpression(ast.left, state, dialect)})`;
117037
+ return `json_contains(${renderJsonInputExpression(ast.right, state, dialect)}, ${renderJsonInputExpression(ast.left, state, dialect)})`;
115694
117038
  }
115695
117039
  throw new Error("Unsupported container operator for SQL rendering");
115696
117040
  case "overlaps":
@@ -115700,7 +117044,7 @@ var renderExpression = (expression, state, dialect) => {
115700
117044
  return `(${left} && ${right})`;
115701
117045
  }
115702
117046
  if (dialect.name === "mysql" && isJsonExpression(ast.left) && isJsonExpression(ast.right)) {
115703
- return `json_overlaps(${renderExpression(ast.left, state, dialect)}, ${renderExpression(ast.right, state, dialect)})`;
117047
+ return `json_overlaps(${renderJsonInputExpression(ast.left, state, dialect)}, ${renderJsonInputExpression(ast.right, state, dialect)})`;
115704
117048
  }
115705
117049
  throw new Error("Unsupported container operator for SQL rendering");
115706
117050
  case "isNull":
@@ -115720,14 +117064,26 @@ var renderExpression = (expression, state, dialect) => {
115720
117064
  case "min":
115721
117065
  return `min(${renderExpression(ast.value, state, dialect)})`;
115722
117066
  case "and":
117067
+ if (ast.values.length === 0) {
117068
+ throw new Error("and(...) requires at least one predicate");
117069
+ }
115723
117070
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
115724
117071
  case "or":
117072
+ if (ast.values.length === 0) {
117073
+ throw new Error("or(...) requires at least one predicate");
117074
+ }
115725
117075
  return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
115726
117076
  case "coalesce":
115727
117077
  return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
115728
117078
  case "in":
117079
+ if (ast.values.length < 2) {
117080
+ throw new Error("in(...) requires at least one candidate value");
117081
+ }
115729
117082
  return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
115730
117083
  case "notIn":
117084
+ if (ast.values.length < 2) {
117085
+ throw new Error("notIn(...) requires at least one candidate value");
117086
+ }
115731
117087
  return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
115732
117088
  case "between":
115733
117089
  return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
@@ -115736,15 +117092,15 @@ var renderExpression = (expression, state, dialect) => {
115736
117092
  case "case":
115737
117093
  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`;
115738
117094
  case "exists":
115739
- return `exists (${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
117095
+ return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
115740
117096
  case "scalarSubquery":
115741
- return `(${renderQueryAst(getAst(ast.plan), state, dialect).sql})`;
117097
+ return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
115742
117098
  case "inSubquery":
115743
- return `(${renderExpression(ast.left, state, dialect)} in (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
117099
+ return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
115744
117100
  case "comparisonAny":
115745
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
117101
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
115746
117102
  case "comparisonAll":
115747
- return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderQueryAst(getAst(ast.plan), state, dialect).sql}))`;
117103
+ return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
115748
117104
  case "window": {
115749
117105
  if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
115750
117106
  break;
@@ -115774,17 +117130,20 @@ var renderExpression = (expression, state, dialect) => {
115774
117130
  };
115775
117131
 
115776
117132
  // src/mysql/internal/renderer.ts
115777
- var renderMysqlPlan = (plan) => {
117133
+ var renderMysqlPlan = (plan, options2 = {}) => {
115778
117134
  const state = {
115779
117135
  params: [],
117136
+ valueMappings: options2.valueMappings,
115780
117137
  ctes: [],
115781
- cteNames: new Set
117138
+ cteNames: new Set,
117139
+ cteSources: new Map
115782
117140
  };
115783
117141
  const rendered = renderQueryAst(getAst(plan), state, mysqlDialect);
115784
117142
  return {
115785
117143
  sql: rendered.sql,
115786
117144
  params: state.params,
115787
- projections: rendered.projections
117145
+ projections: rendered.projections,
117146
+ valueMappings: state.valueMappings
115788
117147
  };
115789
117148
  };
115790
117149
 
@@ -115794,12 +117153,12 @@ var withSavepoint2 = withSavepoint;
115794
117153
  function driver2(executeOrHandlers) {
115795
117154
  return driver("mysql", executeOrHandlers);
115796
117155
  }
115797
- var fromDriver = (renderer, sqlDriver, driverMode = "raw") => ({
117156
+ var fromDriver = (renderer, sqlDriver, driverMode = "raw", valueMappings) => ({
115798
117157
  dialect: "mysql",
115799
117158
  execute(plan) {
115800
117159
  const rendered = renderer.render(plan);
115801
117160
  return Effect2.mapError(Effect2.flatMap(sqlDriver.execute(rendered), (rows) => Effect2.try({
115802
- try: () => decodeRows(rendered, plan, rows, { driverMode }),
117161
+ try: () => decodeRows(rendered, plan, rows, { driverMode, valueMappings }),
115803
117162
  catch: (error) => error
115804
117163
  })), (error) => {
115805
117164
  if (typeof error === "object" && error !== null && "_tag" in error && error._tag === "RowDecodeError") {
@@ -115812,7 +117171,7 @@ var fromDriver = (renderer, sqlDriver, driverMode = "raw") => ({
115812
117171
  stream(plan) {
115813
117172
  const rendered = renderer.render(plan);
115814
117173
  return Stream2.mapError(Stream2.mapChunksEffect(sqlDriver.stream(rendered), (rows) => Effect2.try({
115815
- try: () => decodeChunk(rendered, plan, rows, { driverMode }),
117174
+ try: () => decodeChunk(rendered, plan, rows, { driverMode, valueMappings }),
115816
117175
  catch: (error) => error
115817
117176
  })), (error) => {
115818
117177
  if (typeof error === "object" && error !== null && "_tag" in error && error._tag === "RowDecodeError") {
@@ -115829,9 +117188,9 @@ var sqlClientDriver = () => driver2({
115829
117188
  });
115830
117189
  function make6(options2 = {}) {
115831
117190
  if (options2.driver) {
115832
- return fromDriver(options2.renderer ?? make5("mysql", renderMysqlPlan), options2.driver, options2.driverMode);
117191
+ return fromDriver(options2.renderer ?? make5("mysql", (plan) => renderMysqlPlan(plan, { valueMappings: options2.valueMappings })), options2.driver, options2.driverMode, options2.valueMappings);
115833
117192
  }
115834
- return fromDriver(options2.renderer ?? make5("mysql", renderMysqlPlan), sqlClientDriver(), options2.driverMode);
117193
+ return fromDriver(options2.renderer ?? make5("mysql", (plan) => renderMysqlPlan(plan, { valueMappings: options2.valueMappings })), sqlClientDriver(), options2.driverMode, options2.valueMappings);
115835
117194
  }
115836
117195
  var custom3 = (execute) => make4("mysql", execute);
115837
117196
  // src/mysql/query.ts
@@ -115946,10 +117305,13 @@ var TypeId10 = TypeId4;
115946
117305
  var OptionsSymbol2 = OptionsSymbol;
115947
117306
  var options2 = options;
115948
117307
  var make7 = (name, fields2, schemaName = undefined) => make2(name, fields2, schemaName);
115949
- var schema4 = (schemaName) => ({
115950
- schemaName,
115951
- table: (name, fields2, ...declaredOptions) => schema3(schemaName).table(name, fields2, ...declaredOptions)
115952
- });
117308
+ var schema4 = (schemaName) => {
117309
+ const table = (name, fields2, ...declaredOptions) => schema3(schemaName).table(name, fields2, ...declaredOptions);
117310
+ return {
117311
+ schemaName,
117312
+ table
117313
+ };
117314
+ };
115953
117315
  var alias2 = (table, aliasName) => alias(table, aliasName);
115954
117316
  var Class2 = (name, schemaName = undefined) => {
115955
117317
  const base = Class(name, schemaName);
@@ -115967,7 +117329,7 @@ __export(exports_renderer2, {
115967
117329
  make: () => make8,
115968
117330
  TypeId: () => TypeId8
115969
117331
  });
115970
- var make8 = () => make5("mysql", renderMysqlPlan);
117332
+ var make8 = (options3 = {}) => make5("mysql", (plan) => renderMysqlPlan(plan, options3));
115971
117333
  var mysql = make8();
115972
117334
  export {
115973
117335
  exports_table2 as Table,