prisma-sql 1.69.0 → 1.71.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/generator.cjs +294 -263
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +294 -263
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +542 -502
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +6 -3
- package/dist/index.d.ts +6 -3
- package/dist/index.js +541 -503
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -57,235 +57,6 @@ var __async = (__this, __arguments, generator) => {
|
|
|
57
57
|
});
|
|
58
58
|
};
|
|
59
59
|
|
|
60
|
-
// src/utils/normalize-value.ts
|
|
61
|
-
var MAX_DEPTH = 20;
|
|
62
|
-
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
63
|
-
if (depth > MAX_DEPTH) {
|
|
64
|
-
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
65
|
-
}
|
|
66
|
-
if (value instanceof Date) {
|
|
67
|
-
return normalizeDateValue(value);
|
|
68
|
-
}
|
|
69
|
-
if (typeof value === "bigint") {
|
|
70
|
-
return value.toString();
|
|
71
|
-
}
|
|
72
|
-
if (Array.isArray(value)) {
|
|
73
|
-
return normalizeArrayValue(value, seen, depth);
|
|
74
|
-
}
|
|
75
|
-
if (value && typeof value === "object") {
|
|
76
|
-
return normalizeObjectValue(value, seen, depth);
|
|
77
|
-
}
|
|
78
|
-
return value;
|
|
79
|
-
}
|
|
80
|
-
function normalizeDateValue(date) {
|
|
81
|
-
const t = date.getTime();
|
|
82
|
-
if (!Number.isFinite(t)) {
|
|
83
|
-
throw new Error("Invalid Date value in SQL params");
|
|
84
|
-
}
|
|
85
|
-
return date.toISOString();
|
|
86
|
-
}
|
|
87
|
-
function normalizeArrayValue(value, seen, depth) {
|
|
88
|
-
const arrRef = value;
|
|
89
|
-
if (seen.has(arrRef)) {
|
|
90
|
-
throw new Error("Circular reference in SQL params");
|
|
91
|
-
}
|
|
92
|
-
seen.add(arrRef);
|
|
93
|
-
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
94
|
-
seen.delete(arrRef);
|
|
95
|
-
return out;
|
|
96
|
-
}
|
|
97
|
-
function normalizeObjectValue(value, seen, depth) {
|
|
98
|
-
if (value instanceof Uint8Array) return value;
|
|
99
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
100
|
-
const proto = Object.getPrototypeOf(value);
|
|
101
|
-
const isPlain = proto === Object.prototype || proto === null;
|
|
102
|
-
if (!isPlain) return value;
|
|
103
|
-
const obj = value;
|
|
104
|
-
if (seen.has(obj)) {
|
|
105
|
-
throw new Error("Circular reference in SQL params");
|
|
106
|
-
}
|
|
107
|
-
seen.add(obj);
|
|
108
|
-
const out = {};
|
|
109
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
110
|
-
out[k] = normalizeValue(v, seen, depth + 1);
|
|
111
|
-
}
|
|
112
|
-
seen.delete(obj);
|
|
113
|
-
return out;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/sql-builder-dialect.ts
|
|
117
|
-
var globalDialect = "postgres";
|
|
118
|
-
function getGlobalDialect() {
|
|
119
|
-
return globalDialect;
|
|
120
|
-
}
|
|
121
|
-
function assertNonEmpty(value, name) {
|
|
122
|
-
if (!value || value.trim().length === 0) {
|
|
123
|
-
throw new Error(`${name} is required and cannot be empty`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function arrayContains(column, value, arrayType, dialect) {
|
|
127
|
-
assertNonEmpty(column, "arrayContains column");
|
|
128
|
-
assertNonEmpty(value, "arrayContains value");
|
|
129
|
-
if (dialect === "postgres") {
|
|
130
|
-
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
131
|
-
}
|
|
132
|
-
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
133
|
-
}
|
|
134
|
-
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
135
|
-
assertNonEmpty(column, "arrayOverlaps column");
|
|
136
|
-
assertNonEmpty(value, "arrayOverlaps value");
|
|
137
|
-
if (dialect === "postgres") {
|
|
138
|
-
return `${column} && ${value}::${arrayType}`;
|
|
139
|
-
}
|
|
140
|
-
return `EXISTS (
|
|
141
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
142
|
-
JOIN json_each(${value}) AS val
|
|
143
|
-
WHERE col.value = val.value
|
|
144
|
-
)`;
|
|
145
|
-
}
|
|
146
|
-
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
147
|
-
assertNonEmpty(column, "arrayContainsAll column");
|
|
148
|
-
assertNonEmpty(value, "arrayContainsAll value");
|
|
149
|
-
if (dialect === "postgres") {
|
|
150
|
-
return `${column} @> ${value}::${arrayType}`;
|
|
151
|
-
}
|
|
152
|
-
return `NOT EXISTS (
|
|
153
|
-
SELECT 1 FROM json_each(${value}) AS val
|
|
154
|
-
WHERE NOT EXISTS (
|
|
155
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
156
|
-
WHERE col.value = val.value
|
|
157
|
-
)
|
|
158
|
-
)`;
|
|
159
|
-
}
|
|
160
|
-
function arrayIsEmpty(column, dialect) {
|
|
161
|
-
assertNonEmpty(column, "arrayIsEmpty column");
|
|
162
|
-
if (dialect === "postgres") {
|
|
163
|
-
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
164
|
-
}
|
|
165
|
-
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
166
|
-
}
|
|
167
|
-
function arrayIsNotEmpty(column, dialect) {
|
|
168
|
-
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
169
|
-
if (dialect === "postgres") {
|
|
170
|
-
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
171
|
-
}
|
|
172
|
-
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
173
|
-
}
|
|
174
|
-
function arrayEquals(column, value, arrayType, dialect) {
|
|
175
|
-
assertNonEmpty(column, "arrayEquals column");
|
|
176
|
-
assertNonEmpty(value, "arrayEquals value");
|
|
177
|
-
if (dialect === "postgres") {
|
|
178
|
-
return `${column} = ${value}::${arrayType}`;
|
|
179
|
-
}
|
|
180
|
-
return `json(${column}) = json(${value})`;
|
|
181
|
-
}
|
|
182
|
-
function caseInsensitiveLike(column, pattern, dialect) {
|
|
183
|
-
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
184
|
-
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
185
|
-
if (dialect === "postgres") {
|
|
186
|
-
return `${column} ILIKE ${pattern}`;
|
|
187
|
-
}
|
|
188
|
-
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
189
|
-
}
|
|
190
|
-
function caseInsensitiveEquals(column, value, dialect) {
|
|
191
|
-
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
192
|
-
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
193
|
-
return `LOWER(${column}) = LOWER(${value})`;
|
|
194
|
-
}
|
|
195
|
-
function jsonExtractText(column, path, dialect) {
|
|
196
|
-
assertNonEmpty(column, "jsonExtractText column");
|
|
197
|
-
assertNonEmpty(path, "jsonExtractText path");
|
|
198
|
-
if (dialect === "postgres") {
|
|
199
|
-
const p = String(path).trim();
|
|
200
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
201
|
-
return `${column}#>>${pathExpr}`;
|
|
202
|
-
}
|
|
203
|
-
return `json_extract(${column}, ${path})`;
|
|
204
|
-
}
|
|
205
|
-
function jsonExtractNumeric(column, path, dialect) {
|
|
206
|
-
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
207
|
-
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
208
|
-
if (dialect === "postgres") {
|
|
209
|
-
const p = String(path).trim();
|
|
210
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
211
|
-
return `(${column}#>>${pathExpr})::numeric`;
|
|
212
|
-
}
|
|
213
|
-
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
214
|
-
}
|
|
215
|
-
function jsonToText(column, dialect) {
|
|
216
|
-
assertNonEmpty(column, "jsonToText column");
|
|
217
|
-
if (dialect === "postgres") {
|
|
218
|
-
return `${column}::text`;
|
|
219
|
-
}
|
|
220
|
-
return column;
|
|
221
|
-
}
|
|
222
|
-
function inArray(column, value, dialect) {
|
|
223
|
-
assertNonEmpty(column, "inArray column");
|
|
224
|
-
assertNonEmpty(value, "inArray value");
|
|
225
|
-
if (dialect === "postgres") {
|
|
226
|
-
return `${column} = ANY(${value})`;
|
|
227
|
-
}
|
|
228
|
-
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
229
|
-
}
|
|
230
|
-
function notInArray(column, value, dialect) {
|
|
231
|
-
assertNonEmpty(column, "notInArray column");
|
|
232
|
-
assertNonEmpty(value, "notInArray value");
|
|
233
|
-
if (dialect === "postgres") {
|
|
234
|
-
return `${column} != ALL(${value})`;
|
|
235
|
-
}
|
|
236
|
-
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
237
|
-
}
|
|
238
|
-
function getArrayType(prismaType, dialect) {
|
|
239
|
-
if (!prismaType || prismaType.length === 0) {
|
|
240
|
-
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
241
|
-
}
|
|
242
|
-
if (dialect === "sqlite") {
|
|
243
|
-
return "TEXT";
|
|
244
|
-
}
|
|
245
|
-
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
246
|
-
switch (baseType) {
|
|
247
|
-
case "String":
|
|
248
|
-
return "text[]";
|
|
249
|
-
case "Int":
|
|
250
|
-
return "integer[]";
|
|
251
|
-
case "Float":
|
|
252
|
-
return "double precision[]";
|
|
253
|
-
case "Decimal":
|
|
254
|
-
return "numeric[]";
|
|
255
|
-
case "Boolean":
|
|
256
|
-
return "boolean[]";
|
|
257
|
-
case "BigInt":
|
|
258
|
-
return "bigint[]";
|
|
259
|
-
case "DateTime":
|
|
260
|
-
return "timestamptz[]";
|
|
261
|
-
default:
|
|
262
|
-
return `"${baseType}"[]`;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
function jsonAgg(content, dialect) {
|
|
266
|
-
assertNonEmpty(content, "jsonAgg content");
|
|
267
|
-
if (dialect === "postgres") {
|
|
268
|
-
return `json_agg(${content})`;
|
|
269
|
-
}
|
|
270
|
-
return `json_group_array(${content})`;
|
|
271
|
-
}
|
|
272
|
-
function jsonBuildObject(pairs, dialect) {
|
|
273
|
-
const safePairs = (pairs != null ? pairs : "").trim();
|
|
274
|
-
if (dialect === "postgres") {
|
|
275
|
-
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
276
|
-
}
|
|
277
|
-
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
278
|
-
}
|
|
279
|
-
function prepareArrayParam(value, dialect) {
|
|
280
|
-
if (!Array.isArray(value)) {
|
|
281
|
-
throw new Error("prepareArrayParam requires array value");
|
|
282
|
-
}
|
|
283
|
-
if (dialect === "postgres") {
|
|
284
|
-
return value.map((v) => normalizeValue(v));
|
|
285
|
-
}
|
|
286
|
-
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
287
|
-
}
|
|
288
|
-
|
|
289
60
|
// src/builder/shared/constants.ts
|
|
290
61
|
var IS_PRODUCTION = process.env.NODE_ENV === "production";
|
|
291
62
|
var SQL_SEPARATORS = Object.freeze({
|
|
@@ -1120,25 +891,276 @@ function joinCondition(field, parentModel, childModel, parentAlias, childAlias)
|
|
|
1120
891
|
{ field: field.name }
|
|
1121
892
|
);
|
|
1122
893
|
}
|
|
1123
|
-
const refFields = getReferenceFieldNames(field, fkFields.length);
|
|
1124
|
-
if (refFields.length !== fkFields.length) {
|
|
1125
|
-
throw createError(
|
|
1126
|
-
`Relation '${field.name}' is missing references (or references count does not match foreignKey count). This is required to support non-id and composite keys.`,
|
|
1127
|
-
{ field: field.name }
|
|
1128
|
-
);
|
|
894
|
+
const refFields = getReferenceFieldNames(field, fkFields.length);
|
|
895
|
+
if (refFields.length !== fkFields.length) {
|
|
896
|
+
throw createError(
|
|
897
|
+
`Relation '${field.name}' is missing references (or references count does not match foreignKey count). This is required to support non-id and composite keys.`,
|
|
898
|
+
{ field: field.name }
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
const parts = [];
|
|
902
|
+
for (let i = 0; i < fkFields.length; i++) {
|
|
903
|
+
const fk = fkFields[i];
|
|
904
|
+
const ref = refFields[i];
|
|
905
|
+
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, ref)}` : `${childAlias}.${quoteColumn(childModel, fk)}`;
|
|
906
|
+
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, fk)}` : `${parentAlias}.${quoteColumn(parentModel, ref)}`;
|
|
907
|
+
parts.push(`${left} = ${right}`);
|
|
908
|
+
}
|
|
909
|
+
return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
|
|
910
|
+
}
|
|
911
|
+
function getModelByName(schemas, name) {
|
|
912
|
+
return schemas.find((m) => m.name === name);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// src/utils/normalize-value.ts
|
|
916
|
+
var globalDateMode = "iso";
|
|
917
|
+
function setNormalizeDateMode(mode) {
|
|
918
|
+
globalDateMode = mode;
|
|
919
|
+
}
|
|
920
|
+
function detectSqliteDateMode(client) {
|
|
921
|
+
try {
|
|
922
|
+
const tables = client.prepare(
|
|
923
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_%' LIMIT 50"
|
|
924
|
+
).all();
|
|
925
|
+
for (const { name } of tables) {
|
|
926
|
+
const row = client.prepare(`SELECT typeof("createdAt") as t FROM "${name}" LIMIT 1`).get();
|
|
927
|
+
if (row) {
|
|
928
|
+
return row.t === "integer" ? "ms" : "iso";
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
} catch (e) {
|
|
932
|
+
}
|
|
933
|
+
return "iso";
|
|
934
|
+
}
|
|
935
|
+
var MAX_DEPTH = 20;
|
|
936
|
+
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
937
|
+
if (depth > MAX_DEPTH) {
|
|
938
|
+
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
939
|
+
}
|
|
940
|
+
if (value instanceof Date) {
|
|
941
|
+
return normalizeDateValue(value);
|
|
942
|
+
}
|
|
943
|
+
if (typeof value === "bigint") {
|
|
944
|
+
return value.toString();
|
|
945
|
+
}
|
|
946
|
+
if (Array.isArray(value)) {
|
|
947
|
+
return normalizeArrayValue(value, seen, depth);
|
|
948
|
+
}
|
|
949
|
+
if (value && typeof value === "object") {
|
|
950
|
+
return normalizeObjectValue(value, seen, depth);
|
|
951
|
+
}
|
|
952
|
+
return value;
|
|
953
|
+
}
|
|
954
|
+
function normalizeDateValue(date) {
|
|
955
|
+
const t = date.getTime();
|
|
956
|
+
if (!Number.isFinite(t)) {
|
|
957
|
+
throw new Error("Invalid Date value in SQL params");
|
|
958
|
+
}
|
|
959
|
+
if (globalDateMode === "ms") {
|
|
960
|
+
return t;
|
|
961
|
+
}
|
|
962
|
+
return date.toISOString();
|
|
963
|
+
}
|
|
964
|
+
function normalizeArrayValue(value, seen, depth) {
|
|
965
|
+
const arrRef = value;
|
|
966
|
+
if (seen.has(arrRef)) {
|
|
967
|
+
throw new Error("Circular reference in SQL params");
|
|
968
|
+
}
|
|
969
|
+
seen.add(arrRef);
|
|
970
|
+
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
971
|
+
seen.delete(arrRef);
|
|
972
|
+
return out;
|
|
973
|
+
}
|
|
974
|
+
function normalizeObjectValue(value, seen, depth) {
|
|
975
|
+
if (value instanceof Uint8Array) return value;
|
|
976
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
977
|
+
const proto = Object.getPrototypeOf(value);
|
|
978
|
+
const isPlain = proto === Object.prototype || proto === null;
|
|
979
|
+
if (!isPlain) return value;
|
|
980
|
+
const obj = value;
|
|
981
|
+
if (seen.has(obj)) {
|
|
982
|
+
throw new Error("Circular reference in SQL params");
|
|
983
|
+
}
|
|
984
|
+
seen.add(obj);
|
|
985
|
+
const out = {};
|
|
986
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
987
|
+
out[k] = normalizeValue(v, seen, depth + 1);
|
|
988
|
+
}
|
|
989
|
+
seen.delete(obj);
|
|
990
|
+
return out;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// src/sql-builder-dialect.ts
|
|
994
|
+
var globalDialect = "postgres";
|
|
995
|
+
function getGlobalDialect() {
|
|
996
|
+
return globalDialect;
|
|
997
|
+
}
|
|
998
|
+
function assertNonEmpty(value, name) {
|
|
999
|
+
if (!value || value.trim().length === 0) {
|
|
1000
|
+
throw new Error(`${name} is required and cannot be empty`);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function arrayContains(column, value, arrayType, dialect) {
|
|
1004
|
+
assertNonEmpty(column, "arrayContains column");
|
|
1005
|
+
assertNonEmpty(value, "arrayContains value");
|
|
1006
|
+
if (dialect === "postgres") {
|
|
1007
|
+
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
1008
|
+
}
|
|
1009
|
+
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
1010
|
+
}
|
|
1011
|
+
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
1012
|
+
assertNonEmpty(column, "arrayOverlaps column");
|
|
1013
|
+
assertNonEmpty(value, "arrayOverlaps value");
|
|
1014
|
+
if (dialect === "postgres") {
|
|
1015
|
+
return `${column} && ${value}::${arrayType}`;
|
|
1016
|
+
}
|
|
1017
|
+
return `EXISTS (
|
|
1018
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
1019
|
+
JOIN json_each(${value}) AS val
|
|
1020
|
+
WHERE col.value = val.value
|
|
1021
|
+
)`;
|
|
1022
|
+
}
|
|
1023
|
+
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
1024
|
+
assertNonEmpty(column, "arrayContainsAll column");
|
|
1025
|
+
assertNonEmpty(value, "arrayContainsAll value");
|
|
1026
|
+
if (dialect === "postgres") {
|
|
1027
|
+
return `${column} @> ${value}::${arrayType}`;
|
|
1028
|
+
}
|
|
1029
|
+
return `NOT EXISTS (
|
|
1030
|
+
SELECT 1 FROM json_each(${value}) AS val
|
|
1031
|
+
WHERE NOT EXISTS (
|
|
1032
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
1033
|
+
WHERE col.value = val.value
|
|
1034
|
+
)
|
|
1035
|
+
)`;
|
|
1036
|
+
}
|
|
1037
|
+
function arrayIsEmpty(column, dialect) {
|
|
1038
|
+
assertNonEmpty(column, "arrayIsEmpty column");
|
|
1039
|
+
if (dialect === "postgres") {
|
|
1040
|
+
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
1041
|
+
}
|
|
1042
|
+
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
1043
|
+
}
|
|
1044
|
+
function arrayIsNotEmpty(column, dialect) {
|
|
1045
|
+
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
1046
|
+
if (dialect === "postgres") {
|
|
1047
|
+
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
1048
|
+
}
|
|
1049
|
+
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
1050
|
+
}
|
|
1051
|
+
function arrayEquals(column, value, arrayType, dialect) {
|
|
1052
|
+
assertNonEmpty(column, "arrayEquals column");
|
|
1053
|
+
assertNonEmpty(value, "arrayEquals value");
|
|
1054
|
+
if (dialect === "postgres") {
|
|
1055
|
+
return `${column} = ${value}::${arrayType}`;
|
|
1056
|
+
}
|
|
1057
|
+
return `json(${column}) = json(${value})`;
|
|
1058
|
+
}
|
|
1059
|
+
function caseInsensitiveLike(column, pattern, dialect) {
|
|
1060
|
+
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
1061
|
+
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
1062
|
+
if (dialect === "postgres") {
|
|
1063
|
+
return `${column} ILIKE ${pattern}`;
|
|
1064
|
+
}
|
|
1065
|
+
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
1066
|
+
}
|
|
1067
|
+
function caseInsensitiveEquals(column, value, dialect) {
|
|
1068
|
+
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
1069
|
+
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
1070
|
+
return `LOWER(${column}) = LOWER(${value})`;
|
|
1071
|
+
}
|
|
1072
|
+
function jsonExtractText(column, path, dialect) {
|
|
1073
|
+
assertNonEmpty(column, "jsonExtractText column");
|
|
1074
|
+
assertNonEmpty(path, "jsonExtractText path");
|
|
1075
|
+
if (dialect === "postgres") {
|
|
1076
|
+
const p = String(path).trim();
|
|
1077
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
1078
|
+
return `${column}#>>${pathExpr}`;
|
|
1079
|
+
}
|
|
1080
|
+
return `json_extract(${column}, ${path})`;
|
|
1081
|
+
}
|
|
1082
|
+
function jsonExtractNumeric(column, path, dialect) {
|
|
1083
|
+
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
1084
|
+
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
1085
|
+
if (dialect === "postgres") {
|
|
1086
|
+
const p = String(path).trim();
|
|
1087
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
1088
|
+
return `(${column}#>>${pathExpr})::numeric`;
|
|
1089
|
+
}
|
|
1090
|
+
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
1091
|
+
}
|
|
1092
|
+
function jsonToText(column, dialect) {
|
|
1093
|
+
assertNonEmpty(column, "jsonToText column");
|
|
1094
|
+
if (dialect === "postgres") {
|
|
1095
|
+
return `${column}::text`;
|
|
1096
|
+
}
|
|
1097
|
+
return column;
|
|
1098
|
+
}
|
|
1099
|
+
function inArray(column, value, dialect) {
|
|
1100
|
+
assertNonEmpty(column, "inArray column");
|
|
1101
|
+
assertNonEmpty(value, "inArray value");
|
|
1102
|
+
if (dialect === "postgres") {
|
|
1103
|
+
return `${column} = ANY(${value})`;
|
|
1104
|
+
}
|
|
1105
|
+
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
1106
|
+
}
|
|
1107
|
+
function notInArray(column, value, dialect) {
|
|
1108
|
+
assertNonEmpty(column, "notInArray column");
|
|
1109
|
+
assertNonEmpty(value, "notInArray value");
|
|
1110
|
+
if (dialect === "postgres") {
|
|
1111
|
+
return `${column} != ALL(${value})`;
|
|
1112
|
+
}
|
|
1113
|
+
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
1114
|
+
}
|
|
1115
|
+
function getArrayType(prismaType, dialect) {
|
|
1116
|
+
if (!prismaType || prismaType.length === 0) {
|
|
1117
|
+
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
1118
|
+
}
|
|
1119
|
+
if (dialect === "sqlite") {
|
|
1120
|
+
return "TEXT";
|
|
1121
|
+
}
|
|
1122
|
+
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
1123
|
+
switch (baseType) {
|
|
1124
|
+
case "String":
|
|
1125
|
+
return "text[]";
|
|
1126
|
+
case "Int":
|
|
1127
|
+
return "integer[]";
|
|
1128
|
+
case "Float":
|
|
1129
|
+
return "double precision[]";
|
|
1130
|
+
case "Decimal":
|
|
1131
|
+
return "numeric[]";
|
|
1132
|
+
case "Boolean":
|
|
1133
|
+
return "boolean[]";
|
|
1134
|
+
case "BigInt":
|
|
1135
|
+
return "bigint[]";
|
|
1136
|
+
case "DateTime":
|
|
1137
|
+
return "timestamptz[]";
|
|
1138
|
+
default:
|
|
1139
|
+
return `"${baseType}"[]`;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
function jsonAgg(content, dialect) {
|
|
1143
|
+
assertNonEmpty(content, "jsonAgg content");
|
|
1144
|
+
if (dialect === "postgres") {
|
|
1145
|
+
return `json_agg(${content})`;
|
|
1129
1146
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
parts.push(`${left} = ${right}`);
|
|
1147
|
+
return `json_group_array(${content})`;
|
|
1148
|
+
}
|
|
1149
|
+
function jsonBuildObject(pairs, dialect) {
|
|
1150
|
+
const safePairs = (pairs != null ? pairs : "").trim();
|
|
1151
|
+
if (dialect === "postgres") {
|
|
1152
|
+
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
1137
1153
|
}
|
|
1138
|
-
return
|
|
1154
|
+
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
1139
1155
|
}
|
|
1140
|
-
function
|
|
1141
|
-
|
|
1156
|
+
function prepareArrayParam(value, dialect) {
|
|
1157
|
+
if (!Array.isArray(value)) {
|
|
1158
|
+
throw new Error("prepareArrayParam requires array value");
|
|
1159
|
+
}
|
|
1160
|
+
if (dialect === "postgres") {
|
|
1161
|
+
return value.map((v) => normalizeValue(v));
|
|
1162
|
+
}
|
|
1163
|
+
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
1142
1164
|
}
|
|
1143
1165
|
function normalizeIntLike(name, v, opts = {}) {
|
|
1144
1166
|
var _a3, _b;
|
|
@@ -2278,14 +2300,15 @@ function hasPaginationArgs(value) {
|
|
|
2278
2300
|
const obj = value;
|
|
2279
2301
|
return "take" in obj && obj.take != null || "skip" in obj && typeof obj.skip === "number" && obj.skip > 0;
|
|
2280
2302
|
}
|
|
2281
|
-
function buildCostTree(includeSpec, model, schemas) {
|
|
2303
|
+
function buildCostTree(includeSpec, model, schemas, depth = 0) {
|
|
2304
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return [];
|
|
2282
2305
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
2283
2306
|
const nodes = [];
|
|
2284
2307
|
for (const rel of relations) {
|
|
2285
2308
|
const fan = rel.isList ? getFanOut(model.name, rel.relName) : 1;
|
|
2286
2309
|
const take = rel.isList ? readTake(rel.value) : 1;
|
|
2287
2310
|
const eff = Math.min(fan, take);
|
|
2288
|
-
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas) : [];
|
|
2311
|
+
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(rel.nestedSpec, rel.relModel, schemas, depth + 1) : [];
|
|
2289
2312
|
nodes.push({
|
|
2290
2313
|
name: rel.relName,
|
|
2291
2314
|
fan,
|
|
@@ -2351,19 +2374,26 @@ function hasOnlyToOneRelations(includeSpec, model) {
|
|
|
2351
2374
|
}
|
|
2352
2375
|
return true;
|
|
2353
2376
|
}
|
|
2354
|
-
function countIncludeDepth(includeSpec, model, schemas) {
|
|
2377
|
+
function countIncludeDepth(includeSpec, model, schemas, depth = 0) {
|
|
2378
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return 0;
|
|
2355
2379
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
2356
2380
|
let maxDepth = 0;
|
|
2357
2381
|
for (const rel of relations) {
|
|
2358
2382
|
let childDepth = 1;
|
|
2359
2383
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
2360
|
-
childDepth += countIncludeDepth(
|
|
2384
|
+
childDepth += countIncludeDepth(
|
|
2385
|
+
rel.nestedSpec,
|
|
2386
|
+
rel.relModel,
|
|
2387
|
+
schemas,
|
|
2388
|
+
depth + 1
|
|
2389
|
+
);
|
|
2361
2390
|
}
|
|
2362
2391
|
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
2363
2392
|
}
|
|
2364
2393
|
return maxDepth;
|
|
2365
2394
|
}
|
|
2366
|
-
function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
2395
|
+
function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0) {
|
|
2396
|
+
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return false;
|
|
2367
2397
|
for (const [, value] of Object.entries(includeSpec)) {
|
|
2368
2398
|
if (value === false) continue;
|
|
2369
2399
|
if (hasPaginationArgs(value)) return true;
|
|
@@ -2371,7 +2401,12 @@ function hasChildPaginationAnywhere(includeSpec, model, schemas) {
|
|
|
2371
2401
|
const relations = resolveIncludeRelations(includeSpec, model, schemas);
|
|
2372
2402
|
for (const rel of relations) {
|
|
2373
2403
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
2374
|
-
if (hasChildPaginationAnywhere(
|
|
2404
|
+
if (hasChildPaginationAnywhere(
|
|
2405
|
+
rel.nestedSpec,
|
|
2406
|
+
rel.relModel,
|
|
2407
|
+
schemas,
|
|
2408
|
+
depth + 1
|
|
2409
|
+
)) {
|
|
2375
2410
|
return true;
|
|
2376
2411
|
}
|
|
2377
2412
|
}
|
|
@@ -6136,9 +6171,10 @@ function buildAggregateFields(args, alias, model) {
|
|
|
6136
6171
|
addAggregateFields(fields, args, alias, model);
|
|
6137
6172
|
return fields;
|
|
6138
6173
|
}
|
|
6139
|
-
function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
6174
|
+
function buildAggregateSql(args, whereResult, tableName, alias, model, dialect) {
|
|
6140
6175
|
assertSafeAlias(alias);
|
|
6141
6176
|
assertSafeTableRef(tableName);
|
|
6177
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
6142
6178
|
const aggFields = buildAggregateFields(args, alias, model);
|
|
6143
6179
|
if (!isNonEmptyArray(aggFields)) {
|
|
6144
6180
|
throw new Error("buildAggregateSql requires at least one aggregate field");
|
|
@@ -6157,7 +6193,7 @@ function buildAggregateSql(args, whereResult, tableName, alias, model) {
|
|
|
6157
6193
|
if (whereClause) parts.push(whereClause);
|
|
6158
6194
|
const sql = parts.join(" ").trim();
|
|
6159
6195
|
validateSelectQuery(sql);
|
|
6160
|
-
|
|
6196
|
+
validateParamConsistencyByDialect(sql, whereResult.params, d);
|
|
6161
6197
|
return {
|
|
6162
6198
|
sql,
|
|
6163
6199
|
params: [...whereResult.params],
|
|
@@ -6236,7 +6272,7 @@ function buildGroupBySql(args, whereResult, tableName, alias, model, dialect) {
|
|
|
6236
6272
|
const allParams = [...whereResult.params, ...snapshot.params];
|
|
6237
6273
|
const allMappings = [...whereResult.paramMappings, ...snapshot.mappings];
|
|
6238
6274
|
validateSelectQuery(sql);
|
|
6239
|
-
|
|
6275
|
+
validateParamConsistencyByDialect(sql, allParams, d);
|
|
6240
6276
|
return {
|
|
6241
6277
|
sql,
|
|
6242
6278
|
params: allParams,
|
|
@@ -6253,7 +6289,7 @@ function assertNoNegativeTake(args) {
|
|
|
6253
6289
|
throw new Error("Negative take is not supported for count()");
|
|
6254
6290
|
}
|
|
6255
6291
|
}
|
|
6256
|
-
function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
6292
|
+
function buildSimpleCountSql(whereResult, tableName, alias, dialect) {
|
|
6257
6293
|
const joinsPart = whereResult.joins && whereResult.joins.length > 0 ? whereResult.joins.join(" ") : "";
|
|
6258
6294
|
const whereClause = isValidWhereClause(whereResult.clause) ? SQL_TEMPLATES.WHERE + " " + whereResult.clause : "";
|
|
6259
6295
|
const parts = [
|
|
@@ -6269,7 +6305,7 @@ function buildSimpleCountSql(whereResult, tableName, alias) {
|
|
|
6269
6305
|
if (whereClause) parts.push(whereClause);
|
|
6270
6306
|
const sql = parts.join(" ").trim();
|
|
6271
6307
|
validateSelectQuery(sql);
|
|
6272
|
-
|
|
6308
|
+
validateParamConsistencyByDialect(sql, whereResult.params, dialect);
|
|
6273
6309
|
return {
|
|
6274
6310
|
sql,
|
|
6275
6311
|
params: [...whereResult.params],
|
|
@@ -6281,14 +6317,15 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
6281
6317
|
assertSafeTableRef(tableName);
|
|
6282
6318
|
const args = normalizeCountArgs(argsOrSkip);
|
|
6283
6319
|
assertNoNegativeTake(args);
|
|
6320
|
+
const d = dialect != null ? dialect : getGlobalDialect();
|
|
6284
6321
|
if (!model) {
|
|
6285
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
6322
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
6286
6323
|
}
|
|
6287
6324
|
const pkFields = getPrimaryKeyFields(model);
|
|
6288
6325
|
const distinctFields = isNonEmptyArray(args.distinct) ? args.distinct.map((x) => String(x)).filter((x) => x) : [];
|
|
6289
6326
|
const selectFields = distinctFields.length > 0 ? distinctFields : pkFields;
|
|
6290
6327
|
if (selectFields.length === 0) {
|
|
6291
|
-
return buildSimpleCountSql(whereResult, tableName, alias);
|
|
6328
|
+
return buildSimpleCountSql(whereResult, tableName, alias, d);
|
|
6292
6329
|
}
|
|
6293
6330
|
const select = {};
|
|
6294
6331
|
for (const f of selectFields) select[f] = true;
|
|
@@ -6296,7 +6333,6 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
6296
6333
|
include: void 0,
|
|
6297
6334
|
select
|
|
6298
6335
|
});
|
|
6299
|
-
const d = dialect != null ? dialect : getGlobalDialect();
|
|
6300
6336
|
const subSchemas = Array.isArray(schemas) && schemas.length > 0 ? schemas : [model];
|
|
6301
6337
|
const sub = buildSelectSql({
|
|
6302
6338
|
method: "findMany",
|
|
@@ -6312,7 +6348,7 @@ function buildCountSql(whereResult, tableName, alias, argsOrSkip, dialect, model
|
|
|
6312
6348
|
"_count._all"
|
|
6313
6349
|
)} ${SQL_TEMPLATES.FROM} (${sub.sql}) ${SQL_TEMPLATES.AS} ${countAlias}`;
|
|
6314
6350
|
validateSelectQuery(sql);
|
|
6315
|
-
|
|
6351
|
+
validateParamConsistencyByDialect(sql, sub.params, d);
|
|
6316
6352
|
return {
|
|
6317
6353
|
sql,
|
|
6318
6354
|
params: sub.params,
|
|
@@ -6603,7 +6639,14 @@ function buildSqlResult(args) {
|
|
|
6603
6639
|
dialect
|
|
6604
6640
|
} = args;
|
|
6605
6641
|
if (method === "aggregate") {
|
|
6606
|
-
return buildAggregateSql(
|
|
6642
|
+
return buildAggregateSql(
|
|
6643
|
+
processed,
|
|
6644
|
+
whereResult,
|
|
6645
|
+
tableName,
|
|
6646
|
+
alias,
|
|
6647
|
+
modelDef,
|
|
6648
|
+
dialect
|
|
6649
|
+
);
|
|
6607
6650
|
}
|
|
6608
6651
|
if (method === "groupBy") {
|
|
6609
6652
|
return buildGroupBySql(
|
|
@@ -7310,7 +7353,8 @@ function buildSQLFull(model, models, method, args, dialect) {
|
|
|
7310
7353
|
whereResult,
|
|
7311
7354
|
tableName,
|
|
7312
7355
|
alias,
|
|
7313
|
-
model
|
|
7356
|
+
model,
|
|
7357
|
+
dialect
|
|
7314
7358
|
);
|
|
7315
7359
|
break;
|
|
7316
7360
|
case "groupBy":
|
|
@@ -7328,8 +7372,10 @@ function buildSQLFull(model, models, method, args, dialect) {
|
|
|
7328
7372
|
whereResult,
|
|
7329
7373
|
tableName,
|
|
7330
7374
|
alias,
|
|
7331
|
-
args
|
|
7332
|
-
dialect
|
|
7375
|
+
args,
|
|
7376
|
+
dialect,
|
|
7377
|
+
model,
|
|
7378
|
+
models
|
|
7333
7379
|
);
|
|
7334
7380
|
break;
|
|
7335
7381
|
default:
|
|
@@ -7343,7 +7389,8 @@ function buildSQLFull(model, models, method, args, dialect) {
|
|
|
7343
7389
|
dialect
|
|
7344
7390
|
});
|
|
7345
7391
|
}
|
|
7346
|
-
const
|
|
7392
|
+
const needsPlaceholderConversion = dialect === "sqlite" && result.sql.includes("$");
|
|
7393
|
+
const sqlResult = needsPlaceholderConversion ? pgToSqlitePlaceholders(result.sql, result.params) : { sql: result.sql, params: [...result.params] };
|
|
7347
7394
|
return __spreadProps(__spreadValues({}, sqlResult), {
|
|
7348
7395
|
paramMappings: result.paramMappings,
|
|
7349
7396
|
requiresReduction: result.requiresReduction,
|
|
@@ -7504,68 +7551,234 @@ function validateTimeout(timeout) {
|
|
|
7504
7551
|
`Transaction timeout must be a number, got ${typeof timeout}`
|
|
7505
7552
|
);
|
|
7506
7553
|
}
|
|
7507
|
-
if (!Number.isFinite(timeout)) {
|
|
7508
|
-
throw new Error(`Transaction timeout must be finite, got ${timeout}`);
|
|
7554
|
+
if (!Number.isFinite(timeout)) {
|
|
7555
|
+
throw new Error(`Transaction timeout must be finite, got ${timeout}`);
|
|
7556
|
+
}
|
|
7557
|
+
if (timeout < 0) {
|
|
7558
|
+
throw new Error(`Transaction timeout must be non-negative, got ${timeout}`);
|
|
7559
|
+
}
|
|
7560
|
+
return Math.floor(timeout);
|
|
7561
|
+
}
|
|
7562
|
+
function createTransactionExecutor(deps) {
|
|
7563
|
+
const { modelMap, allModels, dialect, postgresClient } = deps;
|
|
7564
|
+
return {
|
|
7565
|
+
execute(queries, options) {
|
|
7566
|
+
return __async(this, null, function* () {
|
|
7567
|
+
if (queries.length === 0) return [];
|
|
7568
|
+
if (dialect !== "postgres") {
|
|
7569
|
+
throw new Error("$transaction is only supported for postgres dialect");
|
|
7570
|
+
}
|
|
7571
|
+
if (!postgresClient) {
|
|
7572
|
+
throw new Error("postgresClient is required for transactions");
|
|
7573
|
+
}
|
|
7574
|
+
const transactionCallback = (sql) => __async(null, null, function* () {
|
|
7575
|
+
const results = [];
|
|
7576
|
+
const isolationLevel = isolationLevelToPostgresKeyword(
|
|
7577
|
+
options == null ? void 0 : options.isolationLevel
|
|
7578
|
+
);
|
|
7579
|
+
if (isolationLevel) {
|
|
7580
|
+
yield sql.unsafe(
|
|
7581
|
+
`SET TRANSACTION ISOLATION LEVEL ${isolationLevel.toUpperCase()}`
|
|
7582
|
+
);
|
|
7583
|
+
}
|
|
7584
|
+
if ((options == null ? void 0 : options.timeout) !== void 0 && options.timeout !== null) {
|
|
7585
|
+
const validatedTimeout = validateTimeout(options.timeout);
|
|
7586
|
+
yield sql.unsafe(`SET LOCAL statement_timeout = $1`, [
|
|
7587
|
+
validatedTimeout
|
|
7588
|
+
]);
|
|
7589
|
+
}
|
|
7590
|
+
for (const q of queries) {
|
|
7591
|
+
const model = modelMap.get(q.model);
|
|
7592
|
+
if (!model) {
|
|
7593
|
+
throw new Error(
|
|
7594
|
+
`Model '${q.model}' not found. Available: ${[...modelMap.keys()].join(", ")}`
|
|
7595
|
+
);
|
|
7596
|
+
}
|
|
7597
|
+
const { sql: sqlStr, params } = buildSQLWithCache(
|
|
7598
|
+
model,
|
|
7599
|
+
allModels,
|
|
7600
|
+
q.method,
|
|
7601
|
+
q.args || {},
|
|
7602
|
+
dialect
|
|
7603
|
+
);
|
|
7604
|
+
let rawResults = yield sql.unsafe(sqlStr, params);
|
|
7605
|
+
const rowTransformer = getRowTransformer(q.method);
|
|
7606
|
+
if (rowTransformer && Array.isArray(rawResults)) {
|
|
7607
|
+
rawResults = rawResults.map(rowTransformer);
|
|
7608
|
+
}
|
|
7609
|
+
results.push(transformQueryResults(q.method, rawResults));
|
|
7610
|
+
}
|
|
7611
|
+
return results;
|
|
7612
|
+
});
|
|
7613
|
+
return yield postgresClient.begin(transactionCallback);
|
|
7614
|
+
});
|
|
7615
|
+
}
|
|
7616
|
+
};
|
|
7617
|
+
}
|
|
7618
|
+
|
|
7619
|
+
// src/builder/select/segment-planner.ts
|
|
7620
|
+
function isListField2(field) {
|
|
7621
|
+
return typeof field.type === "string" && field.type.endsWith("[]");
|
|
7622
|
+
}
|
|
7623
|
+
function resolveRelation(model, relName, allModels) {
|
|
7624
|
+
const field = model.fields.find((f) => f.name === relName);
|
|
7625
|
+
if (!field || !field.isRelation || !field.relatedModel) return null;
|
|
7626
|
+
const relModel = allModels.find((m) => m.name === field.relatedModel);
|
|
7627
|
+
if (!relModel) return null;
|
|
7628
|
+
return { field, relModel };
|
|
7629
|
+
}
|
|
7630
|
+
function extractPagination(relArgs) {
|
|
7631
|
+
if (!isPlainObject(relArgs)) return {};
|
|
7632
|
+
const obj = relArgs;
|
|
7633
|
+
const result = {};
|
|
7634
|
+
if ("take" in obj && typeof obj.take === "number") {
|
|
7635
|
+
result.take = obj.take;
|
|
7636
|
+
}
|
|
7637
|
+
if ("skip" in obj && typeof obj.skip === "number" && obj.skip > 0) {
|
|
7638
|
+
result.skip = obj.skip;
|
|
7639
|
+
}
|
|
7640
|
+
return result;
|
|
7641
|
+
}
|
|
7642
|
+
function buildWhereInSegment(name, relArgs, field, relModel) {
|
|
7643
|
+
const keys = resolveRelationKeys(field, "whereIn");
|
|
7644
|
+
if (keys.childKeys.length !== 1) return null;
|
|
7645
|
+
const isList = isListField2(field);
|
|
7646
|
+
const pagination = isList ? extractPagination(relArgs) : {};
|
|
7647
|
+
return {
|
|
7648
|
+
relationName: name,
|
|
7649
|
+
relArgs,
|
|
7650
|
+
childModelName: relModel.name,
|
|
7651
|
+
fkFieldName: keys.childKeys[0],
|
|
7652
|
+
parentKeyFieldName: keys.parentKeys[0],
|
|
7653
|
+
isList,
|
|
7654
|
+
perParentTake: pagination.take,
|
|
7655
|
+
perParentSkip: pagination.skip
|
|
7656
|
+
};
|
|
7657
|
+
}
|
|
7658
|
+
function deepClone(obj) {
|
|
7659
|
+
if (obj === null || typeof obj !== "object") return obj;
|
|
7660
|
+
if (obj instanceof Date) return new Date(obj.getTime());
|
|
7661
|
+
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
|
|
7662
|
+
if (Array.isArray(obj)) return obj.map((item) => deepClone(item));
|
|
7663
|
+
const cloned = {};
|
|
7664
|
+
for (const key in obj) {
|
|
7665
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
7666
|
+
cloned[key] = deepClone(obj[key]);
|
|
7667
|
+
}
|
|
7668
|
+
}
|
|
7669
|
+
return cloned;
|
|
7670
|
+
}
|
|
7671
|
+
function removeRelationsFromArgs(args, names) {
|
|
7672
|
+
if (!args) return args;
|
|
7673
|
+
const filtered = deepClone(args);
|
|
7674
|
+
if (filtered.include && isPlainObject(filtered.include)) {
|
|
7675
|
+
for (const name of names) {
|
|
7676
|
+
delete filtered.include[name];
|
|
7677
|
+
}
|
|
7678
|
+
if (Object.keys(filtered.include).length === 0) {
|
|
7679
|
+
delete filtered.include;
|
|
7680
|
+
}
|
|
7681
|
+
}
|
|
7682
|
+
if (filtered.select && isPlainObject(filtered.select)) {
|
|
7683
|
+
for (const name of names) {
|
|
7684
|
+
delete filtered.select[name];
|
|
7685
|
+
}
|
|
7686
|
+
}
|
|
7687
|
+
return filtered;
|
|
7688
|
+
}
|
|
7689
|
+
function ensureParentKeysInSelect(args, segments) {
|
|
7690
|
+
if (!(args == null ? void 0 : args.select)) return { args, injectedKeys: [] };
|
|
7691
|
+
const injected = [];
|
|
7692
|
+
const newSelect = __spreadValues({}, args.select);
|
|
7693
|
+
for (const seg of segments) {
|
|
7694
|
+
if (!newSelect[seg.parentKeyFieldName]) {
|
|
7695
|
+
newSelect[seg.parentKeyFieldName] = true;
|
|
7696
|
+
injected.push(seg.parentKeyFieldName);
|
|
7697
|
+
}
|
|
7698
|
+
}
|
|
7699
|
+
if (injected.length === 0) return { args, injectedKeys: [] };
|
|
7700
|
+
return { args: __spreadProps(__spreadValues({}, args), { select: newSelect }), injectedKeys: injected };
|
|
7701
|
+
}
|
|
7702
|
+
function extractIncludeSpec3(args, model) {
|
|
7703
|
+
const spec = {};
|
|
7704
|
+
const entries = extractRelationEntries(args, model);
|
|
7705
|
+
for (const e of entries) {
|
|
7706
|
+
if (e.value !== false) {
|
|
7707
|
+
spec[e.name] = e.value;
|
|
7708
|
+
}
|
|
7709
|
+
}
|
|
7710
|
+
return spec;
|
|
7711
|
+
}
|
|
7712
|
+
function planQueryStrategy(params) {
|
|
7713
|
+
const { model, args, allModels, dialect, debug } = params;
|
|
7714
|
+
const emptyPlan = {
|
|
7715
|
+
filteredArgs: args,
|
|
7716
|
+
originalArgs: args,
|
|
7717
|
+
whereInSegments: [],
|
|
7718
|
+
injectedParentKeys: []
|
|
7719
|
+
};
|
|
7720
|
+
const entries = extractRelationEntries(args, model);
|
|
7721
|
+
if (entries.length === 0) {
|
|
7722
|
+
return emptyPlan;
|
|
7723
|
+
}
|
|
7724
|
+
if (dialect === "postgres") {
|
|
7725
|
+
const includeSpec = extractIncludeSpec3(args, model);
|
|
7726
|
+
if (Object.keys(includeSpec).length > 0) {
|
|
7727
|
+
isPlainObject(args) && "take" in args && args.take != null;
|
|
7728
|
+
const takeValue = isPlainObject(args) && typeof args.take === "number" ? args.take : null;
|
|
7729
|
+
const canFlatJoin = canUseFlatJoinForAll(includeSpec, model, allModels);
|
|
7730
|
+
canUseLateralJoin(includeSpec, model, allModels);
|
|
7731
|
+
hasChildPaginationAnywhere(
|
|
7732
|
+
includeSpec,
|
|
7733
|
+
model,
|
|
7734
|
+
allModels
|
|
7735
|
+
);
|
|
7736
|
+
const strategy = pickIncludeStrategy({
|
|
7737
|
+
includeSpec,
|
|
7738
|
+
model,
|
|
7739
|
+
schemas: allModels,
|
|
7740
|
+
method: params.method,
|
|
7741
|
+
takeValue,
|
|
7742
|
+
canFlatJoin,
|
|
7743
|
+
debug
|
|
7744
|
+
});
|
|
7745
|
+
if (debug) {
|
|
7746
|
+
console.log(` [planner] ${model.name}: strategy=${strategy}`);
|
|
7747
|
+
}
|
|
7748
|
+
if (strategy !== "where-in") {
|
|
7749
|
+
return emptyPlan;
|
|
7750
|
+
}
|
|
7751
|
+
}
|
|
7752
|
+
}
|
|
7753
|
+
const whereInSegments = [];
|
|
7754
|
+
const toRemove = /* @__PURE__ */ new Set();
|
|
7755
|
+
for (const entry of entries) {
|
|
7756
|
+
const resolved = resolveRelation(model, entry.name, allModels);
|
|
7757
|
+
if (!resolved) continue;
|
|
7758
|
+
const segment = buildWhereInSegment(
|
|
7759
|
+
entry.name,
|
|
7760
|
+
entry.value,
|
|
7761
|
+
resolved.field,
|
|
7762
|
+
resolved.relModel
|
|
7763
|
+
);
|
|
7764
|
+
if (segment) {
|
|
7765
|
+
whereInSegments.push(segment);
|
|
7766
|
+
toRemove.add(entry.name);
|
|
7767
|
+
}
|
|
7509
7768
|
}
|
|
7510
|
-
if (
|
|
7511
|
-
|
|
7769
|
+
if (toRemove.size === 0) {
|
|
7770
|
+
return emptyPlan;
|
|
7512
7771
|
}
|
|
7513
|
-
|
|
7514
|
-
}
|
|
7515
|
-
|
|
7516
|
-
|
|
7772
|
+
const filteredArgs = removeRelationsFromArgs(args, toRemove);
|
|
7773
|
+
const { args: finalArgs, injectedKeys } = ensureParentKeysInSelect(
|
|
7774
|
+
filteredArgs,
|
|
7775
|
+
whereInSegments
|
|
7776
|
+
);
|
|
7517
7777
|
return {
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
throw new Error("$transaction is only supported for postgres dialect");
|
|
7523
|
-
}
|
|
7524
|
-
if (!postgresClient) {
|
|
7525
|
-
throw new Error("postgresClient is required for transactions");
|
|
7526
|
-
}
|
|
7527
|
-
const transactionCallback = (sql) => __async(null, null, function* () {
|
|
7528
|
-
const results = [];
|
|
7529
|
-
const isolationLevel = isolationLevelToPostgresKeyword(
|
|
7530
|
-
options == null ? void 0 : options.isolationLevel
|
|
7531
|
-
);
|
|
7532
|
-
if (isolationLevel) {
|
|
7533
|
-
yield sql.unsafe(
|
|
7534
|
-
`SET TRANSACTION ISOLATION LEVEL ${isolationLevel.toUpperCase()}`
|
|
7535
|
-
);
|
|
7536
|
-
}
|
|
7537
|
-
if ((options == null ? void 0 : options.timeout) !== void 0 && options.timeout !== null) {
|
|
7538
|
-
const validatedTimeout = validateTimeout(options.timeout);
|
|
7539
|
-
yield sql.unsafe(`SET LOCAL statement_timeout = $1`, [
|
|
7540
|
-
validatedTimeout
|
|
7541
|
-
]);
|
|
7542
|
-
}
|
|
7543
|
-
for (const q of queries) {
|
|
7544
|
-
const model = modelMap.get(q.model);
|
|
7545
|
-
if (!model) {
|
|
7546
|
-
throw new Error(
|
|
7547
|
-
`Model '${q.model}' not found. Available: ${[...modelMap.keys()].join(", ")}`
|
|
7548
|
-
);
|
|
7549
|
-
}
|
|
7550
|
-
const { sql: sqlStr, params } = buildSQLWithCache(
|
|
7551
|
-
model,
|
|
7552
|
-
allModels,
|
|
7553
|
-
q.method,
|
|
7554
|
-
q.args || {},
|
|
7555
|
-
dialect
|
|
7556
|
-
);
|
|
7557
|
-
let rawResults = yield sql.unsafe(sqlStr, params);
|
|
7558
|
-
const rowTransformer = getRowTransformer(q.method);
|
|
7559
|
-
if (rowTransformer && Array.isArray(rawResults)) {
|
|
7560
|
-
rawResults = rawResults.map(rowTransformer);
|
|
7561
|
-
}
|
|
7562
|
-
results.push(transformQueryResults(q.method, rawResults));
|
|
7563
|
-
}
|
|
7564
|
-
return results;
|
|
7565
|
-
});
|
|
7566
|
-
return yield postgresClient.begin(transactionCallback);
|
|
7567
|
-
});
|
|
7568
|
-
}
|
|
7778
|
+
filteredArgs: finalArgs,
|
|
7779
|
+
originalArgs: args,
|
|
7780
|
+
whereInSegments,
|
|
7781
|
+
injectedParentKeys: injectedKeys
|
|
7569
7782
|
};
|
|
7570
7783
|
}
|
|
7571
7784
|
|
|
@@ -7609,9 +7822,9 @@ function extractChildLimit(relArgs) {
|
|
|
7609
7822
|
return void 0;
|
|
7610
7823
|
}
|
|
7611
7824
|
function buildReducerConfig(parentModel, includeSpec, allModels, prefix = "", depth = 0) {
|
|
7612
|
-
if (depth >
|
|
7825
|
+
if (depth > LIMITS.MAX_NESTED_JOIN_DEPTH) {
|
|
7613
7826
|
throw new Error(
|
|
7614
|
-
`Reducer config exceeded maximum depth of
|
|
7827
|
+
`Reducer config exceeded maximum depth of ${LIMITS.MAX_NESTED_JOIN_DEPTH} at path '${prefix}'`
|
|
7615
7828
|
);
|
|
7616
7829
|
}
|
|
7617
7830
|
const includedRelations = [];
|
|
@@ -7783,172 +7996,6 @@ function reduceFlatRows(rows, config) {
|
|
|
7783
7996
|
return Array.from(resultMap.values());
|
|
7784
7997
|
}
|
|
7785
7998
|
|
|
7786
|
-
// src/builder/select/segment-planner.ts
|
|
7787
|
-
function isListField2(field) {
|
|
7788
|
-
return typeof field.type === "string" && field.type.endsWith("[]");
|
|
7789
|
-
}
|
|
7790
|
-
function resolveRelation(model, relName, allModels) {
|
|
7791
|
-
const field = model.fields.find((f) => f.name === relName);
|
|
7792
|
-
if (!field || !field.isRelation || !field.relatedModel) return null;
|
|
7793
|
-
const relModel = allModels.find((m) => m.name === field.relatedModel);
|
|
7794
|
-
if (!relModel) return null;
|
|
7795
|
-
return { field, relModel };
|
|
7796
|
-
}
|
|
7797
|
-
function extractPagination(relArgs) {
|
|
7798
|
-
if (!isPlainObject(relArgs)) return {};
|
|
7799
|
-
const obj = relArgs;
|
|
7800
|
-
const result = {};
|
|
7801
|
-
if ("take" in obj && typeof obj.take === "number") {
|
|
7802
|
-
result.take = obj.take;
|
|
7803
|
-
}
|
|
7804
|
-
if ("skip" in obj && typeof obj.skip === "number" && obj.skip > 0) {
|
|
7805
|
-
result.skip = obj.skip;
|
|
7806
|
-
}
|
|
7807
|
-
return result;
|
|
7808
|
-
}
|
|
7809
|
-
function buildWhereInSegment(name, relArgs, field, relModel) {
|
|
7810
|
-
const keys = resolveRelationKeys(field, "whereIn");
|
|
7811
|
-
if (keys.childKeys.length !== 1) return null;
|
|
7812
|
-
const isList = isListField2(field);
|
|
7813
|
-
const pagination = isList ? extractPagination(relArgs) : {};
|
|
7814
|
-
return {
|
|
7815
|
-
relationName: name,
|
|
7816
|
-
relArgs,
|
|
7817
|
-
childModelName: relModel.name,
|
|
7818
|
-
fkFieldName: keys.childKeys[0],
|
|
7819
|
-
parentKeyFieldName: keys.parentKeys[0],
|
|
7820
|
-
isList,
|
|
7821
|
-
perParentTake: pagination.take,
|
|
7822
|
-
perParentSkip: pagination.skip
|
|
7823
|
-
};
|
|
7824
|
-
}
|
|
7825
|
-
function deepClone(obj) {
|
|
7826
|
-
if (obj === null || typeof obj !== "object") return obj;
|
|
7827
|
-
if (obj instanceof Date) return new Date(obj.getTime());
|
|
7828
|
-
if (obj instanceof RegExp) return new RegExp(obj.source, obj.flags);
|
|
7829
|
-
if (Array.isArray(obj)) return obj.map((item) => deepClone(item));
|
|
7830
|
-
const cloned = {};
|
|
7831
|
-
for (const key in obj) {
|
|
7832
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
7833
|
-
cloned[key] = deepClone(obj[key]);
|
|
7834
|
-
}
|
|
7835
|
-
}
|
|
7836
|
-
return cloned;
|
|
7837
|
-
}
|
|
7838
|
-
function removeRelationsFromArgs(args, names) {
|
|
7839
|
-
if (!args) return args;
|
|
7840
|
-
const filtered = deepClone(args);
|
|
7841
|
-
if (filtered.include && isPlainObject(filtered.include)) {
|
|
7842
|
-
for (const name of names) {
|
|
7843
|
-
delete filtered.include[name];
|
|
7844
|
-
}
|
|
7845
|
-
if (Object.keys(filtered.include).length === 0) {
|
|
7846
|
-
delete filtered.include;
|
|
7847
|
-
}
|
|
7848
|
-
}
|
|
7849
|
-
if (filtered.select && isPlainObject(filtered.select)) {
|
|
7850
|
-
for (const name of names) {
|
|
7851
|
-
delete filtered.select[name];
|
|
7852
|
-
}
|
|
7853
|
-
}
|
|
7854
|
-
return filtered;
|
|
7855
|
-
}
|
|
7856
|
-
function ensureParentKeysInSelect(args, segments) {
|
|
7857
|
-
if (!(args == null ? void 0 : args.select)) return { args, injectedKeys: [] };
|
|
7858
|
-
const injected = [];
|
|
7859
|
-
const newSelect = __spreadValues({}, args.select);
|
|
7860
|
-
for (const seg of segments) {
|
|
7861
|
-
if (!newSelect[seg.parentKeyFieldName]) {
|
|
7862
|
-
newSelect[seg.parentKeyFieldName] = true;
|
|
7863
|
-
injected.push(seg.parentKeyFieldName);
|
|
7864
|
-
}
|
|
7865
|
-
}
|
|
7866
|
-
if (injected.length === 0) return { args, injectedKeys: [] };
|
|
7867
|
-
return { args: __spreadProps(__spreadValues({}, args), { select: newSelect }), injectedKeys: injected };
|
|
7868
|
-
}
|
|
7869
|
-
function extractIncludeSpec3(args, model) {
|
|
7870
|
-
const spec = {};
|
|
7871
|
-
const entries = extractRelationEntries(args, model);
|
|
7872
|
-
for (const e of entries) {
|
|
7873
|
-
if (e.value !== false) {
|
|
7874
|
-
spec[e.name] = e.value;
|
|
7875
|
-
}
|
|
7876
|
-
}
|
|
7877
|
-
return spec;
|
|
7878
|
-
}
|
|
7879
|
-
function planQueryStrategy(params) {
|
|
7880
|
-
const { model, args, allModels, dialect, debug } = params;
|
|
7881
|
-
const emptyPlan = {
|
|
7882
|
-
filteredArgs: args,
|
|
7883
|
-
originalArgs: args,
|
|
7884
|
-
whereInSegments: [],
|
|
7885
|
-
injectedParentKeys: []
|
|
7886
|
-
};
|
|
7887
|
-
const entries = extractRelationEntries(args, model);
|
|
7888
|
-
if (entries.length === 0) {
|
|
7889
|
-
return emptyPlan;
|
|
7890
|
-
}
|
|
7891
|
-
if (dialect === "postgres") {
|
|
7892
|
-
const includeSpec = extractIncludeSpec3(args, model);
|
|
7893
|
-
if (Object.keys(includeSpec).length > 0) {
|
|
7894
|
-
isPlainObject(args) && "take" in args && args.take != null;
|
|
7895
|
-
const takeValue = isPlainObject(args) && typeof args.take === "number" ? args.take : null;
|
|
7896
|
-
const canFlatJoin = canUseFlatJoinForAll(includeSpec, model, allModels);
|
|
7897
|
-
canUseLateralJoin(includeSpec, model, allModels);
|
|
7898
|
-
hasChildPaginationAnywhere(
|
|
7899
|
-
includeSpec,
|
|
7900
|
-
model,
|
|
7901
|
-
allModels
|
|
7902
|
-
);
|
|
7903
|
-
const strategy = pickIncludeStrategy({
|
|
7904
|
-
includeSpec,
|
|
7905
|
-
model,
|
|
7906
|
-
schemas: allModels,
|
|
7907
|
-
method: params.method,
|
|
7908
|
-
takeValue,
|
|
7909
|
-
canFlatJoin,
|
|
7910
|
-
debug
|
|
7911
|
-
});
|
|
7912
|
-
if (debug) {
|
|
7913
|
-
console.log(` [planner] ${model.name}: strategy=${strategy}`);
|
|
7914
|
-
}
|
|
7915
|
-
if (strategy !== "where-in") {
|
|
7916
|
-
return emptyPlan;
|
|
7917
|
-
}
|
|
7918
|
-
}
|
|
7919
|
-
}
|
|
7920
|
-
const whereInSegments = [];
|
|
7921
|
-
const toRemove = /* @__PURE__ */ new Set();
|
|
7922
|
-
for (const entry of entries) {
|
|
7923
|
-
const resolved = resolveRelation(model, entry.name, allModels);
|
|
7924
|
-
if (!resolved) continue;
|
|
7925
|
-
const segment = buildWhereInSegment(
|
|
7926
|
-
entry.name,
|
|
7927
|
-
entry.value,
|
|
7928
|
-
resolved.field,
|
|
7929
|
-
resolved.relModel
|
|
7930
|
-
);
|
|
7931
|
-
if (segment) {
|
|
7932
|
-
whereInSegments.push(segment);
|
|
7933
|
-
toRemove.add(entry.name);
|
|
7934
|
-
}
|
|
7935
|
-
}
|
|
7936
|
-
if (toRemove.size === 0) {
|
|
7937
|
-
return emptyPlan;
|
|
7938
|
-
}
|
|
7939
|
-
const filteredArgs = removeRelationsFromArgs(args, toRemove);
|
|
7940
|
-
const { args: finalArgs, injectedKeys } = ensureParentKeysInSelect(
|
|
7941
|
-
filteredArgs,
|
|
7942
|
-
whereInSegments
|
|
7943
|
-
);
|
|
7944
|
-
return {
|
|
7945
|
-
filteredArgs: finalArgs,
|
|
7946
|
-
originalArgs: args,
|
|
7947
|
-
whereInSegments,
|
|
7948
|
-
injectedParentKeys: injectedKeys
|
|
7949
|
-
};
|
|
7950
|
-
}
|
|
7951
|
-
|
|
7952
7999
|
// src/builder/shared/where-in-utils.ts
|
|
7953
8000
|
var MAX_RECURSIVE_DEPTH = 10;
|
|
7954
8001
|
function buildParentKeyIndex(parentRows, parentKeyFieldName) {
|
|
@@ -9298,18 +9345,9 @@ function executePostgresQuery(opts) {
|
|
|
9298
9345
|
return results;
|
|
9299
9346
|
});
|
|
9300
9347
|
}
|
|
9301
|
-
function executeSqliteQuery(client, sql, params, method
|
|
9348
|
+
function executeSqliteQuery(client, sql, params, method) {
|
|
9302
9349
|
const normalizedParams = normalizeParams(params);
|
|
9303
9350
|
const shouldTransform = method === "groupBy" || method === "aggregate" || method === "count";
|
|
9304
|
-
if (requiresReduction && includeSpec) {
|
|
9305
|
-
const config = buildReducerConfig(model, includeSpec, allModels);
|
|
9306
|
-
const stmt2 = getOrPrepareStatement(client, sql);
|
|
9307
|
-
const useGet2 = shouldSqliteUseGet(method);
|
|
9308
|
-
const rawResults2 = useGet2 ? stmt2.get(...normalizedParams) : stmt2.all(...normalizedParams);
|
|
9309
|
-
const results2 = Array.isArray(rawResults2) ? rawResults2 : [rawResults2];
|
|
9310
|
-
const transformed = shouldTransform ? results2.map(transformAggregateRow) : results2;
|
|
9311
|
-
return reduceFlatRows(transformed, config);
|
|
9312
|
-
}
|
|
9313
9351
|
const stmt = getOrPrepareStatement(client, sql);
|
|
9314
9352
|
const useGet = shouldSqliteUseGet(method);
|
|
9315
9353
|
const rawResults = useGet ? stmt.get(...normalizedParams) : stmt.all(...normalizedParams);
|
|
@@ -9342,6 +9380,7 @@ exports.countIncludeDepth = countIncludeDepth;
|
|
|
9342
9380
|
exports.createProgressiveReducer = createProgressiveReducer;
|
|
9343
9381
|
exports.createStreamingReducer = createStreamingReducer;
|
|
9344
9382
|
exports.createTransactionExecutor = createTransactionExecutor;
|
|
9383
|
+
exports.detectSqliteDateMode = detectSqliteDateMode;
|
|
9345
9384
|
exports.executePostgresQuery = executePostgresQuery;
|
|
9346
9385
|
exports.executeRaw = executeRaw;
|
|
9347
9386
|
exports.executeSqliteQuery = executeSqliteQuery;
|
|
@@ -9362,6 +9401,7 @@ exports.planQueryStrategy = planQueryStrategy;
|
|
|
9362
9401
|
exports.reduceFlatRows = reduceFlatRows;
|
|
9363
9402
|
exports.reduceLateralRows = reduceLateralRows;
|
|
9364
9403
|
exports.setJsonRowFactor = setJsonRowFactor;
|
|
9404
|
+
exports.setNormalizeDateMode = setNormalizeDateMode;
|
|
9365
9405
|
exports.setRelationStats = setRelationStats;
|
|
9366
9406
|
exports.setRoundtripRowEquivalent = setRoundtripRowEquivalent;
|
|
9367
9407
|
exports.shouldSqliteUseGet = shouldSqliteUseGet;
|