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.
- package/dist/mysql.js +1957 -595
- package/dist/postgres/metadata.js +2507 -182
- package/dist/postgres.js +9587 -8201
- package/dist/sqlite.js +8360 -0
- package/package.json +7 -2
- package/src/internal/column-state.ts +7 -0
- package/src/internal/column.ts +22 -0
- package/src/internal/derived-table.ts +29 -3
- package/src/internal/dialect.ts +14 -1
- package/src/internal/dsl-mutation-runtime.ts +173 -4
- package/src/internal/dsl-plan-runtime.ts +165 -20
- package/src/internal/dsl-query-runtime.ts +60 -6
- package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
- package/src/internal/executor.ts +62 -13
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +141 -1
- package/src/internal/implication-runtime.ts +2 -1
- package/src/internal/json/types.ts +155 -40
- package/src/internal/predicate/analysis.ts +103 -1
- package/src/internal/predicate/atom.ts +7 -0
- package/src/internal/predicate/context.ts +170 -17
- package/src/internal/predicate/key.ts +64 -2
- package/src/internal/predicate/normalize.ts +115 -34
- package/src/internal/predicate/runtime.ts +144 -13
- package/src/internal/query.ts +563 -103
- package/src/internal/renderer.ts +39 -2
- package/src/internal/runtime/driver-value-mapping.ts +244 -0
- package/src/internal/runtime/normalize.ts +62 -38
- package/src/internal/runtime/schema.ts +5 -3
- package/src/internal/runtime/value.ts +153 -30
- package/src/internal/scalar.ts +11 -0
- package/src/internal/table-options.ts +108 -1
- package/src/internal/table.ts +87 -29
- package/src/mysql/column.ts +19 -2
- package/src/mysql/datatypes/index.ts +21 -0
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +20 -5
- package/src/mysql/internal/dialect.ts +12 -6
- package/src/mysql/internal/dsl.ts +995 -263
- package/src/mysql/internal/renderer.ts +13 -3
- package/src/mysql/internal/sql-expression-renderer.ts +530 -128
- package/src/mysql/query.ts +9 -2
- package/src/mysql/renderer.ts +7 -2
- package/src/mysql/table.ts +38 -12
- package/src/postgres/cast.ts +22 -7
- package/src/postgres/column.ts +5 -2
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +68 -10
- package/src/postgres/function/core.ts +19 -1
- package/src/postgres/internal/dialect.ts +12 -6
- package/src/postgres/internal/dsl.ts +958 -288
- package/src/postgres/internal/renderer.ts +13 -3
- package/src/postgres/internal/schema-ddl.ts +2 -1
- package/src/postgres/internal/schema-model.ts +6 -3
- package/src/postgres/internal/sql-expression-renderer.ts +477 -96
- package/src/postgres/json.ts +57 -17
- package/src/postgres/query.ts +9 -2
- package/src/postgres/renderer.ts +7 -2
- package/src/postgres/schema-management.ts +91 -4
- package/src/postgres/schema.ts +1 -1
- package/src/postgres/table.ts +189 -53
- package/src/postgres/type.ts +4 -0
- package/src/sqlite/column.ts +128 -0
- package/src/sqlite/datatypes/index.ts +79 -0
- package/src/sqlite/datatypes/spec.ts +98 -0
- package/src/sqlite/errors/catalog.ts +103 -0
- package/src/sqlite/errors/fields.ts +19 -0
- package/src/sqlite/errors/index.ts +19 -0
- package/src/sqlite/errors/normalize.ts +229 -0
- package/src/sqlite/errors/requirements.ts +71 -0
- package/src/sqlite/errors/types.ts +29 -0
- package/src/sqlite/executor.ts +227 -0
- package/src/sqlite/function/aggregate.ts +2 -0
- package/src/sqlite/function/core.ts +2 -0
- package/src/sqlite/function/index.ts +19 -0
- package/src/sqlite/function/string.ts +2 -0
- package/src/sqlite/function/temporal.ts +100 -0
- package/src/sqlite/function/window.ts +2 -0
- package/src/sqlite/internal/dialect.ts +37 -0
- package/src/sqlite/internal/dsl.ts +6926 -0
- package/src/sqlite/internal/renderer.ts +47 -0
- package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
- package/src/sqlite/json.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +24 -0
- package/src/sqlite/table.ts +183 -0
- package/src/sqlite.ts +22 -0
|
@@ -74,6 +74,7 @@ var makeColumnDefinition = (schema, metadata) => {
|
|
|
74
74
|
runtime: undefined,
|
|
75
75
|
dbType: metadata.dbType,
|
|
76
76
|
runtimeSchema: schema,
|
|
77
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
77
78
|
nullability: metadata.nullable ? "maybe" : "never",
|
|
78
79
|
dialect: metadata.dbType.dialect,
|
|
79
80
|
kind: "scalar",
|
|
@@ -93,6 +94,7 @@ var makeColumnDefinition = (schema, metadata) => {
|
|
|
93
94
|
defaultValue: metadata.defaultValue,
|
|
94
95
|
generatedValue: metadata.generatedValue,
|
|
95
96
|
ddlType: metadata.ddlType,
|
|
97
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
96
98
|
identity: metadata.identity,
|
|
97
99
|
enum: metadata.enum
|
|
98
100
|
};
|
|
@@ -109,6 +111,7 @@ var remapColumnDefinition = (column, options = {}) => {
|
|
|
109
111
|
runtime: undefined,
|
|
110
112
|
dbType: metadata.dbType,
|
|
111
113
|
runtimeSchema: schema,
|
|
114
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
112
115
|
nullability: metadata.nullable ? "maybe" : "never",
|
|
113
116
|
dialect: metadata.dbType.dialect
|
|
114
117
|
};
|
|
@@ -127,6 +130,7 @@ var remapColumnDefinition = (column, options = {}) => {
|
|
|
127
130
|
defaultValue: metadata.defaultValue,
|
|
128
131
|
generatedValue: metadata.generatedValue,
|
|
129
132
|
ddlType: metadata.ddlType,
|
|
133
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
130
134
|
identity: metadata.identity,
|
|
131
135
|
enum: metadata.enum
|
|
132
136
|
};
|
|
@@ -148,6 +152,7 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
|
|
|
148
152
|
runtime: undefined,
|
|
149
153
|
dbType: column.metadata.dbType,
|
|
150
154
|
runtimeSchema: schema,
|
|
155
|
+
driverValueMapping: column.metadata.driverValueMapping,
|
|
151
156
|
nullability: column.metadata.nullable ? "maybe" : "never",
|
|
152
157
|
dialect: column.metadata.dbType.dialect,
|
|
153
158
|
kind: "scalar",
|
|
@@ -171,6 +176,27 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
|
|
|
171
176
|
};
|
|
172
177
|
|
|
173
178
|
// src/internal/table-options.ts
|
|
179
|
+
var referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault";
|
|
180
|
+
var renderReferentialAction = (action) => {
|
|
181
|
+
switch (action) {
|
|
182
|
+
case "noAction":
|
|
183
|
+
return "no action";
|
|
184
|
+
case "restrict":
|
|
185
|
+
return "restrict";
|
|
186
|
+
case "cascade":
|
|
187
|
+
return "cascade";
|
|
188
|
+
case "setNull":
|
|
189
|
+
return "set null";
|
|
190
|
+
case "setDefault":
|
|
191
|
+
return "set default";
|
|
192
|
+
}
|
|
193
|
+
throw new Error(referentialActionError);
|
|
194
|
+
};
|
|
195
|
+
var validateReferentialAction = (action) => {
|
|
196
|
+
if (action !== undefined) {
|
|
197
|
+
renderReferentialAction(action);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
174
200
|
var normalizeColumnList = (columns) => {
|
|
175
201
|
const normalized = Array.isArray(columns) ? [...columns] : [columns];
|
|
176
202
|
if (normalized.length === 0) {
|
|
@@ -198,6 +224,8 @@ var collectInlineOptions = (fields) => {
|
|
|
198
224
|
});
|
|
199
225
|
}
|
|
200
226
|
if (column.metadata.references) {
|
|
227
|
+
validateReferentialAction(column.metadata.references.onUpdate);
|
|
228
|
+
validateReferentialAction(column.metadata.references.onDelete);
|
|
201
229
|
const local = [columnName];
|
|
202
230
|
options.push({
|
|
203
231
|
kind: "foreignKey",
|
|
@@ -274,6 +302,8 @@ var validateOptions = (tableName, fields, options) => {
|
|
|
274
302
|
}
|
|
275
303
|
}
|
|
276
304
|
if (option.kind === "foreignKey") {
|
|
305
|
+
validateReferentialAction(option.onUpdate);
|
|
306
|
+
validateReferentialAction(option.onDelete);
|
|
277
307
|
const reference = option.references();
|
|
278
308
|
if (reference.columns.length !== columns.length) {
|
|
279
309
|
throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
|
|
@@ -298,7 +328,7 @@ var validateOptions = (tableName, fields, options) => {
|
|
|
298
328
|
throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
|
|
299
329
|
}
|
|
300
330
|
}
|
|
301
|
-
if (
|
|
331
|
+
if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
|
|
302
332
|
throw new Error(`Index on table '${tableName}' requires at least one column or key`);
|
|
303
333
|
}
|
|
304
334
|
}
|
|
@@ -512,10 +542,13 @@ function make2(name, fields, schemaName) {
|
|
|
512
542
|
const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
|
|
513
543
|
return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
|
|
514
544
|
}
|
|
515
|
-
var schema = (schemaName) =>
|
|
516
|
-
schemaName,
|
|
517
|
-
|
|
518
|
-
|
|
545
|
+
var schema = (schemaName) => {
|
|
546
|
+
const table = (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2);
|
|
547
|
+
return {
|
|
548
|
+
schemaName,
|
|
549
|
+
table
|
|
550
|
+
};
|
|
551
|
+
};
|
|
519
552
|
var alias = (table, aliasName) => {
|
|
520
553
|
const state = table[TypeId4];
|
|
521
554
|
const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
|
|
@@ -691,6 +724,9 @@ var normalize = (expression) => (() => {
|
|
|
691
724
|
}
|
|
692
725
|
})();
|
|
693
726
|
|
|
727
|
+
// src/postgres/internal/sql-expression-renderer.ts
|
|
728
|
+
import * as Schema5 from "effect/Schema";
|
|
729
|
+
|
|
694
730
|
// src/internal/query.ts
|
|
695
731
|
import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
|
|
696
732
|
|
|
@@ -711,6 +747,7 @@ var emptyContext = () => ({
|
|
|
711
747
|
nullKeys: new Set,
|
|
712
748
|
eqLiterals: new Map,
|
|
713
749
|
neqLiterals: new Map,
|
|
750
|
+
literalSets: new Map,
|
|
714
751
|
sourceNames: new Set,
|
|
715
752
|
contradiction: false,
|
|
716
753
|
unknown: false
|
|
@@ -720,12 +757,24 @@ var cloneContext = (context) => ({
|
|
|
720
757
|
nullKeys: new Set(context.nullKeys),
|
|
721
758
|
eqLiterals: new Map(context.eqLiterals),
|
|
722
759
|
neqLiterals: new Map(Array.from(context.neqLiterals.entries(), ([key, values]) => [key, new Set(values)])),
|
|
760
|
+
literalSets: new Map(Array.from(context.literalSets.entries(), ([key, values]) => [key, new Set(values)])),
|
|
723
761
|
sourceNames: new Set(context.sourceNames),
|
|
724
762
|
contradiction: context.contradiction,
|
|
725
763
|
unknown: context.unknown
|
|
726
764
|
});
|
|
727
765
|
var freezeContext = (context) => context;
|
|
728
|
-
var
|
|
766
|
+
var columnPredicateKey = (tableName, columnName) => JSON.stringify([tableName, columnName]);
|
|
767
|
+
var columnPredicateKeyParts = (key) => {
|
|
768
|
+
const jsonSeparator = key.indexOf("#json:");
|
|
769
|
+
const columnKey = jsonSeparator === -1 ? key : key.slice(0, jsonSeparator);
|
|
770
|
+
try {
|
|
771
|
+
const parsed = JSON.parse(columnKey);
|
|
772
|
+
return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : undefined;
|
|
773
|
+
} catch {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
var sourceNameOfKey = (key) => columnPredicateKeyParts(key)?.[0] ?? key.split(".", 1)[0] ?? key;
|
|
729
778
|
var addSourceName = (context, key) => {
|
|
730
779
|
context.sourceNames.add(sourceNameOfKey(key));
|
|
731
780
|
};
|
|
@@ -753,7 +802,12 @@ var addEqLiteral = (context, key, value) => {
|
|
|
753
802
|
if (neqValues?.has(value)) {
|
|
754
803
|
context.contradiction = true;
|
|
755
804
|
}
|
|
805
|
+
const existingSet = context.literalSets.get(key);
|
|
806
|
+
if (existingSet !== undefined && !existingSet.has(value)) {
|
|
807
|
+
context.contradiction = true;
|
|
808
|
+
}
|
|
756
809
|
context.eqLiterals.set(key, value);
|
|
810
|
+
context.literalSets.set(key, new Set([value]));
|
|
757
811
|
};
|
|
758
812
|
var addNeqLiteral = (context, key, value) => {
|
|
759
813
|
addNonNull(context, key);
|
|
@@ -764,6 +818,18 @@ var addNeqLiteral = (context, key, value) => {
|
|
|
764
818
|
values.add(value);
|
|
765
819
|
context.neqLiterals.set(key, values);
|
|
766
820
|
};
|
|
821
|
+
var addLiteralSet = (context, key, values) => {
|
|
822
|
+
addNonNull(context, key);
|
|
823
|
+
const existingEq = context.eqLiterals.get(key);
|
|
824
|
+
if (existingEq !== undefined && !values.has(existingEq)) {
|
|
825
|
+
context.contradiction = true;
|
|
826
|
+
}
|
|
827
|
+
const existing = context.literalSets.get(key);
|
|
828
|
+
context.literalSets.set(key, existing === undefined ? new Set(values) : new Set(Array.from(existing).filter((value) => values.has(value))));
|
|
829
|
+
if (context.literalSets.get(key)?.size === 0) {
|
|
830
|
+
context.contradiction = true;
|
|
831
|
+
}
|
|
832
|
+
};
|
|
767
833
|
var applyEqColumn = (context, left, right) => {
|
|
768
834
|
const leftValue = context.eqLiterals.get(left);
|
|
769
835
|
const rightValue = context.eqLiterals.get(right);
|
|
@@ -803,6 +869,9 @@ var applyAtom = (context, atom) => {
|
|
|
803
869
|
case "neq-literal":
|
|
804
870
|
addNeqLiteral(context, atom.key, atom.value);
|
|
805
871
|
return;
|
|
872
|
+
case "literal-set":
|
|
873
|
+
addLiteralSet(context, atom.key, new Set(atom.values));
|
|
874
|
+
return;
|
|
806
875
|
case "eq-column":
|
|
807
876
|
applyEqColumn(context, atom.left, atom.right);
|
|
808
877
|
return;
|
|
@@ -825,6 +894,9 @@ var applyNegativeAtom = (context, atom) => {
|
|
|
825
894
|
case "neq-literal":
|
|
826
895
|
addEqLiteral(context, atom.key, atom.value);
|
|
827
896
|
return;
|
|
897
|
+
case "literal-set":
|
|
898
|
+
addNonNull(context, atom.key);
|
|
899
|
+
return;
|
|
828
900
|
case "eq-column":
|
|
829
901
|
addNonNull(context, atom.left);
|
|
830
902
|
addNonNull(context, atom.right);
|
|
@@ -857,6 +929,17 @@ var intersectNeqLiterals = (left, right) => {
|
|
|
857
929
|
}
|
|
858
930
|
return result;
|
|
859
931
|
};
|
|
932
|
+
var unionLiteralSets = (left, right) => {
|
|
933
|
+
const result = new Map;
|
|
934
|
+
for (const [key, leftValues] of left) {
|
|
935
|
+
const rightValues = right.get(key);
|
|
936
|
+
if (rightValues === undefined) {
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
result.set(key, new Set([...leftValues, ...rightValues]));
|
|
940
|
+
}
|
|
941
|
+
return result;
|
|
942
|
+
};
|
|
860
943
|
var intersectContexts = (left, right) => {
|
|
861
944
|
if (left.contradiction) {
|
|
862
945
|
return cloneContext(right);
|
|
@@ -869,6 +952,7 @@ var intersectContexts = (left, right) => {
|
|
|
869
952
|
nullKeys: new Set(Array.from(left.nullKeys).filter((key) => right.nullKeys.has(key))),
|
|
870
953
|
eqLiterals: intersectEqLiterals(left.eqLiterals, right.eqLiterals),
|
|
871
954
|
neqLiterals: intersectNeqLiterals(left.neqLiterals, right.neqLiterals),
|
|
955
|
+
literalSets: unionLiteralSets(left.literalSets, right.literalSets),
|
|
872
956
|
sourceNames: new Set(Array.from(left.sourceNames).filter((name) => right.sourceNames.has(name))),
|
|
873
957
|
contradiction: false,
|
|
874
958
|
unknown: left.unknown || right.unknown
|
|
@@ -940,7 +1024,47 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
|
|
|
940
1024
|
var astOf = (value) => value[TypeId3];
|
|
941
1025
|
var columnKeyOfExpression = (value) => {
|
|
942
1026
|
const ast = astOf(value);
|
|
943
|
-
return ast.kind === "column" ?
|
|
1027
|
+
return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
|
|
1028
|
+
};
|
|
1029
|
+
var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
|
|
1030
|
+
var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
|
|
1031
|
+
var jsonPathPredicateKeyOfExpression = (value) => {
|
|
1032
|
+
const ast = astOf(value);
|
|
1033
|
+
switch (ast.kind) {
|
|
1034
|
+
case "jsonGetText":
|
|
1035
|
+
case "jsonPathText":
|
|
1036
|
+
case "jsonAccessText":
|
|
1037
|
+
case "jsonTraverseText": {
|
|
1038
|
+
const jsonAst = ast;
|
|
1039
|
+
const segments = jsonAst.segments;
|
|
1040
|
+
if (segments.length === 0 || segments.length > 8) {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const path = [];
|
|
1044
|
+
for (const segment of segments) {
|
|
1045
|
+
if (typeof segment !== "object" || segment === null || segment.kind !== "key") {
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
path.push(segment.key);
|
|
1049
|
+
}
|
|
1050
|
+
if (path.length === 0) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
const baseKey = columnKeyOfExpression(jsonAst.base);
|
|
1054
|
+
return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
|
|
1055
|
+
}
|
|
1056
|
+
default:
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
var predicateKeyOfExpression = (value) => columnKeyOfExpression(value) ?? castPredicateKeyOfExpression(value) ?? jsonPathPredicateKeyOfExpression(value);
|
|
1061
|
+
var castPredicateKeyOfExpression = (value) => {
|
|
1062
|
+
const ast = astOf(value);
|
|
1063
|
+
if (ast.kind !== "cast") {
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
const source = ast.value;
|
|
1067
|
+
return sameDbType(source[TypeId2].dbType, ast.target) ? predicateKeyOfExpression(source) : undefined;
|
|
944
1068
|
};
|
|
945
1069
|
var valueKeyOfLiteral = (value) => {
|
|
946
1070
|
if (typeof value === "string") {
|
|
@@ -961,7 +1085,7 @@ var valueKeyOfLiteral = (value) => {
|
|
|
961
1085
|
return "unknown";
|
|
962
1086
|
};
|
|
963
1087
|
var nonNullFactsOfExpression = (value) => {
|
|
964
|
-
const key =
|
|
1088
|
+
const key = predicateKeyOfExpression(value);
|
|
965
1089
|
return key === undefined ? undefined : atomFormula({ kind: "is-not-null", key });
|
|
966
1090
|
};
|
|
967
1091
|
var combineFacts = (left, right) => {
|
|
@@ -974,8 +1098,8 @@ var combineFacts = (left, right) => {
|
|
|
974
1098
|
return andFormula(left, right);
|
|
975
1099
|
};
|
|
976
1100
|
var formulaOfEq = (left, right) => {
|
|
977
|
-
const leftKey =
|
|
978
|
-
const rightKey =
|
|
1101
|
+
const leftKey = predicateKeyOfExpression(left);
|
|
1102
|
+
const rightKey = predicateKeyOfExpression(right);
|
|
979
1103
|
const leftAst = astOf(left);
|
|
980
1104
|
const rightAst = astOf(right);
|
|
981
1105
|
const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
|
|
@@ -1022,8 +1146,8 @@ var formulaOfEq = (left, right) => {
|
|
|
1022
1146
|
});
|
|
1023
1147
|
};
|
|
1024
1148
|
var formulaOfNeq = (left, right) => {
|
|
1025
|
-
const leftKey =
|
|
1026
|
-
const rightKey =
|
|
1149
|
+
const leftKey = predicateKeyOfExpression(left);
|
|
1150
|
+
const rightKey = predicateKeyOfExpression(right);
|
|
1027
1151
|
const leftAst = astOf(left);
|
|
1028
1152
|
const rightAst = astOf(right);
|
|
1029
1153
|
const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
|
|
@@ -1066,8 +1190,8 @@ var formulaOfNeq = (left, right) => {
|
|
|
1066
1190
|
return combineFacts(nonNullFactsOfExpression(left), nonNullFactsOfExpression(right));
|
|
1067
1191
|
};
|
|
1068
1192
|
var formulaOfIsNotDistinctFrom = (left, right) => {
|
|
1069
|
-
const leftKey =
|
|
1070
|
-
const rightKey =
|
|
1193
|
+
const leftKey = predicateKeyOfExpression(left);
|
|
1194
|
+
const rightKey = predicateKeyOfExpression(right);
|
|
1071
1195
|
const leftAst = astOf(left);
|
|
1072
1196
|
const rightAst = astOf(right);
|
|
1073
1197
|
const leftLiteral = leftAst.kind === "literal" ? leftAst.value : undefined;
|
|
@@ -1173,11 +1297,11 @@ var formulaOfExpression = (value) => {
|
|
|
1173
1297
|
}
|
|
1174
1298
|
return unknownTag("literal:non-boolean");
|
|
1175
1299
|
case "isNull": {
|
|
1176
|
-
const key =
|
|
1300
|
+
const key = predicateKeyOfExpression(ast.value);
|
|
1177
1301
|
return key === undefined ? unknownTag("isNull:unsupported") : atomFormula({ kind: "is-null", key });
|
|
1178
1302
|
}
|
|
1179
1303
|
case "isNotNull": {
|
|
1180
|
-
const key =
|
|
1304
|
+
const key = predicateKeyOfExpression(ast.value);
|
|
1181
1305
|
return key === undefined ? unknownTag("isNotNull:unsupported") : atomFormula({ kind: "is-not-null", key });
|
|
1182
1306
|
}
|
|
1183
1307
|
case "not":
|
|
@@ -1196,7 +1320,15 @@ var formulaOfExpression = (value) => {
|
|
|
1196
1320
|
return anyFormula(ast.values.map((value2) => formulaOfExpression(value2)));
|
|
1197
1321
|
case "in": {
|
|
1198
1322
|
const [left, ...rest] = ast.values;
|
|
1199
|
-
|
|
1323
|
+
if (left === undefined) {
|
|
1324
|
+
return falseFormula();
|
|
1325
|
+
}
|
|
1326
|
+
const key = predicateKeyOfExpression(left);
|
|
1327
|
+
const literalValues = rest.map((entry) => {
|
|
1328
|
+
const entryAst = astOf(entry);
|
|
1329
|
+
return entryAst.kind === "literal" && entryAst.value !== null ? valueKeyOfLiteral(entryAst.value) : undefined;
|
|
1330
|
+
});
|
|
1331
|
+
return key !== undefined && literalValues.every((entry) => entry !== undefined) ? atomFormula({ kind: "literal-set", key, values: literalValues }) : anyFormula(rest.map((value2) => formulaOfEq(left, value2)));
|
|
1200
1332
|
}
|
|
1201
1333
|
case "notIn": {
|
|
1202
1334
|
const [left, ...rest] = ast.values;
|
|
@@ -1264,6 +1396,7 @@ var makeExpression = (state, ast) => {
|
|
|
1264
1396
|
runtime: state.runtime,
|
|
1265
1397
|
dbType: state.dbType,
|
|
1266
1398
|
runtimeSchema: state.runtimeSchema,
|
|
1399
|
+
driverValueMapping: state.driverValueMapping,
|
|
1267
1400
|
nullability: state.nullability,
|
|
1268
1401
|
dialect: state.dialect,
|
|
1269
1402
|
kind: state.kind ?? "scalar",
|
|
@@ -1272,7 +1405,7 @@ var makeExpression = (state, ast) => {
|
|
|
1272
1405
|
expression[TypeId3] = ast;
|
|
1273
1406
|
return expression;
|
|
1274
1407
|
};
|
|
1275
|
-
var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState) => {
|
|
1408
|
+
var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _insertState, _facts) => {
|
|
1276
1409
|
const plan = Object.create(PlanProto);
|
|
1277
1410
|
Object.defineProperty(plan, "pipe", {
|
|
1278
1411
|
configurable: true,
|
|
@@ -1288,89 +1421,1845 @@ var makePlan = (state, ast, _assumptions, _capabilities, _statement, _target, _i
|
|
|
1288
1421
|
availableNames: undefined,
|
|
1289
1422
|
grouped: undefined,
|
|
1290
1423
|
assumptions: _assumptions ?? trueFormula(),
|
|
1424
|
+
facts: _facts ?? undefined,
|
|
1291
1425
|
capabilities: undefined,
|
|
1292
1426
|
statement: _statement ?? "select",
|
|
1293
1427
|
target: _target ?? undefined,
|
|
1294
1428
|
insertSource: _insertState ?? "ready"
|
|
1295
1429
|
};
|
|
1296
|
-
return plan;
|
|
1430
|
+
return plan;
|
|
1431
|
+
};
|
|
1432
|
+
var getAst = (plan) => plan[TypeId6];
|
|
1433
|
+
var getQueryState = (plan) => plan[QueryTypeId];
|
|
1434
|
+
var extractRequiredRuntime = (selection) => {
|
|
1435
|
+
const required = new Set;
|
|
1436
|
+
const visit = (value) => {
|
|
1437
|
+
if (TypeId2 in value) {
|
|
1438
|
+
for (const tableName of Object.keys(value[TypeId2].dependencies)) {
|
|
1439
|
+
required.add(tableName);
|
|
1440
|
+
}
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
for (const nested of Object.values(value)) {
|
|
1444
|
+
visit(nested);
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
visit(selection);
|
|
1448
|
+
return [...required];
|
|
1449
|
+
};
|
|
1450
|
+
var extractSingleSelectedExpressionRuntime = (selection) => {
|
|
1451
|
+
const keys = Object.keys(selection);
|
|
1452
|
+
if (keys.length !== 1) {
|
|
1453
|
+
throw new Error("scalar subqueries must select exactly one top-level expression");
|
|
1454
|
+
}
|
|
1455
|
+
const record = selection;
|
|
1456
|
+
const value = record[keys[0]];
|
|
1457
|
+
if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
|
|
1458
|
+
throw new Error("scalar subqueries must select a scalar expression");
|
|
1459
|
+
}
|
|
1460
|
+
return value;
|
|
1461
|
+
};
|
|
1462
|
+
var currentRequiredList = (required) => Array.isArray(required) ? [...required] : required === undefined ? [] : [required];
|
|
1463
|
+
|
|
1464
|
+
// src/internal/json/path.ts
|
|
1465
|
+
var SegmentTypeId = Symbol.for("effect-qb/JsonPathSegment");
|
|
1466
|
+
var TypeId7 = Symbol.for("effect-qb/JsonPath");
|
|
1467
|
+
var makeSegment = (segment) => segment;
|
|
1468
|
+
var key = (value) => makeSegment({
|
|
1469
|
+
[SegmentTypeId]: {
|
|
1470
|
+
kind: "key"
|
|
1471
|
+
},
|
|
1472
|
+
kind: "key",
|
|
1473
|
+
key: value
|
|
1474
|
+
});
|
|
1475
|
+
var index2 = (value) => makeSegment({
|
|
1476
|
+
[SegmentTypeId]: {
|
|
1477
|
+
kind: "index"
|
|
1478
|
+
},
|
|
1479
|
+
kind: "index",
|
|
1480
|
+
index: value
|
|
1481
|
+
});
|
|
1482
|
+
var wildcard = () => makeSegment({
|
|
1483
|
+
[SegmentTypeId]: {
|
|
1484
|
+
kind: "wildcard"
|
|
1485
|
+
},
|
|
1486
|
+
kind: "wildcard"
|
|
1487
|
+
});
|
|
1488
|
+
var slice = (start, end) => makeSegment({
|
|
1489
|
+
[SegmentTypeId]: {
|
|
1490
|
+
kind: "slice"
|
|
1491
|
+
},
|
|
1492
|
+
kind: "slice",
|
|
1493
|
+
start,
|
|
1494
|
+
end
|
|
1495
|
+
});
|
|
1496
|
+
var descend = () => makeSegment({
|
|
1497
|
+
[SegmentTypeId]: {
|
|
1498
|
+
kind: "descend"
|
|
1499
|
+
},
|
|
1500
|
+
kind: "descend"
|
|
1501
|
+
});
|
|
1502
|
+
var path = (...segments) => ({
|
|
1503
|
+
[TypeId7]: {
|
|
1504
|
+
segments
|
|
1505
|
+
},
|
|
1506
|
+
segments
|
|
1507
|
+
});
|
|
1508
|
+
|
|
1509
|
+
// src/internal/dsl-plan-runtime.ts
|
|
1510
|
+
var renderSelectLockMode = (mode) => {
|
|
1511
|
+
switch (mode) {
|
|
1512
|
+
case "update":
|
|
1513
|
+
return "for update";
|
|
1514
|
+
case "share":
|
|
1515
|
+
return "for share";
|
|
1516
|
+
}
|
|
1517
|
+
throw new Error("lock(...) mode must be update or share for select statements");
|
|
1518
|
+
};
|
|
1519
|
+
var renderMysqlMutationLockMode = (mode, statement) => {
|
|
1520
|
+
switch (mode) {
|
|
1521
|
+
case "lowPriority":
|
|
1522
|
+
return " low_priority";
|
|
1523
|
+
case "ignore":
|
|
1524
|
+
return " ignore";
|
|
1525
|
+
case "quick":
|
|
1526
|
+
if (statement === "delete") {
|
|
1527
|
+
return " quick";
|
|
1528
|
+
}
|
|
1529
|
+
break;
|
|
1530
|
+
}
|
|
1531
|
+
throw new Error(statement === "update" ? "lock(...) mode must be lowPriority or ignore for update statements" : "lock(...) mode must be lowPriority, quick, or ignore for delete statements");
|
|
1532
|
+
};
|
|
1533
|
+
var makeDslPlanRuntime = (ctx) => {
|
|
1534
|
+
const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
|
|
1535
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
1536
|
+
const isPlan = (value) => isRecord(value) && (TypeId in value);
|
|
1537
|
+
const hasColumnRecord = (value) => isRecord(value.columns);
|
|
1538
|
+
const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
|
|
1539
|
+
const isAliasedSource = (source) => {
|
|
1540
|
+
if (!isRecord(source)) {
|
|
1541
|
+
return false;
|
|
1542
|
+
}
|
|
1543
|
+
if (TypeId4 in source) {
|
|
1544
|
+
return true;
|
|
1545
|
+
}
|
|
1546
|
+
if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1549
|
+
if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1552
|
+
if (typeof source.name !== "string" || typeof source.baseName !== "string") {
|
|
1553
|
+
return false;
|
|
1554
|
+
}
|
|
1555
|
+
switch (source.kind) {
|
|
1556
|
+
case "derived":
|
|
1557
|
+
case "cte":
|
|
1558
|
+
case "lateral":
|
|
1559
|
+
return isPlan(source.plan) && hasColumnRecord(source);
|
|
1560
|
+
case "values":
|
|
1561
|
+
return Array.isArray(source.rows) && hasColumnRecord(source);
|
|
1562
|
+
case "unnest":
|
|
1563
|
+
return isRecord(source.arrays) && hasColumnRecord(source);
|
|
1564
|
+
case "tableFunction":
|
|
1565
|
+
return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
|
|
1566
|
+
}
|
|
1567
|
+
return false;
|
|
1568
|
+
};
|
|
1569
|
+
const assertAliasedSource = (source, message) => {
|
|
1570
|
+
if (!isAliasedSource(source)) {
|
|
1571
|
+
throw new Error(message);
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
const assertPlanComplete = (plan) => {
|
|
1575
|
+
const required = ctx.currentRequiredList(plan[TypeId].required);
|
|
1576
|
+
if (required.length > 0) {
|
|
1577
|
+
throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
const assertSourceNameAvailable = (available, sourceName) => {
|
|
1581
|
+
if (sourceName in available) {
|
|
1582
|
+
throw new Error(`query source name is already in scope: ${sourceName}`);
|
|
1583
|
+
}
|
|
1584
|
+
};
|
|
1585
|
+
const assertSelectHasBaseSourceForJoin = (statement, available) => {
|
|
1586
|
+
if (statement === "select" && Object.keys(available).length === 0) {
|
|
1587
|
+
throw new Error("select joins require a from(...) source before joining");
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
|
|
1591
|
+
const assertSetOperandStatement = (plan) => {
|
|
1592
|
+
const statement = ctx.getQueryState(plan).statement;
|
|
1593
|
+
if (statement !== "select" && statement !== "set") {
|
|
1594
|
+
throw new Error("set operator operands only accept select-like query plans");
|
|
1595
|
+
}
|
|
1596
|
+
};
|
|
1597
|
+
const buildSetOperation = (kind, all, left, right) => {
|
|
1598
|
+
assertSetOperandStatement(left);
|
|
1599
|
+
assertSetOperandStatement(right);
|
|
1600
|
+
assertPlanComplete(left);
|
|
1601
|
+
assertPlanComplete(right);
|
|
1602
|
+
const leftState = left[TypeId];
|
|
1603
|
+
const leftAst = ctx.getAst(left);
|
|
1604
|
+
const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
|
|
1605
|
+
const leftOperations = leftAst.kind === "set" ? [...leftAst.setOperations ?? []] : [];
|
|
1606
|
+
return ctx.makePlan({
|
|
1607
|
+
selection: leftState.selection,
|
|
1608
|
+
required: undefined,
|
|
1609
|
+
available: {},
|
|
1610
|
+
dialect: leftState.dialect ?? right[TypeId].dialect
|
|
1611
|
+
}, {
|
|
1612
|
+
kind: "set",
|
|
1613
|
+
select: leftState.selection,
|
|
1614
|
+
where: [],
|
|
1615
|
+
having: [],
|
|
1616
|
+
joins: [],
|
|
1617
|
+
groupBy: [],
|
|
1618
|
+
orderBy: [],
|
|
1619
|
+
setBase: basePlan,
|
|
1620
|
+
setOperations: [
|
|
1621
|
+
...leftOperations,
|
|
1622
|
+
{
|
|
1623
|
+
kind,
|
|
1624
|
+
all,
|
|
1625
|
+
query: right
|
|
1626
|
+
}
|
|
1627
|
+
]
|
|
1628
|
+
}, undefined, undefined, "set");
|
|
1629
|
+
};
|
|
1630
|
+
const where = (predicate) => (plan) => {
|
|
1631
|
+
const current = plan[TypeId];
|
|
1632
|
+
const currentAst = ctx.getAst(plan);
|
|
1633
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1634
|
+
const predicateExpression = ctx.toDialectExpression(predicate);
|
|
1635
|
+
const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
|
|
1636
|
+
return ctx.makePlan({
|
|
1637
|
+
selection: current.selection,
|
|
1638
|
+
required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1639
|
+
available: current.available,
|
|
1640
|
+
dialect: current.dialect ?? predicateExpression[TypeId2].dialect
|
|
1641
|
+
}, {
|
|
1642
|
+
...currentAst,
|
|
1643
|
+
where: [...currentAst.where, {
|
|
1644
|
+
kind: "where",
|
|
1645
|
+
predicate: predicateExpression
|
|
1646
|
+
}]
|
|
1647
|
+
}, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
|
|
1648
|
+
};
|
|
1649
|
+
const from = (source) => (plan) => {
|
|
1650
|
+
const current = plan[TypeId];
|
|
1651
|
+
const currentAst = ctx.getAst(plan);
|
|
1652
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1653
|
+
if (currentQuery.statement === "insert") {
|
|
1654
|
+
return ctx.attachInsertSource(plan, source);
|
|
1655
|
+
}
|
|
1656
|
+
assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
|
|
1657
|
+
if (currentQuery.statement === "select" && currentAst.from !== undefined) {
|
|
1658
|
+
throw new Error("select statements accept only one from(...) source; use joins for additional sources");
|
|
1659
|
+
}
|
|
1660
|
+
const sourceLike = source;
|
|
1661
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
|
|
1662
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
|
|
1663
|
+
const sourceRequired = sourceRequiredList(sourceLike);
|
|
1664
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1665
|
+
if (currentQuery.statement === "select") {
|
|
1666
|
+
const nextAvailable = {
|
|
1667
|
+
[sourceName]: {
|
|
1668
|
+
name: sourceName,
|
|
1669
|
+
mode: "required",
|
|
1670
|
+
baseName: sourceBaseName,
|
|
1671
|
+
_presentFormula: ctx.trueFormula(),
|
|
1672
|
+
_presenceWitnesses: presenceWitnesses
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
return ctx.makePlan({
|
|
1676
|
+
selection: current.selection,
|
|
1677
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1678
|
+
available: nextAvailable,
|
|
1679
|
+
dialect: current.dialect
|
|
1680
|
+
}, {
|
|
1681
|
+
...currentAst,
|
|
1682
|
+
from: {
|
|
1683
|
+
kind: "from",
|
|
1684
|
+
tableName: sourceName,
|
|
1685
|
+
baseTableName: sourceBaseName,
|
|
1686
|
+
source: sourceLike
|
|
1687
|
+
}
|
|
1688
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1689
|
+
}
|
|
1690
|
+
if (currentQuery.statement === "update") {
|
|
1691
|
+
const nextAvailable = {
|
|
1692
|
+
...current.available,
|
|
1693
|
+
[sourceName]: {
|
|
1694
|
+
name: sourceName,
|
|
1695
|
+
mode: "required",
|
|
1696
|
+
baseName: sourceBaseName,
|
|
1697
|
+
_presentFormula: ctx.trueFormula(),
|
|
1698
|
+
_presenceWitnesses: presenceWitnesses
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
return ctx.makePlan({
|
|
1702
|
+
selection: current.selection,
|
|
1703
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1704
|
+
available: nextAvailable,
|
|
1705
|
+
dialect: current.dialect
|
|
1706
|
+
}, {
|
|
1707
|
+
...currentAst,
|
|
1708
|
+
fromSources: [
|
|
1709
|
+
...currentAst.fromSources ?? [],
|
|
1710
|
+
{
|
|
1711
|
+
kind: "from",
|
|
1712
|
+
tableName: sourceName,
|
|
1713
|
+
baseTableName: sourceBaseName,
|
|
1714
|
+
source: sourceLike
|
|
1715
|
+
}
|
|
1716
|
+
]
|
|
1717
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1718
|
+
}
|
|
1719
|
+
throw new Error(`from(...) is not supported for ${currentQuery.statement} statements`);
|
|
1720
|
+
};
|
|
1721
|
+
const having = (predicate) => (plan) => {
|
|
1722
|
+
const current = plan[TypeId];
|
|
1723
|
+
const currentAst = ctx.getAst(plan);
|
|
1724
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1725
|
+
const predicateExpression = ctx.toDialectExpression(predicate);
|
|
1726
|
+
const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
|
|
1727
|
+
return ctx.makePlan({
|
|
1728
|
+
selection: current.selection,
|
|
1729
|
+
required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1730
|
+
available: current.available,
|
|
1731
|
+
dialect: current.dialect ?? predicateExpression[TypeId2].dialect
|
|
1732
|
+
}, {
|
|
1733
|
+
...currentAst,
|
|
1734
|
+
having: [...currentAst.having, {
|
|
1735
|
+
kind: "having",
|
|
1736
|
+
predicate: predicateExpression
|
|
1737
|
+
}]
|
|
1738
|
+
}, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
|
|
1739
|
+
};
|
|
1740
|
+
const crossJoin = (table) => (plan) => {
|
|
1741
|
+
const current = plan[TypeId];
|
|
1742
|
+
const currentAst = ctx.getAst(plan);
|
|
1743
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1744
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1745
|
+
assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
|
|
1746
|
+
assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
|
|
1747
|
+
}
|
|
1748
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
|
|
1749
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
|
|
1750
|
+
const sourceRequired = sourceRequiredList(table);
|
|
1751
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1752
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1753
|
+
}
|
|
1754
|
+
const nextAvailable = {
|
|
1755
|
+
...current.available,
|
|
1756
|
+
[sourceName]: {
|
|
1757
|
+
name: sourceName,
|
|
1758
|
+
mode: "required",
|
|
1759
|
+
baseName: sourceBaseName,
|
|
1760
|
+
_presentFormula: ctx.trueFormula(),
|
|
1761
|
+
_presenceWitnesses: presenceWitnesses
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
return ctx.makePlan({
|
|
1765
|
+
selection: current.selection,
|
|
1766
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1767
|
+
available: nextAvailable,
|
|
1768
|
+
dialect: current.dialect ?? table[TypeId]?.dialect ?? table.dialect
|
|
1769
|
+
}, {
|
|
1770
|
+
...currentAst,
|
|
1771
|
+
joins: [...currentAst.joins, {
|
|
1772
|
+
kind: "cross",
|
|
1773
|
+
tableName: sourceName,
|
|
1774
|
+
baseTableName: sourceBaseName,
|
|
1775
|
+
source: table
|
|
1776
|
+
}]
|
|
1777
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1778
|
+
};
|
|
1779
|
+
const join = (kind, table, on) => (plan) => {
|
|
1780
|
+
const current = plan[TypeId];
|
|
1781
|
+
const currentAst = ctx.getAst(plan);
|
|
1782
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1783
|
+
const onExpression = ctx.toDialectExpression(on);
|
|
1784
|
+
const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
|
|
1785
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1786
|
+
assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
|
|
1787
|
+
assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
|
|
1788
|
+
}
|
|
1789
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
|
|
1790
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
|
|
1791
|
+
const sourceRequired = sourceRequiredList(table);
|
|
1792
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1793
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1794
|
+
}
|
|
1795
|
+
const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
|
|
1796
|
+
name: source.name,
|
|
1797
|
+
mode: "optional",
|
|
1798
|
+
baseName: source.baseName,
|
|
1799
|
+
_presentFormula: source._presentFormula,
|
|
1800
|
+
_presenceWitnesses: source._presenceWitnesses
|
|
1801
|
+
}])) : current.available;
|
|
1802
|
+
const nextAvailable = {
|
|
1803
|
+
...baseAvailable,
|
|
1804
|
+
[sourceName]: {
|
|
1805
|
+
name: sourceName,
|
|
1806
|
+
mode: kind === "left" || kind === "full" ? "optional" : "required",
|
|
1807
|
+
baseName: sourceBaseName,
|
|
1808
|
+
_presentFormula: kind === "inner" || kind === "left" ? onFormula : ctx.trueFormula(),
|
|
1809
|
+
_presenceWitnesses: presenceWitnesses
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
return ctx.makePlan({
|
|
1813
|
+
selection: current.selection,
|
|
1814
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1815
|
+
available: nextAvailable,
|
|
1816
|
+
dialect: current.dialect ?? table.dialect ?? onExpression[TypeId2].dialect
|
|
1817
|
+
}, {
|
|
1818
|
+
...currentAst,
|
|
1819
|
+
joins: [...currentAst.joins, {
|
|
1820
|
+
kind,
|
|
1821
|
+
tableName: sourceName,
|
|
1822
|
+
baseTableName: sourceBaseName,
|
|
1823
|
+
source: table,
|
|
1824
|
+
on: onExpression
|
|
1825
|
+
}]
|
|
1826
|
+
}, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1827
|
+
};
|
|
1828
|
+
const orderBy = (value, direction = "asc") => (plan) => {
|
|
1829
|
+
if (direction !== "asc" && direction !== "desc") {
|
|
1830
|
+
throw new Error("orderBy(...) direction must be asc or desc");
|
|
1831
|
+
}
|
|
1832
|
+
const current = plan[TypeId];
|
|
1833
|
+
const currentAst = ctx.getAst(plan);
|
|
1834
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1835
|
+
const expression = ctx.toDialectExpression(value);
|
|
1836
|
+
const required = ctx.extractRequiredFromDialectInputRuntime(value);
|
|
1837
|
+
return ctx.makePlan({
|
|
1838
|
+
selection: current.selection,
|
|
1839
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1840
|
+
available: current.available,
|
|
1841
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1842
|
+
}, {
|
|
1843
|
+
...currentAst,
|
|
1844
|
+
orderBy: [...currentAst.orderBy, {
|
|
1845
|
+
kind: "orderBy",
|
|
1846
|
+
value: expression,
|
|
1847
|
+
direction
|
|
1848
|
+
}]
|
|
1849
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1850
|
+
};
|
|
1851
|
+
const lock = (mode, options2 = {}) => (plan) => {
|
|
1852
|
+
const current = plan[TypeId];
|
|
1853
|
+
const currentAst = ctx.getAst(plan);
|
|
1854
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1855
|
+
if (currentQuery.statement === "select") {
|
|
1856
|
+
renderSelectLockMode(mode);
|
|
1857
|
+
}
|
|
1858
|
+
if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
|
|
1859
|
+
renderMysqlMutationLockMode(mode, "update");
|
|
1860
|
+
}
|
|
1861
|
+
if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
|
|
1862
|
+
renderMysqlMutationLockMode(mode, "delete");
|
|
1863
|
+
}
|
|
1864
|
+
return ctx.makePlan({
|
|
1865
|
+
selection: current.selection,
|
|
1866
|
+
required: current.required,
|
|
1867
|
+
available: current.available,
|
|
1868
|
+
dialect: current.dialect
|
|
1869
|
+
}, {
|
|
1870
|
+
...currentAst,
|
|
1871
|
+
lock: {
|
|
1872
|
+
kind: "lock",
|
|
1873
|
+
mode,
|
|
1874
|
+
nowait: options2.nowait ?? false,
|
|
1875
|
+
skipLocked: options2.skipLocked ?? false
|
|
1876
|
+
}
|
|
1877
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1878
|
+
};
|
|
1879
|
+
const distinct = () => (plan) => {
|
|
1880
|
+
const current = plan[TypeId];
|
|
1881
|
+
const currentAst = ctx.getAst(plan);
|
|
1882
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1883
|
+
return ctx.makePlan({
|
|
1884
|
+
selection: current.selection,
|
|
1885
|
+
required: current.required,
|
|
1886
|
+
available: current.available,
|
|
1887
|
+
dialect: current.dialect
|
|
1888
|
+
}, {
|
|
1889
|
+
...currentAst,
|
|
1890
|
+
distinct: true
|
|
1891
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1892
|
+
};
|
|
1893
|
+
const limit = (value) => (plan) => {
|
|
1894
|
+
const current = plan[TypeId];
|
|
1895
|
+
const currentAst = ctx.getAst(plan);
|
|
1896
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1897
|
+
const expression = ctx.toDialectNumericExpression(value);
|
|
1898
|
+
const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
|
|
1899
|
+
return ctx.makePlan({
|
|
1900
|
+
selection: current.selection,
|
|
1901
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1902
|
+
available: current.available,
|
|
1903
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1904
|
+
}, {
|
|
1905
|
+
...currentAst,
|
|
1906
|
+
limit: expression
|
|
1907
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1908
|
+
};
|
|
1909
|
+
const offset = (value) => (plan) => {
|
|
1910
|
+
const current = plan[TypeId];
|
|
1911
|
+
const currentAst = ctx.getAst(plan);
|
|
1912
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1913
|
+
const expression = ctx.toDialectNumericExpression(value);
|
|
1914
|
+
const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
|
|
1915
|
+
return ctx.makePlan({
|
|
1916
|
+
selection: current.selection,
|
|
1917
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1918
|
+
available: current.available,
|
|
1919
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1920
|
+
}, {
|
|
1921
|
+
...currentAst,
|
|
1922
|
+
offset: expression
|
|
1923
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1924
|
+
};
|
|
1925
|
+
return {
|
|
1926
|
+
buildSetOperation,
|
|
1927
|
+
where,
|
|
1928
|
+
from,
|
|
1929
|
+
having,
|
|
1930
|
+
crossJoin,
|
|
1931
|
+
join,
|
|
1932
|
+
orderBy,
|
|
1933
|
+
lock,
|
|
1934
|
+
distinct,
|
|
1935
|
+
limit,
|
|
1936
|
+
offset
|
|
1937
|
+
};
|
|
1938
|
+
};
|
|
1939
|
+
|
|
1940
|
+
// src/internal/dsl-mutation-runtime.ts
|
|
1941
|
+
var expectInsertSourceKind = (source) => {
|
|
1942
|
+
if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
|
|
1943
|
+
throw new Error("Unsupported insert source kind");
|
|
1944
|
+
}
|
|
1945
|
+
return source;
|
|
1946
|
+
};
|
|
1947
|
+
var expectConflictClause = (conflict) => {
|
|
1948
|
+
if (conflict === undefined) {
|
|
1949
|
+
return conflict;
|
|
1950
|
+
}
|
|
1951
|
+
if (conflict.kind !== "conflict") {
|
|
1952
|
+
throw new Error("Unsupported conflict clause kind");
|
|
1953
|
+
}
|
|
1954
|
+
if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
|
|
1955
|
+
throw new Error("Unsupported conflict action");
|
|
1956
|
+
}
|
|
1957
|
+
if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
|
|
1958
|
+
throw new Error("Unsupported conflict target kind");
|
|
1959
|
+
}
|
|
1960
|
+
return conflict;
|
|
1961
|
+
};
|
|
1962
|
+
var makeDslMutationRuntime = (ctx) => {
|
|
1963
|
+
const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
|
|
1964
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
1965
|
+
const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId in target);
|
|
1966
|
+
const hasColumnRecord = (value) => isRecord(value.columns);
|
|
1967
|
+
const isAliasedSource = (source) => {
|
|
1968
|
+
if (!isRecord(source)) {
|
|
1969
|
+
return false;
|
|
1970
|
+
}
|
|
1971
|
+
if (isTableTarget(source)) {
|
|
1972
|
+
return true;
|
|
1973
|
+
}
|
|
1974
|
+
if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
|
|
1975
|
+
return false;
|
|
1976
|
+
}
|
|
1977
|
+
if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
|
|
1978
|
+
return false;
|
|
1979
|
+
}
|
|
1980
|
+
if (typeof source.name !== "string" || typeof source.baseName !== "string") {
|
|
1981
|
+
return false;
|
|
1982
|
+
}
|
|
1983
|
+
switch (source.kind) {
|
|
1984
|
+
case "derived":
|
|
1985
|
+
case "cte":
|
|
1986
|
+
case "lateral":
|
|
1987
|
+
return isRecord(source.plan) && TypeId in source.plan && hasColumnRecord(source);
|
|
1988
|
+
case "values":
|
|
1989
|
+
return Array.isArray(source.rows) && hasColumnRecord(source);
|
|
1990
|
+
case "unnest":
|
|
1991
|
+
return isRecord(source.arrays) && hasColumnRecord(source);
|
|
1992
|
+
case "tableFunction":
|
|
1993
|
+
return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
|
|
1994
|
+
}
|
|
1995
|
+
return false;
|
|
1996
|
+
};
|
|
1997
|
+
const assertMutationTarget = (target, apiName) => {
|
|
1998
|
+
if (!isTableTarget(target)) {
|
|
1999
|
+
throw new Error(`${apiName}(...) requires table targets`);
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
const assertAliasedSource = (source, apiName) => {
|
|
2003
|
+
if (!isAliasedSource(source)) {
|
|
2004
|
+
throw new Error(`${apiName}(...) requires an aliased source`);
|
|
2005
|
+
}
|
|
2006
|
+
};
|
|
2007
|
+
const assertMutationTargets = (target, apiName, options2 = {}) => {
|
|
2008
|
+
const targets = Array.isArray(target) ? target : [target];
|
|
2009
|
+
if (targets.length === 0) {
|
|
2010
|
+
throw new Error(`${apiName}(...) requires at least one table target`);
|
|
2011
|
+
}
|
|
2012
|
+
if (Array.isArray(target) && targets.length === 1) {
|
|
2013
|
+
throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
|
|
2014
|
+
}
|
|
2015
|
+
for (const entry of targets) {
|
|
2016
|
+
assertMutationTarget(entry, apiName);
|
|
2017
|
+
}
|
|
2018
|
+
if (targets.length > 1 && options2.allowMultiple !== true) {
|
|
2019
|
+
throw new Error(`${apiName}(...) requires a single table target`);
|
|
2020
|
+
}
|
|
2021
|
+
if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
|
|
2022
|
+
throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
const assertUniqueTargetNames = (targets) => {
|
|
2026
|
+
const seen = new Set;
|
|
2027
|
+
for (const target of targets) {
|
|
2028
|
+
if (seen.has(target.tableName)) {
|
|
2029
|
+
throw new Error(`mutation target source names must be unique: ${target.tableName}`);
|
|
2030
|
+
}
|
|
2031
|
+
seen.add(target.tableName);
|
|
2032
|
+
}
|
|
2033
|
+
};
|
|
2034
|
+
const assertInsertSelectSource = (sourcePlan, selection) => {
|
|
2035
|
+
const statement = ctx.getQueryState(sourcePlan).statement;
|
|
2036
|
+
if (statement !== "select" && statement !== "set") {
|
|
2037
|
+
throw new Error("insert sources only accept select-like query plans");
|
|
2038
|
+
}
|
|
2039
|
+
for (const value of Object.values(selection)) {
|
|
2040
|
+
if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
|
|
2041
|
+
throw new Error("insert sources require a flat selection object");
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
};
|
|
2045
|
+
const insert = (target, values) => {
|
|
2046
|
+
assertMutationTargets(target, "insert");
|
|
2047
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2048
|
+
const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
|
|
2049
|
+
const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies));
|
|
2050
|
+
const insertState = values === undefined ? "missing" : "ready";
|
|
2051
|
+
return ctx.makePlan({
|
|
2052
|
+
selection: {},
|
|
2053
|
+
required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
|
|
2054
|
+
available: {
|
|
2055
|
+
[sourceName]: {
|
|
2056
|
+
name: sourceName,
|
|
2057
|
+
mode: "required",
|
|
2058
|
+
baseName: sourceBaseName
|
|
2059
|
+
}
|
|
2060
|
+
},
|
|
2061
|
+
dialect: target[TypeId].dialect
|
|
2062
|
+
}, {
|
|
2063
|
+
kind: "insert",
|
|
2064
|
+
select: {},
|
|
2065
|
+
into: {
|
|
2066
|
+
kind: "from",
|
|
2067
|
+
tableName: sourceName,
|
|
2068
|
+
baseTableName: sourceBaseName,
|
|
2069
|
+
source: target
|
|
2070
|
+
},
|
|
2071
|
+
values: assignments,
|
|
2072
|
+
conflict: undefined,
|
|
2073
|
+
where: [],
|
|
2074
|
+
having: [],
|
|
2075
|
+
joins: [],
|
|
2076
|
+
groupBy: [],
|
|
2077
|
+
orderBy: []
|
|
2078
|
+
}, undefined, "write", "insert", target, insertState);
|
|
2079
|
+
};
|
|
2080
|
+
const attachInsertSource = (plan, source) => {
|
|
2081
|
+
const current = plan[TypeId];
|
|
2082
|
+
const currentAst = ctx.getAst(plan);
|
|
2083
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
2084
|
+
const target = currentQuery.target;
|
|
2085
|
+
const sourceName = currentAst.into.tableName;
|
|
2086
|
+
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "values") {
|
|
2087
|
+
const normalized = ctx.buildInsertValuesRows(target, source.rows);
|
|
2088
|
+
return ctx.makePlan({
|
|
2089
|
+
selection: current.selection,
|
|
2090
|
+
required: normalized.required.filter((name) => name !== sourceName),
|
|
2091
|
+
available: current.available,
|
|
2092
|
+
dialect: current.dialect
|
|
2093
|
+
}, {
|
|
2094
|
+
...currentAst,
|
|
2095
|
+
values: [],
|
|
2096
|
+
insertSource: {
|
|
2097
|
+
kind: "values",
|
|
2098
|
+
columns: normalized.columns,
|
|
2099
|
+
rows: normalized.rows
|
|
2100
|
+
}
|
|
2101
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2102
|
+
}
|
|
2103
|
+
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "unnest") {
|
|
2104
|
+
const normalized = ctx.normalizeInsertUnnestValues(target, source.values);
|
|
2105
|
+
return ctx.makePlan({
|
|
2106
|
+
selection: current.selection,
|
|
2107
|
+
required: [],
|
|
2108
|
+
available: current.available,
|
|
2109
|
+
dialect: current.dialect
|
|
2110
|
+
}, {
|
|
2111
|
+
...currentAst,
|
|
2112
|
+
values: [],
|
|
2113
|
+
insertSource: {
|
|
2114
|
+
kind: "unnest",
|
|
2115
|
+
columns: normalized.columns,
|
|
2116
|
+
values: normalized.values
|
|
2117
|
+
}
|
|
2118
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2119
|
+
}
|
|
2120
|
+
const sourcePlan = source;
|
|
2121
|
+
const selection = sourcePlan[TypeId].selection;
|
|
2122
|
+
assertInsertSelectSource(sourcePlan, selection);
|
|
2123
|
+
const columns = ctx.normalizeInsertSelectColumns(selection);
|
|
2124
|
+
return ctx.makePlan({
|
|
2125
|
+
selection: current.selection,
|
|
2126
|
+
required: ctx.currentRequiredList(sourcePlan[TypeId].required),
|
|
2127
|
+
available: current.available,
|
|
2128
|
+
dialect: current.dialect
|
|
2129
|
+
}, {
|
|
2130
|
+
...currentAst,
|
|
2131
|
+
values: [],
|
|
2132
|
+
insertSource: {
|
|
2133
|
+
kind: "query",
|
|
2134
|
+
columns,
|
|
2135
|
+
query: sourcePlan
|
|
2136
|
+
}
|
|
2137
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2138
|
+
};
|
|
2139
|
+
const onConflict = (target, options2 = {}) => (plan) => {
|
|
2140
|
+
const current = plan[TypeId];
|
|
2141
|
+
const currentAst = ctx.getAst(plan);
|
|
2142
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
2143
|
+
if (currentQuery.statement !== "insert") {
|
|
2144
|
+
throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
|
|
2145
|
+
}
|
|
2146
|
+
const insertTarget = currentAst.into.source;
|
|
2147
|
+
const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
|
|
2148
|
+
const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
|
|
2149
|
+
if (options2.update !== undefined && updateAssignments.length === 0) {
|
|
2150
|
+
throw new Error("conflict update assignments require at least one assignment");
|
|
2151
|
+
}
|
|
2152
|
+
const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
|
|
2153
|
+
const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
|
|
2154
|
+
const required = [
|
|
2155
|
+
...ctx.currentRequiredList(current.required),
|
|
2156
|
+
...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2157
|
+
...updateWhere ? Object.keys(updateWhere[TypeId2].dependencies) : [],
|
|
2158
|
+
...targetWhere ? Object.keys(targetWhere[TypeId2].dependencies) : []
|
|
2159
|
+
].filter((name, index3, list) => !(name in current.available) && list.indexOf(name) === index3);
|
|
2160
|
+
return ctx.makePlan({
|
|
2161
|
+
selection: current.selection,
|
|
2162
|
+
required,
|
|
2163
|
+
available: current.available,
|
|
2164
|
+
dialect: current.dialect
|
|
2165
|
+
}, {
|
|
2166
|
+
...currentAst,
|
|
2167
|
+
conflict: {
|
|
2168
|
+
kind: "conflict",
|
|
2169
|
+
target: conflictTarget,
|
|
2170
|
+
action: updateAssignments.length === 0 ? "doNothing" : "doUpdate",
|
|
2171
|
+
values: updateAssignments.length === 0 ? undefined : updateAssignments,
|
|
2172
|
+
where: updateWhere
|
|
2173
|
+
}
|
|
2174
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
|
|
2175
|
+
};
|
|
2176
|
+
const update = (target, values) => {
|
|
2177
|
+
assertMutationTargets(target, "update", { allowMultiple: true });
|
|
2178
|
+
const targets = ctx.mutationTargetClauses(target);
|
|
2179
|
+
assertUniqueTargetNames(targets);
|
|
2180
|
+
const primaryTarget = targets[0];
|
|
2181
|
+
const assignments = ctx.buildMutationAssignments(target, values);
|
|
2182
|
+
const targetNames = new Set(targets.map((entry) => entry.tableName));
|
|
2183
|
+
const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)).filter((name, index3, list) => !targetNames.has(name) && list.indexOf(name) === index3);
|
|
2184
|
+
return ctx.makePlan({
|
|
2185
|
+
selection: {},
|
|
2186
|
+
required,
|
|
2187
|
+
available: ctx.mutationAvailableSources(target),
|
|
2188
|
+
dialect: primaryTarget.source[TypeId].dialect
|
|
2189
|
+
}, {
|
|
2190
|
+
kind: "update",
|
|
2191
|
+
select: {},
|
|
2192
|
+
target: primaryTarget,
|
|
2193
|
+
targets,
|
|
2194
|
+
set: assignments,
|
|
2195
|
+
where: [],
|
|
2196
|
+
having: [],
|
|
2197
|
+
joins: [],
|
|
2198
|
+
groupBy: [],
|
|
2199
|
+
orderBy: []
|
|
2200
|
+
}, undefined, "write", "update");
|
|
2201
|
+
};
|
|
2202
|
+
const upsert = (target, values, conflictColumns, updateValues) => {
|
|
2203
|
+
assertMutationTargets(target, "upsert");
|
|
2204
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2205
|
+
const assignments = ctx.buildMutationAssignments(target, values);
|
|
2206
|
+
const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
|
|
2207
|
+
if (updateValues !== undefined && updateAssignments.length === 0) {
|
|
2208
|
+
throw new Error("upsert update assignments require at least one assignment");
|
|
2209
|
+
}
|
|
2210
|
+
const required = [
|
|
2211
|
+
...assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2212
|
+
...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies))
|
|
2213
|
+
];
|
|
2214
|
+
return ctx.makePlan({
|
|
2215
|
+
selection: {},
|
|
2216
|
+
required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
|
|
2217
|
+
available: {
|
|
2218
|
+
[sourceName]: {
|
|
2219
|
+
name: sourceName,
|
|
2220
|
+
mode: "required",
|
|
2221
|
+
baseName: sourceBaseName
|
|
2222
|
+
}
|
|
2223
|
+
},
|
|
2224
|
+
dialect: target[TypeId].dialect
|
|
2225
|
+
}, {
|
|
2226
|
+
kind: "insert",
|
|
2227
|
+
select: {},
|
|
2228
|
+
into: {
|
|
2229
|
+
kind: "from",
|
|
2230
|
+
tableName: sourceName,
|
|
2231
|
+
baseTableName: sourceBaseName,
|
|
2232
|
+
source: target
|
|
2233
|
+
},
|
|
2234
|
+
values: assignments,
|
|
2235
|
+
conflict: {
|
|
2236
|
+
kind: "conflict",
|
|
2237
|
+
target: {
|
|
2238
|
+
kind: "columns",
|
|
2239
|
+
columns: ctx.normalizeConflictColumns(target, conflictColumns)
|
|
2240
|
+
},
|
|
2241
|
+
action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
|
|
2242
|
+
values: updateAssignments.length > 0 ? updateAssignments : undefined
|
|
2243
|
+
},
|
|
2244
|
+
where: [],
|
|
2245
|
+
having: [],
|
|
2246
|
+
joins: [],
|
|
2247
|
+
groupBy: [],
|
|
2248
|
+
orderBy: []
|
|
2249
|
+
}, undefined, "write", "insert", target, "ready");
|
|
2250
|
+
};
|
|
2251
|
+
const delete_ = (target) => {
|
|
2252
|
+
assertMutationTargets(target, "delete", { allowMultiple: true });
|
|
2253
|
+
const targets = ctx.mutationTargetClauses(target);
|
|
2254
|
+
assertUniqueTargetNames(targets);
|
|
2255
|
+
const primaryTarget = targets[0];
|
|
2256
|
+
return ctx.makePlan({
|
|
2257
|
+
selection: {},
|
|
2258
|
+
required: [],
|
|
2259
|
+
available: ctx.mutationAvailableSources(target),
|
|
2260
|
+
dialect: primaryTarget.source[TypeId].dialect
|
|
2261
|
+
}, {
|
|
2262
|
+
kind: "delete",
|
|
2263
|
+
select: {},
|
|
2264
|
+
target: primaryTarget,
|
|
2265
|
+
targets,
|
|
2266
|
+
where: [],
|
|
2267
|
+
having: [],
|
|
2268
|
+
joins: [],
|
|
2269
|
+
groupBy: [],
|
|
2270
|
+
orderBy: []
|
|
2271
|
+
}, undefined, "write", "delete");
|
|
2272
|
+
};
|
|
2273
|
+
const truncate = (target, options2 = {}) => {
|
|
2274
|
+
assertMutationTargets(target, "truncate");
|
|
2275
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2276
|
+
return ctx.makePlan({
|
|
2277
|
+
selection: {},
|
|
2278
|
+
required: [],
|
|
2279
|
+
available: {},
|
|
2280
|
+
dialect: target[TypeId].dialect
|
|
2281
|
+
}, {
|
|
2282
|
+
kind: "truncate",
|
|
2283
|
+
select: {},
|
|
2284
|
+
target: {
|
|
2285
|
+
kind: "from",
|
|
2286
|
+
tableName: sourceName,
|
|
2287
|
+
baseTableName: sourceBaseName,
|
|
2288
|
+
source: target
|
|
2289
|
+
},
|
|
2290
|
+
truncate: {
|
|
2291
|
+
kind: "truncate",
|
|
2292
|
+
restartIdentity: options2.restartIdentity ?? false,
|
|
2293
|
+
cascade: options2.cascade ?? false
|
|
2294
|
+
},
|
|
2295
|
+
where: [],
|
|
2296
|
+
having: [],
|
|
2297
|
+
joins: [],
|
|
2298
|
+
groupBy: [],
|
|
2299
|
+
orderBy: []
|
|
2300
|
+
}, undefined, "write", "truncate");
|
|
2301
|
+
};
|
|
2302
|
+
const merge = (target, source, on, options2 = {}) => {
|
|
2303
|
+
assertMutationTargets(target, "merge");
|
|
2304
|
+
assertAliasedSource(source, "merge");
|
|
2305
|
+
const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
|
|
2306
|
+
const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
|
|
2307
|
+
if (targetName === usingName) {
|
|
2308
|
+
throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
|
|
2309
|
+
}
|
|
2310
|
+
const onExpression = ctx.toDialectExpression(on);
|
|
2311
|
+
const matched = options2.whenMatched;
|
|
2312
|
+
const notMatched = options2.whenNotMatched;
|
|
2313
|
+
if (matched && "delete" in matched && "update" in matched) {
|
|
2314
|
+
throw new Error("merge whenMatched cannot specify both update and delete");
|
|
2315
|
+
}
|
|
2316
|
+
const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined;
|
|
2317
|
+
const matchedAssignments = matched && "update" in matched && matched.update ? ctx.buildMutationAssignments(target, matched.update) : [];
|
|
2318
|
+
const notMatchedPredicate = notMatched?.predicate ? ctx.toDialectExpression(notMatched.predicate) : undefined;
|
|
2319
|
+
const notMatchedAssignments = notMatched ? ctx.buildMutationAssignments(target, notMatched.values) : [];
|
|
2320
|
+
const required = [
|
|
2321
|
+
...Object.keys(onExpression[TypeId2].dependencies),
|
|
2322
|
+
...matchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2323
|
+
...notMatchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2324
|
+
...matchedPredicate ? Object.keys(matchedPredicate[TypeId2].dependencies) : [],
|
|
2325
|
+
...notMatchedPredicate ? Object.keys(notMatchedPredicate[TypeId2].dependencies) : []
|
|
2326
|
+
].filter((name, index3, values) => name !== targetName && name !== usingName && values.indexOf(name) === index3);
|
|
2327
|
+
return ctx.makePlan({
|
|
2328
|
+
selection: {},
|
|
2329
|
+
required,
|
|
2330
|
+
available: {
|
|
2331
|
+
[targetName]: {
|
|
2332
|
+
name: targetName,
|
|
2333
|
+
mode: "required",
|
|
2334
|
+
baseName: targetBaseName
|
|
2335
|
+
},
|
|
2336
|
+
[usingName]: {
|
|
2337
|
+
name: usingName,
|
|
2338
|
+
mode: "required",
|
|
2339
|
+
baseName: usingBaseName
|
|
2340
|
+
}
|
|
2341
|
+
},
|
|
2342
|
+
dialect: target[TypeId].dialect
|
|
2343
|
+
}, {
|
|
2344
|
+
kind: "merge",
|
|
2345
|
+
select: {},
|
|
2346
|
+
target: {
|
|
2347
|
+
kind: "from",
|
|
2348
|
+
tableName: targetName,
|
|
2349
|
+
baseTableName: targetBaseName,
|
|
2350
|
+
source: target
|
|
2351
|
+
},
|
|
2352
|
+
using: {
|
|
2353
|
+
kind: "from",
|
|
2354
|
+
tableName: usingName,
|
|
2355
|
+
baseTableName: usingBaseName,
|
|
2356
|
+
source
|
|
2357
|
+
},
|
|
2358
|
+
merge: {
|
|
2359
|
+
kind: "merge",
|
|
2360
|
+
on: onExpression,
|
|
2361
|
+
whenMatched: matched ? "delete" in matched && matched.delete ? {
|
|
2362
|
+
kind: "delete",
|
|
2363
|
+
predicate: matchedPredicate
|
|
2364
|
+
} : {
|
|
2365
|
+
kind: "update",
|
|
2366
|
+
values: matchedAssignments,
|
|
2367
|
+
predicate: matchedPredicate
|
|
2368
|
+
} : undefined,
|
|
2369
|
+
whenNotMatched: notMatched ? {
|
|
2370
|
+
kind: "insert",
|
|
2371
|
+
values: notMatchedAssignments,
|
|
2372
|
+
predicate: notMatchedPredicate
|
|
2373
|
+
} : undefined
|
|
2374
|
+
},
|
|
2375
|
+
where: [],
|
|
2376
|
+
having: [],
|
|
2377
|
+
joins: [],
|
|
2378
|
+
groupBy: [],
|
|
2379
|
+
orderBy: []
|
|
2380
|
+
}, undefined, "write", "merge");
|
|
2381
|
+
};
|
|
2382
|
+
return {
|
|
2383
|
+
insert,
|
|
2384
|
+
attachInsertSource,
|
|
2385
|
+
onConflict,
|
|
2386
|
+
update,
|
|
2387
|
+
upsert,
|
|
2388
|
+
delete_,
|
|
2389
|
+
truncate,
|
|
2390
|
+
merge
|
|
2391
|
+
};
|
|
2392
|
+
};
|
|
2393
|
+
|
|
2394
|
+
// src/internal/dsl-transaction-ddl-runtime.ts
|
|
2395
|
+
var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
|
|
2396
|
+
var renderTransactionIsolationLevel = (isolationLevel) => {
|
|
2397
|
+
if (isolationLevel === undefined) {
|
|
2398
|
+
return "";
|
|
2399
|
+
}
|
|
2400
|
+
if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
|
|
2401
|
+
throw new Error("Unsupported transaction isolation level");
|
|
2402
|
+
}
|
|
2403
|
+
return `isolation level ${isolationLevel}`;
|
|
2404
|
+
};
|
|
2405
|
+
var expectDdlClauseKind = (ddl, kind) => {
|
|
2406
|
+
if (ddl === undefined || ddl.kind !== kind) {
|
|
2407
|
+
throw new Error("Unsupported DDL statement kind");
|
|
2408
|
+
}
|
|
2409
|
+
return ddl;
|
|
2410
|
+
};
|
|
2411
|
+
var expectTruncateClause = (truncate) => {
|
|
2412
|
+
if (truncate === undefined || truncate.kind !== "truncate") {
|
|
2413
|
+
throw new Error("Unsupported truncate statement kind");
|
|
2414
|
+
}
|
|
2415
|
+
return truncate;
|
|
2416
|
+
};
|
|
2417
|
+
var validateIsolationLevel = (isolationLevel) => {
|
|
2418
|
+
renderTransactionIsolationLevel(isolationLevel);
|
|
2419
|
+
};
|
|
2420
|
+
var makeDslTransactionDdlRuntime = (ctx) => {
|
|
2421
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
2422
|
+
const assertTableTarget = (target, apiName) => {
|
|
2423
|
+
if (!isRecord(target) || !(TypeId4 in target) || !(TypeId in target)) {
|
|
2424
|
+
throw new Error(`${apiName}(...) requires a table target`);
|
|
2425
|
+
}
|
|
2426
|
+
};
|
|
2427
|
+
const validateIndexColumns = (target, columns) => {
|
|
2428
|
+
const fields = target[TypeId4]?.fields;
|
|
2429
|
+
if (fields === undefined) {
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
for (const columnName of columns) {
|
|
2433
|
+
if (!(columnName in fields)) {
|
|
2434
|
+
throw new Error(`effect-qb: unknown index column '${columnName}'`);
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
};
|
|
2438
|
+
const transaction = (options2 = {}) => {
|
|
2439
|
+
validateIsolationLevel(options2.isolationLevel);
|
|
2440
|
+
return ctx.makePlan({
|
|
2441
|
+
selection: {},
|
|
2442
|
+
required: [],
|
|
2443
|
+
available: {},
|
|
2444
|
+
dialect: ctx.profile.dialect
|
|
2445
|
+
}, {
|
|
2446
|
+
kind: "transaction",
|
|
2447
|
+
select: {},
|
|
2448
|
+
transaction: {
|
|
2449
|
+
kind: "transaction",
|
|
2450
|
+
isolationLevel: options2.isolationLevel,
|
|
2451
|
+
readOnly: options2.readOnly
|
|
2452
|
+
},
|
|
2453
|
+
where: [],
|
|
2454
|
+
having: [],
|
|
2455
|
+
joins: [],
|
|
2456
|
+
groupBy: [],
|
|
2457
|
+
orderBy: []
|
|
2458
|
+
}, undefined, "transaction", "transaction");
|
|
2459
|
+
};
|
|
2460
|
+
const commit = () => ctx.makePlan({
|
|
2461
|
+
selection: {},
|
|
2462
|
+
required: [],
|
|
2463
|
+
available: {},
|
|
2464
|
+
dialect: ctx.profile.dialect
|
|
2465
|
+
}, {
|
|
2466
|
+
kind: "commit",
|
|
2467
|
+
select: {},
|
|
2468
|
+
transaction: {
|
|
2469
|
+
kind: "commit"
|
|
2470
|
+
},
|
|
2471
|
+
where: [],
|
|
2472
|
+
having: [],
|
|
2473
|
+
joins: [],
|
|
2474
|
+
groupBy: [],
|
|
2475
|
+
orderBy: []
|
|
2476
|
+
}, undefined, "transaction", "commit");
|
|
2477
|
+
const rollback = () => ctx.makePlan({
|
|
2478
|
+
selection: {},
|
|
2479
|
+
required: [],
|
|
2480
|
+
available: {},
|
|
2481
|
+
dialect: ctx.profile.dialect
|
|
2482
|
+
}, {
|
|
2483
|
+
kind: "rollback",
|
|
2484
|
+
select: {},
|
|
2485
|
+
transaction: {
|
|
2486
|
+
kind: "rollback"
|
|
2487
|
+
},
|
|
2488
|
+
where: [],
|
|
2489
|
+
having: [],
|
|
2490
|
+
joins: [],
|
|
2491
|
+
groupBy: [],
|
|
2492
|
+
orderBy: []
|
|
2493
|
+
}, undefined, "transaction", "rollback");
|
|
2494
|
+
const savepoint = (name) => ctx.makePlan({
|
|
2495
|
+
selection: {},
|
|
2496
|
+
required: [],
|
|
2497
|
+
available: {},
|
|
2498
|
+
dialect: ctx.profile.dialect
|
|
2499
|
+
}, {
|
|
2500
|
+
kind: "savepoint",
|
|
2501
|
+
select: {},
|
|
2502
|
+
transaction: {
|
|
2503
|
+
kind: "savepoint",
|
|
2504
|
+
name
|
|
2505
|
+
},
|
|
2506
|
+
where: [],
|
|
2507
|
+
having: [],
|
|
2508
|
+
joins: [],
|
|
2509
|
+
groupBy: [],
|
|
2510
|
+
orderBy: []
|
|
2511
|
+
}, undefined, "transaction", "savepoint");
|
|
2512
|
+
const rollbackTo = (name) => ctx.makePlan({
|
|
2513
|
+
selection: {},
|
|
2514
|
+
required: [],
|
|
2515
|
+
available: {},
|
|
2516
|
+
dialect: ctx.profile.dialect
|
|
2517
|
+
}, {
|
|
2518
|
+
kind: "rollbackTo",
|
|
2519
|
+
select: {},
|
|
2520
|
+
transaction: {
|
|
2521
|
+
kind: "rollbackTo",
|
|
2522
|
+
name
|
|
2523
|
+
},
|
|
2524
|
+
where: [],
|
|
2525
|
+
having: [],
|
|
2526
|
+
joins: [],
|
|
2527
|
+
groupBy: [],
|
|
2528
|
+
orderBy: []
|
|
2529
|
+
}, undefined, "transaction", "rollbackTo");
|
|
2530
|
+
const releaseSavepoint = (name) => ctx.makePlan({
|
|
2531
|
+
selection: {},
|
|
2532
|
+
required: [],
|
|
2533
|
+
available: {},
|
|
2534
|
+
dialect: ctx.profile.dialect
|
|
2535
|
+
}, {
|
|
2536
|
+
kind: "releaseSavepoint",
|
|
2537
|
+
select: {},
|
|
2538
|
+
transaction: {
|
|
2539
|
+
kind: "releaseSavepoint",
|
|
2540
|
+
name
|
|
2541
|
+
},
|
|
2542
|
+
where: [],
|
|
2543
|
+
having: [],
|
|
2544
|
+
joins: [],
|
|
2545
|
+
groupBy: [],
|
|
2546
|
+
orderBy: []
|
|
2547
|
+
}, undefined, "transaction", "releaseSavepoint");
|
|
2548
|
+
const createTable = (target, options2 = {}) => {
|
|
2549
|
+
assertTableTarget(target, "createTable");
|
|
2550
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2551
|
+
return ctx.makePlan({
|
|
2552
|
+
selection: {},
|
|
2553
|
+
required: [],
|
|
2554
|
+
available: {},
|
|
2555
|
+
dialect: target[TypeId].dialect
|
|
2556
|
+
}, {
|
|
2557
|
+
kind: "createTable",
|
|
2558
|
+
select: {},
|
|
2559
|
+
target: {
|
|
2560
|
+
kind: "from",
|
|
2561
|
+
tableName: sourceName,
|
|
2562
|
+
baseTableName: sourceBaseName,
|
|
2563
|
+
source: target
|
|
2564
|
+
},
|
|
2565
|
+
ddl: {
|
|
2566
|
+
kind: "createTable",
|
|
2567
|
+
ifNotExists: options2.ifNotExists ?? false
|
|
2568
|
+
},
|
|
2569
|
+
where: [],
|
|
2570
|
+
having: [],
|
|
2571
|
+
joins: [],
|
|
2572
|
+
groupBy: [],
|
|
2573
|
+
orderBy: []
|
|
2574
|
+
}, undefined, "ddl", "createTable");
|
|
2575
|
+
};
|
|
2576
|
+
const dropTable = (target, options2 = {}) => {
|
|
2577
|
+
assertTableTarget(target, "dropTable");
|
|
2578
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2579
|
+
return ctx.makePlan({
|
|
2580
|
+
selection: {},
|
|
2581
|
+
required: [],
|
|
2582
|
+
available: {},
|
|
2583
|
+
dialect: target[TypeId].dialect
|
|
2584
|
+
}, {
|
|
2585
|
+
kind: "dropTable",
|
|
2586
|
+
select: {},
|
|
2587
|
+
target: {
|
|
2588
|
+
kind: "from",
|
|
2589
|
+
tableName: sourceName,
|
|
2590
|
+
baseTableName: sourceBaseName,
|
|
2591
|
+
source: target
|
|
2592
|
+
},
|
|
2593
|
+
ddl: {
|
|
2594
|
+
kind: "dropTable",
|
|
2595
|
+
ifExists: options2.ifExists ?? false
|
|
2596
|
+
},
|
|
2597
|
+
where: [],
|
|
2598
|
+
having: [],
|
|
2599
|
+
joins: [],
|
|
2600
|
+
groupBy: [],
|
|
2601
|
+
orderBy: []
|
|
2602
|
+
}, undefined, "ddl", "dropTable");
|
|
2603
|
+
};
|
|
2604
|
+
const createIndex = (target, columns, options2 = {}) => {
|
|
2605
|
+
assertTableTarget(target, "createIndex");
|
|
2606
|
+
const normalizedColumns = ctx.normalizeColumnList(columns);
|
|
2607
|
+
validateIndexColumns(target, normalizedColumns);
|
|
2608
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2609
|
+
return ctx.makePlan({
|
|
2610
|
+
selection: {},
|
|
2611
|
+
required: [],
|
|
2612
|
+
available: {},
|
|
2613
|
+
dialect: target[TypeId].dialect
|
|
2614
|
+
}, {
|
|
2615
|
+
kind: "createIndex",
|
|
2616
|
+
select: {},
|
|
2617
|
+
target: {
|
|
2618
|
+
kind: "from",
|
|
2619
|
+
tableName: sourceName,
|
|
2620
|
+
baseTableName: sourceBaseName,
|
|
2621
|
+
source: target
|
|
2622
|
+
},
|
|
2623
|
+
ddl: {
|
|
2624
|
+
kind: "createIndex",
|
|
2625
|
+
name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options2.unique ?? false),
|
|
2626
|
+
columns: normalizedColumns,
|
|
2627
|
+
unique: options2.unique ?? false,
|
|
2628
|
+
ifNotExists: options2.ifNotExists ?? false
|
|
2629
|
+
},
|
|
2630
|
+
where: [],
|
|
2631
|
+
having: [],
|
|
2632
|
+
joins: [],
|
|
2633
|
+
groupBy: [],
|
|
2634
|
+
orderBy: []
|
|
2635
|
+
}, undefined, "ddl", "createIndex");
|
|
2636
|
+
};
|
|
2637
|
+
const dropIndex = (target, columns, options2 = {}) => {
|
|
2638
|
+
assertTableTarget(target, "dropIndex");
|
|
2639
|
+
const normalizedColumns = ctx.normalizeColumnList(columns);
|
|
2640
|
+
validateIndexColumns(target, normalizedColumns);
|
|
2641
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2642
|
+
return ctx.makePlan({
|
|
2643
|
+
selection: {},
|
|
2644
|
+
required: [],
|
|
2645
|
+
available: {},
|
|
2646
|
+
dialect: target[TypeId].dialect
|
|
2647
|
+
}, {
|
|
2648
|
+
kind: "dropIndex",
|
|
2649
|
+
select: {},
|
|
2650
|
+
target: {
|
|
2651
|
+
kind: "from",
|
|
2652
|
+
tableName: sourceName,
|
|
2653
|
+
baseTableName: sourceBaseName,
|
|
2654
|
+
source: target
|
|
2655
|
+
},
|
|
2656
|
+
ddl: {
|
|
2657
|
+
kind: "dropIndex",
|
|
2658
|
+
name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
|
|
2659
|
+
ifExists: options2.ifExists ?? false
|
|
2660
|
+
},
|
|
2661
|
+
where: [],
|
|
2662
|
+
having: [],
|
|
2663
|
+
joins: [],
|
|
2664
|
+
groupBy: [],
|
|
2665
|
+
orderBy: []
|
|
2666
|
+
}, undefined, "ddl", "dropIndex");
|
|
2667
|
+
};
|
|
2668
|
+
return {
|
|
2669
|
+
transaction,
|
|
2670
|
+
commit,
|
|
2671
|
+
rollback,
|
|
2672
|
+
savepoint,
|
|
2673
|
+
rollbackTo,
|
|
2674
|
+
releaseSavepoint,
|
|
2675
|
+
createTable,
|
|
2676
|
+
dropTable,
|
|
2677
|
+
createIndex,
|
|
2678
|
+
dropIndex
|
|
2679
|
+
};
|
|
2680
|
+
};
|
|
2681
|
+
|
|
2682
|
+
// src/internal/runtime/driver-value-mapping.ts
|
|
2683
|
+
import * as Schema4 from "effect/Schema";
|
|
2684
|
+
|
|
2685
|
+
// src/internal/runtime/value.ts
|
|
2686
|
+
import * as Schema3 from "effect/Schema";
|
|
2687
|
+
var brandString = (pattern2, brand4) => Schema3.String.pipe(Schema3.pattern(pattern2), Schema3.brand(brand4));
|
|
2688
|
+
var localDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
2689
|
+
var isValidLocalDateString = (value) => {
|
|
2690
|
+
const match = localDatePattern.exec(value);
|
|
2691
|
+
if (match === null) {
|
|
2692
|
+
return false;
|
|
2693
|
+
}
|
|
2694
|
+
const year = Number(match[1]);
|
|
2695
|
+
const month = Number(match[2]);
|
|
2696
|
+
const day = Number(match[3]);
|
|
2697
|
+
const parsed = new Date(Date.UTC(year, month - 1, day));
|
|
2698
|
+
parsed.setUTCFullYear(year);
|
|
2699
|
+
return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
|
|
2700
|
+
};
|
|
2701
|
+
var localTimePattern = /^(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
|
|
2702
|
+
var isValidLocalTimeString = (value) => {
|
|
2703
|
+
const match = localTimePattern.exec(value);
|
|
2704
|
+
if (match === null) {
|
|
2705
|
+
return false;
|
|
2706
|
+
}
|
|
2707
|
+
const hour = Number(match[1]);
|
|
2708
|
+
const minute = Number(match[2]);
|
|
2709
|
+
const second = Number(match[3]);
|
|
2710
|
+
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
|
|
2711
|
+
};
|
|
2712
|
+
var offsetPattern = /^(?:Z|[+-](\d{2}):(\d{2}))$/;
|
|
2713
|
+
var isValidOffset = (value) => {
|
|
2714
|
+
const match = offsetPattern.exec(value);
|
|
2715
|
+
if (match === null) {
|
|
2716
|
+
return false;
|
|
2717
|
+
}
|
|
2718
|
+
if (value === "Z") {
|
|
2719
|
+
return true;
|
|
2720
|
+
}
|
|
2721
|
+
const hour = Number(match[1]);
|
|
2722
|
+
const minute = Number(match[2]);
|
|
2723
|
+
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59;
|
|
2724
|
+
};
|
|
2725
|
+
var offsetTimePattern = /^(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
|
|
2726
|
+
var isValidOffsetTimeString = (value) => {
|
|
2727
|
+
const match = offsetTimePattern.exec(value);
|
|
2728
|
+
return match !== null && isValidLocalTimeString(match[1]) && isValidOffset(match[2]);
|
|
2729
|
+
};
|
|
2730
|
+
var localDateTimePattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
|
|
2731
|
+
var isValidLocalDateTimeString = (value) => {
|
|
2732
|
+
const match = localDateTimePattern.exec(value);
|
|
2733
|
+
return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]);
|
|
2734
|
+
};
|
|
2735
|
+
var instantPattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
|
|
2736
|
+
var isValidInstantString = (value) => {
|
|
2737
|
+
const match = instantPattern.exec(value);
|
|
2738
|
+
return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]) && isValidOffset(match[3]);
|
|
2739
|
+
};
|
|
2740
|
+
var LocalDateStringSchema = Schema3.String.pipe(Schema3.pattern(localDatePattern), Schema3.filter(isValidLocalDateString), Schema3.brand("LocalDateString"));
|
|
2741
|
+
var LocalTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localTimePattern), Schema3.filter(isValidLocalTimeString), Schema3.brand("LocalTimeString"));
|
|
2742
|
+
var OffsetTimeStringSchema = Schema3.String.pipe(Schema3.pattern(offsetTimePattern), Schema3.filter(isValidOffsetTimeString), Schema3.brand("OffsetTimeString"));
|
|
2743
|
+
var LocalDateTimeStringSchema = Schema3.String.pipe(Schema3.pattern(localDateTimePattern), Schema3.filter(isValidLocalDateTimeString), Schema3.brand("LocalDateTimeString"));
|
|
2744
|
+
var InstantStringSchema = Schema3.String.pipe(Schema3.pattern(instantPattern), Schema3.filter(isValidInstantString), Schema3.brand("InstantString"));
|
|
2745
|
+
var YearStringSchema = brandString(/^\d{4}$/, "YearString");
|
|
2746
|
+
var canonicalizeBigIntString = (input) => {
|
|
2747
|
+
const trimmed = input.trim();
|
|
2748
|
+
if (!/^-?\d+$/.test(trimmed)) {
|
|
2749
|
+
throw new Error("Expected an integer-like bigint value");
|
|
2750
|
+
}
|
|
2751
|
+
return BigInt(trimmed).toString();
|
|
2752
|
+
};
|
|
2753
|
+
var isCanonicalBigIntString = (value) => {
|
|
2754
|
+
try {
|
|
2755
|
+
return canonicalizeBigIntString(value) === value;
|
|
2756
|
+
} catch {
|
|
2757
|
+
return false;
|
|
2758
|
+
}
|
|
2759
|
+
};
|
|
2760
|
+
var canonicalizeDecimalString = (input) => {
|
|
2761
|
+
const trimmed = input.trim();
|
|
2762
|
+
const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
|
|
2763
|
+
if (match === null) {
|
|
2764
|
+
throw new Error("Expected a decimal string");
|
|
2765
|
+
}
|
|
2766
|
+
const sign = match[1] === "-" ? "-" : "";
|
|
2767
|
+
const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
|
|
2768
|
+
const fraction = (match[3] ?? "").replace(/0+$/, "");
|
|
2769
|
+
if (fraction.length === 0) {
|
|
2770
|
+
if (integer === "0") {
|
|
2771
|
+
return "0";
|
|
2772
|
+
}
|
|
2773
|
+
return `${sign}${integer}`;
|
|
2774
|
+
}
|
|
2775
|
+
return `${sign}${integer}.${fraction}`;
|
|
2776
|
+
};
|
|
2777
|
+
var isCanonicalDecimalString = (value) => {
|
|
2778
|
+
try {
|
|
2779
|
+
return canonicalizeDecimalString(value) === value;
|
|
2780
|
+
} catch {
|
|
2781
|
+
return false;
|
|
2782
|
+
}
|
|
2783
|
+
};
|
|
2784
|
+
var BigIntStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalBigIntString), Schema3.brand("BigIntString"));
|
|
2785
|
+
var DecimalStringSchema = Schema3.String.pipe(Schema3.filter(isCanonicalDecimalString), Schema3.brand("DecimalString"));
|
|
2786
|
+
var JsonValueSchema = Schema3.suspend(() => Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null, Schema3.Array(JsonValueSchema), Schema3.Record({
|
|
2787
|
+
key: Schema3.String,
|
|
2788
|
+
value: JsonValueSchema
|
|
2789
|
+
})));
|
|
2790
|
+
var JsonPrimitiveSchema = Schema3.Union(Schema3.String, Schema3.Number.pipe(Schema3.finite()), Schema3.Boolean, Schema3.Null);
|
|
2791
|
+
|
|
2792
|
+
// src/internal/runtime/normalize.ts
|
|
2793
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2794
|
+
var isPlainRecord = (value) => {
|
|
2795
|
+
if (!isRecord(value)) {
|
|
2796
|
+
return false;
|
|
2797
|
+
}
|
|
2798
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2799
|
+
return prototype === Object.prototype || prototype === null;
|
|
2800
|
+
};
|
|
2801
|
+
var pad = (value, width = 2) => value.toString().padStart(width, "0");
|
|
2802
|
+
var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
|
|
2803
|
+
var formatLocalTime = (value) => {
|
|
2804
|
+
const milliseconds = value.getUTCMilliseconds();
|
|
2805
|
+
const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
|
|
2806
|
+
return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
|
|
2807
|
+
};
|
|
2808
|
+
var formatLocalDateTime = (value) => {
|
|
2809
|
+
const milliseconds = value.getUTCMilliseconds();
|
|
2810
|
+
const base = `${formatLocalDate(value)}T${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
|
|
2811
|
+
return milliseconds === 0 ? base : `${base}.${pad(milliseconds, 3)}`;
|
|
2812
|
+
};
|
|
2813
|
+
var runtimeTagOfBaseDbType = (dbType) => {
|
|
2814
|
+
return dbType.runtime;
|
|
2815
|
+
};
|
|
2816
|
+
var expectString = (value, label) => {
|
|
2817
|
+
if (typeof value === "string") {
|
|
2818
|
+
return value;
|
|
2819
|
+
}
|
|
2820
|
+
throw new Error(`Expected ${label} as string`);
|
|
2821
|
+
};
|
|
2822
|
+
var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
|
|
2823
|
+
var normalizeNumber = (value) => {
|
|
2824
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2825
|
+
return value;
|
|
2826
|
+
}
|
|
2827
|
+
if (typeof value === "string") {
|
|
2828
|
+
const trimmed = value.trim();
|
|
2829
|
+
const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
|
|
2830
|
+
if (Number.isFinite(parsed)) {
|
|
2831
|
+
return parsed;
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
if (typeof value === "bigint" && Number.isSafeInteger(Number(value))) {
|
|
2835
|
+
return Number(value);
|
|
2836
|
+
}
|
|
2837
|
+
throw new Error("Expected a finite numeric value");
|
|
2838
|
+
};
|
|
2839
|
+
var normalizeBoolean = (value) => {
|
|
2840
|
+
if (typeof value === "boolean") {
|
|
2841
|
+
return value;
|
|
2842
|
+
}
|
|
2843
|
+
if (typeof value === "number") {
|
|
2844
|
+
if (value === 1) {
|
|
2845
|
+
return true;
|
|
2846
|
+
}
|
|
2847
|
+
if (value === 0) {
|
|
2848
|
+
return false;
|
|
2849
|
+
}
|
|
2850
|
+
}
|
|
2851
|
+
if (typeof value === "string") {
|
|
2852
|
+
const normalized = value.trim().toLowerCase();
|
|
2853
|
+
if (normalized === "true" || normalized === "t" || normalized === "1") {
|
|
2854
|
+
return true;
|
|
2855
|
+
}
|
|
2856
|
+
if (normalized === "false" || normalized === "f" || normalized === "0") {
|
|
2857
|
+
return false;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
throw new Error("Expected a boolean-like value");
|
|
2861
|
+
};
|
|
2862
|
+
var normalizeBigIntString = (value) => {
|
|
2863
|
+
if (typeof value === "bigint") {
|
|
2864
|
+
return value.toString();
|
|
2865
|
+
}
|
|
2866
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
2867
|
+
return BigInt(value).toString();
|
|
2868
|
+
}
|
|
2869
|
+
if (typeof value === "string") {
|
|
2870
|
+
return canonicalizeBigIntString(value);
|
|
2871
|
+
}
|
|
2872
|
+
throw new Error("Expected an integer-like bigint value");
|
|
2873
|
+
};
|
|
2874
|
+
var normalizeDecimalString = (value) => {
|
|
2875
|
+
if (typeof value === "string") {
|
|
2876
|
+
return canonicalizeDecimalString(value);
|
|
2877
|
+
}
|
|
2878
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2879
|
+
const rendered = String(value);
|
|
2880
|
+
if (/[eE]/.test(rendered)) {
|
|
2881
|
+
throw new Error("Scientific notation is not a supported decimal runtime");
|
|
2882
|
+
}
|
|
2883
|
+
return canonicalizeDecimalString(rendered);
|
|
2884
|
+
}
|
|
2885
|
+
throw new Error("Expected a decimal-like value");
|
|
2886
|
+
};
|
|
2887
|
+
var normalizeLocalDate = (value) => {
|
|
2888
|
+
if (value instanceof Date) {
|
|
2889
|
+
return formatLocalDate(value);
|
|
2890
|
+
}
|
|
2891
|
+
const raw = expectString(value, "local date").trim();
|
|
2892
|
+
if (isValidLocalDateString(raw)) {
|
|
2893
|
+
return raw;
|
|
2894
|
+
}
|
|
2895
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
2896
|
+
if (isValidInstantString(canonicalInstant)) {
|
|
2897
|
+
const parsed = new Date(canonicalInstant);
|
|
2898
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
2899
|
+
return formatLocalDate(parsed);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
throw new Error("Expected a local-date value");
|
|
2903
|
+
};
|
|
2904
|
+
var normalizeLocalTime = (value) => {
|
|
2905
|
+
if (value instanceof Date) {
|
|
2906
|
+
return formatLocalTime(value);
|
|
2907
|
+
}
|
|
2908
|
+
const raw = expectString(value, "local time").trim();
|
|
2909
|
+
if (isValidLocalTimeString(raw)) {
|
|
2910
|
+
return raw;
|
|
2911
|
+
}
|
|
2912
|
+
throw new Error("Expected a local-time value");
|
|
2913
|
+
};
|
|
2914
|
+
var normalizeOffsetTime = (value) => {
|
|
2915
|
+
if (value instanceof Date) {
|
|
2916
|
+
return `${formatLocalTime(value)}Z`;
|
|
2917
|
+
}
|
|
2918
|
+
const raw = expectString(value, "offset time").trim();
|
|
2919
|
+
if (isValidOffsetTimeString(raw)) {
|
|
2920
|
+
return raw;
|
|
2921
|
+
}
|
|
2922
|
+
throw new Error("Expected an offset-time value");
|
|
2923
|
+
};
|
|
2924
|
+
var normalizeLocalDateTime = (value) => {
|
|
2925
|
+
if (value instanceof Date) {
|
|
2926
|
+
return formatLocalDateTime(value);
|
|
2927
|
+
}
|
|
2928
|
+
const raw = expectString(value, "local datetime").trim();
|
|
2929
|
+
const canonicalLocalDateTime = raw.replace(" ", "T");
|
|
2930
|
+
if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
|
|
2931
|
+
return canonicalLocalDateTime;
|
|
2932
|
+
}
|
|
2933
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
2934
|
+
if (isValidInstantString(canonicalInstant)) {
|
|
2935
|
+
const parsed = new Date(canonicalInstant);
|
|
2936
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
2937
|
+
return formatLocalDateTime(parsed);
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
throw new Error("Expected a local-datetime value");
|
|
2941
|
+
};
|
|
2942
|
+
var normalizeInstant = (value) => {
|
|
2943
|
+
if (value instanceof Date) {
|
|
2944
|
+
return value.toISOString();
|
|
2945
|
+
}
|
|
2946
|
+
const raw = expectString(value, "instant").trim();
|
|
2947
|
+
if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
|
|
2948
|
+
throw new Error("Instant values require a timezone offset");
|
|
2949
|
+
}
|
|
2950
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
2951
|
+
if (!isValidInstantString(canonicalInstant)) {
|
|
2952
|
+
throw new Error("Expected an ISO instant value");
|
|
2953
|
+
}
|
|
2954
|
+
const parsed = new Date(canonicalInstant);
|
|
2955
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
2956
|
+
throw new Error("Expected an ISO instant value");
|
|
2957
|
+
}
|
|
2958
|
+
return parsed.toISOString();
|
|
2959
|
+
};
|
|
2960
|
+
var normalizeYear = (value) => {
|
|
2961
|
+
if (typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 9999) {
|
|
2962
|
+
return pad(value, 4);
|
|
2963
|
+
}
|
|
2964
|
+
const raw = expectString(value, "year").trim();
|
|
2965
|
+
if (/^\d{4}$/.test(raw)) {
|
|
2966
|
+
return raw;
|
|
2967
|
+
}
|
|
2968
|
+
throw new Error("Expected a four-digit year");
|
|
2969
|
+
};
|
|
2970
|
+
var normalizeBytes = (value) => {
|
|
2971
|
+
if (value instanceof Uint8Array) {
|
|
2972
|
+
return new Uint8Array(value);
|
|
2973
|
+
}
|
|
2974
|
+
const BufferConstructor = globalThis.Buffer;
|
|
2975
|
+
if (BufferConstructor !== undefined && value instanceof BufferConstructor) {
|
|
2976
|
+
return new Uint8Array(value);
|
|
2977
|
+
}
|
|
2978
|
+
throw new Error("Expected a byte array value");
|
|
2979
|
+
};
|
|
2980
|
+
var isJsonValue = (value) => {
|
|
2981
|
+
if (value === null) {
|
|
2982
|
+
return true;
|
|
2983
|
+
}
|
|
2984
|
+
switch (typeof value) {
|
|
2985
|
+
case "string":
|
|
2986
|
+
case "boolean":
|
|
2987
|
+
return true;
|
|
2988
|
+
case "number":
|
|
2989
|
+
return Number.isFinite(value);
|
|
2990
|
+
case "object":
|
|
2991
|
+
if (Array.isArray(value)) {
|
|
2992
|
+
return value.every(isJsonValue);
|
|
2993
|
+
}
|
|
2994
|
+
return isPlainRecord(value) && Object.values(value).every(isJsonValue);
|
|
2995
|
+
default:
|
|
2996
|
+
return false;
|
|
2997
|
+
}
|
|
2998
|
+
};
|
|
2999
|
+
var normalizeJson = (value) => {
|
|
3000
|
+
if (typeof value === "string") {
|
|
3001
|
+
try {
|
|
3002
|
+
const parsed = JSON.parse(value);
|
|
3003
|
+
if (isJsonValue(parsed)) {
|
|
3004
|
+
return parsed;
|
|
3005
|
+
}
|
|
3006
|
+
throw new Error("Parsed JSON value is not a valid JSON runtime");
|
|
3007
|
+
} catch (error) {
|
|
3008
|
+
if (error instanceof SyntaxError) {
|
|
3009
|
+
return value;
|
|
3010
|
+
}
|
|
3011
|
+
throw error;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
if (isJsonValue(value)) {
|
|
3015
|
+
return value;
|
|
3016
|
+
}
|
|
3017
|
+
throw new Error("Expected a JSON value");
|
|
3018
|
+
};
|
|
3019
|
+
var normalizeDbValue = (dbType, value) => {
|
|
3020
|
+
if (value === null) {
|
|
3021
|
+
return null;
|
|
3022
|
+
}
|
|
3023
|
+
if ("base" in dbType) {
|
|
3024
|
+
return normalizeDbValue(dbType.base, value);
|
|
3025
|
+
}
|
|
3026
|
+
if ("element" in dbType) {
|
|
3027
|
+
if (!Array.isArray(value)) {
|
|
3028
|
+
throw new Error("Expected an array value");
|
|
3029
|
+
}
|
|
3030
|
+
return value.map((entry) => normalizeDbValue(dbType.element, entry));
|
|
3031
|
+
}
|
|
3032
|
+
if ("fields" in dbType) {
|
|
3033
|
+
if (!isRecord(value)) {
|
|
3034
|
+
throw new Error("Expected a record value");
|
|
3035
|
+
}
|
|
3036
|
+
const normalized = {};
|
|
3037
|
+
for (const [key2, fieldDbType] of Object.entries(dbType.fields)) {
|
|
3038
|
+
if (key2 in value) {
|
|
3039
|
+
normalized[key2] = normalizeDbValue(fieldDbType, value[key2]);
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
return normalized;
|
|
3043
|
+
}
|
|
3044
|
+
if ("variant" in dbType && dbType.variant === "json") {
|
|
3045
|
+
return normalizeJson(value);
|
|
3046
|
+
}
|
|
3047
|
+
if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
|
|
3048
|
+
return expectString(value, "text");
|
|
3049
|
+
}
|
|
3050
|
+
switch (runtimeTagOfBaseDbType(dbType)) {
|
|
3051
|
+
case "string":
|
|
3052
|
+
return expectString(value, "text");
|
|
3053
|
+
case "number":
|
|
3054
|
+
return normalizeNumber(value);
|
|
3055
|
+
case "bigintString":
|
|
3056
|
+
return normalizeBigIntString(value);
|
|
3057
|
+
case "boolean":
|
|
3058
|
+
return normalizeBoolean(value);
|
|
3059
|
+
case "json":
|
|
3060
|
+
return normalizeJson(value);
|
|
3061
|
+
case "localDate":
|
|
3062
|
+
return normalizeLocalDate(value);
|
|
3063
|
+
case "localTime":
|
|
3064
|
+
return normalizeLocalTime(value);
|
|
3065
|
+
case "offsetTime":
|
|
3066
|
+
return normalizeOffsetTime(value);
|
|
3067
|
+
case "localDateTime":
|
|
3068
|
+
return normalizeLocalDateTime(value);
|
|
3069
|
+
case "instant":
|
|
3070
|
+
return normalizeInstant(value);
|
|
3071
|
+
case "year":
|
|
3072
|
+
return normalizeYear(value);
|
|
3073
|
+
case "decimalString":
|
|
3074
|
+
return normalizeDecimalString(value);
|
|
3075
|
+
case "bytes":
|
|
3076
|
+
return normalizeBytes(value);
|
|
3077
|
+
case "array":
|
|
3078
|
+
if (!Array.isArray(value)) {
|
|
3079
|
+
throw new Error("Expected an array value");
|
|
3080
|
+
}
|
|
3081
|
+
return value;
|
|
3082
|
+
case "record":
|
|
3083
|
+
if (!isRecord(value)) {
|
|
3084
|
+
throw new Error("Expected a record value");
|
|
3085
|
+
}
|
|
3086
|
+
return value;
|
|
3087
|
+
case "null":
|
|
3088
|
+
return null;
|
|
3089
|
+
case "unknown":
|
|
3090
|
+
case undefined:
|
|
3091
|
+
return value;
|
|
3092
|
+
}
|
|
3093
|
+
};
|
|
3094
|
+
|
|
3095
|
+
// src/internal/runtime/driver-value-mapping.ts
|
|
3096
|
+
var runtimeTagOfDbType = (dbType) => {
|
|
3097
|
+
if (dbType === undefined) {
|
|
3098
|
+
return;
|
|
3099
|
+
}
|
|
3100
|
+
if ("base" in dbType) {
|
|
3101
|
+
return runtimeTagOfDbType(dbType.base);
|
|
3102
|
+
}
|
|
3103
|
+
if ("element" in dbType) {
|
|
3104
|
+
return "array";
|
|
3105
|
+
}
|
|
3106
|
+
if ("fields" in dbType) {
|
|
3107
|
+
return "record";
|
|
3108
|
+
}
|
|
3109
|
+
if ("variant" in dbType && dbType.variant === "json") {
|
|
3110
|
+
return "json";
|
|
3111
|
+
}
|
|
3112
|
+
if ("variant" in dbType && (dbType.variant === "enum" || dbType.variant === "set")) {
|
|
3113
|
+
return "string";
|
|
3114
|
+
}
|
|
3115
|
+
return dbType.runtime;
|
|
3116
|
+
};
|
|
3117
|
+
var familyOfDbType = (dbType) => {
|
|
3118
|
+
if (dbType === undefined) {
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
if ("base" in dbType) {
|
|
3122
|
+
return familyOfDbType(dbType.base);
|
|
3123
|
+
}
|
|
3124
|
+
return dbType.family;
|
|
3125
|
+
};
|
|
3126
|
+
var mappingCandidates = (context) => {
|
|
3127
|
+
const dbType = context.dbType;
|
|
3128
|
+
const runtimeTag = runtimeTagOfDbType(dbType);
|
|
3129
|
+
const family = familyOfDbType(dbType);
|
|
3130
|
+
return [
|
|
3131
|
+
context.driverValueMapping,
|
|
3132
|
+
dbType?.driverValueMapping,
|
|
3133
|
+
dbType === undefined ? undefined : context.valueMappings?.[dbType.kind],
|
|
3134
|
+
family === undefined ? undefined : context.valueMappings?.[family],
|
|
3135
|
+
runtimeTag === undefined ? undefined : context.valueMappings?.[runtimeTag]
|
|
3136
|
+
];
|
|
3137
|
+
};
|
|
3138
|
+
var findMapping = (context, key2) => {
|
|
3139
|
+
for (const candidate of mappingCandidates(context)) {
|
|
3140
|
+
const value = candidate?.[key2];
|
|
3141
|
+
if (value !== undefined) {
|
|
3142
|
+
return value;
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
return;
|
|
3146
|
+
};
|
|
3147
|
+
var isJsonDbType = (dbType) => {
|
|
3148
|
+
if (dbType === undefined) {
|
|
3149
|
+
return false;
|
|
3150
|
+
}
|
|
3151
|
+
if ("base" in dbType) {
|
|
3152
|
+
return isJsonDbType(dbType.base);
|
|
3153
|
+
}
|
|
3154
|
+
if (!("variant" in dbType)) {
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3157
|
+
const variant = dbType.variant;
|
|
3158
|
+
return variant === "json" || variant === "jsonb";
|
|
3159
|
+
};
|
|
3160
|
+
var schemaAccepts = (schema2, value) => schema2 !== undefined && Schema4.is(schema2)(value);
|
|
3161
|
+
var encodeWithSchema = (schema2, value) => {
|
|
3162
|
+
if (schema2 === undefined) {
|
|
3163
|
+
return { value, encoded: false };
|
|
3164
|
+
}
|
|
3165
|
+
if (!Schema4.is(schema2)(value)) {
|
|
3166
|
+
return { value, encoded: false };
|
|
3167
|
+
}
|
|
3168
|
+
return {
|
|
3169
|
+
value: Schema4.encodeUnknownSync(schema2)(value),
|
|
3170
|
+
encoded: true
|
|
3171
|
+
};
|
|
1297
3172
|
};
|
|
1298
|
-
var
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
}
|
|
1307
|
-
return;
|
|
3173
|
+
var normalizeJsonDriverString = (value, context) => {
|
|
3174
|
+
if (!isJsonDbType(context.dbType) || context.runtimeSchema === undefined) {
|
|
3175
|
+
return;
|
|
3176
|
+
}
|
|
3177
|
+
try {
|
|
3178
|
+
const parsed = JSON.parse(value);
|
|
3179
|
+
if (value.trimStart().startsWith('"') && schemaAccepts(context.runtimeSchema, parsed)) {
|
|
3180
|
+
return parsed;
|
|
1308
3181
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
3182
|
+
if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
|
|
3183
|
+
return value;
|
|
1311
3184
|
}
|
|
1312
|
-
}
|
|
1313
|
-
|
|
1314
|
-
|
|
3185
|
+
} catch (error) {
|
|
3186
|
+
if (error instanceof SyntaxError && schemaAccepts(context.runtimeSchema, value)) {
|
|
3187
|
+
return value;
|
|
3188
|
+
}
|
|
3189
|
+
if (!(error instanceof SyntaxError)) {
|
|
3190
|
+
throw error;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
return;
|
|
1315
3194
|
};
|
|
1316
|
-
var
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
throw new Error("scalar subqueries must select exactly one top-level expression");
|
|
3195
|
+
var toDriverValue = (value, context) => {
|
|
3196
|
+
if (value === null) {
|
|
3197
|
+
return null;
|
|
1320
3198
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
|
|
1324
|
-
throw new Error("scalar subqueries must select a scalar expression");
|
|
3199
|
+
if (value instanceof Date && Number.isNaN(value.getTime())) {
|
|
3200
|
+
throw new Error("Expected a valid Date value");
|
|
1325
3201
|
}
|
|
1326
|
-
|
|
3202
|
+
const dbType = context.dbType;
|
|
3203
|
+
const encoded = encodeWithSchema(context.runtimeSchema, value);
|
|
3204
|
+
let current = encoded.value;
|
|
3205
|
+
const custom = findMapping(context, "toDriver");
|
|
3206
|
+
if (custom !== undefined && dbType !== undefined) {
|
|
3207
|
+
return custom(current, dbType);
|
|
3208
|
+
}
|
|
3209
|
+
if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
|
|
3210
|
+
return current;
|
|
3211
|
+
}
|
|
3212
|
+
return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
|
|
3213
|
+
};
|
|
3214
|
+
var fromDriverValue = (value, context) => {
|
|
3215
|
+
if (value === null) {
|
|
3216
|
+
return null;
|
|
3217
|
+
}
|
|
3218
|
+
const dbType = context.dbType;
|
|
3219
|
+
const custom = findMapping(context, "fromDriver");
|
|
3220
|
+
if (custom !== undefined && dbType !== undefined) {
|
|
3221
|
+
return custom(value, dbType);
|
|
3222
|
+
}
|
|
3223
|
+
if (typeof value === "string") {
|
|
3224
|
+
const normalizedJsonString = normalizeJsonDriverString(value, context);
|
|
3225
|
+
if (normalizedJsonString !== undefined) {
|
|
3226
|
+
return normalizedJsonString;
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
return dbType === undefined ? value : normalizeDbValue(dbType, value);
|
|
3230
|
+
};
|
|
3231
|
+
var textCast = (sql) => `(${sql})::text`;
|
|
3232
|
+
var postgresJsonSql = (sql, dbType) => {
|
|
3233
|
+
const runtimeTag = runtimeTagOfDbType(dbType);
|
|
3234
|
+
switch (runtimeTag) {
|
|
3235
|
+
case "bigintString":
|
|
3236
|
+
case "decimalString":
|
|
3237
|
+
case "localDate":
|
|
3238
|
+
case "localTime":
|
|
3239
|
+
case "offsetTime":
|
|
3240
|
+
case "localDateTime":
|
|
3241
|
+
case "instant":
|
|
3242
|
+
case "year":
|
|
3243
|
+
return textCast(sql);
|
|
3244
|
+
case "bytes":
|
|
3245
|
+
return `encode(${sql}, 'base64')`;
|
|
3246
|
+
default:
|
|
3247
|
+
return sql;
|
|
3248
|
+
}
|
|
3249
|
+
};
|
|
3250
|
+
var renderSelectSql = (sql, context) => {
|
|
3251
|
+
const dbType = context.dbType;
|
|
3252
|
+
const custom = findMapping(context, "selectSql");
|
|
3253
|
+
return custom !== undefined && dbType !== undefined ? custom(sql, dbType) : sql;
|
|
3254
|
+
};
|
|
3255
|
+
var renderJsonSelectSql = (sql, context) => {
|
|
3256
|
+
const dbType = context.dbType;
|
|
3257
|
+
const custom = findMapping(context, "jsonSelectSql");
|
|
3258
|
+
if (custom !== undefined && dbType !== undefined) {
|
|
3259
|
+
return custom(sql, dbType);
|
|
3260
|
+
}
|
|
3261
|
+
return context.dialect === "postgres" && dbType !== undefined ? postgresJsonSql(sql, dbType) : sql;
|
|
1327
3262
|
};
|
|
1328
|
-
var currentRequiredList = (required) => Array.isArray(required) ? [...required] : required === undefined ? [] : [required];
|
|
1329
|
-
|
|
1330
|
-
// src/internal/json/path.ts
|
|
1331
|
-
var SegmentTypeId = Symbol.for("effect-qb/JsonPathSegment");
|
|
1332
|
-
var TypeId7 = Symbol.for("effect-qb/JsonPath");
|
|
1333
|
-
var makeSegment = (segment) => segment;
|
|
1334
|
-
var key = (value) => makeSegment({
|
|
1335
|
-
[SegmentTypeId]: {
|
|
1336
|
-
kind: "key"
|
|
1337
|
-
},
|
|
1338
|
-
kind: "key",
|
|
1339
|
-
key: value
|
|
1340
|
-
});
|
|
1341
|
-
var index2 = (value) => makeSegment({
|
|
1342
|
-
[SegmentTypeId]: {
|
|
1343
|
-
kind: "index"
|
|
1344
|
-
},
|
|
1345
|
-
kind: "index",
|
|
1346
|
-
index: value
|
|
1347
|
-
});
|
|
1348
|
-
var wildcard = () => makeSegment({
|
|
1349
|
-
[SegmentTypeId]: {
|
|
1350
|
-
kind: "wildcard"
|
|
1351
|
-
},
|
|
1352
|
-
kind: "wildcard"
|
|
1353
|
-
});
|
|
1354
|
-
var slice = (start, end) => makeSegment({
|
|
1355
|
-
[SegmentTypeId]: {
|
|
1356
|
-
kind: "slice"
|
|
1357
|
-
},
|
|
1358
|
-
kind: "slice",
|
|
1359
|
-
start,
|
|
1360
|
-
end
|
|
1361
|
-
});
|
|
1362
|
-
var descend = () => makeSegment({
|
|
1363
|
-
[SegmentTypeId]: {
|
|
1364
|
-
kind: "descend"
|
|
1365
|
-
},
|
|
1366
|
-
kind: "descend"
|
|
1367
|
-
});
|
|
1368
|
-
var path = (...segments) => ({
|
|
1369
|
-
[TypeId7]: {
|
|
1370
|
-
segments
|
|
1371
|
-
},
|
|
1372
|
-
segments
|
|
1373
|
-
});
|
|
1374
3263
|
|
|
1375
3264
|
// src/internal/projection-alias.ts
|
|
1376
3265
|
var TypeId8 = Symbol.for("effect-qb/ProjectionAlias");
|
|
@@ -1424,6 +3313,20 @@ var validateProjections = (projections) => {
|
|
|
1424
3313
|
};
|
|
1425
3314
|
|
|
1426
3315
|
// src/internal/grouping-key.ts
|
|
3316
|
+
var subqueryPlanIds = new WeakMap;
|
|
3317
|
+
var nextSubqueryPlanId = 0;
|
|
3318
|
+
var subqueryPlanGroupingKey = (plan) => {
|
|
3319
|
+
if (plan === null || typeof plan !== "object") {
|
|
3320
|
+
return "unknown";
|
|
3321
|
+
}
|
|
3322
|
+
const existing = subqueryPlanIds.get(plan);
|
|
3323
|
+
if (existing !== undefined) {
|
|
3324
|
+
return existing;
|
|
3325
|
+
}
|
|
3326
|
+
const next = `${nextSubqueryPlanId++}`;
|
|
3327
|
+
subqueryPlanIds.set(plan, next);
|
|
3328
|
+
return next;
|
|
3329
|
+
};
|
|
1427
3330
|
var literalGroupingKey = (value) => {
|
|
1428
3331
|
if (value instanceof Date) {
|
|
1429
3332
|
return `date:${value.toISOString()}`;
|
|
@@ -1442,15 +3345,62 @@ var literalGroupingKey = (value) => {
|
|
|
1442
3345
|
return `literal:${JSON.stringify(value)}`;
|
|
1443
3346
|
}
|
|
1444
3347
|
};
|
|
3348
|
+
var isExpression2 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
|
|
3349
|
+
var expressionGroupingKey = (value) => isExpression2(value) ? groupingKeyOfExpression(value) : "missing";
|
|
3350
|
+
var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
|
|
3351
|
+
var jsonSegmentGroupingKey = (segment) => {
|
|
3352
|
+
if (segment !== null && typeof segment === "object" && "kind" in segment) {
|
|
3353
|
+
switch (segment.kind) {
|
|
3354
|
+
case "key":
|
|
3355
|
+
return `key:${escapeGroupingText(segment.key)}`;
|
|
3356
|
+
case "index":
|
|
3357
|
+
return `index:${segment.index}`;
|
|
3358
|
+
case "wildcard":
|
|
3359
|
+
return "wildcard";
|
|
3360
|
+
case "slice": {
|
|
3361
|
+
const slice2 = segment;
|
|
3362
|
+
return `slice:${slice2.start ?? ""}:${slice2.end ?? ""}`;
|
|
3363
|
+
}
|
|
3364
|
+
case "descend":
|
|
3365
|
+
return "descend";
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
if (typeof segment === "string") {
|
|
3369
|
+
return `key:${escapeGroupingText(segment)}`;
|
|
3370
|
+
}
|
|
3371
|
+
if (typeof segment === "number") {
|
|
3372
|
+
return `index:${segment}`;
|
|
3373
|
+
}
|
|
3374
|
+
return "unknown";
|
|
3375
|
+
};
|
|
3376
|
+
var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
|
|
3377
|
+
var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
|
|
3378
|
+
var jsonOpaquePathGroupingKey = (value) => {
|
|
3379
|
+
if (isJsonPath(value)) {
|
|
3380
|
+
return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
|
|
3381
|
+
}
|
|
3382
|
+
if (typeof value === "string") {
|
|
3383
|
+
return `jsonpath:${escapeGroupingText(value)}`;
|
|
3384
|
+
}
|
|
3385
|
+
if (isExpression2(value)) {
|
|
3386
|
+
return `jsonpath:${groupingKeyOfExpression(value)}`;
|
|
3387
|
+
}
|
|
3388
|
+
return "jsonpath:unknown";
|
|
3389
|
+
};
|
|
3390
|
+
var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
|
|
1445
3391
|
var groupingKeyOfExpression = (expression) => {
|
|
1446
3392
|
const ast = expression[TypeId3];
|
|
1447
3393
|
switch (ast.kind) {
|
|
1448
3394
|
case "column":
|
|
1449
|
-
return `column:${ast.tableName
|
|
3395
|
+
return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
|
|
1450
3396
|
case "literal":
|
|
1451
3397
|
return `literal:${literalGroupingKey(ast.value)}`;
|
|
1452
3398
|
case "cast":
|
|
1453
3399
|
return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
|
|
3400
|
+
case "collate":
|
|
3401
|
+
return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
|
|
3402
|
+
case "function":
|
|
3403
|
+
return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
|
|
1454
3404
|
case "isNull":
|
|
1455
3405
|
case "isNotNull":
|
|
1456
3406
|
case "not":
|
|
@@ -1468,8 +3418,15 @@ var groupingKeyOfExpression = (expression) => {
|
|
|
1468
3418
|
case "gte":
|
|
1469
3419
|
case "like":
|
|
1470
3420
|
case "ilike":
|
|
3421
|
+
case "regexMatch":
|
|
3422
|
+
case "regexIMatch":
|
|
3423
|
+
case "regexNotMatch":
|
|
3424
|
+
case "regexNotIMatch":
|
|
1471
3425
|
case "isDistinctFrom":
|
|
1472
3426
|
case "isNotDistinctFrom":
|
|
3427
|
+
case "contains":
|
|
3428
|
+
case "containedBy":
|
|
3429
|
+
case "overlaps":
|
|
1473
3430
|
return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
|
|
1474
3431
|
case "and":
|
|
1475
3432
|
case "or":
|
|
@@ -1481,6 +3438,54 @@ var groupingKeyOfExpression = (expression) => {
|
|
|
1481
3438
|
return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
|
|
1482
3439
|
case "case":
|
|
1483
3440
|
return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
|
|
3441
|
+
case "exists":
|
|
3442
|
+
return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3443
|
+
case "scalarSubquery":
|
|
3444
|
+
return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3445
|
+
case "inSubquery":
|
|
3446
|
+
return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3447
|
+
case "comparisonAny":
|
|
3448
|
+
case "comparisonAll":
|
|
3449
|
+
return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3450
|
+
case "jsonGet":
|
|
3451
|
+
case "jsonPath":
|
|
3452
|
+
case "jsonAccess":
|
|
3453
|
+
case "jsonTraverse":
|
|
3454
|
+
case "jsonGetText":
|
|
3455
|
+
case "jsonPathText":
|
|
3456
|
+
case "jsonAccessText":
|
|
3457
|
+
case "jsonTraverseText":
|
|
3458
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3459
|
+
case "jsonHasKey":
|
|
3460
|
+
case "jsonKeyExists":
|
|
3461
|
+
case "jsonHasAnyKeys":
|
|
3462
|
+
case "jsonHasAllKeys":
|
|
3463
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
|
|
3464
|
+
case "jsonConcat":
|
|
3465
|
+
case "jsonMerge":
|
|
3466
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
|
|
3467
|
+
case "jsonDelete":
|
|
3468
|
+
case "jsonDeletePath":
|
|
3469
|
+
case "jsonRemove":
|
|
3470
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(undefined)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3471
|
+
case "jsonSet":
|
|
3472
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.newValue)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3473
|
+
case "jsonInsert":
|
|
3474
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.insert)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3475
|
+
case "jsonPathExists":
|
|
3476
|
+
case "jsonPathMatch":
|
|
3477
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
|
|
3478
|
+
case "jsonBuildObject":
|
|
3479
|
+
return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
|
|
3480
|
+
case "jsonBuildArray":
|
|
3481
|
+
return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
|
|
3482
|
+
case "jsonToJson":
|
|
3483
|
+
case "jsonToJsonb":
|
|
3484
|
+
case "jsonTypeOf":
|
|
3485
|
+
case "jsonLength":
|
|
3486
|
+
case "jsonKeys":
|
|
3487
|
+
case "jsonStripNulls":
|
|
3488
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
|
|
1484
3489
|
default:
|
|
1485
3490
|
throw new Error("Unsupported expression for grouping key generation");
|
|
1486
3491
|
}
|
|
@@ -1498,15 +3503,15 @@ var dedupeGroupedExpressions = (values) => {
|
|
|
1498
3503
|
};
|
|
1499
3504
|
|
|
1500
3505
|
// src/internal/aggregation-validation.ts
|
|
1501
|
-
var
|
|
3506
|
+
var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
|
|
1502
3507
|
var selectionHasAggregate = (selection) => {
|
|
1503
|
-
if (
|
|
3508
|
+
if (isExpression3(selection)) {
|
|
1504
3509
|
return selection[TypeId2].kind === "aggregate";
|
|
1505
3510
|
}
|
|
1506
3511
|
return Object.values(selection).some((value) => selectionHasAggregate(value));
|
|
1507
3512
|
};
|
|
1508
3513
|
var isGroupedSelectionValid = (selection, groupedExpressions) => {
|
|
1509
|
-
if (
|
|
3514
|
+
if (isExpression3(selection)) {
|
|
1510
3515
|
const aggregation = selection[TypeId2].kind;
|
|
1511
3516
|
if (aggregation === "aggregate") {
|
|
1512
3517
|
return true;
|
|
@@ -1559,7 +3564,46 @@ var renderCastType = (dialect, dbType) => {
|
|
|
1559
3564
|
return dbType.kind;
|
|
1560
3565
|
}
|
|
1561
3566
|
};
|
|
1562
|
-
var
|
|
3567
|
+
var renderPostgresDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
3568
|
+
var renderPostgresDdlBytes = (value) => `decode('${Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("")}', 'hex')`;
|
|
3569
|
+
var renderPostgresDdlLiteral = (value, state, context = {}) => {
|
|
3570
|
+
const driverValue = toDriverValue(value, {
|
|
3571
|
+
dialect: "postgres",
|
|
3572
|
+
valueMappings: state.valueMappings,
|
|
3573
|
+
...context
|
|
3574
|
+
});
|
|
3575
|
+
if (driverValue === null) {
|
|
3576
|
+
return "null";
|
|
3577
|
+
}
|
|
3578
|
+
switch (typeof driverValue) {
|
|
3579
|
+
case "boolean":
|
|
3580
|
+
return driverValue ? "true" : "false";
|
|
3581
|
+
case "number":
|
|
3582
|
+
if (!Number.isFinite(driverValue)) {
|
|
3583
|
+
throw new Error("Expected a finite numeric value");
|
|
3584
|
+
}
|
|
3585
|
+
return String(driverValue);
|
|
3586
|
+
case "bigint":
|
|
3587
|
+
return driverValue.toString();
|
|
3588
|
+
case "string":
|
|
3589
|
+
return renderPostgresDdlString(driverValue);
|
|
3590
|
+
case "object":
|
|
3591
|
+
if (driverValue instanceof Uint8Array) {
|
|
3592
|
+
return renderPostgresDdlBytes(driverValue);
|
|
3593
|
+
}
|
|
3594
|
+
break;
|
|
3595
|
+
}
|
|
3596
|
+
throw new Error("Unsupported postgres DDL literal value");
|
|
3597
|
+
};
|
|
3598
|
+
var renderDdlExpression = (expression, state, dialect) => {
|
|
3599
|
+
if (isSchemaExpression(expression)) {
|
|
3600
|
+
return render(expression);
|
|
3601
|
+
}
|
|
3602
|
+
return renderExpression(expression, state, {
|
|
3603
|
+
...dialect,
|
|
3604
|
+
renderLiteral: renderPostgresDdlLiteral
|
|
3605
|
+
});
|
|
3606
|
+
};
|
|
1563
3607
|
var renderColumnDefinition = (dialect, state, columnName, column) => {
|
|
1564
3608
|
const clauses = [
|
|
1565
3609
|
dialect.quoteIdentifier(columnName),
|
|
@@ -1591,14 +3635,16 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
|
|
|
1591
3635
|
break;
|
|
1592
3636
|
case "foreignKey": {
|
|
1593
3637
|
const reference = option2.references();
|
|
1594
|
-
definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete ? ` on delete ${option2.onDelete
|
|
3638
|
+
definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
|
|
1595
3639
|
break;
|
|
1596
3640
|
}
|
|
1597
3641
|
case "check":
|
|
1598
|
-
definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, state, dialect)})${option2.noInherit ? " no inherit" : ""}`);
|
|
3642
|
+
definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
|
|
1599
3643
|
break;
|
|
1600
3644
|
case "index":
|
|
1601
3645
|
break;
|
|
3646
|
+
default:
|
|
3647
|
+
throw new Error("Unsupported table option kind");
|
|
1602
3648
|
}
|
|
1603
3649
|
}
|
|
1604
3650
|
return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
|
|
@@ -1607,10 +3653,56 @@ var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
|
|
|
1607
3653
|
const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
|
|
1608
3654
|
return `create${ddl.unique ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`;
|
|
1609
3655
|
};
|
|
1610
|
-
var renderDropIndexSql = (targetSource, ddl, state, dialect) =>
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
3656
|
+
var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
|
|
3657
|
+
if (dialect.name === "postgres") {
|
|
3658
|
+
const schemaName = typeof targetSource.source === "object" && targetSource.source !== null && TypeId4 in targetSource.source ? targetSource.source[TypeId4].schemaName : undefined;
|
|
3659
|
+
const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(ddl.name) : `${dialect.quoteIdentifier(schemaName)}.${dialect.quoteIdentifier(ddl.name)}`;
|
|
3660
|
+
return `drop index${ddl.ifExists ? " if exists" : ""} ${indexName}`;
|
|
3661
|
+
}
|
|
3662
|
+
return `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
|
|
3663
|
+
};
|
|
3664
|
+
var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
|
|
3665
|
+
var isJsonDbType2 = (dbType) => {
|
|
3666
|
+
if (dbType.kind === "jsonb" || dbType.kind === "json") {
|
|
3667
|
+
return true;
|
|
3668
|
+
}
|
|
3669
|
+
if (!("variant" in dbType)) {
|
|
3670
|
+
return false;
|
|
3671
|
+
}
|
|
3672
|
+
const variant = dbType.variant;
|
|
3673
|
+
return variant === "json" || variant === "jsonb";
|
|
3674
|
+
};
|
|
3675
|
+
var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId2].dbType);
|
|
3676
|
+
var postgresRangeSubtypeByKind = {
|
|
3677
|
+
int4range: "int4",
|
|
3678
|
+
int8range: "int8",
|
|
3679
|
+
numrange: "numeric",
|
|
3680
|
+
tsrange: "timestamp",
|
|
3681
|
+
tstzrange: "timestamptz",
|
|
3682
|
+
daterange: "date",
|
|
3683
|
+
int4multirange: "int4",
|
|
3684
|
+
int8multirange: "int8",
|
|
3685
|
+
nummultirange: "numeric",
|
|
3686
|
+
tsmultirange: "timestamp",
|
|
3687
|
+
tstzmultirange: "timestamptz",
|
|
3688
|
+
datemultirange: "date"
|
|
3689
|
+
};
|
|
3690
|
+
var postgresRangeSubtypeKey = (dbType) => {
|
|
3691
|
+
if ("base" in dbType) {
|
|
3692
|
+
return postgresRangeSubtypeKey(dbType.base);
|
|
3693
|
+
}
|
|
3694
|
+
if ("subtype" in dbType) {
|
|
3695
|
+
return postgresRangeSubtypeKey(dbType.subtype) ?? dbType.subtype.kind;
|
|
3696
|
+
}
|
|
3697
|
+
return postgresRangeSubtypeByKind[dbType.kind];
|
|
3698
|
+
};
|
|
3699
|
+
var assertCompatiblePostgresRangeOperands = (left, right) => {
|
|
3700
|
+
const leftKey = postgresRangeSubtypeKey(left[TypeId2].dbType);
|
|
3701
|
+
const rightKey = postgresRangeSubtypeKey(right[TypeId2].dbType);
|
|
3702
|
+
if (leftKey !== undefined && rightKey !== undefined && leftKey !== rightKey) {
|
|
3703
|
+
throw new Error("Incompatible postgres range operands");
|
|
3704
|
+
}
|
|
3705
|
+
};
|
|
1614
3706
|
var unsupportedJsonFeature = (dialect, feature) => {
|
|
1615
3707
|
const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
|
|
1616
3708
|
Object.assign(error, {
|
|
@@ -1653,15 +3745,16 @@ var extractJsonPathSegments = (node) => {
|
|
|
1653
3745
|
};
|
|
1654
3746
|
var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
|
|
1655
3747
|
var renderJsonPathSegment = (segment) => {
|
|
3748
|
+
const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
|
|
1656
3749
|
if (typeof segment === "string") {
|
|
1657
|
-
return
|
|
3750
|
+
return renderKey(segment);
|
|
1658
3751
|
}
|
|
1659
3752
|
if (typeof segment === "number") {
|
|
1660
3753
|
return `[${segment}]`;
|
|
1661
3754
|
}
|
|
1662
3755
|
switch (segment.kind) {
|
|
1663
3756
|
case "key":
|
|
1664
|
-
return
|
|
3757
|
+
return renderKey(segment.key);
|
|
1665
3758
|
case "index":
|
|
1666
3759
|
return `[${segment.index}]`;
|
|
1667
3760
|
case "wildcard":
|
|
@@ -1704,18 +3797,45 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
|
|
|
1704
3797
|
case "key":
|
|
1705
3798
|
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.key, state)}`;
|
|
1706
3799
|
case "index":
|
|
1707
|
-
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(
|
|
3800
|
+
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.index, state)}`;
|
|
1708
3801
|
default:
|
|
1709
3802
|
throw new Error("Postgres exact JSON access requires key/index segments");
|
|
1710
3803
|
}
|
|
1711
3804
|
};
|
|
1712
3805
|
var renderPostgresJsonValue = (value, state, dialect) => {
|
|
1713
|
-
if (!
|
|
3806
|
+
if (!isExpression4(value)) {
|
|
1714
3807
|
throw new Error("Expected a JSON expression");
|
|
1715
3808
|
}
|
|
1716
3809
|
const rendered = renderExpression(value, state, dialect);
|
|
3810
|
+
const ast = value[TypeId3];
|
|
3811
|
+
if (ast.kind === "literal") {
|
|
3812
|
+
return `cast(${rendered} as jsonb)`;
|
|
3813
|
+
}
|
|
1717
3814
|
return value[TypeId2].dbType.kind === "jsonb" ? rendered : `cast(${rendered} as jsonb)`;
|
|
1718
3815
|
};
|
|
3816
|
+
var expressionDriverContext = (expression, state, dialect) => ({
|
|
3817
|
+
dialect: dialect.name,
|
|
3818
|
+
valueMappings: state.valueMappings,
|
|
3819
|
+
dbType: expression[TypeId2].dbType,
|
|
3820
|
+
runtimeSchema: expression[TypeId2].runtimeSchema,
|
|
3821
|
+
driverValueMapping: expression[TypeId2].driverValueMapping
|
|
3822
|
+
});
|
|
3823
|
+
var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
|
|
3824
|
+
var encodeArrayValues = (values, column, state, dialect) => values.map((value) => {
|
|
3825
|
+
if (value === null && column.metadata.nullable) {
|
|
3826
|
+
return null;
|
|
3827
|
+
}
|
|
3828
|
+
const runtimeSchemaAccepts = column.schema !== undefined && Schema5.is(column.schema)(value);
|
|
3829
|
+
const normalizedValue = runtimeSchemaAccepts ? value : normalizeDbValue(column.metadata.dbType, value);
|
|
3830
|
+
const encodedValue = column.schema === undefined || runtimeSchemaAccepts ? normalizedValue : Schema5.decodeUnknownSync(column.schema)(normalizedValue);
|
|
3831
|
+
return toDriverValue(encodedValue, {
|
|
3832
|
+
dialect: dialect.name,
|
|
3833
|
+
valueMappings: state.valueMappings,
|
|
3834
|
+
dbType: column.metadata.dbType,
|
|
3835
|
+
runtimeSchema: column.schema,
|
|
3836
|
+
driverValueMapping: column.metadata.driverValueMapping
|
|
3837
|
+
});
|
|
3838
|
+
});
|
|
1719
3839
|
var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
|
|
1720
3840
|
var renderJsonOpaquePath = (value, state, dialect) => {
|
|
1721
3841
|
if (isJsonPathValue(value)) {
|
|
@@ -1724,7 +3844,7 @@ var renderJsonOpaquePath = (value, state, dialect) => {
|
|
|
1724
3844
|
if (typeof value === "string") {
|
|
1725
3845
|
return dialect.renderLiteral(value, state);
|
|
1726
3846
|
}
|
|
1727
|
-
if (
|
|
3847
|
+
if (isExpression4(value)) {
|
|
1728
3848
|
return renderExpression(value, state, dialect);
|
|
1729
3849
|
}
|
|
1730
3850
|
throw new Error("Unsupported SQL/JSON path input");
|
|
@@ -1742,7 +3862,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
|
|
|
1742
3862
|
if (source === undefined) {
|
|
1743
3863
|
throw new Error("Unsupported SQL extract expression");
|
|
1744
3864
|
}
|
|
1745
|
-
const fieldRuntime =
|
|
3865
|
+
const fieldRuntime = isExpression4(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
|
|
1746
3866
|
const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
|
|
1747
3867
|
return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
|
|
1748
3868
|
}
|
|
@@ -1780,7 +3900,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1780
3900
|
case "jsonPathText":
|
|
1781
3901
|
case "jsonAccessText":
|
|
1782
3902
|
case "jsonTraverseText": {
|
|
1783
|
-
if (!
|
|
3903
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
1784
3904
|
return;
|
|
1785
3905
|
}
|
|
1786
3906
|
const baseSql = renderExpression(base, state, dialect);
|
|
@@ -1803,7 +3923,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1803
3923
|
case "jsonKeyExists":
|
|
1804
3924
|
case "jsonHasAnyKeys":
|
|
1805
3925
|
case "jsonHasAllKeys": {
|
|
1806
|
-
if (!
|
|
3926
|
+
if (!isExpression4(base)) {
|
|
1807
3927
|
return;
|
|
1808
3928
|
}
|
|
1809
3929
|
const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
|
|
@@ -1829,7 +3949,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1829
3949
|
}
|
|
1830
3950
|
case "jsonConcat":
|
|
1831
3951
|
case "jsonMerge": {
|
|
1832
|
-
if (!
|
|
3952
|
+
if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
|
|
1833
3953
|
return;
|
|
1834
3954
|
}
|
|
1835
3955
|
if (dialect.name === "postgres") {
|
|
@@ -1844,7 +3964,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1844
3964
|
const entries = Array.isArray(ast.entries) ? ast.entries : [];
|
|
1845
3965
|
const renderedEntries = entries.flatMap((entry) => [
|
|
1846
3966
|
dialect.renderLiteral(entry.key, state),
|
|
1847
|
-
|
|
3967
|
+
renderJsonInputExpression(entry.value, state, dialect)
|
|
1848
3968
|
]);
|
|
1849
3969
|
if (dialect.name === "postgres") {
|
|
1850
3970
|
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_object(${renderedEntries.join(", ")})`;
|
|
@@ -1856,7 +3976,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1856
3976
|
}
|
|
1857
3977
|
case "jsonBuildArray": {
|
|
1858
3978
|
const values = Array.isArray(ast.values) ? ast.values : [];
|
|
1859
|
-
const renderedValues = values.map((value) =>
|
|
3979
|
+
const renderedValues = values.map((value) => renderJsonInputExpression(value, state, dialect)).join(", ");
|
|
1860
3980
|
if (dialect.name === "postgres") {
|
|
1861
3981
|
return `${postgresExpressionKind === "jsonb" ? "jsonb" : "json"}_build_array(${renderedValues})`;
|
|
1862
3982
|
}
|
|
@@ -1866,29 +3986,29 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1866
3986
|
return;
|
|
1867
3987
|
}
|
|
1868
3988
|
case "jsonToJson":
|
|
1869
|
-
if (!
|
|
3989
|
+
if (!isExpression4(base)) {
|
|
1870
3990
|
return;
|
|
1871
3991
|
}
|
|
1872
3992
|
if (dialect.name === "postgres") {
|
|
1873
|
-
return `to_json(${
|
|
3993
|
+
return `to_json(${renderJsonInputExpression(base, state, dialect)})`;
|
|
1874
3994
|
}
|
|
1875
3995
|
if (dialect.name === "mysql") {
|
|
1876
3996
|
return `cast(${renderExpression(base, state, dialect)} as json)`;
|
|
1877
3997
|
}
|
|
1878
3998
|
return;
|
|
1879
3999
|
case "jsonToJsonb":
|
|
1880
|
-
if (!
|
|
4000
|
+
if (!isExpression4(base)) {
|
|
1881
4001
|
return;
|
|
1882
4002
|
}
|
|
1883
4003
|
if (dialect.name === "postgres") {
|
|
1884
|
-
return `to_jsonb(${
|
|
4004
|
+
return `to_jsonb(${renderJsonInputExpression(base, state, dialect)})`;
|
|
1885
4005
|
}
|
|
1886
4006
|
if (dialect.name === "mysql") {
|
|
1887
4007
|
return `cast(${renderExpression(base, state, dialect)} as json)`;
|
|
1888
4008
|
}
|
|
1889
4009
|
return;
|
|
1890
4010
|
case "jsonTypeOf":
|
|
1891
|
-
if (!
|
|
4011
|
+
if (!isExpression4(base)) {
|
|
1892
4012
|
return;
|
|
1893
4013
|
}
|
|
1894
4014
|
if (dialect.name === "postgres") {
|
|
@@ -1900,7 +4020,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1900
4020
|
}
|
|
1901
4021
|
return;
|
|
1902
4022
|
case "jsonLength":
|
|
1903
|
-
if (!
|
|
4023
|
+
if (!isExpression4(base)) {
|
|
1904
4024
|
return;
|
|
1905
4025
|
}
|
|
1906
4026
|
if (dialect.name === "postgres") {
|
|
@@ -1915,21 +4035,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1915
4035
|
}
|
|
1916
4036
|
return;
|
|
1917
4037
|
case "jsonKeys":
|
|
1918
|
-
if (!
|
|
4038
|
+
if (!isExpression4(base)) {
|
|
1919
4039
|
return;
|
|
1920
4040
|
}
|
|
1921
4041
|
if (dialect.name === "postgres") {
|
|
1922
4042
|
const baseSql = renderExpression(base, state, dialect);
|
|
1923
4043
|
const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
|
|
1924
4044
|
const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
|
|
1925
|
-
return `(case when ${typeOf}(${baseSql}) = 'object' then array(select ${objectKeys}(${baseSql})) else null end)`;
|
|
4045
|
+
return `(case when ${typeOf}(${baseSql}) = 'object' then to_json(array(select ${objectKeys}(${baseSql}))) else null end)`;
|
|
1926
4046
|
}
|
|
1927
4047
|
if (dialect.name === "mysql") {
|
|
1928
4048
|
return `json_keys(${renderExpression(base, state, dialect)})`;
|
|
1929
4049
|
}
|
|
1930
4050
|
return;
|
|
1931
4051
|
case "jsonStripNulls":
|
|
1932
|
-
if (!
|
|
4052
|
+
if (!isExpression4(base)) {
|
|
1933
4053
|
return;
|
|
1934
4054
|
}
|
|
1935
4055
|
if (dialect.name === "postgres") {
|
|
@@ -1940,14 +4060,14 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1940
4060
|
case "jsonDelete":
|
|
1941
4061
|
case "jsonDeletePath":
|
|
1942
4062
|
case "jsonRemove": {
|
|
1943
|
-
if (!
|
|
4063
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
1944
4064
|
return;
|
|
1945
4065
|
}
|
|
1946
4066
|
if (dialect.name === "postgres") {
|
|
1947
4067
|
const baseSql = renderPostgresJsonValue(base, state, dialect);
|
|
1948
4068
|
if (segments.length === 1 && (segments[0].kind === "key" || segments[0].kind === "index")) {
|
|
1949
4069
|
const segment = segments[0];
|
|
1950
|
-
return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(
|
|
4070
|
+
return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(segment.index, state)})`;
|
|
1951
4071
|
}
|
|
1952
4072
|
return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
|
|
1953
4073
|
}
|
|
@@ -1958,11 +4078,11 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1958
4078
|
}
|
|
1959
4079
|
case "jsonSet":
|
|
1960
4080
|
case "jsonInsert": {
|
|
1961
|
-
if (!
|
|
4081
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
1962
4082
|
return;
|
|
1963
4083
|
}
|
|
1964
4084
|
const nextValue = extractJsonValue(ast);
|
|
1965
|
-
if (!
|
|
4085
|
+
if (!isExpression4(nextValue)) {
|
|
1966
4086
|
return;
|
|
1967
4087
|
}
|
|
1968
4088
|
const createMissing = ast.createMissing === true;
|
|
@@ -1979,7 +4099,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1979
4099
|
return;
|
|
1980
4100
|
}
|
|
1981
4101
|
case "jsonPathExists": {
|
|
1982
|
-
if (!
|
|
4102
|
+
if (!isExpression4(base)) {
|
|
1983
4103
|
return;
|
|
1984
4104
|
}
|
|
1985
4105
|
const path2 = ast.path ?? ast.query ?? ast.right;
|
|
@@ -1995,7 +4115,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
1995
4115
|
return;
|
|
1996
4116
|
}
|
|
1997
4117
|
case "jsonPathMatch": {
|
|
1998
|
-
if (!
|
|
4118
|
+
if (!isExpression4(base)) {
|
|
1999
4119
|
return;
|
|
2000
4120
|
}
|
|
2001
4121
|
const path2 = ast.path ?? ast.query ?? ast.right;
|
|
@@ -2022,6 +4142,11 @@ var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) =
|
|
|
2022
4142
|
var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
|
|
2023
4143
|
var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
|
|
2024
4144
|
var renderDeleteTargets = (targets, dialect) => targets.map((target) => dialect.quoteIdentifier(target.tableName)).join(", ");
|
|
4145
|
+
var assertMergeActionKind = (kind, allowed) => {
|
|
4146
|
+
if (typeof kind !== "string" || !allowed.includes(kind)) {
|
|
4147
|
+
throw new Error("Unsupported merge action kind");
|
|
4148
|
+
}
|
|
4149
|
+
};
|
|
2025
4150
|
var renderMysqlMutationLock = (lock, statement) => {
|
|
2026
4151
|
if (!lock) {
|
|
2027
4152
|
return "";
|
|
@@ -2041,8 +4166,9 @@ var renderTransactionClause = (clause, dialect) => {
|
|
|
2041
4166
|
switch (clause.kind) {
|
|
2042
4167
|
case "transaction": {
|
|
2043
4168
|
const modes = [];
|
|
2044
|
-
|
|
2045
|
-
|
|
4169
|
+
const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
|
|
4170
|
+
if (isolationLevel) {
|
|
4171
|
+
modes.push(isolationLevel);
|
|
2046
4172
|
}
|
|
2047
4173
|
if (clause.readOnly === true) {
|
|
2048
4174
|
modes.push("read only");
|
|
@@ -2060,21 +4186,101 @@ var renderTransactionClause = (clause, dialect) => {
|
|
|
2060
4186
|
case "releaseSavepoint":
|
|
2061
4187
|
return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
|
|
2062
4188
|
}
|
|
2063
|
-
|
|
4189
|
+
throw new Error("Unsupported transaction statement kind");
|
|
2064
4190
|
};
|
|
2065
4191
|
var renderSelectionList = (selection, state, dialect, validateAggregation) => {
|
|
2066
4192
|
if (validateAggregation) {
|
|
2067
4193
|
validateAggregationSelection(selection, []);
|
|
2068
4194
|
}
|
|
2069
4195
|
const flattened = flattenSelection(selection);
|
|
4196
|
+
if (dialect.name === "mysql" && flattened.length === 0) {
|
|
4197
|
+
throw new Error("mysql select statements require at least one selected expression");
|
|
4198
|
+
}
|
|
2070
4199
|
const projections = selectionProjections(selection);
|
|
2071
|
-
const sql = flattened.map(({ expression, alias: alias2 }) => `${renderExpression(expression, state, dialect)} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
|
|
4200
|
+
const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
|
|
2072
4201
|
return {
|
|
2073
4202
|
sql,
|
|
2074
4203
|
projections
|
|
2075
4204
|
};
|
|
2076
4205
|
};
|
|
2077
|
-
var
|
|
4206
|
+
var nestedRenderState = (state) => ({
|
|
4207
|
+
params: state.params,
|
|
4208
|
+
valueMappings: state.valueMappings,
|
|
4209
|
+
ctes: [],
|
|
4210
|
+
cteNames: new Set(state.cteNames),
|
|
4211
|
+
cteSources: new Map(state.cteSources)
|
|
4212
|
+
});
|
|
4213
|
+
var assertMatchingSetProjections = (left, right) => {
|
|
4214
|
+
const leftKeys = left.map((projection) => JSON.stringify(projection.path));
|
|
4215
|
+
const rightKeys = right.map((projection) => JSON.stringify(projection.path));
|
|
4216
|
+
if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index3) => key2 !== rightKeys[index3])) {
|
|
4217
|
+
throw new Error("set operator operands must have matching result rows");
|
|
4218
|
+
}
|
|
4219
|
+
};
|
|
4220
|
+
var assertNoGroupedMutationClauses = (ast, statement) => {
|
|
4221
|
+
if (ast.groupBy.length > 0) {
|
|
4222
|
+
throw new Error(`groupBy(...) is not supported for ${statement} statements`);
|
|
4223
|
+
}
|
|
4224
|
+
if (ast.having.length > 0) {
|
|
4225
|
+
throw new Error(`having(...) is not supported for ${statement} statements`);
|
|
4226
|
+
}
|
|
4227
|
+
};
|
|
4228
|
+
var assertNoInsertQueryClauses = (ast) => {
|
|
4229
|
+
if (ast.where.length > 0) {
|
|
4230
|
+
throw new Error("where(...) is not supported for insert statements");
|
|
4231
|
+
}
|
|
4232
|
+
if (ast.joins.length > 0) {
|
|
4233
|
+
throw new Error("join(...) is not supported for insert statements");
|
|
4234
|
+
}
|
|
4235
|
+
if (ast.orderBy.length > 0) {
|
|
4236
|
+
throw new Error("orderBy(...) is not supported for insert statements");
|
|
4237
|
+
}
|
|
4238
|
+
if (ast.limit) {
|
|
4239
|
+
throw new Error("limit(...) is not supported for insert statements");
|
|
4240
|
+
}
|
|
4241
|
+
if (ast.offset) {
|
|
4242
|
+
throw new Error("offset(...) is not supported for insert statements");
|
|
4243
|
+
}
|
|
4244
|
+
if (ast.lock) {
|
|
4245
|
+
throw new Error("lock(...) is not supported for insert statements");
|
|
4246
|
+
}
|
|
4247
|
+
};
|
|
4248
|
+
var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
|
|
4249
|
+
if (ast.distinct) {
|
|
4250
|
+
throw new Error(`distinct(...) is not supported for ${statement} statements`);
|
|
4251
|
+
}
|
|
4252
|
+
if (ast.where.length > 0) {
|
|
4253
|
+
throw new Error(`where(...) is not supported for ${statement} statements`);
|
|
4254
|
+
}
|
|
4255
|
+
if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
|
|
4256
|
+
throw new Error(`from(...) is not supported for ${statement} statements`);
|
|
4257
|
+
}
|
|
4258
|
+
if (ast.joins.length > 0) {
|
|
4259
|
+
throw new Error(`join(...) is not supported for ${statement} statements`);
|
|
4260
|
+
}
|
|
4261
|
+
if (ast.groupBy.length > 0) {
|
|
4262
|
+
throw new Error(`groupBy(...) is not supported for ${statement} statements`);
|
|
4263
|
+
}
|
|
4264
|
+
if (ast.having.length > 0) {
|
|
4265
|
+
throw new Error(`having(...) is not supported for ${statement} statements`);
|
|
4266
|
+
}
|
|
4267
|
+
if (ast.orderBy.length > 0) {
|
|
4268
|
+
throw new Error(`orderBy(...) is not supported for ${statement} statements`);
|
|
4269
|
+
}
|
|
4270
|
+
if (ast.limit) {
|
|
4271
|
+
throw new Error(`limit(...) is not supported for ${statement} statements`);
|
|
4272
|
+
}
|
|
4273
|
+
if (ast.offset) {
|
|
4274
|
+
throw new Error(`offset(...) is not supported for ${statement} statements`);
|
|
4275
|
+
}
|
|
4276
|
+
if (ast.lock) {
|
|
4277
|
+
throw new Error(`lock(...) is not supported for ${statement} statements`);
|
|
4278
|
+
}
|
|
4279
|
+
if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
|
|
4280
|
+
throw new Error(`returning(...) is not supported for ${statement} statements`);
|
|
4281
|
+
}
|
|
4282
|
+
};
|
|
4283
|
+
var renderQueryAst = (ast, state, dialect, options2 = {}) => {
|
|
2078
4284
|
let sql = "";
|
|
2079
4285
|
let projections = [];
|
|
2080
4286
|
switch (ast.kind) {
|
|
@@ -2082,8 +4288,9 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2082
4288
|
validateAggregationSelection(ast.select, ast.groupBy);
|
|
2083
4289
|
const rendered = renderSelectionList(ast.select, state, dialect, false);
|
|
2084
4290
|
projections = rendered.projections;
|
|
4291
|
+
const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
|
|
2085
4292
|
const clauses = [
|
|
2086
|
-
ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})
|
|
4293
|
+
ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
|
|
2087
4294
|
];
|
|
2088
4295
|
if (ast.from) {
|
|
2089
4296
|
clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
|
|
@@ -2111,19 +4318,25 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2111
4318
|
clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
|
|
2112
4319
|
}
|
|
2113
4320
|
if (ast.lock) {
|
|
2114
|
-
|
|
4321
|
+
if (ast.lock.nowait && ast.lock.skipLocked) {
|
|
4322
|
+
throw new Error("lock(...) cannot specify both nowait and skipLocked");
|
|
4323
|
+
}
|
|
4324
|
+
clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
|
|
2115
4325
|
}
|
|
2116
4326
|
sql = clauses.join(" ");
|
|
2117
4327
|
break;
|
|
2118
4328
|
}
|
|
2119
4329
|
case "set": {
|
|
2120
4330
|
const setAst = ast;
|
|
4331
|
+
assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
|
|
2121
4332
|
const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
|
|
2122
4333
|
projections = selectionProjections(setAst.select);
|
|
4334
|
+
assertMatchingSetProjections(projections, base.projections);
|
|
2123
4335
|
sql = [
|
|
2124
4336
|
`(${base.sql})`,
|
|
2125
4337
|
...(setAst.setOperations ?? []).map((entry) => {
|
|
2126
4338
|
const rendered = renderQueryAst(getAst(entry.query), state, dialect);
|
|
4339
|
+
assertMatchingSetProjections(projections, rendered.projections);
|
|
2127
4340
|
return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
|
|
2128
4341
|
})
|
|
2129
4342
|
].join(" ");
|
|
@@ -2131,28 +4344,34 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2131
4344
|
}
|
|
2132
4345
|
case "insert": {
|
|
2133
4346
|
const insertAst = ast;
|
|
4347
|
+
if (insertAst.distinct) {
|
|
4348
|
+
throw new Error("distinct(...) is not supported for insert statements");
|
|
4349
|
+
}
|
|
4350
|
+
assertNoGroupedMutationClauses(insertAst, "insert");
|
|
4351
|
+
assertNoInsertQueryClauses(insertAst);
|
|
2134
4352
|
const targetSource = insertAst.into;
|
|
2135
4353
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
4354
|
+
const insertSource = expectInsertSourceKind(insertAst.insertSource);
|
|
4355
|
+
const conflict = expectConflictClause(insertAst.conflict);
|
|
2136
4356
|
sql = `insert into ${target}`;
|
|
2137
|
-
if (
|
|
2138
|
-
const columns =
|
|
2139
|
-
const rows =
|
|
4357
|
+
if (insertSource?.kind === "values") {
|
|
4358
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4359
|
+
const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
|
|
2140
4360
|
sql += ` (${columns}) values ${rows}`;
|
|
2141
|
-
} else if (
|
|
2142
|
-
const columns =
|
|
2143
|
-
const renderedQuery = renderQueryAst(getAst(
|
|
4361
|
+
} else if (insertSource?.kind === "query") {
|
|
4362
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4363
|
+
const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
|
|
2144
4364
|
sql += ` (${columns}) ${renderedQuery.sql}`;
|
|
2145
|
-
} else if (
|
|
2146
|
-
const
|
|
2147
|
-
const columns = unnestSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4365
|
+
} else if (insertSource?.kind === "unnest") {
|
|
4366
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
2148
4367
|
if (dialect.name === "postgres") {
|
|
2149
4368
|
const table = targetSource.source;
|
|
2150
4369
|
const fields = table[TypeId4].fields;
|
|
2151
|
-
const rendered =
|
|
4370
|
+
const rendered = insertSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName], state, dialect), state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
|
|
2152
4371
|
sql += ` (${columns}) select * from unnest(${rendered})`;
|
|
2153
4372
|
} else {
|
|
2154
|
-
const rowCount =
|
|
2155
|
-
const rows = Array.from({ length: rowCount }, (_, index3) => `(${
|
|
4373
|
+
const rowCount = insertSource.values[0]?.values.length ?? 0;
|
|
4374
|
+
const rows = Array.from({ length: rowCount }, (_, index3) => `(${insertSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
|
|
2156
4375
|
sql += ` (${columns}) values ${rows}`;
|
|
2157
4376
|
}
|
|
2158
4377
|
} else {
|
|
@@ -2164,13 +4383,16 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2164
4383
|
sql += " default values";
|
|
2165
4384
|
}
|
|
2166
4385
|
}
|
|
2167
|
-
if (
|
|
2168
|
-
|
|
4386
|
+
if (conflict) {
|
|
4387
|
+
if (conflict.action === "doNothing" && conflict.where) {
|
|
4388
|
+
throw new Error("conflict action predicates require update assignments");
|
|
4389
|
+
}
|
|
4390
|
+
const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
|
|
2169
4391
|
if (dialect.name === "postgres") {
|
|
2170
|
-
const targetSql =
|
|
4392
|
+
const targetSql = conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(conflict.target.name)}` : conflict.target?.kind === "columns" ? ` on conflict (${conflict.target.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${conflict.target.where ? ` where ${renderExpression(conflict.target.where, state, dialect)}` : ""}` : " on conflict";
|
|
2171
4393
|
sql += targetSql;
|
|
2172
|
-
sql +=
|
|
2173
|
-
} else if (
|
|
4394
|
+
sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
|
|
4395
|
+
} else if (conflict.action === "doNothing") {
|
|
2174
4396
|
sql = sql.replace(/^insert/, "insert ignore");
|
|
2175
4397
|
} else {
|
|
2176
4398
|
sql += ` on duplicate key update ${updateValues}`;
|
|
@@ -2185,10 +4407,29 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2185
4407
|
}
|
|
2186
4408
|
case "update": {
|
|
2187
4409
|
const updateAst = ast;
|
|
4410
|
+
if (updateAst.distinct) {
|
|
4411
|
+
throw new Error("distinct(...) is not supported for update statements");
|
|
4412
|
+
}
|
|
4413
|
+
assertNoGroupedMutationClauses(updateAst, "update");
|
|
4414
|
+
if (updateAst.orderBy.length > 0) {
|
|
4415
|
+
throw new Error("orderBy(...) is not supported for update statements");
|
|
4416
|
+
}
|
|
4417
|
+
if (updateAst.limit) {
|
|
4418
|
+
throw new Error("limit(...) is not supported for update statements");
|
|
4419
|
+
}
|
|
4420
|
+
if (updateAst.offset) {
|
|
4421
|
+
throw new Error("offset(...) is not supported for update statements");
|
|
4422
|
+
}
|
|
4423
|
+
if (updateAst.lock) {
|
|
4424
|
+
throw new Error("lock(...) is not supported for update statements");
|
|
4425
|
+
}
|
|
2188
4426
|
const targetSource = updateAst.target;
|
|
2189
4427
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
2190
4428
|
const targets = updateAst.targets ?? [targetSource];
|
|
2191
4429
|
const fromSources = updateAst.fromSources ?? [];
|
|
4430
|
+
if ((updateAst.set ?? []).length === 0) {
|
|
4431
|
+
throw new Error("update statements require at least one assignment");
|
|
4432
|
+
}
|
|
2192
4433
|
const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
|
|
2193
4434
|
if (dialect.name === "mysql") {
|
|
2194
4435
|
const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
|
|
@@ -2231,6 +4472,22 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2231
4472
|
}
|
|
2232
4473
|
case "delete": {
|
|
2233
4474
|
const deleteAst = ast;
|
|
4475
|
+
if (deleteAst.distinct) {
|
|
4476
|
+
throw new Error("distinct(...) is not supported for delete statements");
|
|
4477
|
+
}
|
|
4478
|
+
assertNoGroupedMutationClauses(deleteAst, "delete");
|
|
4479
|
+
if (deleteAst.orderBy.length > 0 && dialect.name === "postgres") {
|
|
4480
|
+
throw new Error("orderBy(...) is not supported for delete statements");
|
|
4481
|
+
}
|
|
4482
|
+
if (deleteAst.limit && dialect.name === "postgres") {
|
|
4483
|
+
throw new Error("limit(...) is not supported for delete statements");
|
|
4484
|
+
}
|
|
4485
|
+
if (deleteAst.offset) {
|
|
4486
|
+
throw new Error("offset(...) is not supported for delete statements");
|
|
4487
|
+
}
|
|
4488
|
+
if (deleteAst.lock) {
|
|
4489
|
+
throw new Error("lock(...) is not supported for delete statements");
|
|
4490
|
+
}
|
|
2234
4491
|
const targetSource = deleteAst.target;
|
|
2235
4492
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
2236
4493
|
const targets = deleteAst.targets ?? [targetSource];
|
|
@@ -2269,12 +4526,14 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2269
4526
|
}
|
|
2270
4527
|
case "truncate": {
|
|
2271
4528
|
const truncateAst = ast;
|
|
4529
|
+
assertNoStatementQueryClauses(truncateAst, "truncate");
|
|
4530
|
+
const truncate = expectTruncateClause(truncateAst.truncate);
|
|
2272
4531
|
const targetSource = truncateAst.target;
|
|
2273
4532
|
sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
|
|
2274
|
-
if (
|
|
4533
|
+
if (truncate.restartIdentity) {
|
|
2275
4534
|
sql += " restart identity";
|
|
2276
4535
|
}
|
|
2277
|
-
if (
|
|
4536
|
+
if (truncate.cascade) {
|
|
2278
4537
|
sql += " cascade";
|
|
2279
4538
|
}
|
|
2280
4539
|
break;
|
|
@@ -2287,8 +4546,18 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2287
4546
|
const targetSource = mergeAst.target;
|
|
2288
4547
|
const usingSource = mergeAst.using;
|
|
2289
4548
|
const merge = mergeAst.merge;
|
|
4549
|
+
if (merge.kind !== "merge") {
|
|
4550
|
+
throw new Error("Unsupported merge statement kind");
|
|
4551
|
+
}
|
|
4552
|
+
if (Object.keys(mergeAst.select).length > 0) {
|
|
4553
|
+
throw new Error("returning(...) is not supported for merge statements");
|
|
4554
|
+
}
|
|
4555
|
+
if (!merge.whenMatched && !merge.whenNotMatched) {
|
|
4556
|
+
throw new Error("merge statements require at least one action");
|
|
4557
|
+
}
|
|
2290
4558
|
sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression(merge.on, state, dialect)}`;
|
|
2291
4559
|
if (merge.whenMatched) {
|
|
4560
|
+
assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
|
|
2292
4561
|
sql += " when matched";
|
|
2293
4562
|
if (merge.whenMatched.predicate) {
|
|
2294
4563
|
sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
|
|
@@ -2296,14 +4565,21 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2296
4565
|
if (merge.whenMatched.kind === "delete") {
|
|
2297
4566
|
sql += " then delete";
|
|
2298
4567
|
} else {
|
|
4568
|
+
if (merge.whenMatched.values.length === 0) {
|
|
4569
|
+
throw new Error("merge update actions require at least one assignment");
|
|
4570
|
+
}
|
|
2299
4571
|
sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
|
|
2300
4572
|
}
|
|
2301
4573
|
}
|
|
2302
4574
|
if (merge.whenNotMatched) {
|
|
4575
|
+
assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
|
|
2303
4576
|
sql += " when not matched";
|
|
2304
4577
|
if (merge.whenNotMatched.predicate) {
|
|
2305
4578
|
sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
|
|
2306
4579
|
}
|
|
4580
|
+
if (merge.whenNotMatched.values.length === 0) {
|
|
4581
|
+
throw new Error("merge insert actions require at least one value");
|
|
4582
|
+
}
|
|
2307
4583
|
sql += ` then insert (${merge.whenNotMatched.values.map((entry) => dialect.quoteIdentifier(entry.columnName)).join(", ")}) values (${merge.whenNotMatched.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`;
|
|
2308
4584
|
}
|
|
2309
4585
|
break;
|
|
@@ -2314,32 +4590,40 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2314
4590
|
case "savepoint":
|
|
2315
4591
|
case "rollbackTo":
|
|
2316
4592
|
case "releaseSavepoint": {
|
|
4593
|
+
assertNoStatementQueryClauses(ast, ast.kind);
|
|
2317
4594
|
sql = renderTransactionClause(ast.transaction, dialect);
|
|
2318
4595
|
break;
|
|
2319
4596
|
}
|
|
2320
4597
|
case "createTable": {
|
|
2321
4598
|
const createTableAst = ast;
|
|
2322
|
-
|
|
4599
|
+
assertNoStatementQueryClauses(createTableAst, "createTable");
|
|
4600
|
+
const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
|
|
4601
|
+
sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
|
|
2323
4602
|
break;
|
|
2324
4603
|
}
|
|
2325
4604
|
case "dropTable": {
|
|
2326
4605
|
const dropTableAst = ast;
|
|
2327
|
-
|
|
2328
|
-
|
|
4606
|
+
assertNoStatementQueryClauses(dropTableAst, "dropTable");
|
|
4607
|
+
const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
|
|
4608
|
+
sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
|
|
2329
4609
|
break;
|
|
2330
4610
|
}
|
|
2331
4611
|
case "createIndex": {
|
|
2332
4612
|
const createIndexAst = ast;
|
|
2333
|
-
|
|
4613
|
+
assertNoStatementQueryClauses(createIndexAst, "createIndex");
|
|
4614
|
+
sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
|
|
2334
4615
|
break;
|
|
2335
4616
|
}
|
|
2336
4617
|
case "dropIndex": {
|
|
2337
4618
|
const dropIndexAst = ast;
|
|
2338
|
-
|
|
4619
|
+
assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
|
|
4620
|
+
sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
|
|
2339
4621
|
break;
|
|
2340
4622
|
}
|
|
4623
|
+
default:
|
|
4624
|
+
throw new Error("Unsupported query statement kind");
|
|
2341
4625
|
}
|
|
2342
|
-
if (state.ctes.length === 0) {
|
|
4626
|
+
if (state.ctes.length === 0 || options2.emitCtes === false) {
|
|
2343
4627
|
return {
|
|
2344
4628
|
sql,
|
|
2345
4629
|
projections
|
|
@@ -2362,9 +4646,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2362
4646
|
};
|
|
2363
4647
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
|
|
2364
4648
|
const cte = source;
|
|
4649
|
+
const registeredCteSource = state.cteSources.get(cte.name);
|
|
4650
|
+
if (registeredCteSource !== undefined && registeredCteSource !== cte.plan) {
|
|
4651
|
+
throw new Error(`common table expression name is already registered with a different plan: ${cte.name}`);
|
|
4652
|
+
}
|
|
2365
4653
|
if (!state.cteNames.has(cte.name)) {
|
|
2366
4654
|
state.cteNames.add(cte.name);
|
|
2367
|
-
|
|
4655
|
+
state.cteSources.set(cte.name, cte.plan);
|
|
4656
|
+
const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
|
|
2368
4657
|
state.ctes.push({
|
|
2369
4658
|
name: cte.name,
|
|
2370
4659
|
sql: rendered.sql,
|
|
@@ -2376,11 +4665,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2376
4665
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
|
|
2377
4666
|
const derived = source;
|
|
2378
4667
|
if (!state.cteNames.has(derived.name)) {}
|
|
2379
|
-
return `(${renderQueryAst(getAst(derived.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
|
|
4668
|
+
return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
|
|
2380
4669
|
}
|
|
2381
4670
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
|
|
2382
4671
|
const lateral = source;
|
|
2383
|
-
return `lateral (${renderQueryAst(getAst(lateral.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
|
|
4672
|
+
return `lateral (${renderQueryAst(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
|
|
2384
4673
|
}
|
|
2385
4674
|
if (typeof source === "object" && source !== null && source.kind === "values") {
|
|
2386
4675
|
const values = source;
|
|
@@ -2401,6 +4690,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2401
4690
|
const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
|
|
2402
4691
|
return dialect.renderTableReference(tableName, baseTableName, schemaName);
|
|
2403
4692
|
};
|
|
4693
|
+
var renderSubqueryExpressionPlan = (plan, state, dialect) => {
|
|
4694
|
+
const statement = getQueryState(plan).statement;
|
|
4695
|
+
if (statement !== "select" && statement !== "set") {
|
|
4696
|
+
throw new Error("subquery expressions only accept select-like query plans");
|
|
4697
|
+
}
|
|
4698
|
+
return renderQueryAst(getAst(plan), state, dialect).sql;
|
|
4699
|
+
};
|
|
2404
4700
|
var renderExpression = (expression, state, dialect) => {
|
|
2405
4701
|
const rawAst = expression[TypeId3];
|
|
2406
4702
|
const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
|
|
@@ -2411,9 +4707,12 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2411
4707
|
const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
|
|
2412
4708
|
switch (ast.kind) {
|
|
2413
4709
|
case "column":
|
|
2414
|
-
return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
4710
|
+
return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
2415
4711
|
case "literal":
|
|
2416
|
-
|
|
4712
|
+
if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
|
|
4713
|
+
throw new Error("Expected a finite numeric value");
|
|
4714
|
+
}
|
|
4715
|
+
return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
|
|
2417
4716
|
case "excluded":
|
|
2418
4717
|
return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
2419
4718
|
case "cast":
|
|
@@ -2452,6 +4751,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2452
4751
|
return dialect.name === "mysql" ? `(${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} is not distinct from ${renderExpression(ast.right, state, dialect)})`;
|
|
2453
4752
|
case "contains":
|
|
2454
4753
|
if (dialect.name === "postgres") {
|
|
4754
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
2455
4755
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
2456
4756
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
2457
4757
|
return `(${left} @> ${right})`;
|
|
@@ -2462,6 +4762,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2462
4762
|
throw new Error("Unsupported container operator for SQL rendering");
|
|
2463
4763
|
case "containedBy":
|
|
2464
4764
|
if (dialect.name === "postgres") {
|
|
4765
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
2465
4766
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
2466
4767
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
2467
4768
|
return `(${left} <@ ${right})`;
|
|
@@ -2472,6 +4773,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2472
4773
|
throw new Error("Unsupported container operator for SQL rendering");
|
|
2473
4774
|
case "overlaps":
|
|
2474
4775
|
if (dialect.name === "postgres") {
|
|
4776
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
2475
4777
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
2476
4778
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
2477
4779
|
return `(${left} && ${right})`;
|
|
@@ -2497,14 +4799,26 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2497
4799
|
case "min":
|
|
2498
4800
|
return `min(${renderExpression(ast.value, state, dialect)})`;
|
|
2499
4801
|
case "and":
|
|
4802
|
+
if (ast.values.length === 0) {
|
|
4803
|
+
throw new Error("and(...) requires at least one predicate");
|
|
4804
|
+
}
|
|
2500
4805
|
return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
|
|
2501
4806
|
case "or":
|
|
4807
|
+
if (ast.values.length === 0) {
|
|
4808
|
+
throw new Error("or(...) requires at least one predicate");
|
|
4809
|
+
}
|
|
2502
4810
|
return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
|
|
2503
4811
|
case "coalesce":
|
|
2504
4812
|
return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
|
|
2505
4813
|
case "in":
|
|
4814
|
+
if (ast.values.length < 2) {
|
|
4815
|
+
throw new Error("in(...) requires at least one candidate value");
|
|
4816
|
+
}
|
|
2506
4817
|
return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
|
|
2507
4818
|
case "notIn":
|
|
4819
|
+
if (ast.values.length < 2) {
|
|
4820
|
+
throw new Error("notIn(...) requires at least one candidate value");
|
|
4821
|
+
}
|
|
2508
4822
|
return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
|
|
2509
4823
|
case "between":
|
|
2510
4824
|
return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
|
|
@@ -2513,15 +4827,15 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2513
4827
|
case "case":
|
|
2514
4828
|
return `case ${ast.branches.map((branch) => `when ${renderExpression(branch.when, state, dialect)} then ${renderExpression(branch.then, state, dialect)}`).join(" ")} else ${renderExpression(ast.else, state, dialect)} end`;
|
|
2515
4829
|
case "exists":
|
|
2516
|
-
return `exists (${
|
|
4830
|
+
return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
|
|
2517
4831
|
case "scalarSubquery":
|
|
2518
|
-
return `(${
|
|
4832
|
+
return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
|
|
2519
4833
|
case "inSubquery":
|
|
2520
|
-
return `(${renderExpression(ast.left, state, dialect)} in (${
|
|
4834
|
+
return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
2521
4835
|
case "comparisonAny":
|
|
2522
|
-
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${
|
|
4836
|
+
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
2523
4837
|
case "comparisonAll":
|
|
2524
|
-
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${
|
|
4838
|
+
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
2525
4839
|
case "window": {
|
|
2526
4840
|
if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
|
|
2527
4841
|
break;
|
|
@@ -2555,14 +4869,19 @@ import { parse as parse2, toSql as toSql2 } from "pgsql-ast-parser";
|
|
|
2555
4869
|
|
|
2556
4870
|
// src/postgres/internal/dialect.ts
|
|
2557
4871
|
var quoteIdentifier = (value) => `"${value.replaceAll('"', '""')}"`;
|
|
2558
|
-
var renderLiteral = (value, state) => {
|
|
2559
|
-
|
|
4872
|
+
var renderLiteral = (value, state, context = {}) => {
|
|
4873
|
+
const driverValue = toDriverValue(value, {
|
|
4874
|
+
dialect: "postgres",
|
|
4875
|
+
valueMappings: state.valueMappings,
|
|
4876
|
+
...context
|
|
4877
|
+
});
|
|
4878
|
+
if (driverValue === null) {
|
|
2560
4879
|
return "null";
|
|
2561
4880
|
}
|
|
2562
|
-
if (typeof
|
|
2563
|
-
return
|
|
4881
|
+
if (typeof driverValue === "boolean") {
|
|
4882
|
+
return driverValue ? "true" : "false";
|
|
2564
4883
|
}
|
|
2565
|
-
state.params.push(
|
|
4884
|
+
state.params.push(driverValue);
|
|
2566
4885
|
return `$${state.params.length}`;
|
|
2567
4886
|
};
|
|
2568
4887
|
var postgresDialect = {
|
|
@@ -2601,7 +4920,8 @@ var inlineLiteralDialect = {
|
|
|
2601
4920
|
var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
|
|
2602
4921
|
params: [],
|
|
2603
4922
|
ctes: [],
|
|
2604
|
-
cteNames: new Set
|
|
4923
|
+
cteNames: new Set,
|
|
4924
|
+
cteSources: new Map
|
|
2605
4925
|
}, inlineLiteralDialect);
|
|
2606
4926
|
var stripRedundantOuterParens = (value) => {
|
|
2607
4927
|
let current = value.trim();
|
|
@@ -2652,10 +4972,14 @@ var normalizeDdlExpressionSql = (expression) => {
|
|
|
2652
4972
|
};
|
|
2653
4973
|
|
|
2654
4974
|
// src/postgres/schema-management.ts
|
|
2655
|
-
import * as
|
|
4975
|
+
import * as Schema6 from "effect/Schema";
|
|
2656
4976
|
import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
|
|
2657
4977
|
var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
|
|
2658
4978
|
var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
|
|
4979
|
+
var safeUnquotedIdentifier = /^[a-z_][a-z0-9_$]*$/;
|
|
4980
|
+
var quoteIdentifier2 = (value) => `"${value.replaceAll('"', '""')}"`;
|
|
4981
|
+
var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier2(value);
|
|
4982
|
+
var renderQualifiedTypeName = (name, schemaName) => schemaName === undefined || schemaName === "public" ? renderIdentifier(name) : `${renderIdentifier(schemaName)}.${renderIdentifier(name)}`;
|
|
2659
4983
|
var EnumProto = {
|
|
2660
4984
|
pipe() {
|
|
2661
4985
|
return pipeArguments5(this, arguments);
|
|
@@ -2666,13 +4990,13 @@ var EnumProto = {
|
|
|
2666
4990
|
type() {
|
|
2667
4991
|
return {
|
|
2668
4992
|
dialect: "postgres",
|
|
2669
|
-
kind: this.
|
|
4993
|
+
kind: renderQualifiedTypeName(this.name, this.schemaName),
|
|
2670
4994
|
variant: "enum"
|
|
2671
4995
|
};
|
|
2672
4996
|
},
|
|
2673
4997
|
column() {
|
|
2674
|
-
const values = this.values.map((value) =>
|
|
2675
|
-
return makeColumnDefinition(values.length === 1 ? values[0] :
|
|
4998
|
+
const values = this.values.map((value) => Schema6.Literal(value));
|
|
4999
|
+
return makeColumnDefinition(values.length === 1 ? values[0] : Schema6.Union(...values), {
|
|
2676
5000
|
dbType: this.type(),
|
|
2677
5001
|
nullable: false,
|
|
2678
5002
|
hasDefault: false,
|
|
@@ -2680,7 +5004,7 @@ var EnumProto = {
|
|
|
2680
5004
|
primaryKey: false,
|
|
2681
5005
|
unique: false,
|
|
2682
5006
|
references: undefined,
|
|
2683
|
-
ddlType: this.
|
|
5007
|
+
ddlType: renderQualifiedTypeName(this.name, this.schemaName),
|
|
2684
5008
|
identity: undefined,
|
|
2685
5009
|
enum: {
|
|
2686
5010
|
name: this.name,
|
|
@@ -2781,17 +5105,17 @@ var fromDiscoveredValues = (values) => {
|
|
|
2781
5105
|
const enums = new Map;
|
|
2782
5106
|
for (const value of values) {
|
|
2783
5107
|
if (isEnumDefinition(value)) {
|
|
2784
|
-
enums.set(
|
|
5108
|
+
enums.set(modelIdentityKey(value.schemaName, value.name), toEnumModel(value));
|
|
2785
5109
|
} else if (isTableDefinition(value)) {
|
|
2786
5110
|
for (const enumModel of enumModelsOfTable(value)) {
|
|
2787
|
-
const key2 =
|
|
5111
|
+
const key2 = modelIdentityKey(enumModel.schemaName, enumModel.name);
|
|
2788
5112
|
const existing = enums.get(key2);
|
|
2789
5113
|
if (existing === undefined) {
|
|
2790
5114
|
enums.set(key2, enumModel);
|
|
2791
5115
|
continue;
|
|
2792
5116
|
}
|
|
2793
5117
|
if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
|
|
2794
|
-
throw new Error(`Conflicting enum definitions discovered for '${
|
|
5118
|
+
throw new Error(`Conflicting enum definitions discovered for '${enumKey(enumModel.schemaName, enumModel.name)}'`);
|
|
2795
5119
|
}
|
|
2796
5120
|
}
|
|
2797
5121
|
}
|
|
@@ -2804,6 +5128,7 @@ var fromDiscoveredValues = (values) => {
|
|
|
2804
5128
|
};
|
|
2805
5129
|
var tableKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
|
|
2806
5130
|
var enumKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
|
|
5131
|
+
var modelIdentityKey = (schemaName, name) => JSON.stringify([schemaName ?? "public", name]);
|
|
2807
5132
|
export {
|
|
2808
5133
|
toTableModel,
|
|
2809
5134
|
toEnumModel,
|