prisma-sql 1.71.0 → 1.73.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 +293 -252
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +293 -252
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +459 -389
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +459 -390
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -55,6 +55,265 @@ var __async = (__this, __arguments, generator) => {
|
|
|
55
55
|
});
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
// src/utils/normalize-value.ts
|
|
59
|
+
var globalDateMode = "iso";
|
|
60
|
+
function setNormalizeDateMode(mode) {
|
|
61
|
+
globalDateMode = mode;
|
|
62
|
+
}
|
|
63
|
+
function detectSqliteDateMode(client) {
|
|
64
|
+
try {
|
|
65
|
+
const tables = client.prepare(
|
|
66
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_%' LIMIT 50"
|
|
67
|
+
).all();
|
|
68
|
+
for (const { name } of tables) {
|
|
69
|
+
const row = client.prepare(`SELECT typeof("createdAt") as t FROM "${name}" LIMIT 1`).get();
|
|
70
|
+
if (row) {
|
|
71
|
+
return row.t === "integer" ? "ms" : "iso";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
}
|
|
76
|
+
return "iso";
|
|
77
|
+
}
|
|
78
|
+
var MAX_DEPTH = 20;
|
|
79
|
+
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
80
|
+
if (depth > MAX_DEPTH) {
|
|
81
|
+
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
82
|
+
}
|
|
83
|
+
if (value instanceof Date) {
|
|
84
|
+
return normalizeDateValue(value);
|
|
85
|
+
}
|
|
86
|
+
if (typeof value === "bigint") {
|
|
87
|
+
return value.toString();
|
|
88
|
+
}
|
|
89
|
+
if (Array.isArray(value)) {
|
|
90
|
+
return normalizeArrayValue(value, seen, depth);
|
|
91
|
+
}
|
|
92
|
+
if (value && typeof value === "object") {
|
|
93
|
+
return normalizeObjectValue(value, seen, depth);
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function normalizeDateValue(date) {
|
|
98
|
+
const t = date.getTime();
|
|
99
|
+
if (!Number.isFinite(t)) {
|
|
100
|
+
throw new Error("Invalid Date value in SQL params");
|
|
101
|
+
}
|
|
102
|
+
if (globalDateMode === "ms") {
|
|
103
|
+
return t;
|
|
104
|
+
}
|
|
105
|
+
return date.toISOString();
|
|
106
|
+
}
|
|
107
|
+
function normalizeArrayValue(value, seen, depth) {
|
|
108
|
+
const arrRef = value;
|
|
109
|
+
if (seen.has(arrRef)) {
|
|
110
|
+
throw new Error("Circular reference in SQL params");
|
|
111
|
+
}
|
|
112
|
+
seen.add(arrRef);
|
|
113
|
+
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
114
|
+
seen.delete(arrRef);
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
function normalizeObjectValue(value, seen, depth) {
|
|
118
|
+
if (value instanceof Uint8Array) return value;
|
|
119
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
120
|
+
const proto = Object.getPrototypeOf(value);
|
|
121
|
+
const isPlain = proto === Object.prototype || proto === null;
|
|
122
|
+
if (!isPlain) return value;
|
|
123
|
+
const obj = value;
|
|
124
|
+
if (seen.has(obj)) {
|
|
125
|
+
throw new Error("Circular reference in SQL params");
|
|
126
|
+
}
|
|
127
|
+
seen.add(obj);
|
|
128
|
+
const out = {};
|
|
129
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
130
|
+
out[k] = normalizeValue(v, seen, depth + 1);
|
|
131
|
+
}
|
|
132
|
+
seen.delete(obj);
|
|
133
|
+
return out;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// src/sql-builder-dialect.ts
|
|
137
|
+
var globalDialect = "postgres";
|
|
138
|
+
function setGlobalDialect(dialect) {
|
|
139
|
+
if (dialect !== "postgres" && dialect !== "sqlite") {
|
|
140
|
+
throw new Error(
|
|
141
|
+
`Invalid dialect: ${dialect}. Must be 'postgres' or 'sqlite'`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
globalDialect = dialect;
|
|
145
|
+
}
|
|
146
|
+
function getGlobalDialect() {
|
|
147
|
+
return globalDialect;
|
|
148
|
+
}
|
|
149
|
+
function assertNonEmpty(value, name) {
|
|
150
|
+
if (!value || value.trim().length === 0) {
|
|
151
|
+
throw new Error(`${name} is required and cannot be empty`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function arrayContains(column, value, arrayType, dialect) {
|
|
155
|
+
assertNonEmpty(column, "arrayContains column");
|
|
156
|
+
assertNonEmpty(value, "arrayContains value");
|
|
157
|
+
if (dialect === "postgres") {
|
|
158
|
+
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
159
|
+
}
|
|
160
|
+
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
161
|
+
}
|
|
162
|
+
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
163
|
+
assertNonEmpty(column, "arrayOverlaps column");
|
|
164
|
+
assertNonEmpty(value, "arrayOverlaps value");
|
|
165
|
+
if (dialect === "postgres") {
|
|
166
|
+
return `${column} && ${value}::${arrayType}`;
|
|
167
|
+
}
|
|
168
|
+
return `EXISTS (
|
|
169
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
170
|
+
JOIN json_each(${value}) AS val
|
|
171
|
+
WHERE col.value = val.value
|
|
172
|
+
)`;
|
|
173
|
+
}
|
|
174
|
+
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
175
|
+
assertNonEmpty(column, "arrayContainsAll column");
|
|
176
|
+
assertNonEmpty(value, "arrayContainsAll value");
|
|
177
|
+
if (dialect === "postgres") {
|
|
178
|
+
return `${column} @> ${value}::${arrayType}`;
|
|
179
|
+
}
|
|
180
|
+
return `NOT EXISTS (
|
|
181
|
+
SELECT 1 FROM json_each(${value}) AS val
|
|
182
|
+
WHERE NOT EXISTS (
|
|
183
|
+
SELECT 1 FROM json_each(${column}) AS col
|
|
184
|
+
WHERE col.value = val.value
|
|
185
|
+
)
|
|
186
|
+
)`;
|
|
187
|
+
}
|
|
188
|
+
function arrayIsEmpty(column, dialect) {
|
|
189
|
+
assertNonEmpty(column, "arrayIsEmpty column");
|
|
190
|
+
if (dialect === "postgres") {
|
|
191
|
+
return `(${column} IS NULL OR array_length(${column}, 1) IS NULL)`;
|
|
192
|
+
}
|
|
193
|
+
return `(${column} IS NULL OR json_array_length(${column}) = 0)`;
|
|
194
|
+
}
|
|
195
|
+
function arrayIsNotEmpty(column, dialect) {
|
|
196
|
+
assertNonEmpty(column, "arrayIsNotEmpty column");
|
|
197
|
+
if (dialect === "postgres") {
|
|
198
|
+
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
199
|
+
}
|
|
200
|
+
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
201
|
+
}
|
|
202
|
+
function arrayEquals(column, value, arrayType, dialect) {
|
|
203
|
+
assertNonEmpty(column, "arrayEquals column");
|
|
204
|
+
assertNonEmpty(value, "arrayEquals value");
|
|
205
|
+
if (dialect === "postgres") {
|
|
206
|
+
return `${column} = ${value}::${arrayType}`;
|
|
207
|
+
}
|
|
208
|
+
return `json(${column}) = json(${value})`;
|
|
209
|
+
}
|
|
210
|
+
function caseInsensitiveLike(column, pattern, dialect) {
|
|
211
|
+
assertNonEmpty(column, "caseInsensitiveLike column");
|
|
212
|
+
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
213
|
+
if (dialect === "postgres") {
|
|
214
|
+
return `${column} ILIKE ${pattern}`;
|
|
215
|
+
}
|
|
216
|
+
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
217
|
+
}
|
|
218
|
+
function caseInsensitiveEquals(column, value, dialect) {
|
|
219
|
+
assertNonEmpty(column, "caseInsensitiveEquals column");
|
|
220
|
+
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
221
|
+
return `LOWER(${column}) = LOWER(${value})`;
|
|
222
|
+
}
|
|
223
|
+
function jsonExtractText(column, path, dialect) {
|
|
224
|
+
assertNonEmpty(column, "jsonExtractText column");
|
|
225
|
+
assertNonEmpty(path, "jsonExtractText path");
|
|
226
|
+
if (dialect === "postgres") {
|
|
227
|
+
const p = String(path).trim();
|
|
228
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
229
|
+
return `${column}#>>${pathExpr}`;
|
|
230
|
+
}
|
|
231
|
+
return `json_extract(${column}, ${path})`;
|
|
232
|
+
}
|
|
233
|
+
function jsonExtractNumeric(column, path, dialect) {
|
|
234
|
+
assertNonEmpty(column, "jsonExtractNumeric column");
|
|
235
|
+
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
236
|
+
if (dialect === "postgres") {
|
|
237
|
+
const p = String(path).trim();
|
|
238
|
+
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
239
|
+
return `(${column}#>>${pathExpr})::numeric`;
|
|
240
|
+
}
|
|
241
|
+
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
242
|
+
}
|
|
243
|
+
function jsonToText(column, dialect) {
|
|
244
|
+
assertNonEmpty(column, "jsonToText column");
|
|
245
|
+
if (dialect === "postgres") {
|
|
246
|
+
return `${column}::text`;
|
|
247
|
+
}
|
|
248
|
+
return column;
|
|
249
|
+
}
|
|
250
|
+
function inArray(column, value, dialect) {
|
|
251
|
+
assertNonEmpty(column, "inArray column");
|
|
252
|
+
assertNonEmpty(value, "inArray value");
|
|
253
|
+
if (dialect === "postgres") {
|
|
254
|
+
return `${column} = ANY(${value})`;
|
|
255
|
+
}
|
|
256
|
+
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
257
|
+
}
|
|
258
|
+
function notInArray(column, value, dialect) {
|
|
259
|
+
assertNonEmpty(column, "notInArray column");
|
|
260
|
+
assertNonEmpty(value, "notInArray value");
|
|
261
|
+
if (dialect === "postgres") {
|
|
262
|
+
return `${column} != ALL(${value})`;
|
|
263
|
+
}
|
|
264
|
+
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
265
|
+
}
|
|
266
|
+
function getArrayType(prismaType, dialect) {
|
|
267
|
+
if (!prismaType || prismaType.length === 0) {
|
|
268
|
+
return dialect === "sqlite" ? "TEXT" : "text[]";
|
|
269
|
+
}
|
|
270
|
+
if (dialect === "sqlite") {
|
|
271
|
+
return "TEXT";
|
|
272
|
+
}
|
|
273
|
+
const baseType = prismaType.replace(/\[\]|\?/g, "");
|
|
274
|
+
switch (baseType) {
|
|
275
|
+
case "String":
|
|
276
|
+
return "text[]";
|
|
277
|
+
case "Int":
|
|
278
|
+
return "integer[]";
|
|
279
|
+
case "Float":
|
|
280
|
+
return "double precision[]";
|
|
281
|
+
case "Decimal":
|
|
282
|
+
return "numeric[]";
|
|
283
|
+
case "Boolean":
|
|
284
|
+
return "boolean[]";
|
|
285
|
+
case "BigInt":
|
|
286
|
+
return "bigint[]";
|
|
287
|
+
case "DateTime":
|
|
288
|
+
return "timestamptz[]";
|
|
289
|
+
default:
|
|
290
|
+
return `"${baseType}"[]`;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function jsonAgg(content, dialect) {
|
|
294
|
+
assertNonEmpty(content, "jsonAgg content");
|
|
295
|
+
if (dialect === "postgres") {
|
|
296
|
+
return `json_agg(${content})`;
|
|
297
|
+
}
|
|
298
|
+
return `json_group_array(${content})`;
|
|
299
|
+
}
|
|
300
|
+
function jsonBuildObject(pairs, dialect) {
|
|
301
|
+
const safePairs = (pairs != null ? pairs : "").trim();
|
|
302
|
+
if (dialect === "postgres") {
|
|
303
|
+
return safePairs.length > 0 ? `json_build_object(${safePairs})` : `json_build_object()`;
|
|
304
|
+
}
|
|
305
|
+
return safePairs.length > 0 ? `json_object(${safePairs})` : `json_object()`;
|
|
306
|
+
}
|
|
307
|
+
function prepareArrayParam(value, dialect) {
|
|
308
|
+
if (!Array.isArray(value)) {
|
|
309
|
+
throw new Error("prepareArrayParam requires array value");
|
|
310
|
+
}
|
|
311
|
+
if (dialect === "postgres") {
|
|
312
|
+
return value.map((v) => normalizeValue(v));
|
|
313
|
+
}
|
|
314
|
+
return JSON.stringify(value.map((v) => normalizeValue(v)));
|
|
315
|
+
}
|
|
316
|
+
|
|
58
317
|
// src/builder/shared/constants.ts
|
|
59
318
|
var IS_PRODUCTION = process.env.NODE_ENV === "production";
|
|
60
319
|
var SQL_SEPARATORS = Object.freeze({
|
|
@@ -759,406 +1018,155 @@ function normalizeKeyList(input) {
|
|
|
759
1018
|
}
|
|
760
1019
|
|
|
761
1020
|
// src/builder/shared/model-field-cache.ts
|
|
762
|
-
var FIELD_INDICES_CACHE = /* @__PURE__ */ new WeakMap();
|
|
763
|
-
function normalizeField(field) {
|
|
764
|
-
return field;
|
|
765
|
-
}
|
|
766
|
-
function getFieldIndices(model) {
|
|
767
|
-
var _a3;
|
|
768
|
-
let cached = FIELD_INDICES_CACHE.get(model);
|
|
769
|
-
if (cached) return cached;
|
|
770
|
-
const scalarFields = /* @__PURE__ */ new Map();
|
|
771
|
-
const relationFields = /* @__PURE__ */ new Map();
|
|
772
|
-
const allFieldsByName = /* @__PURE__ */ new Map();
|
|
773
|
-
const scalarNames = [];
|
|
774
|
-
const relationNames = [];
|
|
775
|
-
const jsonFields = /* @__PURE__ */ new Set();
|
|
776
|
-
const pkFields = [];
|
|
777
|
-
const columnMap = /* @__PURE__ */ new Map();
|
|
778
|
-
const quotedColumns = /* @__PURE__ */ new Map();
|
|
779
|
-
for (const rawField of model.fields) {
|
|
780
|
-
const field = normalizeField(rawField);
|
|
781
|
-
allFieldsByName.set(field.name, field);
|
|
782
|
-
if (field.isRelation) {
|
|
783
|
-
relationFields.set(field.name, field);
|
|
784
|
-
relationNames.push(field.name);
|
|
785
|
-
} else {
|
|
786
|
-
scalarFields.set(field.name, field);
|
|
787
|
-
scalarNames.push(field.name);
|
|
788
|
-
const fieldType = String((_a3 = field.type) != null ? _a3 : "").toLowerCase();
|
|
789
|
-
if (fieldType === "json") {
|
|
790
|
-
jsonFields.add(field.name);
|
|
791
|
-
}
|
|
792
|
-
if (field.isId || field.isPrimaryKey || field.primaryKey) {
|
|
793
|
-
pkFields.push(field.name);
|
|
794
|
-
}
|
|
795
|
-
if (field.dbName && field.dbName !== field.name) {
|
|
796
|
-
columnMap.set(field.name, field.dbName);
|
|
797
|
-
}
|
|
798
|
-
const columnName = field.dbName || field.name;
|
|
799
|
-
quotedColumns.set(field.name, quote(columnName));
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
cached = Object.freeze({
|
|
803
|
-
scalarFields,
|
|
804
|
-
relationFields,
|
|
805
|
-
allFieldsByName,
|
|
806
|
-
scalarNames,
|
|
807
|
-
relationNames,
|
|
808
|
-
jsonFields,
|
|
809
|
-
pkFields,
|
|
810
|
-
columnMap,
|
|
811
|
-
quotedColumns
|
|
812
|
-
});
|
|
813
|
-
FIELD_INDICES_CACHE.set(model, cached);
|
|
814
|
-
return cached;
|
|
815
|
-
}
|
|
816
|
-
function getRelationFieldSet(model) {
|
|
817
|
-
return new Set(getFieldIndices(model).relationNames);
|
|
818
|
-
}
|
|
819
|
-
function getScalarFieldSet(model) {
|
|
820
|
-
return new Set(getFieldIndices(model).scalarNames);
|
|
821
|
-
}
|
|
822
|
-
function getColumnMap(model) {
|
|
823
|
-
return getFieldIndices(model).columnMap;
|
|
824
|
-
}
|
|
825
|
-
function getScalarFieldNames(model) {
|
|
826
|
-
return [...getFieldIndices(model).scalarNames];
|
|
827
|
-
}
|
|
828
|
-
function getQuotedColumn(model, fieldName) {
|
|
829
|
-
return getFieldIndices(model).quotedColumns.get(fieldName);
|
|
830
|
-
}
|
|
831
|
-
function getJsonFieldSet(model) {
|
|
832
|
-
return getFieldIndices(model).jsonFields;
|
|
833
|
-
}
|
|
834
|
-
function parseJsonIfNeeded(isJson, value) {
|
|
835
|
-
if (!isJson) return value;
|
|
836
|
-
if (value == null) return value;
|
|
837
|
-
if (typeof value !== "string") return value;
|
|
838
|
-
try {
|
|
839
|
-
return JSON.parse(value);
|
|
840
|
-
} catch (e) {
|
|
841
|
-
return value;
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
function maybeParseJson(value, jsonSet, fieldName) {
|
|
845
|
-
if (!jsonSet.has(fieldName)) return value;
|
|
846
|
-
if (value == null) return value;
|
|
847
|
-
if (typeof value !== "string") return value;
|
|
848
|
-
try {
|
|
849
|
-
return JSON.parse(value);
|
|
850
|
-
} catch (e) {
|
|
851
|
-
return value;
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
// src/builder/joins.ts
|
|
856
|
-
function isRelationField(fieldName, model) {
|
|
857
|
-
return getRelationFieldSet(model).has(fieldName);
|
|
858
|
-
}
|
|
859
|
-
function isValidRelationField(field) {
|
|
860
|
-
if (!isNotNullish(field)) return false;
|
|
861
|
-
if (!field.isRelation) return false;
|
|
862
|
-
if (!isNotNullish(field.relatedModel) || field.relatedModel.trim().length === 0)
|
|
863
|
-
return false;
|
|
864
|
-
const fk = normalizeKeyList(field.foreignKey);
|
|
865
|
-
if (fk.length === 0) return false;
|
|
866
|
-
const refs = normalizeKeyList(field.references);
|
|
867
|
-
if (refs.length === 0) {
|
|
868
|
-
return fk.length === 1;
|
|
869
|
-
}
|
|
870
|
-
if (refs.length !== fk.length) return false;
|
|
871
|
-
return true;
|
|
872
|
-
}
|
|
873
|
-
function getReferenceFieldNames(field, foreignKeyCount) {
|
|
874
|
-
const refs = normalizeKeyList(field.references);
|
|
875
|
-
if (refs.length === 0) {
|
|
876
|
-
if (foreignKeyCount === 1) return [SPECIAL_FIELDS.ID];
|
|
877
|
-
return [];
|
|
878
|
-
}
|
|
879
|
-
if (refs.length !== foreignKeyCount) return [];
|
|
880
|
-
return refs;
|
|
881
|
-
}
|
|
882
|
-
function joinCondition(field, parentModel, childModel, parentAlias, childAlias) {
|
|
883
|
-
assertSafeAlias(parentAlias);
|
|
884
|
-
assertSafeAlias(childAlias);
|
|
885
|
-
const fkFields = normalizeKeyList(field.foreignKey);
|
|
886
|
-
if (fkFields.length === 0) {
|
|
887
|
-
throw createError(
|
|
888
|
-
`Relation '${field.name}' is missing foreignKey. This indicates a schema parsing error. Relations must specify fields/references.`,
|
|
889
|
-
{ field: field.name }
|
|
890
|
-
);
|
|
891
|
-
}
|
|
892
|
-
const refFields = getReferenceFieldNames(field, fkFields.length);
|
|
893
|
-
if (refFields.length !== fkFields.length) {
|
|
894
|
-
throw createError(
|
|
895
|
-
`Relation '${field.name}' is missing references (or references count does not match foreignKey count). This is required to support non-id and composite keys.`,
|
|
896
|
-
{ field: field.name }
|
|
897
|
-
);
|
|
898
|
-
}
|
|
899
|
-
const parts = [];
|
|
900
|
-
for (let i = 0; i < fkFields.length; i++) {
|
|
901
|
-
const fk = fkFields[i];
|
|
902
|
-
const ref = refFields[i];
|
|
903
|
-
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, ref)}` : `${childAlias}.${quoteColumn(childModel, fk)}`;
|
|
904
|
-
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, fk)}` : `${parentAlias}.${quoteColumn(parentModel, ref)}`;
|
|
905
|
-
parts.push(`${left} = ${right}`);
|
|
906
|
-
}
|
|
907
|
-
return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
|
|
908
|
-
}
|
|
909
|
-
function getModelByName(schemas, name) {
|
|
910
|
-
return schemas.find((m) => m.name === name);
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// src/utils/normalize-value.ts
|
|
914
|
-
var globalDateMode = "iso";
|
|
915
|
-
function setNormalizeDateMode(mode) {
|
|
916
|
-
globalDateMode = mode;
|
|
917
|
-
}
|
|
918
|
-
function detectSqliteDateMode(client) {
|
|
919
|
-
try {
|
|
920
|
-
const tables = client.prepare(
|
|
921
|
-
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_%' LIMIT 50"
|
|
922
|
-
).all();
|
|
923
|
-
for (const { name } of tables) {
|
|
924
|
-
const row = client.prepare(`SELECT typeof("createdAt") as t FROM "${name}" LIMIT 1`).get();
|
|
925
|
-
if (row) {
|
|
926
|
-
return row.t === "integer" ? "ms" : "iso";
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
} catch (e) {
|
|
930
|
-
}
|
|
931
|
-
return "iso";
|
|
932
|
-
}
|
|
933
|
-
var MAX_DEPTH = 20;
|
|
934
|
-
function normalizeValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
935
|
-
if (depth > MAX_DEPTH) {
|
|
936
|
-
throw new Error(`Max normalization depth exceeded (${MAX_DEPTH} levels)`);
|
|
937
|
-
}
|
|
938
|
-
if (value instanceof Date) {
|
|
939
|
-
return normalizeDateValue(value);
|
|
940
|
-
}
|
|
941
|
-
if (typeof value === "bigint") {
|
|
942
|
-
return value.toString();
|
|
943
|
-
}
|
|
944
|
-
if (Array.isArray(value)) {
|
|
945
|
-
return normalizeArrayValue(value, seen, depth);
|
|
946
|
-
}
|
|
947
|
-
if (value && typeof value === "object") {
|
|
948
|
-
return normalizeObjectValue(value, seen, depth);
|
|
949
|
-
}
|
|
950
|
-
return value;
|
|
951
|
-
}
|
|
952
|
-
function normalizeDateValue(date) {
|
|
953
|
-
const t = date.getTime();
|
|
954
|
-
if (!Number.isFinite(t)) {
|
|
955
|
-
throw new Error("Invalid Date value in SQL params");
|
|
956
|
-
}
|
|
957
|
-
if (globalDateMode === "ms") {
|
|
958
|
-
return t;
|
|
959
|
-
}
|
|
960
|
-
return date.toISOString();
|
|
961
|
-
}
|
|
962
|
-
function normalizeArrayValue(value, seen, depth) {
|
|
963
|
-
const arrRef = value;
|
|
964
|
-
if (seen.has(arrRef)) {
|
|
965
|
-
throw new Error("Circular reference in SQL params");
|
|
966
|
-
}
|
|
967
|
-
seen.add(arrRef);
|
|
968
|
-
const out = value.map((v) => normalizeValue(v, seen, depth + 1));
|
|
969
|
-
seen.delete(arrRef);
|
|
970
|
-
return out;
|
|
971
|
-
}
|
|
972
|
-
function normalizeObjectValue(value, seen, depth) {
|
|
973
|
-
if (value instanceof Uint8Array) return value;
|
|
974
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return value;
|
|
975
|
-
const proto = Object.getPrototypeOf(value);
|
|
976
|
-
const isPlain = proto === Object.prototype || proto === null;
|
|
977
|
-
if (!isPlain) return value;
|
|
978
|
-
const obj = value;
|
|
979
|
-
if (seen.has(obj)) {
|
|
980
|
-
throw new Error("Circular reference in SQL params");
|
|
981
|
-
}
|
|
982
|
-
seen.add(obj);
|
|
983
|
-
const out = {};
|
|
984
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
985
|
-
out[k] = normalizeValue(v, seen, depth + 1);
|
|
986
|
-
}
|
|
987
|
-
seen.delete(obj);
|
|
988
|
-
return out;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
// src/sql-builder-dialect.ts
|
|
992
|
-
var globalDialect = "postgres";
|
|
993
|
-
function getGlobalDialect() {
|
|
994
|
-
return globalDialect;
|
|
995
|
-
}
|
|
996
|
-
function assertNonEmpty(value, name) {
|
|
997
|
-
if (!value || value.trim().length === 0) {
|
|
998
|
-
throw new Error(`${name} is required and cannot be empty`);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
function arrayContains(column, value, arrayType, dialect) {
|
|
1002
|
-
assertNonEmpty(column, "arrayContains column");
|
|
1003
|
-
assertNonEmpty(value, "arrayContains value");
|
|
1004
|
-
if (dialect === "postgres") {
|
|
1005
|
-
return `${column} @> ARRAY[${value}]::${arrayType}`;
|
|
1006
|
-
}
|
|
1007
|
-
return `EXISTS (SELECT 1 FROM json_each(${column}) WHERE value = ${value})`;
|
|
1008
|
-
}
|
|
1009
|
-
function arrayOverlaps(column, value, arrayType, dialect) {
|
|
1010
|
-
assertNonEmpty(column, "arrayOverlaps column");
|
|
1011
|
-
assertNonEmpty(value, "arrayOverlaps value");
|
|
1012
|
-
if (dialect === "postgres") {
|
|
1013
|
-
return `${column} && ${value}::${arrayType}`;
|
|
1014
|
-
}
|
|
1015
|
-
return `EXISTS (
|
|
1016
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
1017
|
-
JOIN json_each(${value}) AS val
|
|
1018
|
-
WHERE col.value = val.value
|
|
1019
|
-
)`;
|
|
1020
|
-
}
|
|
1021
|
-
function arrayContainsAll(column, value, arrayType, dialect) {
|
|
1022
|
-
assertNonEmpty(column, "arrayContainsAll column");
|
|
1023
|
-
assertNonEmpty(value, "arrayContainsAll value");
|
|
1024
|
-
if (dialect === "postgres") {
|
|
1025
|
-
return `${column} @> ${value}::${arrayType}`;
|
|
1026
|
-
}
|
|
1027
|
-
return `NOT EXISTS (
|
|
1028
|
-
SELECT 1 FROM json_each(${value}) AS val
|
|
1029
|
-
WHERE NOT EXISTS (
|
|
1030
|
-
SELECT 1 FROM json_each(${column}) AS col
|
|
1031
|
-
WHERE col.value = val.value
|
|
1032
|
-
)
|
|
1033
|
-
)`;
|
|
1021
|
+
var FIELD_INDICES_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1022
|
+
function normalizeField(field) {
|
|
1023
|
+
return field;
|
|
1034
1024
|
}
|
|
1035
|
-
function
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1025
|
+
function getFieldIndices(model) {
|
|
1026
|
+
var _a3;
|
|
1027
|
+
let cached = FIELD_INDICES_CACHE.get(model);
|
|
1028
|
+
if (cached) return cached;
|
|
1029
|
+
const scalarFields = /* @__PURE__ */ new Map();
|
|
1030
|
+
const relationFields = /* @__PURE__ */ new Map();
|
|
1031
|
+
const allFieldsByName = /* @__PURE__ */ new Map();
|
|
1032
|
+
const scalarNames = [];
|
|
1033
|
+
const relationNames = [];
|
|
1034
|
+
const jsonFields = /* @__PURE__ */ new Set();
|
|
1035
|
+
const pkFields = [];
|
|
1036
|
+
const columnMap = /* @__PURE__ */ new Map();
|
|
1037
|
+
const quotedColumns = /* @__PURE__ */ new Map();
|
|
1038
|
+
for (const rawField of model.fields) {
|
|
1039
|
+
const field = normalizeField(rawField);
|
|
1040
|
+
allFieldsByName.set(field.name, field);
|
|
1041
|
+
if (field.isRelation) {
|
|
1042
|
+
relationFields.set(field.name, field);
|
|
1043
|
+
relationNames.push(field.name);
|
|
1044
|
+
} else {
|
|
1045
|
+
scalarFields.set(field.name, field);
|
|
1046
|
+
scalarNames.push(field.name);
|
|
1047
|
+
const fieldType = String((_a3 = field.type) != null ? _a3 : "").toLowerCase();
|
|
1048
|
+
if (fieldType === "json") {
|
|
1049
|
+
jsonFields.add(field.name);
|
|
1050
|
+
}
|
|
1051
|
+
if (field.isId || field.isPrimaryKey || field.primaryKey) {
|
|
1052
|
+
pkFields.push(field.name);
|
|
1053
|
+
}
|
|
1054
|
+
if (field.dbName && field.dbName !== field.name) {
|
|
1055
|
+
columnMap.set(field.name, field.dbName);
|
|
1056
|
+
}
|
|
1057
|
+
const columnName = field.dbName || field.name;
|
|
1058
|
+
quotedColumns.set(field.name, quote(columnName));
|
|
1059
|
+
}
|
|
1039
1060
|
}
|
|
1040
|
-
|
|
1061
|
+
cached = Object.freeze({
|
|
1062
|
+
scalarFields,
|
|
1063
|
+
relationFields,
|
|
1064
|
+
allFieldsByName,
|
|
1065
|
+
scalarNames,
|
|
1066
|
+
relationNames,
|
|
1067
|
+
jsonFields,
|
|
1068
|
+
pkFields,
|
|
1069
|
+
columnMap,
|
|
1070
|
+
quotedColumns
|
|
1071
|
+
});
|
|
1072
|
+
FIELD_INDICES_CACHE.set(model, cached);
|
|
1073
|
+
return cached;
|
|
1041
1074
|
}
|
|
1042
|
-
function
|
|
1043
|
-
|
|
1044
|
-
if (dialect === "postgres") {
|
|
1045
|
-
return `(${column} IS NOT NULL AND array_length(${column}, 1) IS NOT NULL)`;
|
|
1046
|
-
}
|
|
1047
|
-
return `(${column} IS NOT NULL AND json_array_length(${column}) > 0)`;
|
|
1075
|
+
function getRelationFieldSet(model) {
|
|
1076
|
+
return new Set(getFieldIndices(model).relationNames);
|
|
1048
1077
|
}
|
|
1049
|
-
function
|
|
1050
|
-
|
|
1051
|
-
assertNonEmpty(value, "arrayEquals value");
|
|
1052
|
-
if (dialect === "postgres") {
|
|
1053
|
-
return `${column} = ${value}::${arrayType}`;
|
|
1054
|
-
}
|
|
1055
|
-
return `json(${column}) = json(${value})`;
|
|
1078
|
+
function getScalarFieldSet(model) {
|
|
1079
|
+
return new Set(getFieldIndices(model).scalarNames);
|
|
1056
1080
|
}
|
|
1057
|
-
function
|
|
1058
|
-
|
|
1059
|
-
assertNonEmpty(pattern, "caseInsensitiveLike pattern");
|
|
1060
|
-
if (dialect === "postgres") {
|
|
1061
|
-
return `${column} ILIKE ${pattern}`;
|
|
1062
|
-
}
|
|
1063
|
-
return `LOWER(${column}) LIKE LOWER(${pattern})`;
|
|
1081
|
+
function getColumnMap(model) {
|
|
1082
|
+
return getFieldIndices(model).columnMap;
|
|
1064
1083
|
}
|
|
1065
|
-
function
|
|
1066
|
-
|
|
1067
|
-
assertNonEmpty(value, "caseInsensitiveEquals value");
|
|
1068
|
-
return `LOWER(${column}) = LOWER(${value})`;
|
|
1084
|
+
function getScalarFieldNames(model) {
|
|
1085
|
+
return [...getFieldIndices(model).scalarNames];
|
|
1069
1086
|
}
|
|
1070
|
-
function
|
|
1071
|
-
|
|
1072
|
-
assertNonEmpty(path, "jsonExtractText path");
|
|
1073
|
-
if (dialect === "postgres") {
|
|
1074
|
-
const p = String(path).trim();
|
|
1075
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
1076
|
-
return `${column}#>>${pathExpr}`;
|
|
1077
|
-
}
|
|
1078
|
-
return `json_extract(${column}, ${path})`;
|
|
1087
|
+
function getQuotedColumn(model, fieldName) {
|
|
1088
|
+
return getFieldIndices(model).quotedColumns.get(fieldName);
|
|
1079
1089
|
}
|
|
1080
|
-
function
|
|
1081
|
-
|
|
1082
|
-
assertNonEmpty(path, "jsonExtractNumeric path");
|
|
1083
|
-
if (dialect === "postgres") {
|
|
1084
|
-
const p = String(path).trim();
|
|
1085
|
-
const pathExpr = /^\$\d+$/.test(p) ? `${p}::text[]` : p;
|
|
1086
|
-
return `(${column}#>>${pathExpr})::numeric`;
|
|
1087
|
-
}
|
|
1088
|
-
return `CAST(json_extract(${column}, ${path}) AS REAL)`;
|
|
1090
|
+
function getJsonFieldSet(model) {
|
|
1091
|
+
return getFieldIndices(model).jsonFields;
|
|
1089
1092
|
}
|
|
1090
|
-
function
|
|
1091
|
-
|
|
1092
|
-
if (
|
|
1093
|
-
|
|
1093
|
+
function parseJsonIfNeeded(isJson, value) {
|
|
1094
|
+
if (!isJson) return value;
|
|
1095
|
+
if (value == null) return value;
|
|
1096
|
+
if (typeof value !== "string") return value;
|
|
1097
|
+
try {
|
|
1098
|
+
return JSON.parse(value);
|
|
1099
|
+
} catch (e) {
|
|
1100
|
+
return value;
|
|
1094
1101
|
}
|
|
1095
|
-
return column;
|
|
1096
1102
|
}
|
|
1097
|
-
function
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
if (
|
|
1101
|
-
|
|
1103
|
+
function maybeParseJson(value, jsonSet, fieldName) {
|
|
1104
|
+
if (!jsonSet.has(fieldName)) return value;
|
|
1105
|
+
if (value == null) return value;
|
|
1106
|
+
if (typeof value !== "string") return value;
|
|
1107
|
+
try {
|
|
1108
|
+
return JSON.parse(value);
|
|
1109
|
+
} catch (e) {
|
|
1110
|
+
return value;
|
|
1102
1111
|
}
|
|
1103
|
-
return `${column} IN (SELECT value FROM json_each(${value}))`;
|
|
1104
1112
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
return `${column} != ALL(${value})`;
|
|
1110
|
-
}
|
|
1111
|
-
return `${column} NOT IN (SELECT value FROM json_each(${value}))`;
|
|
1113
|
+
|
|
1114
|
+
// src/builder/joins.ts
|
|
1115
|
+
function isRelationField(fieldName, model) {
|
|
1116
|
+
return getRelationFieldSet(model).has(fieldName);
|
|
1112
1117
|
}
|
|
1113
|
-
function
|
|
1114
|
-
if (!
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
return "text[]";
|
|
1124
|
-
case "Int":
|
|
1125
|
-
return "integer[]";
|
|
1126
|
-
case "Float":
|
|
1127
|
-
return "double precision[]";
|
|
1128
|
-
case "Decimal":
|
|
1129
|
-
return "numeric[]";
|
|
1130
|
-
case "Boolean":
|
|
1131
|
-
return "boolean[]";
|
|
1132
|
-
case "BigInt":
|
|
1133
|
-
return "bigint[]";
|
|
1134
|
-
case "DateTime":
|
|
1135
|
-
return "timestamptz[]";
|
|
1136
|
-
default:
|
|
1137
|
-
return `"${baseType}"[]`;
|
|
1118
|
+
function isValidRelationField(field) {
|
|
1119
|
+
if (!isNotNullish(field)) return false;
|
|
1120
|
+
if (!field.isRelation) return false;
|
|
1121
|
+
if (!isNotNullish(field.relatedModel) || field.relatedModel.trim().length === 0)
|
|
1122
|
+
return false;
|
|
1123
|
+
const fk = normalizeKeyList(field.foreignKey);
|
|
1124
|
+
if (fk.length === 0) return false;
|
|
1125
|
+
const refs = normalizeKeyList(field.references);
|
|
1126
|
+
if (refs.length === 0) {
|
|
1127
|
+
return fk.length === 1;
|
|
1138
1128
|
}
|
|
1129
|
+
if (refs.length !== fk.length) return false;
|
|
1130
|
+
return true;
|
|
1139
1131
|
}
|
|
1140
|
-
function
|
|
1141
|
-
|
|
1142
|
-
if (
|
|
1143
|
-
|
|
1132
|
+
function getReferenceFieldNames(field, foreignKeyCount) {
|
|
1133
|
+
const refs = normalizeKeyList(field.references);
|
|
1134
|
+
if (refs.length === 0) {
|
|
1135
|
+
if (foreignKeyCount === 1) return [SPECIAL_FIELDS.ID];
|
|
1136
|
+
return [];
|
|
1144
1137
|
}
|
|
1145
|
-
|
|
1138
|
+
if (refs.length !== foreignKeyCount) return [];
|
|
1139
|
+
return refs;
|
|
1146
1140
|
}
|
|
1147
|
-
function
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1141
|
+
function joinCondition(field, parentModel, childModel, parentAlias, childAlias) {
|
|
1142
|
+
assertSafeAlias(parentAlias);
|
|
1143
|
+
assertSafeAlias(childAlias);
|
|
1144
|
+
const fkFields = normalizeKeyList(field.foreignKey);
|
|
1145
|
+
if (fkFields.length === 0) {
|
|
1146
|
+
throw createError(
|
|
1147
|
+
`Relation '${field.name}' is missing foreignKey. This indicates a schema parsing error. Relations must specify fields/references.`,
|
|
1148
|
+
{ field: field.name }
|
|
1149
|
+
);
|
|
1151
1150
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1151
|
+
const refFields = getReferenceFieldNames(field, fkFields.length);
|
|
1152
|
+
if (refFields.length !== fkFields.length) {
|
|
1153
|
+
throw createError(
|
|
1154
|
+
`Relation '${field.name}' is missing references (or references count does not match foreignKey count). This is required to support non-id and composite keys.`,
|
|
1155
|
+
{ field: field.name }
|
|
1156
|
+
);
|
|
1157
1157
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1158
|
+
const parts = [];
|
|
1159
|
+
for (let i = 0; i < fkFields.length; i++) {
|
|
1160
|
+
const fk = fkFields[i];
|
|
1161
|
+
const ref = refFields[i];
|
|
1162
|
+
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, ref)}` : `${childAlias}.${quoteColumn(childModel, fk)}`;
|
|
1163
|
+
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, fk)}` : `${parentAlias}.${quoteColumn(parentModel, ref)}`;
|
|
1164
|
+
parts.push(`${left} = ${right}`);
|
|
1160
1165
|
}
|
|
1161
|
-
return
|
|
1166
|
+
return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
|
|
1167
|
+
}
|
|
1168
|
+
function getModelByName(schemas, name) {
|
|
1169
|
+
return schemas.find((m) => m.name === name);
|
|
1162
1170
|
}
|
|
1163
1171
|
function normalizeIntLike(name, v, opts = {}) {
|
|
1164
1172
|
var _a3, _b;
|
|
@@ -4866,7 +4874,6 @@ var DEFAULT_SELECT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
|
4866
4874
|
function toSelectEntries(select) {
|
|
4867
4875
|
const out = [];
|
|
4868
4876
|
for (const [k, v] of Object.entries(select)) {
|
|
4869
|
-
if (k === "_count") continue;
|
|
4870
4877
|
if (v !== false && v !== void 0) out.push([k, v]);
|
|
4871
4878
|
}
|
|
4872
4879
|
return out;
|
|
@@ -4959,7 +4966,9 @@ function validateFieldKeys(entries, scalarSet, relationSet, allowCount = false)
|
|
|
4959
4966
|
if (!scalarSet.has(k) && !relationSet.has(k)) unknown.push(k);
|
|
4960
4967
|
}
|
|
4961
4968
|
if (unknown.length > 0) {
|
|
4962
|
-
throw new Error(
|
|
4969
|
+
throw new Error(
|
|
4970
|
+
`Unknown field '${unknown.join("', '")}' does not exist on this model`
|
|
4971
|
+
);
|
|
4963
4972
|
}
|
|
4964
4973
|
}
|
|
4965
4974
|
function buildSelectedScalarParts(entries, scalarNames, alias, model) {
|
|
@@ -5140,23 +5149,56 @@ function buildNestedToOneJoins(relations, baseAlias, baseModel, aliasGen, dialec
|
|
|
5140
5149
|
}
|
|
5141
5150
|
return { joins, aliasMap };
|
|
5142
5151
|
}
|
|
5143
|
-
function buildNestedToOneSelects(relations, aliasMap) {
|
|
5152
|
+
function buildNestedToOneSelects(relations, aliasMap, dialect) {
|
|
5144
5153
|
const selects = [];
|
|
5145
5154
|
for (const rel of relations) {
|
|
5146
5155
|
const relAlias = aliasMap.get(rel.name);
|
|
5147
5156
|
if (!relAlias) continue;
|
|
5148
5157
|
const relSelect = buildRelationSelect(rel.args, rel.model, relAlias);
|
|
5149
5158
|
if (!relSelect || relSelect.trim().length === 0) continue;
|
|
5150
|
-
|
|
5159
|
+
const jsonExpr = jsonBuildObject(relSelect, dialect);
|
|
5160
|
+
const pkField = getPrimaryKeyField(rel.model);
|
|
5161
|
+
const pkCol = `${relAlias}.${quoteColumn(rel.model, pkField)}`;
|
|
5162
|
+
const nullSafeExpr = `CASE WHEN ${pkCol} IS NOT NULL THEN ${jsonExpr} ELSE NULL END`;
|
|
5163
|
+
selects.push(`${sqlStringLiteral(rel.name)}, ${nullSafeExpr}`);
|
|
5151
5164
|
}
|
|
5152
5165
|
return selects;
|
|
5153
5166
|
}
|
|
5167
|
+
function extractCountSelectFromRelArgs(relArgs) {
|
|
5168
|
+
if (!isPlainObject(relArgs)) return null;
|
|
5169
|
+
const obj = relArgs;
|
|
5170
|
+
if (!isPlainObject(obj.select)) return null;
|
|
5171
|
+
const sel = obj.select;
|
|
5172
|
+
const countRaw = sel["_count"];
|
|
5173
|
+
if (!countRaw) return null;
|
|
5174
|
+
if (isPlainObject(countRaw) && "select" in countRaw) {
|
|
5175
|
+
return countRaw.select;
|
|
5176
|
+
}
|
|
5177
|
+
return null;
|
|
5178
|
+
}
|
|
5154
5179
|
function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
5155
5180
|
const nestedToOnes = extractNestedToOneRelations(
|
|
5156
5181
|
relArgs,
|
|
5157
5182
|
relModel,
|
|
5158
5183
|
ctx.schemaByName
|
|
5159
5184
|
);
|
|
5185
|
+
const countSelect = extractCountSelectFromRelArgs(relArgs);
|
|
5186
|
+
const countJoins = [];
|
|
5187
|
+
function appendCountToSelect(baseSelect2) {
|
|
5188
|
+
if (!countSelect || Object.keys(countSelect).length === 0) return baseSelect2;
|
|
5189
|
+
const countBuild = buildRelationCountSql(
|
|
5190
|
+
countSelect,
|
|
5191
|
+
relModel,
|
|
5192
|
+
ctx.schemas,
|
|
5193
|
+
relAlias,
|
|
5194
|
+
ctx.params,
|
|
5195
|
+
ctx.dialect
|
|
5196
|
+
);
|
|
5197
|
+
if (!countBuild.jsonPairs) return baseSelect2;
|
|
5198
|
+
countJoins.push(...countBuild.joins);
|
|
5199
|
+
const countExpr = `'_count', ${jsonBuildObject(countBuild.jsonPairs, ctx.dialect)}`;
|
|
5200
|
+
return baseSelect2 ? `${baseSelect2}${SQL_SEPARATORS.FIELD_LIST}${countExpr}` : countExpr;
|
|
5201
|
+
}
|
|
5160
5202
|
if (nestedToOnes.length === 0) {
|
|
5161
5203
|
let relSelect = buildRelationSelect(relArgs, relModel, relAlias);
|
|
5162
5204
|
let nestedIncludes = [];
|
|
@@ -5185,7 +5227,8 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
|
5185
5227
|
).join(SQL_SEPARATORS.FIELD_LIST);
|
|
5186
5228
|
relSelect = isNotNullish(relSelect) && relSelect.trim().length > 0 ? `${relSelect}${SQL_SEPARATORS.FIELD_LIST}${nestedSelects2}` : nestedSelects2;
|
|
5187
5229
|
}
|
|
5188
|
-
|
|
5230
|
+
relSelect = appendCountToSelect(relSelect);
|
|
5231
|
+
return { select: relSelect, nestedJoins: countJoins };
|
|
5189
5232
|
}
|
|
5190
5233
|
const { joins, aliasMap } = buildNestedToOneJoins(
|
|
5191
5234
|
nestedToOnes,
|
|
@@ -5195,7 +5238,11 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
|
5195
5238
|
ctx.dialect
|
|
5196
5239
|
);
|
|
5197
5240
|
const baseSelect = buildRelationSelect(relArgs, relModel, relAlias);
|
|
5198
|
-
const nestedSelects = buildNestedToOneSelects(
|
|
5241
|
+
const nestedSelects = buildNestedToOneSelects(
|
|
5242
|
+
nestedToOnes,
|
|
5243
|
+
aliasMap,
|
|
5244
|
+
ctx.dialect
|
|
5245
|
+
);
|
|
5199
5246
|
const allParts = [];
|
|
5200
5247
|
if (baseSelect && baseSelect.trim().length > 0) {
|
|
5201
5248
|
allParts.push(baseSelect);
|
|
@@ -5203,9 +5250,11 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
|
5203
5250
|
for (const ns of nestedSelects) {
|
|
5204
5251
|
allParts.push(ns);
|
|
5205
5252
|
}
|
|
5253
|
+
let finalSelect = allParts.join(SQL_SEPARATORS.FIELD_LIST);
|
|
5254
|
+
finalSelect = appendCountToSelect(finalSelect);
|
|
5206
5255
|
return {
|
|
5207
|
-
select:
|
|
5208
|
-
nestedJoins: joins
|
|
5256
|
+
select: finalSelect,
|
|
5257
|
+
nestedJoins: [...joins, ...countJoins]
|
|
5209
5258
|
};
|
|
5210
5259
|
}
|
|
5211
5260
|
function buildWhereParts(whereInput, relModel, relAlias, ctx) {
|
|
@@ -5587,7 +5636,7 @@ function validateDistinct(model, distinct) {
|
|
|
5587
5636
|
const relationSet = getRelationFieldSet(model);
|
|
5588
5637
|
if (relationSet.has(f)) {
|
|
5589
5638
|
throw new Error(
|
|
5590
|
-
`distinct field '${f}' is a relation. Only scalar fields are allowed.
|
|
5639
|
+
`distinct field '${f}' is a relation field. Only scalar fields are allowed.
|
|
5591
5640
|
Available scalar fields: ${[...scalarSet].join(", ")}`
|
|
5592
5641
|
);
|
|
5593
5642
|
}
|
|
@@ -5625,7 +5674,7 @@ function validateOrderBy(model, orderBy) {
|
|
|
5625
5674
|
if (!scalarSet.has(f)) {
|
|
5626
5675
|
if (relationSet.has(f)) {
|
|
5627
5676
|
throw new Error(
|
|
5628
|
-
`orderBy field '${f}' is a relation. Only scalar fields are allowed.
|
|
5677
|
+
`orderBy field '${f}' is a relation field. Only scalar fields are allowed.
|
|
5629
5678
|
Available scalar fields: ${[...scalarSet].join(", ")}`
|
|
5630
5679
|
);
|
|
5631
5680
|
}
|
|
@@ -9365,10 +9414,30 @@ function executeRaw(client, sql, params, dialect) {
|
|
|
9365
9414
|
function buildSQL(model, models, method, args, dialect) {
|
|
9366
9415
|
return buildSQLWithCache(model, models, method, args, dialect);
|
|
9367
9416
|
}
|
|
9417
|
+
function createToSQLFunction(models, dialect) {
|
|
9418
|
+
if (!models || !Array.isArray(models) || models.length === 0) {
|
|
9419
|
+
throw new Error("createToSQL requires non-empty models array");
|
|
9420
|
+
}
|
|
9421
|
+
const modelMap = new Map(models.map((m) => [m.name, m]));
|
|
9422
|
+
setGlobalDialect(dialect);
|
|
9423
|
+
return function toSQL(model, method, args = {}) {
|
|
9424
|
+
const m = modelMap.get(model);
|
|
9425
|
+
if (!m) {
|
|
9426
|
+
throw new Error(
|
|
9427
|
+
`Model '${model}' not found. Available: ${[...modelMap.keys()].join(", ")}`
|
|
9428
|
+
);
|
|
9429
|
+
}
|
|
9430
|
+
return buildSQL(m, models, method, args, dialect);
|
|
9431
|
+
};
|
|
9432
|
+
}
|
|
9433
|
+
function createToSQL(modelsOrDmmf, dialect) {
|
|
9434
|
+
const models = Array.isArray(modelsOrDmmf) ? modelsOrDmmf : convertDMMFToModels(modelsOrDmmf.datamodel);
|
|
9435
|
+
return createToSQLFunction(models, dialect);
|
|
9436
|
+
}
|
|
9368
9437
|
function generateSQL2(directive) {
|
|
9369
9438
|
return generateSQL(directive);
|
|
9370
9439
|
}
|
|
9371
9440
|
|
|
9372
|
-
export { buildBatchCountSql, buildBatchSql, buildLateralReducerConfig, buildReducerConfig, buildSQL, countIncludeDepth, createProgressiveReducer, createStreamingReducer, createTransactionExecutor, detectSqliteDateMode, executePostgresQuery, executeRaw, executeSqliteQuery, executeWhereInSegments, executeWhereInSegmentsStreaming, executeWithPreFetchedParents, extractCountValue, generateSQL2 as generateSQL, getOrPrepareStatement, getPrimaryKeyField, getRelationStats, getRowTransformer, normalizeParams, normalizeValue, parseBatchCountResults, parseBatchResults, planQueryStrategy, reduceFlatRows, reduceLateralRows, setJsonRowFactor, setNormalizeDateMode, setRelationStats, setRoundtripRowEquivalent, shouldSqliteUseGet, transformAggregateRow, transformQueryResults };
|
|
9441
|
+
export { buildBatchCountSql, buildBatchSql, buildLateralReducerConfig, buildReducerConfig, buildSQL, countIncludeDepth, createProgressiveReducer, createStreamingReducer, createToSQL, createTransactionExecutor, detectSqliteDateMode, executePostgresQuery, executeRaw, executeSqliteQuery, executeWhereInSegments, executeWhereInSegmentsStreaming, executeWithPreFetchedParents, extractCountValue, generateSQL2 as generateSQL, getOrPrepareStatement, getPrimaryKeyField, getRelationStats, getRowTransformer, normalizeParams, normalizeValue, parseBatchCountResults, parseBatchResults, planQueryStrategy, reduceFlatRows, reduceLateralRows, setJsonRowFactor, setNormalizeDateMode, setRelationStats, setRoundtripRowEquivalent, shouldSqliteUseGet, transformAggregateRow, transformQueryResults };
|
|
9373
9442
|
//# sourceMappingURL=index.js.map
|
|
9374
9443
|
//# sourceMappingURL=index.js.map
|