prisma-sql 1.75.12 → 1.76.1
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 +318 -186
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +318 -186
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +364 -227
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +364 -227
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/generator.js
CHANGED
|
@@ -68,7 +68,7 @@ var require_package = __commonJS({
|
|
|
68
68
|
"package.json"(exports$1, module) {
|
|
69
69
|
module.exports = {
|
|
70
70
|
name: "prisma-sql",
|
|
71
|
-
version: "1.
|
|
71
|
+
version: "1.76.1",
|
|
72
72
|
description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
|
|
73
73
|
main: "dist/index.cjs",
|
|
74
74
|
module: "dist/index.js",
|
|
@@ -135,15 +135,15 @@ var require_package = __commonJS({
|
|
|
135
135
|
license: "MIT",
|
|
136
136
|
dependencies: {
|
|
137
137
|
"@dee-wan/schema-parser": "1.4.0",
|
|
138
|
-
"@prisma/generator-helper": "^7.4.
|
|
139
|
-
"@prisma/internals": "^7.4.
|
|
138
|
+
"@prisma/generator-helper": "^7.4.1",
|
|
139
|
+
"@prisma/internals": "^7.4.1",
|
|
140
140
|
dotenv: "^17.3.1",
|
|
141
141
|
postgres: "^3.4.8"
|
|
142
142
|
},
|
|
143
143
|
devDependencies: {
|
|
144
144
|
"@faker-js/faker": "^10.2.0",
|
|
145
|
-
"@prisma/adapter-better-sqlite3": "^7.4.
|
|
146
|
-
"@prisma/adapter-pg": "^7.4.
|
|
145
|
+
"@prisma/adapter-better-sqlite3": "^7.4.1",
|
|
146
|
+
"@prisma/adapter-pg": "^7.4.1",
|
|
147
147
|
"@semantic-release/changelog": "^6.0.3",
|
|
148
148
|
"@semantic-release/git": "^10.0.1",
|
|
149
149
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -156,8 +156,8 @@ var require_package = __commonJS({
|
|
|
156
156
|
tsx: "^4.21.0",
|
|
157
157
|
typescript: "^5.9.3",
|
|
158
158
|
vitest: "^4.0.18",
|
|
159
|
-
"@prisma/client": "7.4.
|
|
160
|
-
prisma: "7.4.
|
|
159
|
+
"@prisma/client": "7.4.1",
|
|
160
|
+
prisma: "7.4.1"
|
|
161
161
|
},
|
|
162
162
|
engines: {
|
|
163
163
|
node: ">=16.0.0"
|
|
@@ -473,9 +473,6 @@ var SQL_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
473
473
|
]);
|
|
474
474
|
var SQL_RESERVED_WORDS = SQL_KEYWORDS;
|
|
475
475
|
var DEFAULT_WHERE_CLAUSE = "1=1";
|
|
476
|
-
var SPECIAL_FIELDS = Object.freeze({
|
|
477
|
-
ID: "id"
|
|
478
|
-
});
|
|
479
476
|
var SQL_TEMPLATES = Object.freeze({
|
|
480
477
|
PUBLIC_SCHEMA: "public",
|
|
481
478
|
WHERE: "WHERE",
|
|
@@ -604,29 +601,6 @@ function hasRequiredKeywords(sql) {
|
|
|
604
601
|
return hasSelect && hasFrom && upper.indexOf("SELECT") < upper.indexOf("FROM");
|
|
605
602
|
}
|
|
606
603
|
|
|
607
|
-
// src/builder/shared/errors.ts
|
|
608
|
-
var SqlBuilderError = class extends Error {
|
|
609
|
-
constructor(message, code, context) {
|
|
610
|
-
super(message);
|
|
611
|
-
this.name = "SqlBuilderError";
|
|
612
|
-
this.code = code;
|
|
613
|
-
this.context = context;
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
function createError(message, ctx, code = "VALIDATION_ERROR") {
|
|
617
|
-
const parts = [message];
|
|
618
|
-
if (isNonEmptyArray(ctx.path)) {
|
|
619
|
-
parts.push(`Path: ${ctx.path.join(".")}`);
|
|
620
|
-
}
|
|
621
|
-
if (isNotNullish(ctx.modelName)) {
|
|
622
|
-
parts.push(`Model: ${ctx.modelName}`);
|
|
623
|
-
}
|
|
624
|
-
if (isNonEmptyArray(ctx.availableFields)) {
|
|
625
|
-
parts.push(`Available fields: ${ctx.availableFields.join(", ")}`);
|
|
626
|
-
}
|
|
627
|
-
return new SqlBuilderError(parts.join("\n"), code, ctx);
|
|
628
|
-
}
|
|
629
|
-
|
|
630
604
|
// src/builder/shared/validators/sql-validators.ts
|
|
631
605
|
function isValidWhereClause(clause) {
|
|
632
606
|
return isNotNullish(clause) && clause.trim().length > 0 && clause !== DEFAULT_WHERE_CLAUSE;
|
|
@@ -769,8 +743,11 @@ function needsQuoting(identifier) {
|
|
|
769
743
|
}
|
|
770
744
|
|
|
771
745
|
// src/builder/shared/sql-utils.ts
|
|
746
|
+
var _a2;
|
|
747
|
+
var IS_PRODUCTION2 = typeof process !== "undefined" && ((_a2 = process.env) == null ? void 0 : _a2.NODE_ENV) === "production";
|
|
772
748
|
var COL_EXPR_CACHE = /* @__PURE__ */ new WeakMap();
|
|
773
749
|
var COL_WITH_ALIAS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
750
|
+
var TABLE_REF_CACHE = /* @__PURE__ */ new Map();
|
|
774
751
|
function containsControlChars(s) {
|
|
775
752
|
for (let i = 0; i < s.length; i++) {
|
|
776
753
|
const code = s.charCodeAt(i);
|
|
@@ -1005,20 +982,33 @@ function buildTableReference(schemaName, tableName, dialect) {
|
|
|
1005
982
|
"buildTableReference: tableName is required and cannot be empty"
|
|
1006
983
|
);
|
|
1007
984
|
}
|
|
1008
|
-
if (containsControlChars(tableName)) {
|
|
1009
|
-
throw new Error(
|
|
1010
|
-
"buildTableReference: tableName contains invalid characters"
|
|
1011
|
-
);
|
|
1012
|
-
}
|
|
1013
985
|
const d = dialect != null ? dialect : "postgres";
|
|
1014
986
|
if (d === "sqlite") {
|
|
1015
|
-
|
|
987
|
+
const cacheKey2 = `\0${tableName}\0sqlite`;
|
|
988
|
+
let cached2 = TABLE_REF_CACHE.get(cacheKey2);
|
|
989
|
+
if (cached2) return cached2;
|
|
990
|
+
if (containsControlChars(tableName)) {
|
|
991
|
+
throw new Error(
|
|
992
|
+
"buildTableReference: tableName contains invalid characters"
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
cached2 = quote(tableName);
|
|
996
|
+
TABLE_REF_CACHE.set(cacheKey2, cached2);
|
|
997
|
+
return cached2;
|
|
1016
998
|
}
|
|
1017
999
|
if (isEmptyString(schemaName)) {
|
|
1018
1000
|
throw new Error(
|
|
1019
1001
|
"buildTableReference: schemaName is required and cannot be empty"
|
|
1020
1002
|
);
|
|
1021
1003
|
}
|
|
1004
|
+
const cacheKey = `${schemaName}\0${tableName}\0${d}`;
|
|
1005
|
+
let cached = TABLE_REF_CACHE.get(cacheKey);
|
|
1006
|
+
if (cached) return cached;
|
|
1007
|
+
if (containsControlChars(tableName)) {
|
|
1008
|
+
throw new Error(
|
|
1009
|
+
"buildTableReference: tableName contains invalid characters"
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1022
1012
|
if (containsControlChars(schemaName)) {
|
|
1023
1013
|
throw new Error(
|
|
1024
1014
|
"buildTableReference: schemaName contains invalid characters"
|
|
@@ -1026,9 +1016,12 @@ function buildTableReference(schemaName, tableName, dialect) {
|
|
|
1026
1016
|
}
|
|
1027
1017
|
const safeSchema = schemaName.replace(/"/g, '""');
|
|
1028
1018
|
const safeTable = tableName.replace(/"/g, '""');
|
|
1029
|
-
|
|
1019
|
+
cached = `"${safeSchema}"."${safeTable}"`;
|
|
1020
|
+
TABLE_REF_CACHE.set(cacheKey, cached);
|
|
1021
|
+
return cached;
|
|
1030
1022
|
}
|
|
1031
1023
|
function assertSafeAlias(alias) {
|
|
1024
|
+
if (IS_PRODUCTION2) return;
|
|
1032
1025
|
if (typeof alias !== "string") {
|
|
1033
1026
|
throw new Error(`Invalid alias: expected string, got ${typeof alias}`);
|
|
1034
1027
|
}
|
|
@@ -1073,6 +1066,7 @@ function assertSafeAlias(alias) {
|
|
|
1073
1066
|
}
|
|
1074
1067
|
}
|
|
1075
1068
|
function assertSafeTableRef(tableRef) {
|
|
1069
|
+
if (IS_PRODUCTION2) return;
|
|
1076
1070
|
assertSafeQualifiedName(tableRef);
|
|
1077
1071
|
}
|
|
1078
1072
|
function normalizeKeyList(input) {
|
|
@@ -1103,7 +1097,7 @@ function normalizeField(field) {
|
|
|
1103
1097
|
return field;
|
|
1104
1098
|
}
|
|
1105
1099
|
function getFieldIndices(model) {
|
|
1106
|
-
var
|
|
1100
|
+
var _a4;
|
|
1107
1101
|
let cached = FIELD_INDICES_CACHE.get(model);
|
|
1108
1102
|
if (cached) return cached;
|
|
1109
1103
|
const scalarFields = /* @__PURE__ */ new Map();
|
|
@@ -1124,7 +1118,7 @@ function getFieldIndices(model) {
|
|
|
1124
1118
|
} else {
|
|
1125
1119
|
scalarFields.set(field.name, field);
|
|
1126
1120
|
scalarNames.push(field.name);
|
|
1127
|
-
const fieldType = String((
|
|
1121
|
+
const fieldType = String((_a4 = field.type) != null ? _a4 : "").toLowerCase();
|
|
1128
1122
|
if (fieldType === "json") {
|
|
1129
1123
|
jsonFields.add(field.name);
|
|
1130
1124
|
}
|
|
@@ -1138,12 +1132,16 @@ function getFieldIndices(model) {
|
|
|
1138
1132
|
quotedColumns.set(field.name, quote(columnName));
|
|
1139
1133
|
}
|
|
1140
1134
|
}
|
|
1135
|
+
const scalarFieldSet = new Set(scalarNames);
|
|
1136
|
+
const relationFieldSet = new Set(relationNames);
|
|
1141
1137
|
cached = Object.freeze({
|
|
1142
1138
|
scalarFields,
|
|
1143
1139
|
relationFields,
|
|
1144
1140
|
allFieldsByName,
|
|
1145
1141
|
scalarNames,
|
|
1146
1142
|
relationNames,
|
|
1143
|
+
scalarFieldSet,
|
|
1144
|
+
relationFieldSet,
|
|
1147
1145
|
jsonFields,
|
|
1148
1146
|
pkFields,
|
|
1149
1147
|
columnMap,
|
|
@@ -1153,10 +1151,10 @@ function getFieldIndices(model) {
|
|
|
1153
1151
|
return cached;
|
|
1154
1152
|
}
|
|
1155
1153
|
function getRelationFieldSet(model) {
|
|
1156
|
-
return
|
|
1154
|
+
return getFieldIndices(model).relationFieldSet;
|
|
1157
1155
|
}
|
|
1158
1156
|
function getScalarFieldSet(model) {
|
|
1159
|
-
return
|
|
1157
|
+
return getFieldIndices(model).scalarFieldSet;
|
|
1160
1158
|
}
|
|
1161
1159
|
function getColumnMap(model) {
|
|
1162
1160
|
return getFieldIndices(model).columnMap;
|
|
@@ -1168,6 +1166,34 @@ function getJsonFieldSet(model) {
|
|
|
1168
1166
|
return getFieldIndices(model).jsonFields;
|
|
1169
1167
|
}
|
|
1170
1168
|
|
|
1169
|
+
// src/builder/shared/relation-key-utils.ts
|
|
1170
|
+
var RELATION_KEYS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1171
|
+
function computeRelationKeys(field, context) {
|
|
1172
|
+
const fkFields = normalizeKeyList(field.foreignKey);
|
|
1173
|
+
if (fkFields.length === 0) {
|
|
1174
|
+
throw new Error(
|
|
1175
|
+
`Relation '${field.name}' is missing foreignKey for ${context}`
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
const refs = normalizeKeyList(field.references);
|
|
1179
|
+
const refFields = refs.length > 0 ? refs : fkFields.length === 1 ? ["id"] : [];
|
|
1180
|
+
if (refFields.length !== fkFields.length) {
|
|
1181
|
+
throw new Error(
|
|
1182
|
+
`Relation '${field.name}' references count (${refFields.length}) doesn't match foreignKey count (${fkFields.length}) (context: ${context})`
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
const childKeys = field.isForeignKeyLocal ? refFields : fkFields;
|
|
1186
|
+
const parentKeys = field.isForeignKeyLocal ? fkFields : refFields;
|
|
1187
|
+
return { childKeys, parentKeys };
|
|
1188
|
+
}
|
|
1189
|
+
function resolveRelationKeys(field, context = "include") {
|
|
1190
|
+
let cached = RELATION_KEYS_CACHE.get(field);
|
|
1191
|
+
if (cached) return cached;
|
|
1192
|
+
cached = computeRelationKeys(field, context);
|
|
1193
|
+
RELATION_KEYS_CACHE.set(field, cached);
|
|
1194
|
+
return cached;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1171
1197
|
// src/builder/joins.ts
|
|
1172
1198
|
function isRelationField(fieldName, model) {
|
|
1173
1199
|
return getRelationFieldSet(model).has(fieldName);
|
|
@@ -1186,38 +1212,14 @@ function isValidRelationField(field) {
|
|
|
1186
1212
|
if (refs.length !== fk.length) return false;
|
|
1187
1213
|
return true;
|
|
1188
1214
|
}
|
|
1189
|
-
function getReferenceFieldNames(field, foreignKeyCount) {
|
|
1190
|
-
const refs = normalizeKeyList(field.references);
|
|
1191
|
-
if (refs.length === 0) {
|
|
1192
|
-
if (foreignKeyCount === 1) return [SPECIAL_FIELDS.ID];
|
|
1193
|
-
return [];
|
|
1194
|
-
}
|
|
1195
|
-
if (refs.length !== foreignKeyCount) return [];
|
|
1196
|
-
return refs;
|
|
1197
|
-
}
|
|
1198
1215
|
function joinCondition(field, parentModel, childModel, parentAlias, childAlias) {
|
|
1199
1216
|
assertSafeAlias(parentAlias);
|
|
1200
1217
|
assertSafeAlias(childAlias);
|
|
1201
|
-
const
|
|
1202
|
-
if (fkFields.length === 0) {
|
|
1203
|
-
throw createError(
|
|
1204
|
-
`Relation '${field.name}' is missing foreignKey. This indicates a schema parsing error. Relations must specify fields/references.`,
|
|
1205
|
-
{ field: field.name }
|
|
1206
|
-
);
|
|
1207
|
-
}
|
|
1208
|
-
const refFields = getReferenceFieldNames(field, fkFields.length);
|
|
1209
|
-
if (refFields.length !== fkFields.length) {
|
|
1210
|
-
throw createError(
|
|
1211
|
-
`Relation '${field.name}' is missing references (or references count does not match foreignKey count). This is required to support non-id and composite keys.`,
|
|
1212
|
-
{ field: field.name }
|
|
1213
|
-
);
|
|
1214
|
-
}
|
|
1218
|
+
const { childKeys, parentKeys } = resolveRelationKeys(field, "include");
|
|
1215
1219
|
const parts = [];
|
|
1216
|
-
for (let i = 0; i <
|
|
1217
|
-
const
|
|
1218
|
-
const
|
|
1219
|
-
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, ref)}` : `${childAlias}.${quoteColumn(childModel, fk)}`;
|
|
1220
|
-
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, fk)}` : `${parentAlias}.${quoteColumn(parentModel, ref)}`;
|
|
1220
|
+
for (let i = 0; i < parentKeys.length; i++) {
|
|
1221
|
+
const left = field.isForeignKeyLocal ? `${childAlias}.${quoteColumn(childModel, childKeys[i])}` : `${childAlias}.${quoteColumn(childModel, childKeys[i])}`;
|
|
1222
|
+
const right = field.isForeignKeyLocal ? `${parentAlias}.${quoteColumn(parentModel, parentKeys[i])}` : `${parentAlias}.${quoteColumn(parentModel, parentKeys[i])}`;
|
|
1221
1223
|
parts.push(`${left} = ${right}`);
|
|
1222
1224
|
}
|
|
1223
1225
|
return parts.length === 1 ? parts[0] : `(${parts.join(" AND ")})`;
|
|
@@ -1226,13 +1228,13 @@ function getModelByName(schemas, name) {
|
|
|
1226
1228
|
return schemas.find((m) => m.name === name);
|
|
1227
1229
|
}
|
|
1228
1230
|
function normalizeIntLike(name, v, opts = {}) {
|
|
1229
|
-
var
|
|
1231
|
+
var _a4, _b;
|
|
1230
1232
|
if (!isNotNullish(v)) return void 0;
|
|
1231
1233
|
if (isDynamicParameter(v)) return v;
|
|
1232
1234
|
if (typeof v !== "number" || !Number.isFinite(v) || !Number.isInteger(v)) {
|
|
1233
1235
|
throw new Error(`${name} must be an integer`);
|
|
1234
1236
|
}
|
|
1235
|
-
const min = (
|
|
1237
|
+
const min = (_a4 = opts.min) != null ? _a4 : 0;
|
|
1236
1238
|
const allowZero = (_b = opts.allowZero) != null ? _b : true;
|
|
1237
1239
|
if (!allowZero && v === 0) {
|
|
1238
1240
|
throw new Error(`${name} must be > 0`);
|
|
@@ -1378,6 +1380,14 @@ function reverseOrderByInput(orderBy) {
|
|
|
1378
1380
|
var normalizePairs = (pairs, parseValue) => {
|
|
1379
1381
|
const result = [];
|
|
1380
1382
|
for (const [field, rawValue] of pairs) {
|
|
1383
|
+
if (typeof rawValue === "string") {
|
|
1384
|
+
const lower = rawValue.toLowerCase();
|
|
1385
|
+
if (lower !== "asc" && lower !== "desc") {
|
|
1386
|
+
throw new Error(
|
|
1387
|
+
`Invalid orderBy direction '${rawValue}' for field '${field}'. Must be 'asc' or 'desc'`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1381
1391
|
if (!isScalarOrderByValue(rawValue)) continue;
|
|
1382
1392
|
const parsed = parseValue(rawValue, field);
|
|
1383
1393
|
result.push({
|
|
@@ -1459,6 +1469,29 @@ function ensureDeterministicOrderByInput(args) {
|
|
|
1459
1469
|
return addTiebreaker(orderBy, tiebreaker);
|
|
1460
1470
|
}
|
|
1461
1471
|
|
|
1472
|
+
// src/builder/shared/errors.ts
|
|
1473
|
+
var SqlBuilderError = class extends Error {
|
|
1474
|
+
constructor(message, code, context) {
|
|
1475
|
+
super(message);
|
|
1476
|
+
this.name = "SqlBuilderError";
|
|
1477
|
+
this.code = code;
|
|
1478
|
+
this.context = context;
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
function createError(message, ctx, code = "VALIDATION_ERROR") {
|
|
1482
|
+
const parts = [message];
|
|
1483
|
+
if (isNonEmptyArray(ctx.path)) {
|
|
1484
|
+
parts.push(`Path: ${ctx.path.join(".")}`);
|
|
1485
|
+
}
|
|
1486
|
+
if (isNotNullish(ctx.modelName)) {
|
|
1487
|
+
parts.push(`Model: ${ctx.modelName}`);
|
|
1488
|
+
}
|
|
1489
|
+
if (isNonEmptyArray(ctx.availableFields)) {
|
|
1490
|
+
parts.push(`Available fields: ${ctx.availableFields.join(", ")}`);
|
|
1491
|
+
}
|
|
1492
|
+
return new SqlBuilderError(parts.join("\n"), code, ctx);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1462
1495
|
// src/builder/shared/primary-key-utils.ts
|
|
1463
1496
|
var FIELD_BY_NAME_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1464
1497
|
function normalizeField2(field) {
|
|
@@ -1743,7 +1776,7 @@ function assertCursorAndOrderFieldsScalar(model, cursor, orderEntries) {
|
|
|
1743
1776
|
}
|
|
1744
1777
|
}
|
|
1745
1778
|
function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
|
|
1746
|
-
var
|
|
1779
|
+
var _a4;
|
|
1747
1780
|
assertSafeTableRef(tableName);
|
|
1748
1781
|
assertSafeAlias(alias);
|
|
1749
1782
|
const d = dialect != null ? dialect : getGlobalDialect();
|
|
@@ -1838,7 +1871,7 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
1838
1871
|
const e = finalOrderEntries[level];
|
|
1839
1872
|
const c = col(alias, e.field, model);
|
|
1840
1873
|
const cursorField = cteName + "." + quoteColumn(model, e.field);
|
|
1841
|
-
const nulls = (
|
|
1874
|
+
const nulls = (_a4 = e.nulls) != null ? _a4 : defaultNullsFor(d, e.direction);
|
|
1842
1875
|
andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, cursorField));
|
|
1843
1876
|
orClauses.push("(" + andParts.join(SQL_SEPARATORS.CONDITION_AND) + ")");
|
|
1844
1877
|
}
|
|
@@ -1958,34 +1991,6 @@ function createAliasGenerator(maxAliases = 1e4) {
|
|
|
1958
1991
|
};
|
|
1959
1992
|
}
|
|
1960
1993
|
|
|
1961
|
-
// src/builder/shared/relation-key-utils.ts
|
|
1962
|
-
var RELATION_KEYS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
1963
|
-
function computeRelationKeys(field, context) {
|
|
1964
|
-
const fkFields = normalizeKeyList(field.foreignKey);
|
|
1965
|
-
if (fkFields.length === 0) {
|
|
1966
|
-
throw new Error(
|
|
1967
|
-
`Relation '${field.name}' is missing foreignKey for ${context}`
|
|
1968
|
-
);
|
|
1969
|
-
}
|
|
1970
|
-
const refs = normalizeKeyList(field.references);
|
|
1971
|
-
const refFields = refs.length > 0 ? refs : fkFields.length === 1 ? ["id"] : [];
|
|
1972
|
-
if (refFields.length !== fkFields.length) {
|
|
1973
|
-
throw new Error(
|
|
1974
|
-
`Relation '${field.name}' references count (${refFields.length}) doesn't match foreignKey count (${fkFields.length}) (context: ${context})`
|
|
1975
|
-
);
|
|
1976
|
-
}
|
|
1977
|
-
const childKeys = field.isForeignKeyLocal ? refFields : fkFields;
|
|
1978
|
-
const parentKeys = field.isForeignKeyLocal ? fkFields : refFields;
|
|
1979
|
-
return { childKeys, parentKeys };
|
|
1980
|
-
}
|
|
1981
|
-
function resolveRelationKeys(field, context = "include") {
|
|
1982
|
-
let cached = RELATION_KEYS_CACHE.get(field);
|
|
1983
|
-
if (cached) return cached;
|
|
1984
|
-
cached = computeRelationKeys(field, context);
|
|
1985
|
-
RELATION_KEYS_CACHE.set(field, cached);
|
|
1986
|
-
return cached;
|
|
1987
|
-
}
|
|
1988
|
-
|
|
1989
1994
|
// src/builder/shared/fk-join-utils.ts
|
|
1990
1995
|
var FK_COLUMN_PREFIX = "__fk";
|
|
1991
1996
|
function fkColumnName(index) {
|
|
@@ -2171,7 +2176,7 @@ function resolveCountRelationOrThrow(relName, model, schemaByName) {
|
|
|
2171
2176
|
`_count.${relName} references unknown relation on model ${model.name}`
|
|
2172
2177
|
);
|
|
2173
2178
|
}
|
|
2174
|
-
const field = model.
|
|
2179
|
+
const field = getFieldIndices(model).allFieldsByName.get(relName);
|
|
2175
2180
|
if (!field) {
|
|
2176
2181
|
throw new Error(
|
|
2177
2182
|
`_count.${relName} references unknown relation on model ${model.name}`
|
|
@@ -2248,12 +2253,11 @@ function buildCountJoinAndPair(args) {
|
|
|
2248
2253
|
pairSql: `${sqlStringLiteral(args.relName)}, COALESCE(${joinAlias}.${COUNT_COLUMN}, 0)`
|
|
2249
2254
|
};
|
|
2250
2255
|
}
|
|
2251
|
-
function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params, dialect) {
|
|
2256
|
+
function buildRelationCountSql(countSelect, model, schemas, parentAlias, _params, dialect, modelMap) {
|
|
2252
2257
|
const joins = [];
|
|
2253
2258
|
const pairs = [];
|
|
2254
2259
|
const aliasGen = createAliasGenerator();
|
|
2255
|
-
const schemaByName =
|
|
2256
|
-
for (const m of schemas) schemaByName.set(m.name, m);
|
|
2260
|
+
const schemaByName = modelMap != null ? modelMap : new Map(schemas.map((m) => [m.name, m]));
|
|
2257
2261
|
for (const [relName, shouldCount] of Object.entries(countSelect)) {
|
|
2258
2262
|
if (!shouldCount) continue;
|
|
2259
2263
|
const resolved = resolveCountRelationOrThrow(relName, model, schemaByName);
|
|
@@ -2327,14 +2331,23 @@ function extractNestedIncludeSpec(relArgs, relModel) {
|
|
|
2327
2331
|
}
|
|
2328
2332
|
|
|
2329
2333
|
// src/builder/shared/include-tree-walker.ts
|
|
2330
|
-
|
|
2331
|
-
|
|
2334
|
+
var MODEL_MAP_CACHE = /* @__PURE__ */ new WeakMap();
|
|
2335
|
+
function getOrCreateModelMap(schemas) {
|
|
2336
|
+
let map = MODEL_MAP_CACHE.get(schemas);
|
|
2337
|
+
if (map) return map;
|
|
2338
|
+
map = /* @__PURE__ */ new Map();
|
|
2339
|
+
for (const m of schemas) map.set(m.name, m);
|
|
2340
|
+
MODEL_MAP_CACHE.set(schemas, map);
|
|
2341
|
+
return map;
|
|
2342
|
+
}
|
|
2343
|
+
function resolveIncludeRelations(includeSpec, model, schemas, modelMap) {
|
|
2344
|
+
const map = modelMap != null ? modelMap : getOrCreateModelMap(schemas);
|
|
2332
2345
|
const results = [];
|
|
2333
2346
|
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
2334
2347
|
if (value === false) continue;
|
|
2335
|
-
const field = model.
|
|
2348
|
+
const field = getFieldIndices(model).allFieldsByName.get(relName);
|
|
2336
2349
|
if (!(field == null ? void 0 : field.isRelation) || !field.relatedModel) continue;
|
|
2337
|
-
const relModel =
|
|
2350
|
+
const relModel = map.get(field.relatedModel);
|
|
2338
2351
|
if (!relModel) continue;
|
|
2339
2352
|
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
2340
2353
|
const nestedSpec = isPlainObject(value) ? extractNestedIncludeSpec(value, relModel) : {};
|
|
@@ -2355,15 +2368,18 @@ var CORRELATED_S_UNBOUNDED = 3;
|
|
|
2355
2368
|
var CORRELATED_WHERE_PENALTY = 3;
|
|
2356
2369
|
var DEFAULT_FAN = 10;
|
|
2357
2370
|
var DEFAULT_PARENT_COUNT = 50;
|
|
2358
|
-
var SINGLE_PARENT_MAX_FLAT_JOIN_DEPTH =
|
|
2371
|
+
var SINGLE_PARENT_MAX_FLAT_JOIN_DEPTH = 2;
|
|
2359
2372
|
function getFanOut(modelName, relName) {
|
|
2360
2373
|
return DEFAULT_FAN;
|
|
2361
2374
|
}
|
|
2375
|
+
var DYNAMIC_TAKE_ESTIMATE = 10;
|
|
2362
2376
|
function readTake(relArgs) {
|
|
2363
2377
|
if (!isPlainObject(relArgs)) return Infinity;
|
|
2364
2378
|
const obj = relArgs;
|
|
2365
2379
|
if ("take" in obj && typeof obj.take === "number" && obj.take > 0)
|
|
2366
2380
|
return obj.take;
|
|
2381
|
+
if ("take" in obj && obj.take != null && isDynamicParameter(obj.take))
|
|
2382
|
+
return DYNAMIC_TAKE_ESTIMATE;
|
|
2367
2383
|
return Infinity;
|
|
2368
2384
|
}
|
|
2369
2385
|
function hasWhereClause(relArgs) {
|
|
@@ -2377,17 +2393,28 @@ function isListField(field) {
|
|
|
2377
2393
|
function hasPaginationArgs(value) {
|
|
2378
2394
|
if (!isPlainObject(value)) return false;
|
|
2379
2395
|
const obj = value;
|
|
2380
|
-
return "take" in obj && obj.take != null || "skip" in obj && typeof obj.skip === "number" && obj.skip > 0;
|
|
2396
|
+
return "take" in obj && obj.take != null || "skip" in obj && obj.skip != null && (typeof obj.skip === "number" && obj.skip > 0 || isDynamicParameter(obj.skip));
|
|
2381
2397
|
}
|
|
2382
|
-
function buildCostTree(includeSpec, model, schemas, depth = 0) {
|
|
2398
|
+
function buildCostTree(includeSpec, model, schemas, depth = 0, modelMap) {
|
|
2383
2399
|
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return [];
|
|
2384
|
-
const relations = resolveIncludeRelations(
|
|
2400
|
+
const relations = resolveIncludeRelations(
|
|
2401
|
+
includeSpec,
|
|
2402
|
+
model,
|
|
2403
|
+
schemas,
|
|
2404
|
+
modelMap
|
|
2405
|
+
);
|
|
2385
2406
|
const nodes = [];
|
|
2386
2407
|
for (const rel of relations) {
|
|
2387
2408
|
const fan = rel.isList ? getFanOut(model.name, rel.relName) : 1;
|
|
2388
2409
|
const take = rel.isList ? readTake(rel.value) : 1;
|
|
2389
2410
|
const eff = Math.min(fan, take);
|
|
2390
|
-
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(
|
|
2411
|
+
const children = Object.keys(rel.nestedSpec).length > 0 ? buildCostTree(
|
|
2412
|
+
rel.nestedSpec,
|
|
2413
|
+
rel.relModel,
|
|
2414
|
+
schemas,
|
|
2415
|
+
depth + 1,
|
|
2416
|
+
modelMap
|
|
2417
|
+
) : [];
|
|
2391
2418
|
nodes.push({
|
|
2392
2419
|
name: rel.relName,
|
|
2393
2420
|
fan,
|
|
@@ -2451,17 +2478,23 @@ function computeCorrelatedCost(nodes, parentCount) {
|
|
|
2451
2478
|
return R + parentCount * subqueryCost(nodes);
|
|
2452
2479
|
}
|
|
2453
2480
|
function hasOnlyToOneRelations(includeSpec, model) {
|
|
2481
|
+
const indices = getFieldIndices(model);
|
|
2454
2482
|
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
2455
2483
|
if (value === false) continue;
|
|
2456
|
-
const field =
|
|
2484
|
+
const field = indices.allFieldsByName.get(relName);
|
|
2457
2485
|
if (!(field == null ? void 0 : field.isRelation)) continue;
|
|
2458
2486
|
if (isListField(field)) return false;
|
|
2459
2487
|
}
|
|
2460
2488
|
return true;
|
|
2461
2489
|
}
|
|
2462
|
-
function countIncludeDepth(includeSpec, model, schemas, depth = 0) {
|
|
2490
|
+
function countIncludeDepth(includeSpec, model, schemas, depth = 0, modelMap) {
|
|
2463
2491
|
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return 0;
|
|
2464
|
-
const relations = resolveIncludeRelations(
|
|
2492
|
+
const relations = resolveIncludeRelations(
|
|
2493
|
+
includeSpec,
|
|
2494
|
+
model,
|
|
2495
|
+
schemas,
|
|
2496
|
+
modelMap
|
|
2497
|
+
);
|
|
2465
2498
|
let maxDepth = 0;
|
|
2466
2499
|
for (const rel of relations) {
|
|
2467
2500
|
let childDepth = 1;
|
|
@@ -2470,27 +2503,34 @@ function countIncludeDepth(includeSpec, model, schemas, depth = 0) {
|
|
|
2470
2503
|
rel.nestedSpec,
|
|
2471
2504
|
rel.relModel,
|
|
2472
2505
|
schemas,
|
|
2473
|
-
depth + 1
|
|
2506
|
+
depth + 1,
|
|
2507
|
+
modelMap
|
|
2474
2508
|
);
|
|
2475
2509
|
}
|
|
2476
2510
|
if (childDepth > maxDepth) maxDepth = childDepth;
|
|
2477
2511
|
}
|
|
2478
2512
|
return maxDepth;
|
|
2479
2513
|
}
|
|
2480
|
-
function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0) {
|
|
2514
|
+
function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0, modelMap) {
|
|
2481
2515
|
if (depth > LIMITS.MAX_INCLUDE_DEPTH) return false;
|
|
2482
2516
|
for (const [, value] of Object.entries(includeSpec)) {
|
|
2483
2517
|
if (value === false) continue;
|
|
2484
2518
|
if (hasPaginationArgs(value)) return true;
|
|
2485
2519
|
}
|
|
2486
|
-
const relations = resolveIncludeRelations(
|
|
2520
|
+
const relations = resolveIncludeRelations(
|
|
2521
|
+
includeSpec,
|
|
2522
|
+
model,
|
|
2523
|
+
schemas,
|
|
2524
|
+
modelMap
|
|
2525
|
+
);
|
|
2487
2526
|
for (const rel of relations) {
|
|
2488
2527
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
2489
2528
|
if (hasChildPaginationAnywhere(
|
|
2490
2529
|
rel.nestedSpec,
|
|
2491
2530
|
rel.relModel,
|
|
2492
2531
|
schemas,
|
|
2493
|
-
depth + 1
|
|
2532
|
+
depth + 1,
|
|
2533
|
+
modelMap
|
|
2494
2534
|
)) {
|
|
2495
2535
|
return true;
|
|
2496
2536
|
}
|
|
@@ -2499,7 +2539,17 @@ function hasChildPaginationAnywhere(includeSpec, model, schemas, depth = 0) {
|
|
|
2499
2539
|
return false;
|
|
2500
2540
|
}
|
|
2501
2541
|
function pickIncludeStrategy(params) {
|
|
2502
|
-
const {
|
|
2542
|
+
const {
|
|
2543
|
+
includeSpec,
|
|
2544
|
+
model,
|
|
2545
|
+
schemas,
|
|
2546
|
+
method,
|
|
2547
|
+
takeValue,
|
|
2548
|
+
canFlatJoin,
|
|
2549
|
+
hasChildPagination,
|
|
2550
|
+
debug,
|
|
2551
|
+
modelMap
|
|
2552
|
+
} = params;
|
|
2503
2553
|
if (Object.keys(includeSpec).length === 0) return "where-in";
|
|
2504
2554
|
if (canFlatJoin && hasOnlyToOneRelations(includeSpec, model)) {
|
|
2505
2555
|
if (debug)
|
|
@@ -2508,7 +2558,7 @@ function pickIncludeStrategy(params) {
|
|
|
2508
2558
|
}
|
|
2509
2559
|
const isSingleParent = method === "findFirst" || method === "findUnique";
|
|
2510
2560
|
if (isSingleParent && canFlatJoin) {
|
|
2511
|
-
const depth = countIncludeDepth(includeSpec, model, schemas);
|
|
2561
|
+
const depth = countIncludeDepth(includeSpec, model, schemas, 0, modelMap);
|
|
2512
2562
|
if (depth <= SINGLE_PARENT_MAX_FLAT_JOIN_DEPTH) {
|
|
2513
2563
|
if (debug)
|
|
2514
2564
|
console.log(
|
|
@@ -2517,8 +2567,37 @@ function pickIncludeStrategy(params) {
|
|
|
2517
2567
|
return "flat-join";
|
|
2518
2568
|
}
|
|
2519
2569
|
}
|
|
2520
|
-
const costTree = buildCostTree(includeSpec, model, schemas);
|
|
2570
|
+
const costTree = buildCostTree(includeSpec, model, schemas, 0, modelMap);
|
|
2521
2571
|
const treeDepth = maxDepthFromTree(costTree);
|
|
2572
|
+
if (hasChildPagination && treeDepth >= 2) {
|
|
2573
|
+
if (debug)
|
|
2574
|
+
console.log(
|
|
2575
|
+
` [strategy] ${model.name}: childPagination + depth=${treeDepth} \u2265 2 \u2192 fallback`
|
|
2576
|
+
);
|
|
2577
|
+
return "fallback";
|
|
2578
|
+
}
|
|
2579
|
+
if (hasChildPagination && treeDepth === 1) {
|
|
2580
|
+
if (anyChildHasWhere(costTree)) {
|
|
2581
|
+
if (debug)
|
|
2582
|
+
console.log(
|
|
2583
|
+
` [strategy] ${model.name}: childPagination + depth=1 + childWhere \u2192 where-in`
|
|
2584
|
+
);
|
|
2585
|
+
return "where-in";
|
|
2586
|
+
}
|
|
2587
|
+
const hasSelectNarrowing = isPlainObject(params.args) && isPlainObject(params.args.select);
|
|
2588
|
+
if (hasSelectNarrowing) {
|
|
2589
|
+
if (debug)
|
|
2590
|
+
console.log(
|
|
2591
|
+
` [strategy] ${model.name}: childPagination + depth=1 + selectNarrowing \u2192 fallback`
|
|
2592
|
+
);
|
|
2593
|
+
return "fallback";
|
|
2594
|
+
}
|
|
2595
|
+
if (debug)
|
|
2596
|
+
console.log(
|
|
2597
|
+
` [strategy] ${model.name}: childPagination + depth=1 \u2192 where-in`
|
|
2598
|
+
);
|
|
2599
|
+
return "where-in";
|
|
2600
|
+
}
|
|
2522
2601
|
if (treeDepth === 1 && anyChildHasWhere(costTree)) {
|
|
2523
2602
|
if (debug)
|
|
2524
2603
|
console.log(` [strategy] ${model.name}: depth-1 + childWhere \u2192 where-in`);
|
|
@@ -2596,13 +2675,13 @@ function createAliasCounter() {
|
|
|
2596
2675
|
}
|
|
2597
2676
|
};
|
|
2598
2677
|
}
|
|
2599
|
-
function getRelationModel(parentModel, relationName, schemas) {
|
|
2678
|
+
function getRelationModel(parentModel, relationName, schemas, modelMap) {
|
|
2600
2679
|
const indices = getFieldIndices(parentModel);
|
|
2601
2680
|
const field = indices.allFieldsByName.get(relationName);
|
|
2602
2681
|
if (!(field == null ? void 0 : field.isRelation) || !field.relatedModel) {
|
|
2603
2682
|
throw new Error(`Invalid relation ${relationName} on ${parentModel.name}`);
|
|
2604
2683
|
}
|
|
2605
|
-
const relModel = schemas.find((m) => m.name === field.relatedModel);
|
|
2684
|
+
const relModel = modelMap ? modelMap.get(field.relatedModel) : schemas.find((m) => m.name === field.relatedModel);
|
|
2606
2685
|
if (!relModel) {
|
|
2607
2686
|
throw new Error(`Related model ${field.relatedModel} not found`);
|
|
2608
2687
|
}
|
|
@@ -2639,8 +2718,13 @@ function countActiveEntries(spec) {
|
|
|
2639
2718
|
}
|
|
2640
2719
|
return count;
|
|
2641
2720
|
}
|
|
2642
|
-
function canUseFlatJoinForAll(includeSpec, model, schemas, debug) {
|
|
2643
|
-
const relations = resolveIncludeRelations(
|
|
2721
|
+
function canUseFlatJoinForAll(includeSpec, model, schemas, debug, modelMap) {
|
|
2722
|
+
const relations = resolveIncludeRelations(
|
|
2723
|
+
includeSpec,
|
|
2724
|
+
model,
|
|
2725
|
+
schemas,
|
|
2726
|
+
modelMap
|
|
2727
|
+
);
|
|
2644
2728
|
if (relations.length < countActiveEntries(includeSpec)) {
|
|
2645
2729
|
return false;
|
|
2646
2730
|
}
|
|
@@ -2662,14 +2746,20 @@ function canUseFlatJoinForAll(includeSpec, model, schemas, debug) {
|
|
|
2662
2746
|
return false;
|
|
2663
2747
|
}
|
|
2664
2748
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
2665
|
-
if (!canUseFlatJoinForAll(
|
|
2749
|
+
if (!canUseFlatJoinForAll(
|
|
2750
|
+
rel.nestedSpec,
|
|
2751
|
+
rel.relModel,
|
|
2752
|
+
schemas,
|
|
2753
|
+
debug,
|
|
2754
|
+
modelMap
|
|
2755
|
+
)) {
|
|
2666
2756
|
return false;
|
|
2667
2757
|
}
|
|
2668
2758
|
}
|
|
2669
2759
|
}
|
|
2670
2760
|
return true;
|
|
2671
2761
|
}
|
|
2672
|
-
function buildNestedJoins(parentModel, parentAlias, includeSpec, schemas, dialect, prefix, aliasCounter, depth = 0) {
|
|
2762
|
+
function buildNestedJoins(parentModel, parentAlias, includeSpec, schemas, dialect, prefix, aliasCounter, depth = 0, modelMap) {
|
|
2673
2763
|
if (depth > LIMITS.MAX_NESTED_JOIN_DEPTH) {
|
|
2674
2764
|
throw new Error(
|
|
2675
2765
|
`Nested joins exceeded maximum depth of ${LIMITS.MAX_NESTED_JOIN_DEPTH} at prefix '${prefix}'`
|
|
@@ -2683,7 +2773,7 @@ function buildNestedJoins(parentModel, parentAlias, includeSpec, schemas, dialec
|
|
|
2683
2773
|
const indices = getFieldIndices(parentModel);
|
|
2684
2774
|
const field = indices.allFieldsByName.get(relName);
|
|
2685
2775
|
if (!isValidRelationField(field)) continue;
|
|
2686
|
-
const relModel = getRelationModel(parentModel, relName, schemas);
|
|
2776
|
+
const relModel = getRelationModel(parentModel, relName, schemas, modelMap);
|
|
2687
2777
|
const relTable = buildTableReference(
|
|
2688
2778
|
SQL_TEMPLATES.PUBLIC_SCHEMA,
|
|
2689
2779
|
relModel.tableName,
|
|
@@ -2724,7 +2814,8 @@ function buildNestedJoins(parentModel, parentAlias, includeSpec, schemas, dialec
|
|
|
2724
2814
|
dialect,
|
|
2725
2815
|
nestedPrefix,
|
|
2726
2816
|
aliasCounter,
|
|
2727
|
-
depth + 1
|
|
2817
|
+
depth + 1,
|
|
2818
|
+
modelMap
|
|
2728
2819
|
);
|
|
2729
2820
|
joins.push(...deeper.joins);
|
|
2730
2821
|
selects.push(...deeper.selects);
|
|
@@ -2780,6 +2871,8 @@ function buildFlatJoinSql(spec) {
|
|
|
2780
2871
|
requiresReduction: false,
|
|
2781
2872
|
includeSpec: {}
|
|
2782
2873
|
};
|
|
2874
|
+
const modelMap = /* @__PURE__ */ new Map();
|
|
2875
|
+
for (const m of schemas) modelMap.set(m.name, m);
|
|
2783
2876
|
const includeSpec = extractRelationEntries(args, model).reduce(
|
|
2784
2877
|
(acc, { name, value }) => {
|
|
2785
2878
|
acc[name] = value;
|
|
@@ -2790,7 +2883,7 @@ function buildFlatJoinSql(spec) {
|
|
|
2790
2883
|
if (Object.keys(includeSpec).length === 0) {
|
|
2791
2884
|
return emptyResult;
|
|
2792
2885
|
}
|
|
2793
|
-
if (!canUseFlatJoinForAll(includeSpec, model, schemas)) {
|
|
2886
|
+
if (!canUseFlatJoinForAll(includeSpec, model, schemas, false, modelMap)) {
|
|
2794
2887
|
return emptyResult;
|
|
2795
2888
|
}
|
|
2796
2889
|
const { cleanWhere, params } = extractReferencedParams(
|
|
@@ -2826,7 +2919,8 @@ function buildFlatJoinSql(spec) {
|
|
|
2826
2919
|
dialect,
|
|
2827
2920
|
"",
|
|
2828
2921
|
aliasCounter,
|
|
2829
|
-
0
|
|
2922
|
+
0,
|
|
2923
|
+
modelMap
|
|
2830
2924
|
);
|
|
2831
2925
|
if (built.joins.length === 0) {
|
|
2832
2926
|
return emptyResult;
|
|
@@ -3830,8 +3924,8 @@ function buildOperator(expr, op, val, ctx, mode, fieldType) {
|
|
|
3830
3924
|
});
|
|
3831
3925
|
}
|
|
3832
3926
|
var MAX_PARAM_INDEX = Number.MAX_SAFE_INTEGER - 1e3;
|
|
3833
|
-
var
|
|
3834
|
-
var
|
|
3927
|
+
var _a3;
|
|
3928
|
+
var IS_PRODUCTION3 = typeof process !== "undefined" && ((_a3 = process.env) == null ? void 0 : _a3.NODE_ENV) === "production";
|
|
3835
3929
|
function assertSameLength(params, mappings) {
|
|
3836
3930
|
if (params.length !== mappings.length) {
|
|
3837
3931
|
throw new Error(
|
|
@@ -3891,7 +3985,7 @@ function validateMappings(mappings) {
|
|
|
3891
3985
|
}
|
|
3892
3986
|
}
|
|
3893
3987
|
function validateState(params, mappings, index) {
|
|
3894
|
-
if (
|
|
3988
|
+
if (IS_PRODUCTION3) {
|
|
3895
3989
|
assertSameLength(params, mappings);
|
|
3896
3990
|
assertValidNextIndex(index);
|
|
3897
3991
|
return;
|
|
@@ -3949,6 +4043,7 @@ function createStoreInternal(startIndex, dialect, initialParams = [], initialMap
|
|
|
3949
4043
|
if (frozen) {
|
|
3950
4044
|
params = params.slice();
|
|
3951
4045
|
mappings = mappings.slice();
|
|
4046
|
+
dynamicNameToIndex = new Map(dynamicNameToIndex);
|
|
3952
4047
|
frozen = false;
|
|
3953
4048
|
}
|
|
3954
4049
|
}
|
|
@@ -3965,6 +4060,7 @@ function createStoreInternal(startIndex, dialect, initialParams = [], initialMap
|
|
|
3965
4060
|
const dn = validateDynamicName(dynamicName);
|
|
3966
4061
|
const existing = dynamicNameToIndex.get(dn);
|
|
3967
4062
|
if (existing !== void 0) return formatPosition(existing);
|
|
4063
|
+
ensureMutable();
|
|
3968
4064
|
const position = index;
|
|
3969
4065
|
dynamicNameToIndex.set(dn, position);
|
|
3970
4066
|
return registerParam(void 0, { index: position, dynamicName: dn });
|
|
@@ -3995,7 +4091,7 @@ function createStoreInternal(startIndex, dialect, initialParams = [], initialMap
|
|
|
3995
4091
|
index,
|
|
3996
4092
|
params,
|
|
3997
4093
|
mappings,
|
|
3998
|
-
dynamicNameIndex:
|
|
4094
|
+
dynamicNameIndex: dynamicNameToIndex
|
|
3999
4095
|
};
|
|
4000
4096
|
cachedSnapshot = snap;
|
|
4001
4097
|
dirty = false;
|
|
@@ -4050,10 +4146,10 @@ function toPublicResult(clause, joins, params) {
|
|
|
4050
4146
|
|
|
4051
4147
|
// src/builder/where.ts
|
|
4052
4148
|
function buildWhereClause(where, options) {
|
|
4053
|
-
var
|
|
4149
|
+
var _a4, _b, _c, _d, _e;
|
|
4054
4150
|
assertSafeAlias(options.alias);
|
|
4055
4151
|
const dialect = options.dialect || getGlobalDialect();
|
|
4056
|
-
const params = (
|
|
4152
|
+
const params = (_a4 = options.params) != null ? _a4 : createParamStore(1, dialect);
|
|
4057
4153
|
const ctx = {
|
|
4058
4154
|
alias: options.alias,
|
|
4059
4155
|
model: options.model,
|
|
@@ -4136,12 +4232,13 @@ function reindexWhereParams(whereClause, specParams, collector) {
|
|
|
4136
4232
|
}
|
|
4137
4233
|
return clean;
|
|
4138
4234
|
}
|
|
4139
|
-
function getRelationModel2(parentModel, relationName, schemas) {
|
|
4140
|
-
var
|
|
4235
|
+
function getRelationModel2(parentModel, relationName, schemas, modelMap) {
|
|
4236
|
+
var _a4, _b;
|
|
4141
4237
|
const indices = getFieldIndices(parentModel);
|
|
4142
4238
|
const field = indices.allFieldsByName.get(relationName);
|
|
4143
4239
|
if (!(field == null ? void 0 : field.isRelation) || !field.relatedModel) return null;
|
|
4144
|
-
return (
|
|
4240
|
+
if (modelMap) return (_a4 = modelMap.get(field.relatedModel)) != null ? _a4 : null;
|
|
4241
|
+
return (_b = schemas.find((m) => m.name === field.relatedModel)) != null ? _b : null;
|
|
4145
4242
|
}
|
|
4146
4243
|
function extractOrderByInput(relArgs) {
|
|
4147
4244
|
if (!isPlainObject(relArgs)) return void 0;
|
|
@@ -4186,7 +4283,12 @@ function buildLateralForRelation(relationName, relArgs, field, relModel, parentM
|
|
|
4186
4283
|
const nestedIndices = getFieldIndices(relModel);
|
|
4187
4284
|
const nestedField = nestedIndices.allFieldsByName.get(nestedName);
|
|
4188
4285
|
if (!nestedField || !isValidRelationField(nestedField)) continue;
|
|
4189
|
-
const nestedModel = getRelationModel2(
|
|
4286
|
+
const nestedModel = getRelationModel2(
|
|
4287
|
+
relModel,
|
|
4288
|
+
nestedName,
|
|
4289
|
+
ctx.schemas,
|
|
4290
|
+
ctx.modelMap
|
|
4291
|
+
);
|
|
4190
4292
|
if (!nestedModel) continue;
|
|
4191
4293
|
const nested = buildLateralForRelation(
|
|
4192
4294
|
nestedName,
|
|
@@ -4289,12 +4391,12 @@ function buildLateralForRelation(relationName, relArgs, field, relModel, parentM
|
|
|
4289
4391
|
}
|
|
4290
4392
|
const joinSql = `LEFT JOIN LATERAL (${outerSql}) ${latAlias} ON true`;
|
|
4291
4393
|
const fieldTypes = selectedFields.map((fieldName) => {
|
|
4292
|
-
var
|
|
4394
|
+
var _a4;
|
|
4293
4395
|
const f = indices.scalarFields.get(fieldName);
|
|
4294
4396
|
if (!f) return null;
|
|
4295
4397
|
return {
|
|
4296
4398
|
fieldName: f.name,
|
|
4297
|
-
type: String((
|
|
4399
|
+
type: String((_a4 = f.type) != null ? _a4 : "").toLowerCase()
|
|
4298
4400
|
};
|
|
4299
4401
|
}).filter(Boolean);
|
|
4300
4402
|
const meta = {
|
|
@@ -4312,8 +4414,13 @@ function countActiveEntries2(spec) {
|
|
|
4312
4414
|
}
|
|
4313
4415
|
return count;
|
|
4314
4416
|
}
|
|
4315
|
-
function canUseLateralJoin(includeSpec, parentModel, schemas) {
|
|
4316
|
-
const relations = resolveIncludeRelations(
|
|
4417
|
+
function canUseLateralJoin(includeSpec, parentModel, schemas, modelMap) {
|
|
4418
|
+
const relations = resolveIncludeRelations(
|
|
4419
|
+
includeSpec,
|
|
4420
|
+
parentModel,
|
|
4421
|
+
schemas,
|
|
4422
|
+
modelMap
|
|
4423
|
+
);
|
|
4317
4424
|
if (relations.length < countActiveEntries2(includeSpec)) {
|
|
4318
4425
|
return false;
|
|
4319
4426
|
}
|
|
@@ -4322,14 +4429,14 @@ function canUseLateralJoin(includeSpec, parentModel, schemas) {
|
|
|
4322
4429
|
if (!keys || keys.childKeys.length === 0 || keys.parentKeys.length === 0)
|
|
4323
4430
|
return false;
|
|
4324
4431
|
if (Object.keys(rel.nestedSpec).length > 0) {
|
|
4325
|
-
if (!canUseLateralJoin(rel.nestedSpec, rel.relModel, schemas))
|
|
4432
|
+
if (!canUseLateralJoin(rel.nestedSpec, rel.relModel, schemas, modelMap))
|
|
4326
4433
|
return false;
|
|
4327
4434
|
}
|
|
4328
4435
|
}
|
|
4329
4436
|
return true;
|
|
4330
4437
|
}
|
|
4331
4438
|
function buildLateralJoinSql(spec) {
|
|
4332
|
-
var
|
|
4439
|
+
var _a4;
|
|
4333
4440
|
const {
|
|
4334
4441
|
from,
|
|
4335
4442
|
whereClause,
|
|
@@ -4349,6 +4456,8 @@ function buildLateralJoinSql(spec) {
|
|
|
4349
4456
|
isLateral: false,
|
|
4350
4457
|
lateralMeta: []
|
|
4351
4458
|
};
|
|
4459
|
+
const modelMap = /* @__PURE__ */ new Map();
|
|
4460
|
+
for (const m of schemas) modelMap.set(m.name, m);
|
|
4352
4461
|
const entries = extractRelationEntries(args, model);
|
|
4353
4462
|
const includeSpec = {};
|
|
4354
4463
|
for (const e of entries) {
|
|
@@ -4375,7 +4484,8 @@ function buildLateralJoinSql(spec) {
|
|
|
4375
4484
|
schemas,
|
|
4376
4485
|
dialect,
|
|
4377
4486
|
aliasCounter,
|
|
4378
|
-
collector
|
|
4487
|
+
collector,
|
|
4488
|
+
modelMap
|
|
4379
4489
|
};
|
|
4380
4490
|
const lateralJoins = [];
|
|
4381
4491
|
const lateralSelects = [];
|
|
@@ -4385,7 +4495,7 @@ function buildLateralJoinSql(spec) {
|
|
|
4385
4495
|
const indices = getFieldIndices(model);
|
|
4386
4496
|
const field = indices.allFieldsByName.get(relName);
|
|
4387
4497
|
if (!field || !isValidRelationField(field)) continue;
|
|
4388
|
-
const relModel = getRelationModel2(model, relName, schemas);
|
|
4498
|
+
const relModel = getRelationModel2(model, relName, schemas, modelMap);
|
|
4389
4499
|
if (!relModel) continue;
|
|
4390
4500
|
const result = buildLateralForRelation(
|
|
4391
4501
|
relName,
|
|
@@ -4403,7 +4513,7 @@ function buildLateralJoinSql(spec) {
|
|
|
4403
4513
|
lateralMeta.push(result.meta);
|
|
4404
4514
|
}
|
|
4405
4515
|
if (lateralJoins.length === 0) return emptyResult;
|
|
4406
|
-
const baseSelect = ((
|
|
4516
|
+
const baseSelect = ((_a4 = spec.select) != null ? _a4 : "").trim();
|
|
4407
4517
|
const allSelects = [baseSelect, ...lateralSelects].filter((s) => s && s.trim().length > 0).join(", ");
|
|
4408
4518
|
if (!allSelects) {
|
|
4409
4519
|
return emptyResult;
|
|
@@ -4523,9 +4633,9 @@ function renderOrderBySimple(entries, alias) {
|
|
|
4523
4633
|
return out.join(SQL_SEPARATORS.ORDER_BY);
|
|
4524
4634
|
}
|
|
4525
4635
|
function ensureIdTiebreakerEntries(entries, model) {
|
|
4526
|
-
var
|
|
4527
|
-
const idField = (_b = (
|
|
4528
|
-
|
|
4636
|
+
var _a4, _b;
|
|
4637
|
+
const idField = (_b = (_a4 = model == null ? void 0 : model.fields) == null ? void 0 : _a4.find) == null ? void 0 : _b.call(
|
|
4638
|
+
_a4,
|
|
4529
4639
|
(f) => f.name === DEFAULT_PRIMARY_KEY2 && !f.isRelation
|
|
4530
4640
|
);
|
|
4531
4641
|
if (!idField) return entries;
|
|
@@ -4567,14 +4677,14 @@ function buildJoinsSql(...joinGroups) {
|
|
|
4567
4677
|
return all.length > 0 ? " " + all.join(" ") : "";
|
|
4568
4678
|
}
|
|
4569
4679
|
function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
|
|
4570
|
-
var
|
|
4680
|
+
var _a4, _b;
|
|
4571
4681
|
const { includes, from, whereClause, whereJoins, distinct, model } = spec;
|
|
4572
4682
|
if (!isNotNullish(distinct) || !isNonEmptyArray(distinct)) {
|
|
4573
4683
|
throw new Error("buildSqliteDistinctQuery requires distinct fields");
|
|
4574
4684
|
}
|
|
4575
4685
|
const scalarNames = parseSimpleScalarSelect(spec.select, from.alias);
|
|
4576
4686
|
const includeNames = includes.map((i) => i.name);
|
|
4577
|
-
const hasCount = Boolean((_b = (
|
|
4687
|
+
const hasCount = Boolean((_b = (_a4 = spec.args) == null ? void 0 : _a4.select) == null ? void 0 : _b[COUNT_SELECT_KEY]);
|
|
4578
4688
|
const outerSelectCols = buildOutputColumns(
|
|
4579
4689
|
scalarNames,
|
|
4580
4690
|
includeNames,
|
|
@@ -4674,12 +4784,12 @@ function resolveCountSelect(countSelectRaw, model) {
|
|
|
4674
4784
|
return null;
|
|
4675
4785
|
}
|
|
4676
4786
|
function buildIncludeColumns(spec) {
|
|
4677
|
-
var
|
|
4787
|
+
var _a4, _b, _c, _d, _e;
|
|
4678
4788
|
const { select, includes, dialect, model, schemas, from, params } = spec;
|
|
4679
4789
|
const baseSelect = (select != null ? select : "").trim();
|
|
4680
4790
|
let countCols = "";
|
|
4681
4791
|
let countJoins = [];
|
|
4682
|
-
const countSelectRaw = (_e = (_b = (
|
|
4792
|
+
const countSelectRaw = (_e = (_b = (_a4 = spec.args) == null ? void 0 : _a4.select) == null ? void 0 : _b[COUNT_SELECT_KEY]) != null ? _e : (_d = (_c = spec.args) == null ? void 0 : _c.include) == null ? void 0 : _d[COUNT_SELECT_KEY];
|
|
4683
4793
|
if (countSelectRaw) {
|
|
4684
4794
|
const resolvedCountSelect = resolveCountSelect(countSelectRaw, model);
|
|
4685
4795
|
if (resolvedCountSelect && Object.keys(resolvedCountSelect).length > 0) {
|
|
@@ -4861,16 +4971,33 @@ function constructFinalSql(spec) {
|
|
|
4861
4971
|
isNotNullish(pagination.take);
|
|
4862
4972
|
const takeValue = typeof pagination.take === "number" ? pagination.take : null;
|
|
4863
4973
|
if (dialect === "postgres" && hasIncludes) {
|
|
4864
|
-
const
|
|
4865
|
-
|
|
4866
|
-
|
|
4974
|
+
const modelMap = getOrCreateModelMap(schemas);
|
|
4975
|
+
const canFlatJoin = canUseFlatJoinForAll(
|
|
4976
|
+
includeSpec,
|
|
4977
|
+
model,
|
|
4978
|
+
schemas,
|
|
4979
|
+
false,
|
|
4980
|
+
modelMap
|
|
4981
|
+
);
|
|
4982
|
+
canUseLateralJoin(includeSpec, model, schemas, modelMap);
|
|
4983
|
+
const hasChildPag = hasChildPaginationAnywhere(
|
|
4984
|
+
includeSpec,
|
|
4985
|
+
model,
|
|
4986
|
+
schemas,
|
|
4987
|
+
0,
|
|
4988
|
+
modelMap
|
|
4989
|
+
);
|
|
4867
4990
|
const strategy = pickIncludeStrategy({
|
|
4868
4991
|
includeSpec,
|
|
4869
4992
|
model,
|
|
4870
4993
|
schemas,
|
|
4871
4994
|
method,
|
|
4995
|
+
args,
|
|
4872
4996
|
takeValue,
|
|
4873
|
-
canFlatJoin
|
|
4997
|
+
canFlatJoin,
|
|
4998
|
+
hasChildPagination: hasChildPag,
|
|
4999
|
+
modelMap
|
|
5000
|
+
});
|
|
4874
5001
|
if (strategy === "flat-join") {
|
|
4875
5002
|
const flatResult = buildFlatJoinSql(spec);
|
|
4876
5003
|
if (flatResult.sql) {
|
|
@@ -4993,8 +5120,8 @@ function buildDefaultScalarFields(model, alias) {
|
|
|
4993
5120
|
return out;
|
|
4994
5121
|
}
|
|
4995
5122
|
function getDefaultSelectCached(model, alias) {
|
|
4996
|
-
var
|
|
4997
|
-
return (
|
|
5123
|
+
var _a4;
|
|
5124
|
+
return (_a4 = DEFAULT_SELECT_CACHE.get(model)) == null ? void 0 : _a4.get(alias);
|
|
4998
5125
|
}
|
|
4999
5126
|
function cacheDefaultSelect(model, alias, sql) {
|
|
5000
5127
|
let cache = DEFAULT_SELECT_CACHE.get(model);
|
|
@@ -5276,7 +5403,8 @@ function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
|
5276
5403
|
ctx.schemas,
|
|
5277
5404
|
relAlias,
|
|
5278
5405
|
ctx.params,
|
|
5279
|
-
ctx.dialect
|
|
5406
|
+
ctx.dialect,
|
|
5407
|
+
ctx.schemaByName
|
|
5280
5408
|
);
|
|
5281
5409
|
if (!countBuild.jsonPairs) return baseSelect2;
|
|
5282
5410
|
countJoins.push(...countBuild.joins);
|
|
@@ -5664,7 +5792,9 @@ function resolveTableRef(model, dialect) {
|
|
|
5664
5792
|
return buildTableReference(schema, tableName, dialect);
|
|
5665
5793
|
}
|
|
5666
5794
|
function findRelationField(model, fieldName) {
|
|
5667
|
-
|
|
5795
|
+
const field = getFieldIndices(model).allFieldsByName.get(fieldName);
|
|
5796
|
+
if (!field || !field.isRelation) return void 0;
|
|
5797
|
+
return field;
|
|
5668
5798
|
}
|
|
5669
5799
|
function nextJoinAlias(ctx) {
|
|
5670
5800
|
let alias;
|
|
@@ -5691,7 +5821,7 @@ function resolveRelationOrderByChain(relationFieldName, value, currentModel, cur
|
|
|
5691
5821
|
`Relation field '${relationFieldName}' not found on model ${currentModel.name}`
|
|
5692
5822
|
);
|
|
5693
5823
|
}
|
|
5694
|
-
const relatedModel =
|
|
5824
|
+
const relatedModel = ctx.modelMap.get(field.relatedModel);
|
|
5695
5825
|
if (!relatedModel) {
|
|
5696
5826
|
throw new Error(
|
|
5697
5827
|
`Related model '${field.relatedModel}' not found for relation '${relationFieldName}'`
|
|
@@ -5757,12 +5887,14 @@ function buildOrderByWithRelations(orderBy, alias, dialect, model, schemas) {
|
|
|
5757
5887
|
const relationSet = getRelationFieldSet(model);
|
|
5758
5888
|
const scalarSet = getScalarFieldSet(model);
|
|
5759
5889
|
const orderFragments = [];
|
|
5890
|
+
const modelMap = /* @__PURE__ */ new Map();
|
|
5891
|
+
for (const m of schemas) modelMap.set(m.name, m);
|
|
5760
5892
|
const ctx = {
|
|
5761
|
-
schemas,
|
|
5762
5893
|
dialect,
|
|
5763
5894
|
joins: [],
|
|
5764
5895
|
usedAliases: /* @__PURE__ */ new Set(),
|
|
5765
|
-
aliasCounter: { value: 0 }
|
|
5896
|
+
aliasCounter: { value: 0 },
|
|
5897
|
+
modelMap
|
|
5766
5898
|
};
|
|
5767
5899
|
for (const [fieldName, value] of expanded) {
|
|
5768
5900
|
if (scalarSet.has(fieldName)) {
|
|
@@ -5817,11 +5949,11 @@ function mapFirstOrderByByField(existing) {
|
|
|
5817
5949
|
return m;
|
|
5818
5950
|
}
|
|
5819
5951
|
function buildPostgresDistinctOrderBy(distinctFields, existing) {
|
|
5820
|
-
var
|
|
5952
|
+
var _a4;
|
|
5821
5953
|
const firstByField = mapFirstOrderByByField(existing);
|
|
5822
5954
|
const next = [];
|
|
5823
5955
|
for (const f of distinctFields) {
|
|
5824
|
-
next.push((
|
|
5956
|
+
next.push((_a4 = firstByField.get(f)) != null ? _a4 : { [f]: "asc" });
|
|
5825
5957
|
}
|
|
5826
5958
|
const distinctSet = new Set(distinctFields);
|
|
5827
5959
|
for (const obj of existing) {
|
|
@@ -6714,10 +6846,10 @@ function isPrismaMethod(v) {
|
|
|
6714
6846
|
return v === "findMany" || v === "findFirst" || v === "findUnique" || v === "aggregate" || v === "groupBy" || v === "count";
|
|
6715
6847
|
}
|
|
6716
6848
|
function resolveMethod(directive) {
|
|
6717
|
-
var
|
|
6849
|
+
var _a4, _b;
|
|
6718
6850
|
const m = directive == null ? void 0 : directive.method;
|
|
6719
6851
|
if (isPrismaMethod(m)) return m;
|
|
6720
|
-
const pm = (_b = (
|
|
6852
|
+
const pm = (_b = (_a4 = directive == null ? void 0 : directive.query) == null ? void 0 : _a4.processed) == null ? void 0 : _b.method;
|
|
6721
6853
|
if (isPrismaMethod(pm)) return pm;
|
|
6722
6854
|
return "findMany";
|
|
6723
6855
|
}
|
|
@@ -6880,7 +7012,7 @@ function extractIncludeSpec2(processed, modelDef) {
|
|
|
6880
7012
|
return includeSpec;
|
|
6881
7013
|
}
|
|
6882
7014
|
function buildAndNormalizeSql(args) {
|
|
6883
|
-
var
|
|
7015
|
+
var _a4;
|
|
6884
7016
|
const {
|
|
6885
7017
|
method,
|
|
6886
7018
|
processed,
|
|
@@ -6906,7 +7038,7 @@ function buildAndNormalizeSql(args) {
|
|
|
6906
7038
|
sqlResult.paramMappings,
|
|
6907
7039
|
dialect
|
|
6908
7040
|
);
|
|
6909
|
-
const includeSpec = (
|
|
7041
|
+
const includeSpec = (_a4 = sqlResult.includeSpec && isPlainObject(sqlResult.includeSpec) ? sqlResult.includeSpec : null) != null ? _a4 : extractIncludeSpec2(processed, modelDef);
|
|
6910
7042
|
return {
|
|
6911
7043
|
sql: normalized.sql,
|
|
6912
7044
|
paramMappings: normalized.paramMappings,
|
|
@@ -6931,8 +7063,8 @@ function finalizeDirective(args) {
|
|
|
6931
7063
|
skipWhereIn
|
|
6932
7064
|
} = args;
|
|
6933
7065
|
const params = normalizedMappings.map((m) => {
|
|
6934
|
-
var
|
|
6935
|
-
return (
|
|
7066
|
+
var _a4;
|
|
7067
|
+
return (_a4 = m.value) != null ? _a4 : void 0;
|
|
6936
7068
|
});
|
|
6937
7069
|
validateParamConsistencyByDialect(normalizedSql, params, dialect);
|
|
6938
7070
|
const { staticParams, dynamicKeys, paramOrder } = buildParamsFromMappings(normalizedMappings);
|
|
@@ -7365,9 +7497,9 @@ function processAllModelDirectives(directiveResults, config) {
|
|
|
7365
7497
|
}
|
|
7366
7498
|
function generateClient(options) {
|
|
7367
7499
|
return __async(this, null, function* () {
|
|
7368
|
-
var
|
|
7500
|
+
var _a4, _b;
|
|
7369
7501
|
const { datamodel, outputDir, config } = options;
|
|
7370
|
-
const runtimeImportPath = (
|
|
7502
|
+
const runtimeImportPath = (_a4 = options.runtimeImportPath) != null ? _a4 : "prisma-sql";
|
|
7371
7503
|
setGlobalDialect(config.dialect);
|
|
7372
7504
|
const models = convertDMMFToModels(datamodel);
|
|
7373
7505
|
const directiveResults = processAllDirectives(
|
|
@@ -8441,9 +8573,9 @@ function getDialectFromProvider(provider) {
|
|
|
8441
8573
|
);
|
|
8442
8574
|
}
|
|
8443
8575
|
function getOutputDir(options) {
|
|
8444
|
-
var
|
|
8576
|
+
var _a4, _b;
|
|
8445
8577
|
const schemaDir = dirname(options.schemaPath);
|
|
8446
|
-
if ((
|
|
8578
|
+
if ((_a4 = options.generator.output) == null ? void 0 : _a4.value) {
|
|
8447
8579
|
return resolve(schemaDir, options.generator.output.value);
|
|
8448
8580
|
}
|
|
8449
8581
|
const clientGenerator = options.otherGenerators.find(
|