effect-qb 0.14.0 → 0.16.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 (146) hide show
  1. package/dist/mysql.js +61555 -4252
  2. package/dist/postgres/metadata.js +728 -104
  3. package/dist/postgres.js +6906 -4023
  4. package/package.json +15 -2
  5. package/src/internal/aggregation-validation.ts +3 -3
  6. package/src/internal/case-analysis.d.ts +18 -0
  7. package/src/internal/case-analysis.ts +4 -4
  8. package/src/internal/coercion/analysis.d.ts +7 -0
  9. package/src/internal/{coercion-analysis.ts → coercion/analysis.ts} +3 -3
  10. package/src/internal/coercion/errors.d.ts +17 -0
  11. package/src/internal/{coercion-errors.ts → coercion/errors.ts} +1 -1
  12. package/src/internal/coercion/kind.d.ts +4 -0
  13. package/src/internal/{coercion-kind.ts → coercion/kind.ts} +2 -2
  14. package/src/internal/{coercion-normalize.ts → coercion/normalize.ts} +1 -1
  15. package/src/internal/coercion/rules.d.ts +6 -0
  16. package/src/internal/{coercion-rules.ts → coercion/rules.ts} +2 -2
  17. package/src/internal/column-state.d.ts +190 -0
  18. package/src/internal/column-state.ts +43 -47
  19. package/src/internal/column.ts +43 -305
  20. package/src/internal/datatypes/define.d.ts +17 -0
  21. package/src/internal/datatypes/define.ts +18 -4
  22. package/src/internal/datatypes/lookup.d.ts +44 -0
  23. package/src/internal/datatypes/lookup.ts +61 -152
  24. package/src/internal/datatypes/shape.d.ts +16 -0
  25. package/src/internal/datatypes/shape.ts +1 -1
  26. package/src/internal/derived-table.d.ts +4 -0
  27. package/src/internal/derived-table.ts +21 -16
  28. package/src/internal/dialect.ts +12 -1
  29. package/src/internal/dsl-mutation-runtime.ts +378 -0
  30. package/src/internal/dsl-plan-runtime.ts +387 -0
  31. package/src/internal/dsl-query-runtime.ts +160 -0
  32. package/src/internal/dsl-transaction-ddl-runtime.ts +263 -0
  33. package/src/internal/executor.ts +146 -34
  34. package/src/internal/expression-ast.ts +15 -5
  35. package/src/internal/grouping-key.d.ts +3 -0
  36. package/src/internal/grouping-key.ts +1 -1
  37. package/src/internal/implication-runtime.d.ts +15 -0
  38. package/src/internal/implication-runtime.ts +4 -4
  39. package/src/internal/json/ast.d.ts +30 -0
  40. package/src/internal/json/ast.ts +1 -1
  41. package/src/internal/json/errors.d.ts +8 -0
  42. package/src/internal/json/path.d.ts +75 -0
  43. package/src/internal/json/path.ts +1 -1
  44. package/src/internal/json/types.d.ts +62 -0
  45. package/src/internal/predicate/analysis.d.ts +20 -0
  46. package/src/internal/predicate/analysis.ts +183 -0
  47. package/src/internal/predicate/atom.d.ts +28 -0
  48. package/src/internal/{predicate-atom.ts → predicate/atom.ts} +7 -0
  49. package/src/internal/{predicate-branches.ts → predicate/branches.ts} +2 -2
  50. package/src/internal/predicate/context.d.ts +67 -0
  51. package/src/internal/{predicate-context.ts → predicate/context.ts} +163 -20
  52. package/src/internal/predicate/formula.d.ts +35 -0
  53. package/src/internal/{predicate-formula.ts → predicate/formula.ts} +1 -1
  54. package/src/internal/predicate/key.d.ts +11 -0
  55. package/src/internal/predicate/key.ts +73 -0
  56. package/src/internal/{predicate-nnf.ts → predicate/nnf.ts} +2 -2
  57. package/src/internal/predicate/normalize.d.ts +53 -0
  58. package/src/internal/{predicate-normalize.ts → predicate/normalize.ts} +130 -49
  59. package/src/internal/predicate/runtime.d.ts +31 -0
  60. package/src/internal/{predicate-runtime.ts → predicate/runtime.ts} +127 -17
  61. package/src/internal/projection-alias.d.ts +13 -0
  62. package/src/internal/projections.d.ts +31 -0
  63. package/src/internal/projections.ts +1 -1
  64. package/src/internal/query-ast.d.ts +217 -0
  65. package/src/internal/query-ast.ts +1 -1
  66. package/src/internal/query-requirements.d.ts +20 -0
  67. package/src/internal/query.d.ts +775 -0
  68. package/src/internal/query.ts +683 -369
  69. package/src/internal/renderer.ts +11 -21
  70. package/src/internal/row-set.d.ts +53 -0
  71. package/src/internal/{plan.ts → row-set.ts} +11 -9
  72. package/src/internal/runtime/driver-value-mapping.ts +186 -0
  73. package/src/internal/{runtime-normalize.ts → runtime/normalize.ts} +9 -31
  74. package/src/internal/{runtime-schema.ts → runtime/schema.ts} +13 -38
  75. package/src/internal/runtime/value.d.ts +22 -0
  76. package/src/internal/{runtime-value.ts → runtime/value.ts} +2 -2
  77. package/src/internal/scalar.d.ts +107 -0
  78. package/src/internal/scalar.ts +202 -0
  79. package/src/internal/schema-derivation.d.ts +105 -0
  80. package/src/internal/schema-expression.d.ts +18 -0
  81. package/src/internal/schema-expression.ts +38 -7
  82. package/src/internal/table-options.d.ts +94 -0
  83. package/src/internal/table-options.ts +8 -2
  84. package/src/internal/table.d.ts +173 -0
  85. package/src/internal/table.ts +32 -14
  86. package/src/mysql/column.ts +95 -18
  87. package/src/mysql/datatypes/index.ts +47 -7
  88. package/src/mysql/errors/generated.ts +57336 -0
  89. package/src/mysql/errors/index.ts +1 -0
  90. package/src/mysql/errors/normalize.ts +55 -53
  91. package/src/mysql/errors/types.ts +74 -0
  92. package/src/mysql/executor.ts +88 -11
  93. package/src/mysql/function/aggregate.ts +1 -5
  94. package/src/mysql/function/core.ts +1 -4
  95. package/src/mysql/function/index.ts +0 -1
  96. package/src/mysql/function/string.ts +1 -5
  97. package/src/mysql/function/temporal.ts +12 -15
  98. package/src/mysql/function/window.ts +1 -6
  99. package/src/{internal/mysql-dialect.ts → mysql/internal/dialect.ts} +12 -6
  100. package/src/{internal/mysql-query.ts → mysql/internal/dsl.ts} +1299 -2143
  101. package/src/mysql/internal/renderer.ts +46 -0
  102. package/src/mysql/internal/sql-expression-renderer.ts +1501 -0
  103. package/src/mysql/json.ts +2 -0
  104. package/src/mysql/query.ts +111 -91
  105. package/src/mysql/renderer.ts +8 -3
  106. package/src/mysql/table.ts +1 -1
  107. package/src/mysql.ts +6 -4
  108. package/src/postgres/cast.ts +30 -16
  109. package/src/postgres/column.ts +179 -46
  110. package/src/postgres/datatypes/index.d.ts +515 -0
  111. package/src/postgres/datatypes/index.ts +22 -13
  112. package/src/postgres/datatypes/spec.d.ts +412 -0
  113. package/src/postgres/errors/generated.ts +2636 -0
  114. package/src/postgres/errors/index.ts +1 -0
  115. package/src/postgres/errors/normalize.ts +47 -62
  116. package/src/postgres/errors/types.ts +92 -34
  117. package/src/postgres/executor.ts +54 -7
  118. package/src/postgres/function/aggregate.ts +1 -5
  119. package/src/postgres/function/core.ts +12 -6
  120. package/src/postgres/function/index.ts +0 -1
  121. package/src/postgres/function/string.ts +1 -5
  122. package/src/postgres/function/temporal.ts +12 -15
  123. package/src/postgres/function/window.ts +1 -6
  124. package/src/{internal/postgres-dialect.ts → postgres/internal/dialect.ts} +12 -6
  125. package/src/{internal/postgres-query.ts → postgres/internal/dsl.ts} +1356 -2133
  126. package/src/{internal/postgres-renderer.ts → postgres/internal/renderer.ts} +17 -8
  127. package/src/postgres/internal/schema-ddl.ts +108 -0
  128. package/src/{internal/postgres-schema-model.ts → postgres/internal/schema-model.ts} +12 -6
  129. package/src/{internal → postgres/internal}/sql-expression-renderer.ts +79 -25
  130. package/src/postgres/{function/json.ts → json.ts} +77 -85
  131. package/src/postgres/metadata.ts +2 -2
  132. package/src/postgres/query.ts +113 -89
  133. package/src/postgres/renderer.ts +8 -13
  134. package/src/postgres/schema-expression.ts +2 -1
  135. package/src/postgres/schema-management.ts +1 -1
  136. package/src/postgres/table.ts +12 -4
  137. package/src/postgres/type.ts +33 -2
  138. package/src/postgres.ts +6 -4
  139. package/src/internal/expression.ts +0 -327
  140. package/src/internal/mysql-renderer.ts +0 -37
  141. package/src/internal/predicate-analysis.ts +0 -81
  142. package/src/internal/predicate-key.ts +0 -28
  143. package/src/internal/schema-ddl.ts +0 -55
  144. package/src/mysql/function/json.ts +0 -4
  145. package/src/mysql/private/query.ts +0 -1
  146. package/src/postgres/private/query.ts +0 -1
@@ -27,9 +27,9 @@ __export(exports_metadata, {
27
27
  // src/internal/table.ts
28
28
  import { pipeArguments as pipeArguments2 } from "effect/Pipeable";
29
29
 
30
- // src/internal/plan.ts
31
- var exports_plan = {};
32
- __export(exports_plan, {
30
+ // src/internal/row-set.ts
31
+ var exports_row_set = {};
32
+ __export(exports_row_set, {
33
33
  TypeId: () => TypeId
34
34
  });
35
35
  var TypeId = Symbol.for("effect-qb/Plan");
@@ -38,9 +38,9 @@ var TypeId = Symbol.for("effect-qb/Plan");
38
38
  import { pipeArguments } from "effect/Pipeable";
39
39
  import * as Schema from "effect/Schema";
40
40
 
41
- // src/internal/expression.ts
42
- var exports_expression = {};
43
- __export(exports_expression, {
41
+ // src/internal/scalar.ts
42
+ var exports_scalar = {};
43
+ __export(exports_scalar, {
44
44
  TypeId: () => TypeId2
45
45
  });
46
46
  var TypeId2 = Symbol.for("effect-qb/Expression");
@@ -56,19 +56,28 @@ var ColumnProto = {
56
56
  return pipeArguments(this, arguments);
57
57
  }
58
58
  };
59
+ var attachPipe = (value) => {
60
+ Object.defineProperty(value, "pipe", {
61
+ configurable: true,
62
+ writable: true,
63
+ value: function() {
64
+ return pipeArguments(value, arguments);
65
+ }
66
+ });
67
+ return value;
68
+ };
59
69
  var makeColumnDefinition = (schema, metadata) => {
60
- const column = Object.create(ColumnProto);
70
+ const column = attachPipe(Object.create(ColumnProto));
61
71
  column.schema = schema;
62
72
  column.metadata = metadata;
63
73
  column[TypeId2] = {
64
74
  runtime: undefined,
65
75
  dbType: metadata.dbType,
66
76
  runtimeSchema: schema,
77
+ driverValueMapping: metadata.driverValueMapping,
67
78
  nullability: metadata.nullable ? "maybe" : "never",
68
79
  dialect: metadata.dbType.dialect,
69
- aggregation: "scalar",
70
- source: undefined,
71
- sourceNullability: "propagate",
80
+ kind: "scalar",
72
81
  dependencies: {}
73
82
  };
74
83
  column[ColumnTypeId] = {
@@ -85,17 +94,16 @@ var makeColumnDefinition = (schema, metadata) => {
85
94
  defaultValue: metadata.defaultValue,
86
95
  generatedValue: metadata.generatedValue,
87
96
  ddlType: metadata.ddlType,
97
+ driverValueMapping: metadata.driverValueMapping,
88
98
  identity: metadata.identity,
89
- enum: metadata.enum,
90
- source: undefined,
91
- dependencies: {}
99
+ enum: metadata.enum
92
100
  };
93
101
  return column;
94
102
  };
95
103
  var remapColumnDefinition = (column, options = {}) => {
96
104
  const schema = options.schema ?? column.schema;
97
105
  const metadata = options.metadata ?? column.metadata;
98
- const next = Object.create(ColumnProto);
106
+ const next = attachPipe(Object.create(ColumnProto));
99
107
  next.schema = schema;
100
108
  next.metadata = metadata;
101
109
  next[TypeId2] = {
@@ -103,6 +111,7 @@ var remapColumnDefinition = (column, options = {}) => {
103
111
  runtime: undefined,
104
112
  dbType: metadata.dbType,
105
113
  runtimeSchema: schema,
114
+ driverValueMapping: metadata.driverValueMapping,
106
115
  nullability: metadata.nullable ? "maybe" : "never",
107
116
  dialect: metadata.dbType.dialect
108
117
  };
@@ -121,6 +130,7 @@ var remapColumnDefinition = (column, options = {}) => {
121
130
  defaultValue: metadata.defaultValue,
122
131
  generatedValue: metadata.generatedValue,
123
132
  ddlType: metadata.ddlType,
133
+ driverValueMapping: metadata.driverValueMapping,
124
134
  identity: metadata.identity,
125
135
  enum: metadata.enum
126
136
  };
@@ -135,22 +145,17 @@ var remapColumnDefinition = (column, options = {}) => {
135
145
  var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
136
146
  const brandName = `${tableName}.${columnName}`;
137
147
  const schema = column.metadata.brand === true ? Schema.brand(brandName)(column.schema) : column.schema;
138
- const bound = Object.create(ColumnProto);
148
+ const bound = attachPipe(Object.create(ColumnProto));
139
149
  bound.schema = schema;
140
150
  bound.metadata = column.metadata;
141
151
  bound[TypeId2] = {
142
152
  runtime: undefined,
143
153
  dbType: column.metadata.dbType,
144
154
  runtimeSchema: schema,
155
+ driverValueMapping: column.metadata.driverValueMapping,
145
156
  nullability: column.metadata.nullable ? "maybe" : "never",
146
157
  dialect: column.metadata.dbType.dialect,
147
- aggregation: "scalar",
148
- source: {
149
- tableName,
150
- columnName,
151
- baseTableName
152
- },
153
- sourceNullability: "propagate",
158
+ kind: "scalar",
154
159
  dependencies: {
155
160
  [tableName]: true
156
161
  }
@@ -225,7 +230,9 @@ var collectInlineOptions = (fields) => {
225
230
  kind: "column",
226
231
  column: columnName,
227
232
  order: column.metadata.index.order,
228
- nulls: column.metadata.index.nulls
233
+ nulls: column.metadata.index.nulls,
234
+ operatorClass: column.metadata.index.operatorClass,
235
+ collation: column.metadata.index.collation
229
236
  }],
230
237
  name: column.metadata.index.name,
231
238
  method: column.metadata.index.method,
@@ -379,6 +386,16 @@ var TableProto = {
379
386
  return pipeArguments2(this, arguments);
380
387
  }
381
388
  };
389
+ var attachPipe2 = (value) => {
390
+ Object.defineProperty(value, "pipe", {
391
+ configurable: true,
392
+ writable: true,
393
+ value: function() {
394
+ return pipeArguments2(value, arguments);
395
+ }
396
+ });
397
+ return value;
398
+ };
382
399
  var buildArtifacts = (name, fields, declaredOptions, schemaName) => {
383
400
  const normalizedOptions = [...collectInlineOptions(fields), ...declaredOptions];
384
401
  validateFieldDialects(name, fields);
@@ -397,7 +414,7 @@ var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema"
397
414
  const resolvedSchemaName = schemaMode === "explicit" ? schemaName : "public";
398
415
  const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName);
399
416
  const dialect = resolveFieldDialect(fields);
400
- const table = Object.create(TableProto);
417
+ const table = attachPipe2(Object.create(TableProto));
401
418
  table.name = name;
402
419
  table.columns = artifacts.columns;
403
420
  table.schemas = artifacts.schemas;
@@ -448,7 +465,7 @@ var validateClassOptions = (declaredOptions) => {
448
465
  var resolveFieldDialect = (fields) => {
449
466
  const dialects = [...new Set(Object.values(fields).map((field) => field.metadata.dbType.dialect))];
450
467
  if (dialects.length === 0) {
451
- return "postgres";
468
+ throw new Error("Cannot infer table dialect from an empty field set");
452
469
  }
453
470
  if (dialects.length > 1) {
454
471
  throw new Error(`Mixed table dialects are not supported: ${dialects.join(", ")}`);
@@ -507,7 +524,7 @@ var schema = (schemaName) => ({
507
524
  var alias = (table, aliasName) => {
508
525
  const state = table[TypeId4];
509
526
  const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
510
- const aliased = Object.create(TableProto);
527
+ const aliased = attachPipe2(Object.create(TableProto));
511
528
  aliased.name = aliasName;
512
529
  aliased.columns = columns;
513
530
  aliased.schemas = deriveSchemas(aliasName, state.fields, state.primaryKey);
@@ -627,31 +644,6 @@ var check = (name, predicate) => makeOption({
627
644
  predicate
628
645
  });
629
646
 
630
- // src/internal/postgres-dialect.ts
631
- var quoteIdentifier = (value) => `"${value.replaceAll('"', '""')}"`;
632
- var renderLiteral = (value, state) => {
633
- if (value === null) {
634
- return "null";
635
- }
636
- if (typeof value === "boolean") {
637
- return value ? "true" : "false";
638
- }
639
- state.params.push(value);
640
- return `$${state.params.length}`;
641
- };
642
- var postgresDialect = {
643
- name: "postgres",
644
- quoteIdentifier,
645
- renderLiteral,
646
- renderTableReference(tableName, baseTableName, schemaName) {
647
- const renderedBase = schemaName ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}` : quoteIdentifier(baseTableName);
648
- return tableName === baseTableName ? renderedBase : `${renderedBase} as ${quoteIdentifier(tableName)}`;
649
- },
650
- renderConcat(values) {
651
- return `(${values.join(" || ")})`;
652
- }
653
- };
654
-
655
647
  // src/internal/schema-expression.ts
656
648
  import { parse, toSql } from "pgsql-ast-parser";
657
649
  import { pipeArguments as pipeArguments3 } from "effect/Pipeable";
@@ -661,19 +653,48 @@ var SchemaExpressionProto = {
661
653
  return pipeArguments3(this, arguments);
662
654
  }
663
655
  };
656
+ var attachPipe3 = (value) => {
657
+ Object.defineProperty(value, "pipe", {
658
+ configurable: true,
659
+ writable: true,
660
+ value: function() {
661
+ return pipeArguments3(value, arguments);
662
+ }
663
+ });
664
+ return value;
665
+ };
664
666
  var isSchemaExpression = (value) => typeof value === "object" && value !== null && (TypeId5 in value);
665
667
  var fromAst = (ast) => {
666
- const expression = Object.create(SchemaExpressionProto);
668
+ const expression = attachPipe3(Object.create(SchemaExpressionProto));
667
669
  expression[TypeId5] = {
668
- dialect: "postgres",
669
670
  ast
670
671
  };
671
672
  return expression;
672
673
  };
674
+ var fromSql = (sql) => {
675
+ const expression = attachPipe3(Object.create(SchemaExpressionProto));
676
+ expression[TypeId5] = {
677
+ sql: sql.trim()
678
+ };
679
+ return expression;
680
+ };
673
681
  var parseExpression = (sql) => fromAst(parse(sql, "expr"));
674
- var toAst = (expression) => expression[TypeId5].ast;
675
- var render = (expression) => toSql.expr(expression[TypeId5].ast);
676
- var normalize = (expression) => parseExpression(render(expression));
682
+ var toAst = (expression) => {
683
+ const ast = expression[TypeId5].ast;
684
+ if (ast !== undefined) {
685
+ return ast;
686
+ }
687
+ return parse(render(expression), "expr");
688
+ };
689
+ var render = (expression) => expression[TypeId5].sql ?? toSql.expr(toAst(expression));
690
+ var normalize = (expression) => (() => {
691
+ const sql = render(expression);
692
+ try {
693
+ return parseExpression(sql);
694
+ } catch {
695
+ return fromSql(sql);
696
+ }
697
+ })();
677
698
 
678
699
  // src/internal/query.ts
679
700
  import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
@@ -681,7 +702,7 @@ import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
681
702
  // src/internal/query-ast.ts
682
703
  var TypeId6 = Symbol.for("effect-qb/QueryAst");
683
704
 
684
- // src/internal/predicate-runtime.ts
705
+ // src/internal/predicate/runtime.ts
685
706
  var trueFormula = () => ({ kind: "true" });
686
707
  var falseFormula = () => ({ kind: "false" });
687
708
  var atomFormula = (atom) => ({ kind: "atom", atom });
@@ -695,6 +716,7 @@ var emptyContext = () => ({
695
716
  nullKeys: new Set,
696
717
  eqLiterals: new Map,
697
718
  neqLiterals: new Map,
719
+ literalSets: new Map,
698
720
  sourceNames: new Set,
699
721
  contradiction: false,
700
722
  unknown: false
@@ -704,6 +726,7 @@ var cloneContext = (context) => ({
704
726
  nullKeys: new Set(context.nullKeys),
705
727
  eqLiterals: new Map(context.eqLiterals),
706
728
  neqLiterals: new Map(Array.from(context.neqLiterals.entries(), ([key, values]) => [key, new Set(values)])),
729
+ literalSets: new Map(Array.from(context.literalSets.entries(), ([key, values]) => [key, new Set(values)])),
707
730
  sourceNames: new Set(context.sourceNames),
708
731
  contradiction: context.contradiction,
709
732
  unknown: context.unknown
@@ -737,7 +760,12 @@ var addEqLiteral = (context, key, value) => {
737
760
  if (neqValues?.has(value)) {
738
761
  context.contradiction = true;
739
762
  }
763
+ const existingSet = context.literalSets.get(key);
764
+ if (existingSet !== undefined && !existingSet.has(value)) {
765
+ context.contradiction = true;
766
+ }
740
767
  context.eqLiterals.set(key, value);
768
+ context.literalSets.set(key, new Set([value]));
741
769
  };
742
770
  var addNeqLiteral = (context, key, value) => {
743
771
  addNonNull(context, key);
@@ -748,6 +776,18 @@ var addNeqLiteral = (context, key, value) => {
748
776
  values.add(value);
749
777
  context.neqLiterals.set(key, values);
750
778
  };
779
+ var addLiteralSet = (context, key, values) => {
780
+ addNonNull(context, key);
781
+ const existingEq = context.eqLiterals.get(key);
782
+ if (existingEq !== undefined && !values.has(existingEq)) {
783
+ context.contradiction = true;
784
+ }
785
+ const existing = context.literalSets.get(key);
786
+ context.literalSets.set(key, existing === undefined ? new Set(values) : new Set(Array.from(existing).filter((value) => values.has(value))));
787
+ if (context.literalSets.get(key)?.size === 0) {
788
+ context.contradiction = true;
789
+ }
790
+ };
751
791
  var applyEqColumn = (context, left, right) => {
752
792
  const leftValue = context.eqLiterals.get(left);
753
793
  const rightValue = context.eqLiterals.get(right);
@@ -787,6 +827,9 @@ var applyAtom = (context, atom) => {
787
827
  case "neq-literal":
788
828
  addNeqLiteral(context, atom.key, atom.value);
789
829
  return;
830
+ case "literal-set":
831
+ addLiteralSet(context, atom.key, new Set(atom.values));
832
+ return;
790
833
  case "eq-column":
791
834
  applyEqColumn(context, atom.left, atom.right);
792
835
  return;
@@ -809,6 +852,9 @@ var applyNegativeAtom = (context, atom) => {
809
852
  case "neq-literal":
810
853
  addEqLiteral(context, atom.key, atom.value);
811
854
  return;
855
+ case "literal-set":
856
+ addNonNull(context, atom.key);
857
+ return;
812
858
  case "eq-column":
813
859
  addNonNull(context, atom.left);
814
860
  addNonNull(context, atom.right);
@@ -841,6 +887,17 @@ var intersectNeqLiterals = (left, right) => {
841
887
  }
842
888
  return result;
843
889
  };
890
+ var unionLiteralSets = (left, right) => {
891
+ const result = new Map;
892
+ for (const [key, leftValues] of left) {
893
+ const rightValues = right.get(key);
894
+ if (rightValues === undefined) {
895
+ continue;
896
+ }
897
+ result.set(key, new Set([...leftValues, ...rightValues]));
898
+ }
899
+ return result;
900
+ };
844
901
  var intersectContexts = (left, right) => {
845
902
  if (left.contradiction) {
846
903
  return cloneContext(right);
@@ -853,6 +910,7 @@ var intersectContexts = (left, right) => {
853
910
  nullKeys: new Set(Array.from(left.nullKeys).filter((key) => right.nullKeys.has(key))),
854
911
  eqLiterals: intersectEqLiterals(left.eqLiterals, right.eqLiterals),
855
912
  neqLiterals: intersectNeqLiterals(left.neqLiterals, right.neqLiterals),
913
+ literalSets: unionLiteralSets(left.literalSets, right.literalSets),
856
914
  sourceNames: new Set(Array.from(left.sourceNames).filter((name) => right.sourceNames.has(name))),
857
915
  contradiction: false,
858
916
  unknown: left.unknown || right.unknown
@@ -926,6 +984,45 @@ var columnKeyOfExpression = (value) => {
926
984
  const ast = astOf(value);
927
985
  return ast.kind === "column" ? `${ast.tableName}.${ast.columnName}` : undefined;
928
986
  };
987
+ var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
988
+ var jsonPathPredicateKeyOfExpression = (value) => {
989
+ const ast = astOf(value);
990
+ switch (ast.kind) {
991
+ case "jsonGetText":
992
+ case "jsonPathText":
993
+ case "jsonAccessText":
994
+ case "jsonTraverseText": {
995
+ const jsonAst = ast;
996
+ const segments = jsonAst.segments;
997
+ if (segments.length === 0 || segments.length > 8) {
998
+ return;
999
+ }
1000
+ const path = [];
1001
+ for (const segment of segments) {
1002
+ if (typeof segment !== "object" || segment === null || segment.kind !== "key") {
1003
+ return;
1004
+ }
1005
+ path.push(segment.key);
1006
+ }
1007
+ if (path.length === 0) {
1008
+ return;
1009
+ }
1010
+ const baseKey = columnKeyOfExpression(jsonAst.base);
1011
+ return baseKey === undefined ? undefined : `${baseKey}#json:${path.join(".")}`;
1012
+ }
1013
+ default:
1014
+ return;
1015
+ }
1016
+ };
1017
+ var predicateKeyOfExpression = (value) => columnKeyOfExpression(value) ?? castPredicateKeyOfExpression(value) ?? jsonPathPredicateKeyOfExpression(value);
1018
+ var castPredicateKeyOfExpression = (value) => {
1019
+ const ast = astOf(value);
1020
+ if (ast.kind !== "cast") {
1021
+ return;
1022
+ }
1023
+ const source = ast.value;
1024
+ return sameDbType(source[TypeId2].dbType, ast.target) ? predicateKeyOfExpression(source) : undefined;
1025
+ };
929
1026
  var valueKeyOfLiteral = (value) => {
930
1027
  if (typeof value === "string") {
931
1028
  return `string:${value}`;
@@ -945,7 +1042,7 @@ var valueKeyOfLiteral = (value) => {
945
1042
  return "unknown";
946
1043
  };
947
1044
  var nonNullFactsOfExpression = (value) => {
948
- const key = columnKeyOfExpression(value);
1045
+ const key = predicateKeyOfExpression(value);
949
1046
  return key === undefined ? undefined : atomFormula({ kind: "is-not-null", key });
950
1047
  };
951
1048
  var combineFacts = (left, right) => {
@@ -958,8 +1055,8 @@ var combineFacts = (left, right) => {
958
1055
  return andFormula(left, right);
959
1056
  };
960
1057
  var formulaOfEq = (left, right) => {
961
- const leftKey = columnKeyOfExpression(left);
962
- const rightKey = columnKeyOfExpression(right);
1058
+ const leftKey = predicateKeyOfExpression(left);
1059
+ const rightKey = predicateKeyOfExpression(right);
963
1060
  const leftAst = astOf(left);
964
1061
  const rightAst = astOf(right);
965
1062
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1006,8 +1103,8 @@ var formulaOfEq = (left, right) => {
1006
1103
  });
1007
1104
  };
1008
1105
  var formulaOfNeq = (left, right) => {
1009
- const leftKey = columnKeyOfExpression(left);
1010
- const rightKey = columnKeyOfExpression(right);
1106
+ const leftKey = predicateKeyOfExpression(left);
1107
+ const rightKey = predicateKeyOfExpression(right);
1011
1108
  const leftAst = astOf(left);
1012
1109
  const rightAst = astOf(right);
1013
1110
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1050,8 +1147,8 @@ var formulaOfNeq = (left, right) => {
1050
1147
  return combineFacts(nonNullFactsOfExpression(left), nonNullFactsOfExpression(right));
1051
1148
  };
1052
1149
  var formulaOfIsNotDistinctFrom = (left, right) => {
1053
- const leftKey = columnKeyOfExpression(left);
1054
- const rightKey = columnKeyOfExpression(right);
1150
+ const leftKey = predicateKeyOfExpression(left);
1151
+ const rightKey = predicateKeyOfExpression(right);
1055
1152
  const leftAst = astOf(left);
1056
1153
  const rightAst = astOf(right);
1057
1154
  const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
@@ -1157,11 +1254,11 @@ var formulaOfExpression = (value) => {
1157
1254
  }
1158
1255
  return unknownTag("literal:non-boolean");
1159
1256
  case "isNull": {
1160
- const key = columnKeyOfExpression(ast.value);
1257
+ const key = predicateKeyOfExpression(ast.value);
1161
1258
  return key === undefined ? unknownTag("isNull:unsupported") : atomFormula({ kind: "is-null", key });
1162
1259
  }
1163
1260
  case "isNotNull": {
1164
- const key = columnKeyOfExpression(ast.value);
1261
+ const key = predicateKeyOfExpression(ast.value);
1165
1262
  return key === undefined ? unknownTag("isNotNull:unsupported") : atomFormula({ kind: "is-not-null", key });
1166
1263
  }
1167
1264
  case "not":
@@ -1180,11 +1277,19 @@ var formulaOfExpression = (value) => {
1180
1277
  return anyFormula(ast.values.map((value2) => formulaOfExpression(value2)));
1181
1278
  case "in": {
1182
1279
  const [left, ...rest] = ast.values;
1183
- return left === undefined ? falseFormula() : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
1280
+ if (left === undefined) {
1281
+ return falseFormula();
1282
+ }
1283
+ const key = predicateKeyOfExpression(left);
1284
+ const literalValues = rest.map((entry) => {
1285
+ const entryAst = astOf(entry);
1286
+ return entryAst.kind === "literal" && entryAst.value !== null ? valueKeyOfLiteral(entryAst.value) : undefined;
1287
+ });
1288
+ return key !== undefined && literalValues.every((entry) => entry !== undefined) ? atomFormula({ kind: "literal-set", key, values: literalValues }) : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
1184
1289
  }
1185
1290
  case "notIn": {
1186
1291
  const [left, ...rest] = ast.values;
1187
- return left === undefined ? trueFormula() : allFormula(rest.map((value2) => formulaOfNeq(left, value2)));
1292
+ return left === undefined ? trueFormula() : combineFacts(nonNullFactsOfExpression(left), allFormula(rest.map((value2) => formulaOfNeq(left, value2))));
1188
1293
  }
1189
1294
  case "between":
1190
1295
  return combineFacts(ast.values.reduce((current, entry) => combineFacts(current, nonNullFactsOfExpression(entry)), undefined), unknownTag("variadic:between"));
@@ -1226,35 +1331,46 @@ var PlanProto = {
1226
1331
  }
1227
1332
  };
1228
1333
  var QueryTypeId = Symbol.for("effect-qb/Query/internal");
1229
- var normalizeSources = (source) => source === undefined ? [] : Array.isArray(source) ? source : [source];
1230
- var mergeSources = (left, right) => {
1231
- const values = [...normalizeSources(left), ...normalizeSources(right)];
1232
- if (values.length === 0) {
1233
- return;
1234
- }
1235
- if (values.length === 1) {
1236
- return values[0];
1237
- }
1238
- return values;
1239
- };
1240
- var mergeDependencies = (left, right = {}) => ({
1241
- ...left,
1242
- ...right
1334
+ var mergeDependencies = (left, right = undefined) => ({
1335
+ ...left ?? {},
1336
+ ...right ?? {}
1243
1337
  });
1244
1338
  var mergeAggregationRuntime = (left, right = "scalar") => left === "window" || right === "window" ? "window" : left === "aggregate" || right === "aggregate" ? "aggregate" : "scalar";
1245
- var mergeAggregationManyRuntime = (values) => values.reduce((current, value) => mergeAggregationRuntime(current, value[TypeId2].aggregation), "scalar");
1339
+ var mergeAggregationManyRuntime = (values) => values.reduce((current, value) => mergeAggregationRuntime(current, value[TypeId2].kind), "scalar");
1246
1340
  var mergeNullabilityRuntime = (left, right = "never") => left === "always" || right === "always" ? "always" : left === "maybe" || right === "maybe" ? "maybe" : "never";
1247
1341
  var mergeNullabilityManyRuntime = (values) => values.reduce((current, value) => mergeNullabilityRuntime(current, value[TypeId2].nullability), "never");
1248
- var mergeManySources = (values) => values.reduce((current, value) => mergeSources(current, value[TypeId2].source), undefined);
1249
1342
  var mergeManyDependencies = (values) => values.reduce((current, value) => mergeDependencies(current, value[TypeId2].dependencies), {});
1250
1343
  var makeExpression = (state, ast) => {
1251
1344
  const expression = Object.create(ExpressionProto);
1252
- expression[TypeId2] = state;
1345
+ Object.defineProperty(expression, "pipe", {
1346
+ configurable: true,
1347
+ writable: true,
1348
+ value: function() {
1349
+ return pipeArguments4(expression, arguments);
1350
+ }
1351
+ });
1352
+ expression[TypeId2] = {
1353
+ runtime: state.runtime,
1354
+ dbType: state.dbType,
1355
+ runtimeSchema: state.runtimeSchema,
1356
+ driverValueMapping: state.driverValueMapping,
1357
+ nullability: state.nullability,
1358
+ dialect: state.dialect,
1359
+ kind: state.kind ?? "scalar",
1360
+ dependencies: state.dependencies ?? {}
1361
+ };
1253
1362
  expression[TypeId3] = ast;
1254
1363
  return expression;
1255
1364
  };
1256
- var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState) => {
1365
+ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState, _facts) => {
1257
1366
  const plan = Object.create(PlanProto);
1367
+ Object.defineProperty(plan, "pipe", {
1368
+ configurable: true,
1369
+ writable: true,
1370
+ value: function() {
1371
+ return pipeArguments4(plan, arguments);
1372
+ }
1373
+ });
1258
1374
  plan[TypeId] = state;
1259
1375
  plan[TypeId6] = ast;
1260
1376
  plan[QueryTypeId] = {
@@ -1262,6 +1378,7 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
1262
1378
  availableNames: undefined,
1263
1379
  grouped: undefined,
1264
1380
  assumptions: _assumptions ?? trueFormula(),
1381
+ facts: _facts ?? undefined,
1265
1382
  capabilities: undefined,
1266
1383
  statement: _statement ?? "select",
1267
1384
  target: _target ?? undefined,
@@ -1346,6 +1463,421 @@ var path = (...segments) => ({
1346
1463
  segments
1347
1464
  });
1348
1465
 
1466
+ // src/internal/runtime/driver-value-mapping.ts
1467
+ import * as Schema3 from "effect/Schema";
1468
+
1469
+ // src/internal/runtime/normalize.ts
1470
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1471
+ var pad = (value, width = 2) => value.toString().padStart(width, "0");
1472
+ var formatLocalDate = (value) => `${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
1473
+ var formatLocalTime = (value) => {
1474
+ const milliseconds = value.getUTCMilliseconds();
1475
+ const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
1476
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
1477
+ };
1478
+ var formatLocalDateTime = (value) => {
1479
+ const milliseconds = value.getUTCMilliseconds();
1480
+ const base = `${formatLocalDate(value)}T${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
1481
+ return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
1482
+ };
1483
+ var runtimeTagOfBaseDbType = (dbType) => {
1484
+ return dbType.runtime;
1485
+ };
1486
+ var expectString = (value, label) => {
1487
+ if (typeof value === "string") {
1488
+ return value;
1489
+ }
1490
+ throw new Error(`Expected ${label} as string`);
1491
+ };
1492
+ var normalizeNumber = (value) => {
1493
+ if (typeof value === "number" && Number.isFinite(value)) {
1494
+ return value;
1495
+ }
1496
+ if (typeof value === "string" && value.trim() !== "") {
1497
+ const parsed = Number(value);
1498
+ if (Number.isFinite(parsed)) {
1499
+ return parsed;
1500
+ }
1501
+ }
1502
+ if (typeof value === "bigint" && Number.isSafeInteger(Number(value))) {
1503
+ return Number(value);
1504
+ }
1505
+ throw new Error("Expected a finite numeric value");
1506
+ };
1507
+ var normalizeBoolean = (value) => {
1508
+ if (typeof value === "boolean") {
1509
+ return value;
1510
+ }
1511
+ if (typeof value === "number") {
1512
+ if (value === 1) {
1513
+ return true;
1514
+ }
1515
+ if (value === 0) {
1516
+ return false;
1517
+ }
1518
+ }
1519
+ if (typeof value === "string") {
1520
+ const normalized = value.trim().toLowerCase();
1521
+ if (normalized === "true" || normalized === "t" || normalized === "1") {
1522
+ return true;
1523
+ }
1524
+ if (normalized === "false" || normalized === "f" || normalized === "0") {
1525
+ return false;
1526
+ }
1527
+ }
1528
+ throw new Error("Expected a boolean-like value");
1529
+ };
1530
+ var normalizeBigIntString = (value) => {
1531
+ if (typeof value === "bigint") {
1532
+ return value.toString();
1533
+ }
1534
+ if (typeof value === "number" && Number.isSafeInteger(value)) {
1535
+ return BigInt(value).toString();
1536
+ }
1537
+ if (typeof value === "string" && /^-?\d+$/.test(value.trim())) {
1538
+ return BigInt(value.trim()).toString();
1539
+ }
1540
+ throw new Error("Expected an integer-like bigint value");
1541
+ };
1542
+ var canonicalizeDecimalString = (input) => {
1543
+ const trimmed = input.trim();
1544
+ const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
1545
+ if (match === null) {
1546
+ throw new Error("Expected a decimal string");
1547
+ }
1548
+ const sign = match[1] === "-" ? "-" : "";
1549
+ const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
1550
+ const fraction = (match[3] ?? "").replace(/0+$/, "");
1551
+ if (fraction.length === 0) {
1552
+ return `${sign}${integer}`;
1553
+ }
1554
+ return `${sign}${integer}.${fraction}`;
1555
+ };
1556
+ var normalizeDecimalString = (value) => {
1557
+ if (typeof value === "string") {
1558
+ return canonicalizeDecimalString(value);
1559
+ }
1560
+ if (typeof value === "number" && Number.isFinite(value)) {
1561
+ const rendered = String(value);
1562
+ if (/[eE]/.test(rendered)) {
1563
+ throw new Error("Scientific notation is not a supported decimal runtime");
1564
+ }
1565
+ return canonicalizeDecimalString(rendered);
1566
+ }
1567
+ throw new Error("Expected a decimal-like value");
1568
+ };
1569
+ var normalizeLocalDate = (value) => {
1570
+ if (value instanceof Date) {
1571
+ return formatLocalDate(value);
1572
+ }
1573
+ const raw = expectString(value, "local date").trim();
1574
+ if (/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
1575
+ return raw;
1576
+ }
1577
+ const parsed = new Date(raw);
1578
+ if (!Number.isNaN(parsed.getTime())) {
1579
+ return formatLocalDate(parsed);
1580
+ }
1581
+ throw new Error("Expected a local-date value");
1582
+ };
1583
+ var normalizeLocalTime = (value) => {
1584
+ if (value instanceof Date) {
1585
+ return formatLocalTime(value);
1586
+ }
1587
+ const raw = expectString(value, "local time").trim();
1588
+ if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
1589
+ return raw;
1590
+ }
1591
+ throw new Error("Expected a local-time value");
1592
+ };
1593
+ var normalizeOffsetTime = (value) => {
1594
+ if (value instanceof Date) {
1595
+ return `${formatLocalTime(value)}Z`;
1596
+ }
1597
+ const raw = expectString(value, "offset time").trim();
1598
+ if (/^\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
1599
+ return raw;
1600
+ }
1601
+ throw new Error("Expected an offset-time value");
1602
+ };
1603
+ var normalizeLocalDateTime = (value) => {
1604
+ if (value instanceof Date) {
1605
+ return formatLocalDateTime(value);
1606
+ }
1607
+ const raw = expectString(value, "local datetime").trim();
1608
+ if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/.test(raw)) {
1609
+ return raw.replace(" ", "T");
1610
+ }
1611
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(raw)) {
1612
+ const parsed = new Date(raw);
1613
+ if (!Number.isNaN(parsed.getTime())) {
1614
+ return formatLocalDateTime(parsed);
1615
+ }
1616
+ }
1617
+ throw new Error("Expected a local-datetime value");
1618
+ };
1619
+ var normalizeInstant = (value) => {
1620
+ if (value instanceof Date) {
1621
+ return value.toISOString();
1622
+ }
1623
+ const raw = expectString(value, "instant").trim();
1624
+ if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
1625
+ throw new Error("Instant values require a timezone offset");
1626
+ }
1627
+ const parsed = new Date(raw);
1628
+ if (Number.isNaN(parsed.getTime())) {
1629
+ throw new Error("Expected an ISO instant value");
1630
+ }
1631
+ return parsed.toISOString();
1632
+ };
1633
+ var normalizeYear = (value) => {
1634
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 9999) {
1635
+ return pad(value, 4);
1636
+ }
1637
+ const raw = expectString(value, "year").trim();
1638
+ if (/^\d{4}$/.test(raw)) {
1639
+ return raw;
1640
+ }
1641
+ throw new Error("Expected a four-digit year");
1642
+ };
1643
+ var normalizeBytes = (value) => {
1644
+ if (value instanceof Uint8Array) {
1645
+ return new Uint8Array(value);
1646
+ }
1647
+ const BufferConstructor = globalThis.Buffer;
1648
+ if (BufferConstructor !== undefined && value instanceof BufferConstructor) {
1649
+ return new Uint8Array(value);
1650
+ }
1651
+ throw new Error("Expected a byte array value");
1652
+ };
1653
+ var isJsonValue = (value) => {
1654
+ if (value === null) {
1655
+ return true;
1656
+ }
1657
+ switch (typeof value) {
1658
+ case "string":
1659
+ case "number":
1660
+ case "boolean":
1661
+ return true;
1662
+ case "object":
1663
+ if (Array.isArray(value)) {
1664
+ return value.every(isJsonValue);
1665
+ }
1666
+ return isRecord(value) && Object.values(value).every(isJsonValue);
1667
+ default:
1668
+ return false;
1669
+ }
1670
+ };
1671
+ var normalizeJson = (value) => {
1672
+ if (typeof value === "string") {
1673
+ const parsed = JSON.parse(value);
1674
+ if (isJsonValue(parsed)) {
1675
+ return parsed;
1676
+ }
1677
+ throw new Error("Parsed JSON value is not a valid JSON runtime");
1678
+ }
1679
+ if (isJsonValue(value)) {
1680
+ return value;
1681
+ }
1682
+ throw new Error("Expected a JSON value");
1683
+ };
1684
+ var normalizeDbValue = (dbType, value) => {
1685
+ if (value === null) {
1686
+ return null;
1687
+ }
1688
+ if ("base" in dbType) {
1689
+ return normalizeDbValue(dbType.base, value);
1690
+ }
1691
+ if ("element" in dbType) {
1692
+ if (!Array.isArray(value)) {
1693
+ throw new Error("Expected an array value");
1694
+ }
1695
+ return value.map((entry) => normalizeDbValue(dbType.element, entry));
1696
+ }
1697
+ if ("fields" in dbType) {
1698
+ if (!isRecord(value)) {
1699
+ throw new Error("Expected a record value");
1700
+ }
1701
+ const normalized = {};
1702
+ for (const [key2, fieldDbType] of Object.entries(dbType.fields)) {
1703
+ if (key2 in value) {
1704
+ normalized[key2] = normalizeDbValue(fieldDbType, value[key2]);
1705
+ }
1706
+ }
1707
+ return normalized;
1708
+ }
1709
+ if ("variant" in dbType && dbType.variant === "json") {
1710
+ return normalizeJson(value);
1711
+ }
1712
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
1713
+ return expectString(value, "text");
1714
+ }
1715
+ switch (runtimeTagOfBaseDbType(dbType)) {
1716
+ case "string":
1717
+ return expectString(value, "text");
1718
+ case "number":
1719
+ return normalizeNumber(value);
1720
+ case "bigintString":
1721
+ return normalizeBigIntString(value);
1722
+ case "boolean":
1723
+ return normalizeBoolean(value);
1724
+ case "json":
1725
+ return normalizeJson(value);
1726
+ case "localDate":
1727
+ return normalizeLocalDate(value);
1728
+ case "localTime":
1729
+ return normalizeLocalTime(value);
1730
+ case "offsetTime":
1731
+ return normalizeOffsetTime(value);
1732
+ case "localDateTime":
1733
+ return normalizeLocalDateTime(value);
1734
+ case "instant":
1735
+ return normalizeInstant(value);
1736
+ case "year":
1737
+ return normalizeYear(value);
1738
+ case "decimalString":
1739
+ return normalizeDecimalString(value);
1740
+ case "bytes":
1741
+ return normalizeBytes(value);
1742
+ case "array":
1743
+ if (!Array.isArray(value)) {
1744
+ throw new Error("Expected an array value");
1745
+ }
1746
+ return value;
1747
+ case "record":
1748
+ if (!isRecord(value)) {
1749
+ throw new Error("Expected a record value");
1750
+ }
1751
+ return value;
1752
+ case "null":
1753
+ return null;
1754
+ case "unknown":
1755
+ case undefined:
1756
+ return value;
1757
+ }
1758
+ };
1759
+
1760
+ // src/internal/runtime/driver-value-mapping.ts
1761
+ var runtimeTagOfDbType = (dbType) => {
1762
+ if (dbType === undefined) {
1763
+ return;
1764
+ }
1765
+ if ("base" in dbType) {
1766
+ return runtimeTagOfDbType(dbType.base);
1767
+ }
1768
+ if ("element" in dbType) {
1769
+ return "array";
1770
+ }
1771
+ if ("fields" in dbType) {
1772
+ return "record";
1773
+ }
1774
+ if ("variant" in dbType && dbType.variant === "json") {
1775
+ return "json";
1776
+ }
1777
+ if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
1778
+ return "string";
1779
+ }
1780
+ return dbType.runtime;
1781
+ };
1782
+ var familyOfDbType = (dbType) => {
1783
+ if (dbType === undefined) {
1784
+ return;
1785
+ }
1786
+ if ("base" in dbType) {
1787
+ return familyOfDbType(dbType.base);
1788
+ }
1789
+ return dbType.family;
1790
+ };
1791
+ var mappingCandidates = (context) => {
1792
+ const dbType = context.dbType;
1793
+ const runtimeTag = runtimeTagOfDbType(dbType);
1794
+ const family = familyOfDbType(dbType);
1795
+ return [
1796
+ context.driverValueMapping,
1797
+ dbType?.driverValueMapping,
1798
+ dbType === undefined ? undefined : context.valueMappings?.[dbType.kind],
1799
+ family === undefined ? undefined : context.valueMappings?.[family],
1800
+ runtimeTag === undefined ? undefined : context.valueMappings?.[runtimeTag]
1801
+ ];
1802
+ };
1803
+ var findMapping = (context, key2) => {
1804
+ for (const candidate of mappingCandidates(context)) {
1805
+ const value = candidate?.[key2];
1806
+ if (value !== undefined) {
1807
+ return value;
1808
+ }
1809
+ }
1810
+ return;
1811
+ };
1812
+ var encodeWithSchema = (schema2, value) => {
1813
+ if (schema2 === undefined) {
1814
+ return { value, encoded: false };
1815
+ }
1816
+ if (!Schema3.is(schema2)(value)) {
1817
+ return { value, encoded: false };
1818
+ }
1819
+ return {
1820
+ value: Schema3.encodeUnknownSync(schema2)(value),
1821
+ encoded: true
1822
+ };
1823
+ };
1824
+ var toDriverValue = (value, context) => {
1825
+ if (value === null) {
1826
+ return null;
1827
+ }
1828
+ const dbType = context.dbType;
1829
+ const encoded = encodeWithSchema(context.runtimeSchema, value);
1830
+ let current = encoded.value;
1831
+ const custom = findMapping(context, "toDriver");
1832
+ if (custom !== undefined && dbType !== undefined) {
1833
+ return custom(current, dbType);
1834
+ }
1835
+ return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
1836
+ };
1837
+ var fromDriverValue = (value, context) => {
1838
+ if (value === null) {
1839
+ return null;
1840
+ }
1841
+ const dbType = context.dbType;
1842
+ const custom = findMapping(context, "fromDriver");
1843
+ if (custom !== undefined && dbType !== undefined) {
1844
+ return custom(value, dbType);
1845
+ }
1846
+ return dbType === undefined ? value : normalizeDbValue(dbType, value);
1847
+ };
1848
+ var textCast = (sql) => `(${sql})::text`;
1849
+ var postgresJsonSql = (sql, dbType) => {
1850
+ const runtimeTag = runtimeTagOfDbType(dbType);
1851
+ switch (runtimeTag) {
1852
+ case "bigintString":
1853
+ case "decimalString":
1854
+ case "localDate":
1855
+ case "localTime":
1856
+ case "offsetTime":
1857
+ case "localDateTime":
1858
+ case "instant":
1859
+ case "year":
1860
+ return textCast(sql);
1861
+ case "bytes":
1862
+ return `encode(${sql}, 'base64')`;
1863
+ default:
1864
+ return sql;
1865
+ }
1866
+ };
1867
+ var renderSelectSql = (sql, context) => {
1868
+ const dbType = context.dbType;
1869
+ const custom = findMapping(context, "selectSql");
1870
+ return custom !== undefined && dbType !== undefined ? custom(sql, dbType) : sql;
1871
+ };
1872
+ var renderJsonSelectSql = (sql, context) => {
1873
+ const dbType = context.dbType;
1874
+ const custom = findMapping(context, "jsonSelectSql");
1875
+ if (custom !== undefined && dbType !== undefined) {
1876
+ return custom(sql, dbType);
1877
+ }
1878
+ return context.dialect === "postgres" && dbType !== undefined ? postgresJsonSql(sql, dbType) : sql;
1879
+ };
1880
+
1349
1881
  // src/internal/projection-alias.ts
1350
1882
  var TypeId8 = Symbol.for("effect-qb/ProjectionAlias");
1351
1883
 
@@ -1475,13 +2007,13 @@ var dedupeGroupedExpressions = (values) => {
1475
2007
  var isExpression2 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
1476
2008
  var selectionHasAggregate = (selection) => {
1477
2009
  if (isExpression2(selection)) {
1478
- return selection[TypeId2].aggregation === "aggregate";
2010
+ return selection[TypeId2].kind === "aggregate";
1479
2011
  }
1480
2012
  return Object.values(selection).some((value) => selectionHasAggregate(value));
1481
2013
  };
1482
2014
  var isGroupedSelectionValid = (selection, groupedExpressions) => {
1483
2015
  if (isExpression2(selection)) {
1484
- const aggregation = selection[TypeId2].aggregation;
2016
+ const aggregation = selection[TypeId2].kind;
1485
2017
  if (aggregation === "aggregate") {
1486
2018
  return true;
1487
2019
  }
@@ -1504,7 +2036,7 @@ var validateAggregationSelection = (selection, grouped) => {
1504
2036
  }
1505
2037
  };
1506
2038
 
1507
- // src/internal/sql-expression-renderer.ts
2039
+ // src/postgres/internal/sql-expression-renderer.ts
1508
2040
  var renderDbType = (dialect, dbType) => {
1509
2041
  if (dialect.name === "mysql" && dbType.dialect === "mysql" && dbType.kind === "uuid") {
1510
2042
  return "char(36)";
@@ -1688,8 +2220,27 @@ var renderPostgresJsonValue = (value, state, dialect) => {
1688
2220
  throw new Error("Expected a JSON expression");
1689
2221
  }
1690
2222
  const rendered = renderExpression(value, state, dialect);
2223
+ const ast = value[TypeId3];
2224
+ if (ast.kind === "literal") {
2225
+ return `cast(${rendered} as jsonb)`;
2226
+ }
1691
2227
  return value[TypeId2].dbType.kind === "jsonb" ? rendered : `cast(${rendered} as jsonb)`;
1692
2228
  };
2229
+ var expressionDriverContext = (expression, state, dialect) => ({
2230
+ dialect: dialect.name,
2231
+ valueMappings: state.valueMappings,
2232
+ dbType: expression[TypeId2].dbType,
2233
+ runtimeSchema: expression[TypeId2].runtimeSchema,
2234
+ driverValueMapping: expression[TypeId2].driverValueMapping
2235
+ });
2236
+ var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
2237
+ var encodeArrayValues = (values, column, state, dialect) => values.map((value) => toDriverValue(value, {
2238
+ dialect: dialect.name,
2239
+ valueMappings: state.valueMappings,
2240
+ dbType: column.metadata.dbType,
2241
+ runtimeSchema: column.schema,
2242
+ driverValueMapping: column.metadata.driverValueMapping
2243
+ }));
1693
2244
  var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
1694
2245
  var renderJsonOpaquePath = (value, state, dialect) => {
1695
2246
  if (isJsonPathValue(value)) {
@@ -1818,7 +2369,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1818
2369
  const entries = Array.isArray(ast.entries) ? ast.entries : [];
1819
2370
  const renderedEntries = entries.flatMap((entry) => [
1820
2371
  dialect.renderLiteral(entry.key, state),
1821
- renderExpression(entry.value, state, dialect)
2372
+ renderJsonInputExpression(entry.value, state, dialect)
1822
2373
  ]);
1823
2374
  if (dialect.name === "postgres") {
1824
2375
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`;
@@ -1830,7 +2381,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1830
2381
  }
1831
2382
  case "jsonBuildArray": {
1832
2383
  const values = Array.isArray(ast.values) ? ast.values : [];
1833
- const renderedValues = values.map((value) => renderExpression(value, state, dialect)).join(", ");
2384
+ const renderedValues = values.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ");
1834
2385
  if (dialect.name === "postgres") {
1835
2386
  return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`;
1836
2387
  }
@@ -1844,7 +2395,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1844
2395
  return;
1845
2396
  }
1846
2397
  if (dialect.name === "postgres") {
1847
- return `to_json(${renderExpression(base, state, dialect)})`;
2398
+ return `to_json(${renderJsonInputExpression(base, state, dialect)})`;
1848
2399
  }
1849
2400
  if (dialect.name === "mysql") {
1850
2401
  return `cast(${renderExpression(base, state, dialect)} as json)`;
@@ -1855,7 +2406,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
1855
2406
  return;
1856
2407
  }
1857
2408
  if (dialect.name === "postgres") {
1858
- return `to_jsonb(${renderExpression(base, state, dialect)})`;
2409
+ return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`;
1859
2410
  }
1860
2411
  if (dialect.name === "mysql") {
1861
2412
  return `cast(${renderExpression(base, state, dialect)} as json)`;
@@ -2042,7 +2593,7 @@ var renderSelectionList = (selection, state, dialect, validateAggregation) => {
2042
2593
  }
2043
2594
  const flattened = flattenSelection(selection);
2044
2595
  const projections = selectionProjections(selection);
2045
- const sql = flattened.map(({ expression, alias: alias2 }) => `${renderExpression(expression, state, dialect)} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
2596
+ const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
2046
2597
  return {
2047
2598
  sql,
2048
2599
  projections
@@ -2122,11 +2673,11 @@ var renderQueryAst = (ast, state, dialect) => {
2122
2673
  if (dialect.name === "postgres") {
2123
2674
  const table = targetSource.source;
2124
2675
  const fields = table[TypeId4].fields;
2125
- const rendered = unnestSource.values.map((entry) => `cast(${dialect.renderLiteral(entry.values, state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
2676
+ const rendered = unnestSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName], state, dialect), state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
2126
2677
  sql += ` (${columns}) select * from unnest(${rendered})`;
2127
2678
  } else {
2128
2679
  const rowCount = unnestSource.values[0]?.values.length ?? 0;
2129
- const rows = Array.from({ length: rowCount }, (_, index3) => `(${unnestSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state)).join(", ")})`).join(", ");
2680
+ const rows = Array.from({ length: rowCount }, (_, index3) => `(${unnestSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
2130
2681
  sql += ` (${columns}) values ${rows}`;
2131
2682
  }
2132
2683
  } else {
@@ -2387,11 +2938,13 @@ var renderExpression = (expression, state, dialect) => {
2387
2938
  case "column":
2388
2939
  return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
2389
2940
  case "literal":
2390
- return dialect.renderLiteral(ast.value, state);
2941
+ return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
2391
2942
  case "excluded":
2392
2943
  return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
2393
2944
  case "cast":
2394
2945
  return `cast(${renderExpression(ast.value, state, dialect)} as ${renderCastType(dialect, ast.target)})`;
2946
+ case "collate":
2947
+ return `(${renderExpression(ast.value, state, dialect)} collate ${ast.collation.map((segment) => dialect.quoteIdentifier(segment)).join(".")})`;
2395
2948
  case "function":
2396
2949
  return renderFunctionCall(ast.name, Array.isArray(ast.args) ? ast.args : [], state, dialect);
2397
2950
  case "eq":
@@ -2522,8 +3075,40 @@ var renderExpression = (expression, state, dialect) => {
2522
3075
  throw new Error("Unsupported expression for SQL rendering");
2523
3076
  };
2524
3077
 
2525
- // src/internal/schema-ddl.ts
3078
+ // src/postgres/internal/schema-ddl.ts
2526
3079
  import { parse as parse2, toSql as toSql2 } from "pgsql-ast-parser";
3080
+
3081
+ // src/postgres/internal/dialect.ts
3082
+ var quoteIdentifier = (value) => `"${value.replaceAll('"', '""')}"`;
3083
+ var renderLiteral = (value, state, context = {}) => {
3084
+ const driverValue = toDriverValue(value, {
3085
+ dialect: "postgres",
3086
+ valueMappings: state.valueMappings,
3087
+ ...context
3088
+ });
3089
+ if (driverValue === null) {
3090
+ return "null";
3091
+ }
3092
+ if (typeof driverValue === "boolean") {
3093
+ return driverValue ? "true" : "false";
3094
+ }
3095
+ state.params.push(driverValue);
3096
+ return `$${state.params.length}`;
3097
+ };
3098
+ var postgresDialect = {
3099
+ name: "postgres",
3100
+ quoteIdentifier,
3101
+ renderLiteral,
3102
+ renderTableReference(tableName, baseTableName, schemaName) {
3103
+ const renderedBase = schemaName ? `${quoteIdentifier(schemaName)}.${quoteIdentifier(baseTableName)}` : quoteIdentifier(baseTableName);
3104
+ return tableName === baseTableName ? renderedBase : `${renderedBase} as ${quoteIdentifier(tableName)}`;
3105
+ },
3106
+ renderConcat(values) {
3107
+ return `(${values.join(" || ")})`;
3108
+ }
3109
+ };
3110
+
3111
+ // src/postgres/internal/schema-ddl.ts
2527
3112
  var escapeString = (value) => `'${value.replaceAll("'", "''")}'`;
2528
3113
  var inlineLiteralDialect = {
2529
3114
  ...postgresDialect,
@@ -2548,17 +3133,56 @@ var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? re
2548
3133
  ctes: [],
2549
3134
  cteNames: new Set
2550
3135
  }, inlineLiteralDialect);
3136
+ var stripRedundantOuterParens = (value) => {
3137
+ let current = value.trim();
3138
+ while (current.startsWith("(") && current.endsWith(")")) {
3139
+ let depth = 0;
3140
+ let wrapsWholeExpression = true;
3141
+ let inSingleQuote = false;
3142
+ let inDoubleQuote = false;
3143
+ for (let index3 = 0;index3 < current.length; index3++) {
3144
+ const char = current[index3];
3145
+ const previous = index3 > 0 ? current[index3 - 1] : undefined;
3146
+ if (char === "'" && !inDoubleQuote && previous !== "\\") {
3147
+ inSingleQuote = !inSingleQuote;
3148
+ continue;
3149
+ }
3150
+ if (char === '"' && !inSingleQuote && previous !== "\\") {
3151
+ inDoubleQuote = !inDoubleQuote;
3152
+ continue;
3153
+ }
3154
+ if (inSingleQuote || inDoubleQuote) {
3155
+ continue;
3156
+ }
3157
+ if (char === "(") {
3158
+ depth += 1;
3159
+ } else if (char === ")") {
3160
+ depth -= 1;
3161
+ if (depth === 0 && index3 < current.length - 1) {
3162
+ wrapsWholeExpression = false;
3163
+ break;
3164
+ }
3165
+ }
3166
+ }
3167
+ if (!wrapsWholeExpression) {
3168
+ break;
3169
+ }
3170
+ current = current.slice(1, -1).trim();
3171
+ }
3172
+ return current;
3173
+ };
3174
+ var canonicalizeDdlExpressionSql = (value) => stripRedundantOuterParens(value.trim().replace(/\s+/g, " ").replace(/"[^"]+"\./g, "").replace(/"([A-Za-z_][A-Za-z0-9_]*)"/g, "$1").replace(/\bCOLLATE\b/g, "collate").replace(/cast\(((?:'(?:[^']|'')*'|"[^"]+"|[a-zA-Z_][a-zA-Z0-9_]*|\([^()]+\))) as ([^)]+)\)/gi, (_, expression, target) => `${expression}::${target.trim()}`));
2551
3175
  var normalizeDdlExpressionSql = (expression) => {
2552
3176
  const rendered = renderDdlExpressionSql(expression);
2553
3177
  try {
2554
- return toSql2.expr(parse2(rendered, "expr"));
3178
+ return canonicalizeDdlExpressionSql(toSql2.expr(parse2(rendered, "expr")));
2555
3179
  } catch {
2556
- return rendered.trim();
3180
+ return canonicalizeDdlExpressionSql(rendered);
2557
3181
  }
2558
3182
  };
2559
3183
 
2560
3184
  // src/postgres/schema-management.ts
2561
- import * as Schema3 from "effect/Schema";
3185
+ import * as Schema4 from "effect/Schema";
2562
3186
  import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
2563
3187
  var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
2564
3188
  var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
@@ -2577,8 +3201,8 @@ var EnumProto = {
2577
3201
  };
2578
3202
  },
2579
3203
  column() {
2580
- const values = this.values.map((value) => Schema3.Literal(value));
2581
- return makeColumnDefinition(values.length === 1 ? values[0] : Schema3.Union(...values), {
3204
+ const values = this.values.map((value) => Schema4.Literal(value));
3205
+ return makeColumnDefinition(values.length === 1 ? values[0] : Schema4.Union(...values), {
2582
3206
  dbType: this.type(),
2583
3207
  nullable: false,
2584
3208
  hasDefault: false,
@@ -2630,7 +3254,7 @@ function sequence(name, schemaName) {
2630
3254
  }
2631
3255
  var isSequenceDefinition = (value) => typeof value === "object" && value !== null && (SequenceTypeId in value);
2632
3256
 
2633
- // src/internal/postgres-schema-model.ts
3257
+ // src/postgres/internal/schema-model.ts
2634
3258
  var isTableDefinition = (value) => value !== null && (typeof value === "object" || typeof value === "function") && (TypeId4 in value);
2635
3259
  var isEnumDefinition = (value) => typeof value === "object" && value !== null && (EnumTypeId in value);
2636
3260
  var toTableModel = (table) => {