prisma-sql 1.67.0 → 1.68.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 +562 -203
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +562 -203
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +1174 -466
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +52 -27
- package/dist/index.d.ts +52 -27
- package/dist/index.js +1171 -467
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -447,6 +447,8 @@ var AGGREGATE_PREFIXES = /* @__PURE__ */ new Set([
|
|
|
447
447
|
"_min",
|
|
448
448
|
"_max"
|
|
449
449
|
]);
|
|
450
|
+
var _a;
|
|
451
|
+
var DEBUG_PARAMS = typeof process !== "undefined" && ((_a = process.env) == null ? void 0 : _a.DEBUG_PARAMS) === "1";
|
|
450
452
|
|
|
451
453
|
// src/builder/shared/validators/type-guards.ts
|
|
452
454
|
function isNotNullish(value) {
|
|
@@ -990,7 +992,7 @@ function normalizeField(field) {
|
|
|
990
992
|
return field;
|
|
991
993
|
}
|
|
992
994
|
function getFieldIndices(model) {
|
|
993
|
-
var
|
|
995
|
+
var _a3;
|
|
994
996
|
let cached = FIELD_INDICES_CACHE.get(model);
|
|
995
997
|
if (cached) return cached;
|
|
996
998
|
const scalarFields = /* @__PURE__ */ new Map();
|
|
@@ -1009,7 +1011,7 @@ function getFieldIndices(model) {
|
|
|
1009
1011
|
} else {
|
|
1010
1012
|
scalarFields.set(field.name, field);
|
|
1011
1013
|
scalarNames.push(field.name);
|
|
1012
|
-
const fieldType = String((
|
|
1014
|
+
const fieldType = String((_a3 = field.type) != null ? _a3 : "").toLowerCase();
|
|
1013
1015
|
if (fieldType === "json") {
|
|
1014
1016
|
jsonFields.add(field.name);
|
|
1015
1017
|
}
|
|
@@ -1133,13 +1135,13 @@ function getModelByName(schemas, name) {
|
|
|
1133
1135
|
return schemas.find((m) => m.name === name);
|
|
1134
1136
|
}
|
|
1135
1137
|
function normalizeIntLike(name, v, opts = {}) {
|
|
1136
|
-
var
|
|
1138
|
+
var _a3, _b;
|
|
1137
1139
|
if (!isNotNullish(v)) return void 0;
|
|
1138
1140
|
if (isDynamicParameter(v)) return v;
|
|
1139
1141
|
if (typeof v !== "number" || !Number.isFinite(v) || !Number.isInteger(v)) {
|
|
1140
1142
|
throw new Error(`${name} must be an integer`);
|
|
1141
1143
|
}
|
|
1142
|
-
const min = (
|
|
1144
|
+
const min = (_a3 = opts.min) != null ? _a3 : 0;
|
|
1143
1145
|
const allowZero = (_b = opts.allowZero) != null ? _b : true;
|
|
1144
1146
|
if (!allowZero && v === 0) {
|
|
1145
1147
|
throw new Error(`${name} must be > 0`);
|
|
@@ -1161,7 +1163,9 @@ function scopeName(scope, dynamicName) {
|
|
|
1161
1163
|
function addAutoScoped(params, value, scope) {
|
|
1162
1164
|
if (isDynamicParameter(value)) {
|
|
1163
1165
|
const dn = extractDynamicName(value);
|
|
1164
|
-
|
|
1166
|
+
if (DEBUG_PARAMS) {
|
|
1167
|
+
console.log(`[PARAM] ${scope} = ${JSON.stringify(value)}`);
|
|
1168
|
+
}
|
|
1165
1169
|
return params.add(void 0, scopeName(scope, dn));
|
|
1166
1170
|
}
|
|
1167
1171
|
return params.add(value);
|
|
@@ -1602,7 +1606,7 @@ function assertCursorAndOrderFieldsScalar(model, cursor, orderEntries) {
|
|
|
1602
1606
|
}
|
|
1603
1607
|
}
|
|
1604
1608
|
function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
|
|
1605
|
-
var
|
|
1609
|
+
var _a3;
|
|
1606
1610
|
assertSafeTableRef(tableName);
|
|
1607
1611
|
assertSafeAlias(alias);
|
|
1608
1612
|
const d = dialect != null ? dialect : getGlobalDialect();
|
|
@@ -1617,6 +1621,33 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
1617
1621
|
}
|
|
1618
1622
|
if (cursorEntries.length === 0)
|
|
1619
1623
|
throw new Error("cursor must have at least one field with defined value");
|
|
1624
|
+
const orderEntries = normalizeAndValidateOrderBy(
|
|
1625
|
+
orderBy,
|
|
1626
|
+
model,
|
|
1627
|
+
parseOrderByValue
|
|
1628
|
+
);
|
|
1629
|
+
if (cursorEntries.length === 1 && orderEntries.length === 0) {
|
|
1630
|
+
const [field, value] = cursorEntries[0];
|
|
1631
|
+
const ph = addAutoScoped(params, value, `cursor.${field}`);
|
|
1632
|
+
const c = col(alias, field, model);
|
|
1633
|
+
return {
|
|
1634
|
+
cte: "",
|
|
1635
|
+
condition: `${c} >= ${ph}`
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
if (cursorEntries.length === 1 && orderEntries.length === 1) {
|
|
1639
|
+
const [cursorField, cursorValue] = cursorEntries[0];
|
|
1640
|
+
const orderEntry = orderEntries[0];
|
|
1641
|
+
if (orderEntry.field === cursorField) {
|
|
1642
|
+
const ph = addAutoScoped(params, cursorValue, `cursor.${cursorField}`);
|
|
1643
|
+
const c = col(alias, cursorField, model);
|
|
1644
|
+
const op = orderEntry.direction === "asc" ? ">=" : "<=";
|
|
1645
|
+
return {
|
|
1646
|
+
cte: "",
|
|
1647
|
+
condition: `${c} ${op} ${ph}`
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1620
1651
|
const { cteName, srcAlias } = buildCursorNames(alias);
|
|
1621
1652
|
assertSafeAlias(cteName);
|
|
1622
1653
|
assertSafeAlias(srcAlias);
|
|
@@ -1625,49 +1656,52 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
1625
1656
|
model,
|
|
1626
1657
|
parseValue: parseOrderByValue
|
|
1627
1658
|
});
|
|
1628
|
-
let
|
|
1659
|
+
let finalOrderEntries = normalizeAndValidateOrderBy(
|
|
1629
1660
|
orderBy,
|
|
1630
1661
|
model,
|
|
1631
1662
|
parseOrderByValue
|
|
1632
1663
|
);
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1664
|
+
if (finalOrderEntries.length === 0) {
|
|
1665
|
+
finalOrderEntries = cursorEntries.map(([field]) => ({
|
|
1635
1666
|
field,
|
|
1636
1667
|
direction: "asc"
|
|
1637
1668
|
}));
|
|
1638
1669
|
} else {
|
|
1639
|
-
|
|
1670
|
+
finalOrderEntries = ensureCursorFieldsInOrder(
|
|
1671
|
+
finalOrderEntries,
|
|
1672
|
+
cursorEntries
|
|
1673
|
+
);
|
|
1640
1674
|
}
|
|
1641
|
-
assertCursorAndOrderFieldsScalar(model, cursor,
|
|
1675
|
+
assertCursorAndOrderFieldsScalar(model, cursor, finalOrderEntries);
|
|
1642
1676
|
const { whereSql: cursorWhereSql } = buildCursorFilterParts(
|
|
1643
1677
|
cursor,
|
|
1644
1678
|
srcAlias,
|
|
1645
1679
|
params,
|
|
1646
1680
|
model
|
|
1647
1681
|
);
|
|
1648
|
-
const cursorOrderBy =
|
|
1682
|
+
const cursorOrderBy = finalOrderEntries.map(
|
|
1649
1683
|
(e) => srcAlias + "." + quoteColumn(model, e.field) + " " + e.direction.toUpperCase()
|
|
1650
1684
|
).join(", ");
|
|
1651
1685
|
const selectList = buildCursorCteSelectList(
|
|
1652
1686
|
cursorEntries,
|
|
1653
|
-
|
|
1687
|
+
finalOrderEntries,
|
|
1654
1688
|
model
|
|
1655
1689
|
);
|
|
1656
1690
|
const cte = cteName + " AS (\n SELECT " + selectList + " FROM " + tableName + " " + srcAlias + "\n WHERE " + cursorWhereSql + "\n ORDER BY " + cursorOrderBy + "\n LIMIT 1\n )";
|
|
1657
1691
|
const existsExpr = "EXISTS (SELECT 1 FROM " + cteName + ")";
|
|
1658
1692
|
const orClauses = [];
|
|
1659
|
-
for (let level = 0; level <
|
|
1693
|
+
for (let level = 0; level < finalOrderEntries.length; level++) {
|
|
1660
1694
|
const andParts = [];
|
|
1661
1695
|
for (let i = 0; i < level; i++) {
|
|
1662
|
-
const e2 =
|
|
1696
|
+
const e2 = finalOrderEntries[i];
|
|
1663
1697
|
const c2 = col(alias, e2.field, model);
|
|
1664
1698
|
const cursorField2 = cteName + "." + quoteColumn(model, e2.field);
|
|
1665
1699
|
andParts.push(buildCursorEqualityExpr(c2, cursorField2));
|
|
1666
1700
|
}
|
|
1667
|
-
const e =
|
|
1701
|
+
const e = finalOrderEntries[level];
|
|
1668
1702
|
const c = col(alias, e.field, model);
|
|
1669
1703
|
const cursorField = cteName + "." + quoteColumn(model, e.field);
|
|
1670
|
-
const nulls = (
|
|
1704
|
+
const nulls = (_a3 = e.nulls) != null ? _a3 : defaultNullsFor(d, e.direction);
|
|
1671
1705
|
andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, cursorField));
|
|
1672
1706
|
orClauses.push("(" + andParts.join(SQL_SEPARATORS.CONDITION_AND) + ")");
|
|
1673
1707
|
}
|
|
@@ -2213,6 +2247,16 @@ function handleJsonWildcard(expr, op, val, params, wildcards, dialect) {
|
|
|
2213
2247
|
|
|
2214
2248
|
// src/builder/where/relations.ts
|
|
2215
2249
|
var NO_JOINS = [];
|
|
2250
|
+
var SCHEMA_MAP_CACHE = /* @__PURE__ */ new WeakMap();
|
|
2251
|
+
function getSchemaByName(schemas) {
|
|
2252
|
+
let map = SCHEMA_MAP_CACHE.get(schemas);
|
|
2253
|
+
if (!map) {
|
|
2254
|
+
map = /* @__PURE__ */ new Map();
|
|
2255
|
+
for (const m of schemas) map.set(m.name, m);
|
|
2256
|
+
SCHEMA_MAP_CACHE.set(schemas, map);
|
|
2257
|
+
}
|
|
2258
|
+
return map;
|
|
2259
|
+
}
|
|
2216
2260
|
function isListRelation(fieldType) {
|
|
2217
2261
|
return typeof fieldType === "string" && fieldType.endsWith("[]");
|
|
2218
2262
|
}
|
|
@@ -2412,7 +2456,8 @@ function buildRelation(fieldName, value, ctx, whereBuilder) {
|
|
|
2412
2456
|
modelName: ctx.model.name
|
|
2413
2457
|
});
|
|
2414
2458
|
}
|
|
2415
|
-
const
|
|
2459
|
+
const schemaMap = getSchemaByName(ctx.schemaModels);
|
|
2460
|
+
const relModel = schemaMap.get(field.relatedModel);
|
|
2416
2461
|
if (!isNotNullish(relModel)) {
|
|
2417
2462
|
throw createError(
|
|
2418
2463
|
`Related model '${field.relatedModel}' not found in schema. Available models: ${ctx.schemaModels.map((m) => m.name).join(", ")}`,
|
|
@@ -2743,6 +2788,8 @@ function createAliasGenerator(maxAliases = 1e4) {
|
|
|
2743
2788
|
};
|
|
2744
2789
|
}
|
|
2745
2790
|
var MAX_PARAM_INDEX = Number.MAX_SAFE_INTEGER - 1e3;
|
|
2791
|
+
var _a2;
|
|
2792
|
+
var IS_PRODUCTION2 = typeof process !== "undefined" && ((_a2 = process.env) == null ? void 0 : _a2.NODE_ENV) === "production";
|
|
2746
2793
|
function assertSameLength(params, mappings) {
|
|
2747
2794
|
if (params.length !== mappings.length) {
|
|
2748
2795
|
throw new Error(
|
|
@@ -2802,6 +2849,11 @@ function validateMappings(mappings) {
|
|
|
2802
2849
|
}
|
|
2803
2850
|
}
|
|
2804
2851
|
function validateState(params, mappings, index) {
|
|
2852
|
+
if (IS_PRODUCTION2) {
|
|
2853
|
+
assertSameLength(params, mappings);
|
|
2854
|
+
assertValidNextIndex(index);
|
|
2855
|
+
return;
|
|
2856
|
+
}
|
|
2805
2857
|
assertSameLength(params, mappings);
|
|
2806
2858
|
assertValidNextIndex(index);
|
|
2807
2859
|
if (mappings.length === 0) return;
|
|
@@ -2956,10 +3008,10 @@ function toPublicResult(clause, joins, params) {
|
|
|
2956
3008
|
|
|
2957
3009
|
// src/builder/where.ts
|
|
2958
3010
|
function buildWhereClause(where, options) {
|
|
2959
|
-
var
|
|
3011
|
+
var _a3, _b, _c, _d, _e;
|
|
2960
3012
|
assertSafeAlias(options.alias);
|
|
2961
3013
|
const dialect = options.dialect || getGlobalDialect();
|
|
2962
|
-
const params = (
|
|
3014
|
+
const params = (_a3 = options.params) != null ? _a3 : createParamStore(1, dialect);
|
|
2963
3015
|
const ctx = {
|
|
2964
3016
|
alias: options.alias,
|
|
2965
3017
|
model: options.model,
|
|
@@ -3018,8 +3070,8 @@ function buildDefaultScalarFields(model, alias) {
|
|
|
3018
3070
|
return out;
|
|
3019
3071
|
}
|
|
3020
3072
|
function getDefaultSelectCached(model, alias) {
|
|
3021
|
-
var
|
|
3022
|
-
return (
|
|
3073
|
+
var _a3;
|
|
3074
|
+
return (_a3 = DEFAULT_SELECT_CACHE.get(model)) == null ? void 0 : _a3.get(alias);
|
|
3023
3075
|
}
|
|
3024
3076
|
function cacheDefaultSelect(model, alias, sql) {
|
|
3025
3077
|
let cache = DEFAULT_SELECT_CACHE.get(model);
|
|
@@ -3116,7 +3168,8 @@ function buildRelationSelect(relArgs, relModel, relAlias) {
|
|
|
3116
3168
|
}
|
|
3117
3169
|
|
|
3118
3170
|
// src/builder/shared/relation-key-utils.ts
|
|
3119
|
-
|
|
3171
|
+
var RELATION_KEYS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
3172
|
+
function computeRelationKeys(field, context) {
|
|
3120
3173
|
const fkFields = normalizeKeyList(field.foreignKey);
|
|
3121
3174
|
if (fkFields.length === 0) {
|
|
3122
3175
|
throw new Error(
|
|
@@ -3134,6 +3187,13 @@ function resolveRelationKeys(field, context = "include") {
|
|
|
3134
3187
|
const parentKeys = field.isForeignKeyLocal ? fkFields : refFields;
|
|
3135
3188
|
return { childKeys, parentKeys };
|
|
3136
3189
|
}
|
|
3190
|
+
function resolveRelationKeys(field, context = "include") {
|
|
3191
|
+
let cached = RELATION_KEYS_CACHE.get(field);
|
|
3192
|
+
if (cached) return cached;
|
|
3193
|
+
cached = computeRelationKeys(field, context);
|
|
3194
|
+
RELATION_KEYS_CACHE.set(field, cached);
|
|
3195
|
+
return cached;
|
|
3196
|
+
}
|
|
3137
3197
|
|
|
3138
3198
|
// src/builder/shared/relation-extraction-utils.ts
|
|
3139
3199
|
function extractRelationEntries(args, model) {
|
|
@@ -3163,6 +3223,18 @@ function extractRelationEntries(args, model) {
|
|
|
3163
3223
|
var MAX_INCLUDE_DEPTH = 5;
|
|
3164
3224
|
var MAX_INCLUDES_PER_LEVEL = 10;
|
|
3165
3225
|
var MAX_TOTAL_SUBQUERIES = 100;
|
|
3226
|
+
var FIELD_BY_NAME_CACHE2 = /* @__PURE__ */ new WeakMap();
|
|
3227
|
+
function getFieldMap(model) {
|
|
3228
|
+
let map = FIELD_BY_NAME_CACHE2.get(model);
|
|
3229
|
+
if (!map) {
|
|
3230
|
+
map = /* @__PURE__ */ new Map();
|
|
3231
|
+
for (const f of model.fields) {
|
|
3232
|
+
map.set(f.name, f);
|
|
3233
|
+
}
|
|
3234
|
+
FIELD_BY_NAME_CACHE2.set(model, map);
|
|
3235
|
+
}
|
|
3236
|
+
return map;
|
|
3237
|
+
}
|
|
3166
3238
|
function buildIncludeScope(includePath) {
|
|
3167
3239
|
if (includePath.length === 0) return "include";
|
|
3168
3240
|
let scope = "include";
|
|
@@ -3182,7 +3254,8 @@ function getRelationTableReference(relModel, dialect) {
|
|
|
3182
3254
|
);
|
|
3183
3255
|
}
|
|
3184
3256
|
function resolveRelationOrThrow(model, schemaByName, relName) {
|
|
3185
|
-
const
|
|
3257
|
+
const fieldMap = getFieldMap(model);
|
|
3258
|
+
const field = fieldMap.get(relName);
|
|
3186
3259
|
if (!isNotNullish(field)) {
|
|
3187
3260
|
throw new Error(
|
|
3188
3261
|
`Unknown relation '${relName}' on model ${model.name}. Available relation fields: ${model.fields.filter((f) => f.isRelation).map((f) => f.name).join(", ")}`
|
|
@@ -3299,11 +3372,22 @@ function finalizeOrderByForInclude(args) {
|
|
|
3299
3372
|
}
|
|
3300
3373
|
function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
3301
3374
|
let relSelect = buildRelationSelect(relArgs, relModel, relAlias);
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3375
|
+
let nestedIncludes = [];
|
|
3376
|
+
if (isPlainObject(relArgs)) {
|
|
3377
|
+
const prevModel = ctx.model;
|
|
3378
|
+
const prevParentAlias = ctx.parentAlias;
|
|
3379
|
+
const prevDepth = ctx.depth;
|
|
3380
|
+
ctx.model = relModel;
|
|
3381
|
+
ctx.parentAlias = relAlias;
|
|
3382
|
+
ctx.depth = prevDepth + 1;
|
|
3383
|
+
try {
|
|
3384
|
+
nestedIncludes = buildIncludeSqlInternal(relArgs, ctx);
|
|
3385
|
+
} finally {
|
|
3386
|
+
ctx.model = prevModel;
|
|
3387
|
+
ctx.parentAlias = prevParentAlias;
|
|
3388
|
+
ctx.depth = prevDepth;
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3307
3391
|
if (isNonEmptyArray(nestedIncludes)) {
|
|
3308
3392
|
const emptyJson = ctx.dialect === "postgres" ? `'[]'::json` : `json('[]')`;
|
|
3309
3393
|
const nestedSelects = nestedIncludes.map(
|
|
@@ -3447,9 +3531,9 @@ function hasNestedRelationInArgs(relArgs, relModel) {
|
|
|
3447
3531
|
if (checkSource(relArgs.select)) return true;
|
|
3448
3532
|
return false;
|
|
3449
3533
|
}
|
|
3450
|
-
function canUseJoinInclude(dialect,
|
|
3534
|
+
function canUseJoinInclude(dialect, isList, takeVal, skipVal, depth, outerHasLimit, hasNestedIncludes2) {
|
|
3451
3535
|
if (dialect !== "postgres") return false;
|
|
3452
|
-
if (!
|
|
3536
|
+
if (!isList) return false;
|
|
3453
3537
|
if (depth > 0) return false;
|
|
3454
3538
|
if (outerHasLimit) return false;
|
|
3455
3539
|
if (hasNestedIncludes2) return false;
|
|
@@ -3544,7 +3628,7 @@ function buildJoinBasedPaginated(args) {
|
|
|
3544
3628
|
function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
3545
3629
|
const relTable = getRelationTableReference(relModel, ctx.dialect);
|
|
3546
3630
|
const relAlias = ctx.aliasGen.next(relName);
|
|
3547
|
-
const
|
|
3631
|
+
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
3548
3632
|
const joinPredicate = joinCondition(
|
|
3549
3633
|
field,
|
|
3550
3634
|
ctx.model,
|
|
@@ -3561,7 +3645,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
|
3561
3645
|
);
|
|
3562
3646
|
const whereParts = buildWhereParts(whereInput, relModel, relAlias, ctx);
|
|
3563
3647
|
const paginationConfig = extractRelationPaginationConfig(relArgs);
|
|
3564
|
-
if (!
|
|
3648
|
+
if (!isList && typeof paginationConfig.takeVal === "number" && paginationConfig.takeVal < 0) {
|
|
3565
3649
|
throw new Error("Negative take is only supported for list relations");
|
|
3566
3650
|
}
|
|
3567
3651
|
const adjusted = maybeReverseNegativeTake(
|
|
@@ -3582,7 +3666,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
|
3582
3666
|
ctx.dialect,
|
|
3583
3667
|
relModel
|
|
3584
3668
|
);
|
|
3585
|
-
if (!
|
|
3669
|
+
if (!isList) {
|
|
3586
3670
|
const sql = buildOneToOneIncludeSql({
|
|
3587
3671
|
relTable,
|
|
3588
3672
|
relAlias,
|
|
@@ -3602,7 +3686,7 @@ function buildSingleInclude(relName, relArgs, field, relModel, ctx) {
|
|
|
3602
3686
|
const nestedIncludes = hasNestedRelationInArgs(relArgs, relModel);
|
|
3603
3687
|
if (canUseJoinInclude(
|
|
3604
3688
|
ctx.dialect,
|
|
3605
|
-
|
|
3689
|
+
isList,
|
|
3606
3690
|
adjusted.takeVal,
|
|
3607
3691
|
paginationConfig.skipVal,
|
|
3608
3692
|
depth,
|
|
@@ -3700,16 +3784,22 @@ function buildIncludeSqlInternal(args, ctx) {
|
|
|
3700
3784
|
`Circular include detected: ${Array.from(ctx.visitSet).join(" -> ")} -> ${relationPath}. Relation '${relationPath}' creates an infinite loop.`
|
|
3701
3785
|
);
|
|
3702
3786
|
}
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3787
|
+
ctx.includePath.push(relName);
|
|
3788
|
+
ctx.visitSet.add(relationPath);
|
|
3789
|
+
try {
|
|
3790
|
+
includes.push(
|
|
3791
|
+
buildSingleInclude(
|
|
3792
|
+
relName,
|
|
3793
|
+
relArgs,
|
|
3794
|
+
resolved.field,
|
|
3795
|
+
resolved.relModel,
|
|
3796
|
+
ctx
|
|
3797
|
+
)
|
|
3798
|
+
);
|
|
3799
|
+
} finally {
|
|
3800
|
+
ctx.includePath.pop();
|
|
3801
|
+
ctx.visitSet.delete(relationPath);
|
|
3802
|
+
}
|
|
3713
3803
|
}
|
|
3714
3804
|
return includes;
|
|
3715
3805
|
}
|
|
@@ -3993,10 +4083,19 @@ function canUseNestedFlatJoin(relArgs, depth) {
|
|
|
3993
4083
|
}
|
|
3994
4084
|
return true;
|
|
3995
4085
|
}
|
|
3996
|
-
function canUseFlatJoinForAll(includeSpec) {
|
|
3997
|
-
|
|
4086
|
+
function canUseFlatJoinForAll(includeSpec, parentModel, schemas) {
|
|
4087
|
+
const modelMap = new Map(schemas.map((m) => [m.name, m]));
|
|
4088
|
+
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
3998
4089
|
if (value === false) continue;
|
|
4090
|
+
const field = parentModel.fields.find((f) => f.name === relName);
|
|
4091
|
+
if (!field || !field.isRelation) continue;
|
|
3999
4092
|
if (!canUseNestedFlatJoin(value, 0)) return false;
|
|
4093
|
+
const relModel = modelMap.get(field.relatedModel);
|
|
4094
|
+
if (!relModel) continue;
|
|
4095
|
+
const nestedSpec = extractNestedIncludeSpec(value, relModel);
|
|
4096
|
+
if (Object.keys(nestedSpec).length > 0) {
|
|
4097
|
+
if (!canUseFlatJoinForAll(nestedSpec, relModel, schemas)) return false;
|
|
4098
|
+
}
|
|
4000
4099
|
}
|
|
4001
4100
|
return true;
|
|
4002
4101
|
}
|
|
@@ -4093,7 +4192,7 @@ function buildFlatJoinSql(spec) {
|
|
|
4093
4192
|
if (Object.keys(includeSpec).length === 0) {
|
|
4094
4193
|
return { sql: "", requiresReduction: false, includeSpec: {} };
|
|
4095
4194
|
}
|
|
4096
|
-
if (!canUseFlatJoinForAll(includeSpec)) {
|
|
4195
|
+
if (!canUseFlatJoinForAll(includeSpec, model, schemas)) {
|
|
4097
4196
|
return { sql: "", requiresReduction: false, includeSpec: {} };
|
|
4098
4197
|
}
|
|
4099
4198
|
const baseJoins = whereJoins.length > 0 ? whereJoins.join(" ") : "";
|
|
@@ -4139,6 +4238,217 @@ function buildFlatJoinSql(spec) {
|
|
|
4139
4238
|
`.trim();
|
|
4140
4239
|
return { sql, requiresReduction: true, includeSpec };
|
|
4141
4240
|
}
|
|
4241
|
+
|
|
4242
|
+
// src/builder/select/array-agg.ts
|
|
4243
|
+
function canUseArrayAggForAll(includeSpec, parentModel, schemas) {
|
|
4244
|
+
const modelMap = new Map(schemas.map((m) => [m.name, m]));
|
|
4245
|
+
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
4246
|
+
if (value === false) continue;
|
|
4247
|
+
const field = parentModel.fields.find((f) => f.name === relName);
|
|
4248
|
+
if (!field || !field.isRelation) continue;
|
|
4249
|
+
if (isPlainObject(value) && hasChildPagination(value)) return false;
|
|
4250
|
+
const relModel = modelMap.get(field.relatedModel);
|
|
4251
|
+
if (!relModel) continue;
|
|
4252
|
+
const nestedSpec = extractNestedIncludeSpec(value, relModel);
|
|
4253
|
+
if (Object.keys(nestedSpec).length > 0) return false;
|
|
4254
|
+
}
|
|
4255
|
+
return true;
|
|
4256
|
+
}
|
|
4257
|
+
function getRelationModel2(parentModel, relationName, schemas) {
|
|
4258
|
+
const field = parentModel.fields.find((f) => f.name === relationName);
|
|
4259
|
+
if (!(field == null ? void 0 : field.isRelation) || !field.relatedModel) {
|
|
4260
|
+
throw new Error(`Invalid relation ${relationName} on ${parentModel.name}`);
|
|
4261
|
+
}
|
|
4262
|
+
const relModel = schemas.find((m) => m.name === field.relatedModel);
|
|
4263
|
+
if (!relModel) {
|
|
4264
|
+
throw new Error(`Related model ${field.relatedModel} not found`);
|
|
4265
|
+
}
|
|
4266
|
+
return relModel;
|
|
4267
|
+
}
|
|
4268
|
+
function buildSubqueryRawSelect2(model, alias) {
|
|
4269
|
+
const cols = [];
|
|
4270
|
+
for (const f of model.fields) {
|
|
4271
|
+
if (f.isRelation) continue;
|
|
4272
|
+
cols.push(`${alias}.${quoteColumn(model, f.name)}`);
|
|
4273
|
+
}
|
|
4274
|
+
return cols.length > 0 ? cols.join(SQL_SEPARATORS.FIELD_LIST) : "*";
|
|
4275
|
+
}
|
|
4276
|
+
function readWhereInput2(relArgs) {
|
|
4277
|
+
if (!isPlainObject(relArgs)) return {};
|
|
4278
|
+
const obj = relArgs;
|
|
4279
|
+
if (!("where" in obj)) return {};
|
|
4280
|
+
const w = obj.where;
|
|
4281
|
+
return isPlainObject(w) ? w : {};
|
|
4282
|
+
}
|
|
4283
|
+
function buildArrayAggRelation(args) {
|
|
4284
|
+
const {
|
|
4285
|
+
relationName,
|
|
4286
|
+
relArgs,
|
|
4287
|
+
field,
|
|
4288
|
+
relModel,
|
|
4289
|
+
parentModel,
|
|
4290
|
+
parentAlias,
|
|
4291
|
+
schemas,
|
|
4292
|
+
dialect,
|
|
4293
|
+
aliasCounter,
|
|
4294
|
+
params
|
|
4295
|
+
} = args;
|
|
4296
|
+
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
4297
|
+
const { childKeys: relKeyFields, parentKeys: parentKeyFields } = resolveRelationKeys(field, "include");
|
|
4298
|
+
if (relKeyFields.length === 0) return null;
|
|
4299
|
+
const innerAlias = `__aa_r${aliasCounter.count++}`;
|
|
4300
|
+
const joinAlias = `__aa_j${aliasCounter.count++}`;
|
|
4301
|
+
const indices = getFieldIndices(relModel);
|
|
4302
|
+
const scalarSel = extractScalarSelection(relArgs, relModel);
|
|
4303
|
+
const pkFields = getPrimaryKeyFields(relModel);
|
|
4304
|
+
const selectedFields = scalarSel.includeAllScalars ? Array.from(indices.scalarFields.keys()) : [.../* @__PURE__ */ new Set([...pkFields, ...scalarSel.selectedScalarFields])];
|
|
4305
|
+
const pkOrderExpr = pkFields.map((f) => `${innerAlias}.${quoteColumn(relModel, f)}`).join(SQL_SEPARATORS.FIELD_LIST);
|
|
4306
|
+
const pkFilterExpr = `${innerAlias}.${quoteColumn(relModel, pkFields[0])}`;
|
|
4307
|
+
const fkSelectParts = relKeyFields.map(
|
|
4308
|
+
(f, i) => `${innerAlias}.${quoteColumn(relModel, f)} AS "__fk${i}"`
|
|
4309
|
+
);
|
|
4310
|
+
const aggParts = selectedFields.map((fieldName) => {
|
|
4311
|
+
const f = indices.scalarFields.get(fieldName);
|
|
4312
|
+
if (!f) return null;
|
|
4313
|
+
const colRef = `${innerAlias}.${quoteColumn(relModel, fieldName)}`;
|
|
4314
|
+
const alias = `"${relationName}.${f.name}"`;
|
|
4315
|
+
return `array_agg(${colRef} ORDER BY ${pkOrderExpr}) FILTER (WHERE ${pkFilterExpr} IS NOT NULL) AS ${alias}`;
|
|
4316
|
+
}).filter(Boolean);
|
|
4317
|
+
const fkGroupByParts = relKeyFields.map(
|
|
4318
|
+
(f) => `${innerAlias}.${quoteColumn(relModel, f)}`
|
|
4319
|
+
);
|
|
4320
|
+
const relTable = buildTableReference(
|
|
4321
|
+
SQL_TEMPLATES.PUBLIC_SCHEMA,
|
|
4322
|
+
relModel.tableName,
|
|
4323
|
+
dialect
|
|
4324
|
+
);
|
|
4325
|
+
const whereInput = readWhereInput2(relArgs);
|
|
4326
|
+
let whereJoinsSql = "";
|
|
4327
|
+
let whereClauseSql = "";
|
|
4328
|
+
if (Object.keys(whereInput).length > 0) {
|
|
4329
|
+
const aliasGen = createAliasGenerator();
|
|
4330
|
+
const whereResult = buildWhereClause(whereInput, {
|
|
4331
|
+
alias: innerAlias,
|
|
4332
|
+
schemaModels: schemas,
|
|
4333
|
+
model: relModel,
|
|
4334
|
+
params,
|
|
4335
|
+
isSubquery: true,
|
|
4336
|
+
aliasGen,
|
|
4337
|
+
dialect
|
|
4338
|
+
});
|
|
4339
|
+
if (whereResult.joins.length > 0) {
|
|
4340
|
+
whereJoinsSql = " " + whereResult.joins.join(" ");
|
|
4341
|
+
}
|
|
4342
|
+
if (isValidWhereClause(whereResult.clause)) {
|
|
4343
|
+
whereClauseSql = ` ${SQL_TEMPLATES.WHERE} ${whereResult.clause}`;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
const subquery = `SELECT ${fkSelectParts.join(SQL_SEPARATORS.FIELD_LIST)}${SQL_SEPARATORS.FIELD_LIST}${aggParts.join(SQL_SEPARATORS.FIELD_LIST)} FROM ${relTable} ${innerAlias}${whereJoinsSql}${whereClauseSql} GROUP BY ${fkGroupByParts.join(SQL_SEPARATORS.FIELD_LIST)}`;
|
|
4347
|
+
const onParts = parentKeyFields.map(
|
|
4348
|
+
(f, i) => `${joinAlias}."__fk${i}" = ${parentAlias}.${quoteColumn(parentModel, f)}`
|
|
4349
|
+
);
|
|
4350
|
+
const onCondition = onParts.length === 1 ? onParts[0] : `(${onParts.join(" AND ")})`;
|
|
4351
|
+
const joinSql = `LEFT JOIN (${subquery}) ${joinAlias} ON ${onCondition}`;
|
|
4352
|
+
const selectExprs = selectedFields.map((fieldName) => {
|
|
4353
|
+
const f = indices.scalarFields.get(fieldName);
|
|
4354
|
+
if (!f) return null;
|
|
4355
|
+
return `${joinAlias}."${relationName}.${f.name}"`;
|
|
4356
|
+
}).filter(Boolean);
|
|
4357
|
+
return {
|
|
4358
|
+
joinSql,
|
|
4359
|
+
selectExprs,
|
|
4360
|
+
relationName,
|
|
4361
|
+
isList,
|
|
4362
|
+
scalarFieldNames: selectedFields
|
|
4363
|
+
};
|
|
4364
|
+
}
|
|
4365
|
+
function buildArrayAggSql(spec) {
|
|
4366
|
+
const {
|
|
4367
|
+
select,
|
|
4368
|
+
from,
|
|
4369
|
+
whereClause,
|
|
4370
|
+
whereJoins,
|
|
4371
|
+
orderBy,
|
|
4372
|
+
dialect,
|
|
4373
|
+
model,
|
|
4374
|
+
schemas,
|
|
4375
|
+
args,
|
|
4376
|
+
params
|
|
4377
|
+
} = spec;
|
|
4378
|
+
const entries = extractRelationEntries(args, model);
|
|
4379
|
+
const includeSpec = {};
|
|
4380
|
+
for (const e of entries) {
|
|
4381
|
+
includeSpec[e.name] = e.value;
|
|
4382
|
+
}
|
|
4383
|
+
if (Object.keys(includeSpec).length === 0) {
|
|
4384
|
+
return {
|
|
4385
|
+
sql: "",
|
|
4386
|
+
requiresReduction: false,
|
|
4387
|
+
includeSpec: {},
|
|
4388
|
+
isArrayAgg: false
|
|
4389
|
+
};
|
|
4390
|
+
}
|
|
4391
|
+
if (!canUseArrayAggForAll(includeSpec, model, schemas)) {
|
|
4392
|
+
return {
|
|
4393
|
+
sql: "",
|
|
4394
|
+
requiresReduction: false,
|
|
4395
|
+
includeSpec: {},
|
|
4396
|
+
isArrayAgg: false
|
|
4397
|
+
};
|
|
4398
|
+
}
|
|
4399
|
+
const baseJoins = whereJoins.length > 0 ? whereJoins.join(" ") : "";
|
|
4400
|
+
const baseWhere = whereClause && whereClause !== "1=1" ? `WHERE ${whereClause}` : "";
|
|
4401
|
+
const baseOrderBy = orderBy ? `ORDER BY ${orderBy}` : "";
|
|
4402
|
+
const subqueryScalarCols = buildSubqueryRawSelect2(model, from.alias);
|
|
4403
|
+
let baseSubquery = `SELECT ${subqueryScalarCols} FROM ${from.table} ${from.alias}` + (baseJoins ? ` ${baseJoins}` : "") + (baseWhere ? ` ${baseWhere}` : "") + (baseOrderBy ? ` ${baseOrderBy}` : "");
|
|
4404
|
+
baseSubquery = appendPagination(baseSubquery.trim(), spec);
|
|
4405
|
+
const aliasCounter = { count: 0 };
|
|
4406
|
+
const joins = [];
|
|
4407
|
+
const arraySelectExprs = [];
|
|
4408
|
+
for (const [relName, relValue] of Object.entries(includeSpec)) {
|
|
4409
|
+
if (relValue === false) continue;
|
|
4410
|
+
const field = model.fields.find((f) => f.name === relName);
|
|
4411
|
+
if (!field || !isValidRelationField(field)) continue;
|
|
4412
|
+
const relModel = getRelationModel2(model, relName, schemas);
|
|
4413
|
+
const built = buildArrayAggRelation({
|
|
4414
|
+
relationName: relName,
|
|
4415
|
+
relArgs: relValue,
|
|
4416
|
+
field,
|
|
4417
|
+
relModel,
|
|
4418
|
+
parentModel: model,
|
|
4419
|
+
parentAlias: from.alias,
|
|
4420
|
+
schemas,
|
|
4421
|
+
dialect,
|
|
4422
|
+
aliasCounter,
|
|
4423
|
+
params
|
|
4424
|
+
});
|
|
4425
|
+
if (!built) continue;
|
|
4426
|
+
joins.push(built.joinSql);
|
|
4427
|
+
arraySelectExprs.push(...built.selectExprs);
|
|
4428
|
+
}
|
|
4429
|
+
if (joins.length === 0) {
|
|
4430
|
+
return {
|
|
4431
|
+
sql: "",
|
|
4432
|
+
requiresReduction: false,
|
|
4433
|
+
includeSpec: {},
|
|
4434
|
+
isArrayAgg: false
|
|
4435
|
+
};
|
|
4436
|
+
}
|
|
4437
|
+
const baseSelect = (select != null ? select : "").trim();
|
|
4438
|
+
const allSelects = [baseSelect, ...arraySelectExprs].filter((s) => s && s.trim().length > 0).join(SQL_SEPARATORS.FIELD_LIST);
|
|
4439
|
+
if (!allSelects) {
|
|
4440
|
+
throw new Error("Array-agg SELECT requires at least one selected field");
|
|
4441
|
+
}
|
|
4442
|
+
const pkField = getPrimaryKeyField(model);
|
|
4443
|
+
const pkOrder = `${from.alias}.${quoteColumn(model, pkField)} ASC`;
|
|
4444
|
+
const sql = `
|
|
4445
|
+
SELECT ${allSelects}
|
|
4446
|
+
FROM (${baseSubquery}) ${from.alias}
|
|
4447
|
+
${joins.join(" ")}
|
|
4448
|
+
ORDER BY ${pkOrder}
|
|
4449
|
+
`.trim();
|
|
4450
|
+
return { sql, requiresReduction: true, includeSpec, isArrayAgg: true };
|
|
4451
|
+
}
|
|
4142
4452
|
var SELECT_FIELD_REGEX = /^\s*("(?:[^"]|"")+"|[a-z_][a-z0-9_]*)\s*\.\s*("(?:[^"]|"")+"|[a-z_][a-z0-9_]*)(?:\s+AS\s+("(?:[^"]|"")+"|[a-z_][a-z0-9_]*))?\s*$/i;
|
|
4143
4453
|
function buildWhereSql(conditions) {
|
|
4144
4454
|
if (!isNonEmptyArray(conditions)) return "";
|
|
@@ -4226,47 +4536,45 @@ function buildOutputColumns(scalarNames, includeNames, hasCount) {
|
|
|
4226
4536
|
}
|
|
4227
4537
|
return formatted;
|
|
4228
4538
|
}
|
|
4229
|
-
function
|
|
4230
|
-
|
|
4231
|
-
const
|
|
4232
|
-
const
|
|
4233
|
-
const
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
function extractDistinctOrderEntries(spec) {
|
|
4241
|
-
if (isNotNullish(spec.args.orderBy)) {
|
|
4242
|
-
const normalized = normalizeOrderByInput(
|
|
4243
|
-
spec.args.orderBy,
|
|
4244
|
-
parseOrderByValue
|
|
4245
|
-
);
|
|
4246
|
-
const entries = [];
|
|
4247
|
-
for (const item of normalized) {
|
|
4248
|
-
for (const field in item) {
|
|
4249
|
-
if (!Object.prototype.hasOwnProperty.call(item, field)) continue;
|
|
4250
|
-
const value = item[field];
|
|
4251
|
-
if (typeof value === "string") {
|
|
4252
|
-
entries.push({ field, direction: value });
|
|
4253
|
-
continue;
|
|
4254
|
-
}
|
|
4255
|
-
const obj = value;
|
|
4256
|
-
entries.push({ field, direction: obj.direction, nulls: obj.nulls });
|
|
4539
|
+
function getOrderByEntries(spec) {
|
|
4540
|
+
if (!isNotNullish(spec.args.orderBy)) return [];
|
|
4541
|
+
const normalized = normalizeOrderByInput(spec.args.orderBy, parseOrderByValue);
|
|
4542
|
+
const entries = [];
|
|
4543
|
+
for (const item of normalized) {
|
|
4544
|
+
for (const field in item) {
|
|
4545
|
+
if (!Object.prototype.hasOwnProperty.call(item, field)) continue;
|
|
4546
|
+
const value = item[field];
|
|
4547
|
+
if (typeof value === "string") {
|
|
4548
|
+
entries.push({ field, direction: value });
|
|
4549
|
+
continue;
|
|
4257
4550
|
}
|
|
4551
|
+
const obj = value;
|
|
4552
|
+
entries.push({ field, direction: obj.direction, nulls: obj.nulls });
|
|
4258
4553
|
}
|
|
4259
|
-
if (entries.length > 0) return entries;
|
|
4260
4554
|
}
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4555
|
+
return entries;
|
|
4556
|
+
}
|
|
4557
|
+
function renderOrderBySql(entries, alias, dialect, model) {
|
|
4558
|
+
if (entries.length === 0) return "";
|
|
4559
|
+
const out = [];
|
|
4560
|
+
for (const e of entries) {
|
|
4561
|
+
const dir = e.direction.toUpperCase();
|
|
4562
|
+
const c = col(alias, e.field, model);
|
|
4563
|
+
if (dialect === "postgres") {
|
|
4564
|
+
const nulls = isNotNullish(e.nulls) ? ` NULLS ${e.nulls.toUpperCase()}` : "";
|
|
4565
|
+
out.push(c + " " + dir + nulls);
|
|
4566
|
+
} else if (isNotNullish(e.nulls)) {
|
|
4567
|
+
const isNullExpr = `(${c} IS NULL)`;
|
|
4568
|
+
const nullRankDir = e.nulls === "first" ? "DESC" : "ASC";
|
|
4569
|
+
out.push(isNullExpr + " " + nullRankDir);
|
|
4570
|
+
out.push(c + " " + dir);
|
|
4571
|
+
} else {
|
|
4572
|
+
out.push(c + " " + dir);
|
|
4573
|
+
}
|
|
4266
4574
|
}
|
|
4267
|
-
return
|
|
4575
|
+
return out.join(SQL_SEPARATORS.ORDER_BY);
|
|
4268
4576
|
}
|
|
4269
|
-
function
|
|
4577
|
+
function renderOrderBySimple(entries, alias) {
|
|
4270
4578
|
if (entries.length === 0) return "";
|
|
4271
4579
|
const out = [];
|
|
4272
4580
|
for (const e of entries) {
|
|
@@ -4277,40 +4585,73 @@ function buildFieldNameOrderBy(entries, alias) {
|
|
|
4277
4585
|
const nullRankDir = e.nulls === "first" ? "DESC" : "ASC";
|
|
4278
4586
|
out.push(isNullExpr + " " + nullRankDir);
|
|
4279
4587
|
out.push(c + " " + dir);
|
|
4280
|
-
|
|
4588
|
+
} else {
|
|
4589
|
+
out.push(c + " " + dir);
|
|
4281
4590
|
}
|
|
4282
|
-
out.push(c + " " + dir);
|
|
4283
4591
|
}
|
|
4284
4592
|
return out.join(SQL_SEPARATORS.ORDER_BY);
|
|
4285
4593
|
}
|
|
4594
|
+
function ensureIdTiebreakerEntries(entries, model) {
|
|
4595
|
+
var _a3, _b;
|
|
4596
|
+
const idField = (_b = (_a3 = model == null ? void 0 : model.fields) == null ? void 0 : _a3.find) == null ? void 0 : _b.call(
|
|
4597
|
+
_a3,
|
|
4598
|
+
(f) => f.name === "id" && !f.isRelation
|
|
4599
|
+
);
|
|
4600
|
+
if (!idField) return entries;
|
|
4601
|
+
if (entries.some((e) => e.field === "id")) return entries;
|
|
4602
|
+
return [...entries, { field: "id", direction: "asc" }];
|
|
4603
|
+
}
|
|
4604
|
+
function ensurePostgresDistinctOrderEntries(args) {
|
|
4605
|
+
const { entries, distinct, model } = args;
|
|
4606
|
+
const distinctEntries = [...distinct].map((f) => ({
|
|
4607
|
+
field: f,
|
|
4608
|
+
direction: "asc"
|
|
4609
|
+
}));
|
|
4610
|
+
const canKeepAsIs = entries.length >= distinctEntries.length && distinctEntries.every((de, i) => entries[i].field === de.field);
|
|
4611
|
+
const merged = canKeepAsIs ? entries : [...distinctEntries, ...entries];
|
|
4612
|
+
return ensureIdTiebreakerEntries(merged, model);
|
|
4613
|
+
}
|
|
4614
|
+
function extractDistinctOrderEntries(spec) {
|
|
4615
|
+
const entries = getOrderByEntries(spec);
|
|
4616
|
+
if (entries.length > 0) return entries;
|
|
4617
|
+
if (isNotNullish(spec.distinct) && isNonEmptyArray(spec.distinct)) {
|
|
4618
|
+
return [...spec.distinct].map((f) => ({
|
|
4619
|
+
field: f,
|
|
4620
|
+
direction: "asc"
|
|
4621
|
+
}));
|
|
4622
|
+
}
|
|
4623
|
+
return [];
|
|
4624
|
+
}
|
|
4286
4625
|
function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
|
|
4287
|
-
var
|
|
4288
|
-
const { includes, from, whereClause, whereJoins,
|
|
4626
|
+
var _a3, _b;
|
|
4627
|
+
const { includes, from, whereClause, whereJoins, distinct, model } = spec;
|
|
4289
4628
|
if (!isNotNullish(distinct) || !isNonEmptyArray(distinct)) {
|
|
4290
4629
|
throw new Error("buildSqliteDistinctQuery requires distinct fields");
|
|
4291
4630
|
}
|
|
4292
4631
|
const scalarNames = parseSimpleScalarSelect(spec.select, from.alias);
|
|
4293
4632
|
const includeNames = includes.map((i) => i.name);
|
|
4294
|
-
const hasCount = Boolean((_b = (
|
|
4633
|
+
const hasCount = Boolean((_b = (_a3 = spec.args) == null ? void 0 : _a3.select) == null ? void 0 : _b._count);
|
|
4295
4634
|
const outerSelectCols = buildOutputColumns(
|
|
4296
4635
|
scalarNames,
|
|
4297
4636
|
includeNames,
|
|
4298
4637
|
hasCount
|
|
4299
4638
|
);
|
|
4300
4639
|
const distinctCols = buildDistinctColumns([...distinct], from.alias, model);
|
|
4301
|
-
const
|
|
4302
|
-
const
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
const
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4640
|
+
const baseEntries = getOrderByEntries(spec);
|
|
4641
|
+
const fallbackEntries = [...distinct].map((f) => ({
|
|
4642
|
+
field: f,
|
|
4643
|
+
direction: "asc"
|
|
4644
|
+
}));
|
|
4645
|
+
const resolvedEntries = baseEntries.length > 0 ? baseEntries : fallbackEntries;
|
|
4646
|
+
const windowEntries = ensureIdTiebreakerEntries(resolvedEntries, model);
|
|
4647
|
+
const windowOrder = renderOrderBySql(
|
|
4648
|
+
windowEntries,
|
|
4649
|
+
from.alias,
|
|
4650
|
+
"sqlite",
|
|
4310
4651
|
model
|
|
4311
|
-
|
|
4652
|
+
);
|
|
4312
4653
|
const outerEntries = extractDistinctOrderEntries(spec);
|
|
4313
|
-
const outerOrder =
|
|
4654
|
+
const outerOrder = renderOrderBySimple(outerEntries, '"__tp_distinct"');
|
|
4314
4655
|
const joins = buildJoinsSql(whereJoins, countJoins);
|
|
4315
4656
|
const conditions = [];
|
|
4316
4657
|
if (whereClause && whereClause !== "1=1") conditions.push(whereClause);
|
|
@@ -4361,12 +4702,12 @@ function resolveCountSelect(countSelectRaw, model) {
|
|
|
4361
4702
|
return null;
|
|
4362
4703
|
}
|
|
4363
4704
|
function buildIncludeColumns(spec) {
|
|
4364
|
-
var
|
|
4705
|
+
var _a3, _b;
|
|
4365
4706
|
const { select, includes, dialect, model, schemas, from, params } = spec;
|
|
4366
4707
|
const baseSelect = (select != null ? select : "").trim();
|
|
4367
4708
|
let countCols = "";
|
|
4368
4709
|
let countJoins = [];
|
|
4369
|
-
const countSelectRaw = (_b = (
|
|
4710
|
+
const countSelectRaw = (_b = (_a3 = spec.args) == null ? void 0 : _a3.select) == null ? void 0 : _b._count;
|
|
4370
4711
|
if (countSelectRaw) {
|
|
4371
4712
|
const resolvedCountSelect = resolveCountSelect(countSelectRaw, model);
|
|
4372
4713
|
if (resolvedCountSelect && Object.keys(resolvedCountSelect).length > 0) {
|
|
@@ -4525,37 +4866,6 @@ function extractIncludeSpec(args) {
|
|
|
4525
4866
|
function hasNestedIncludes(includeSpec) {
|
|
4526
4867
|
return Object.keys(includeSpec).length > 0;
|
|
4527
4868
|
}
|
|
4528
|
-
function splitOrderByTerms(orderBy) {
|
|
4529
|
-
const raw = orderBy.trim();
|
|
4530
|
-
if (raw.length === 0) return [];
|
|
4531
|
-
return raw.split(SQL_SEPARATORS.ORDER_BY).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
4532
|
-
}
|
|
4533
|
-
function hasIdInOrderBy(orderBy, fromAlias) {
|
|
4534
|
-
const lower = orderBy.toLowerCase();
|
|
4535
|
-
const aliasLower = fromAlias.toLowerCase();
|
|
4536
|
-
return lower.includes(`${aliasLower}.id `) || lower.includes(`${aliasLower}."id"`);
|
|
4537
|
-
}
|
|
4538
|
-
function ensureIdTiebreakerOrderBy(orderBy, fromAlias, model) {
|
|
4539
|
-
var _a, _b;
|
|
4540
|
-
const idField = (_b = (_a = model == null ? void 0 : model.fields) == null ? void 0 : _a.find) == null ? void 0 : _b.call(
|
|
4541
|
-
_a,
|
|
4542
|
-
(f) => f.name === "id" && !f.isRelation
|
|
4543
|
-
);
|
|
4544
|
-
if (!idField) return orderBy;
|
|
4545
|
-
if (hasIdInOrderBy(orderBy, fromAlias)) return orderBy;
|
|
4546
|
-
const t = col(fromAlias, "id", model) + " ASC";
|
|
4547
|
-
return isNonEmptyString(orderBy) ? orderBy + ", " + t : t;
|
|
4548
|
-
}
|
|
4549
|
-
function ensurePostgresDistinctOrderBy(args) {
|
|
4550
|
-
const { orderBy, distinct, fromAlias, model } = args;
|
|
4551
|
-
const distinctTerms = distinct.map((f) => col(fromAlias, f, model) + " ASC");
|
|
4552
|
-
const existing = splitOrderByTerms(orderBy);
|
|
4553
|
-
const canKeepAsIs = existing.length >= distinctTerms.length && distinctTerms.every(
|
|
4554
|
-
(term, i) => existing[i].toLowerCase().startsWith(term.split(" ASC")[0].toLowerCase())
|
|
4555
|
-
);
|
|
4556
|
-
const merged = canKeepAsIs ? orderBy : [...distinctTerms, ...existing].join(SQL_SEPARATORS.ORDER_BY);
|
|
4557
|
-
return ensureIdTiebreakerOrderBy(merged, fromAlias, model);
|
|
4558
|
-
}
|
|
4559
4869
|
function constructFinalSql(spec) {
|
|
4560
4870
|
const {
|
|
4561
4871
|
select,
|
|
@@ -4570,7 +4880,6 @@ function constructFinalSql(spec) {
|
|
|
4570
4880
|
params,
|
|
4571
4881
|
dialect,
|
|
4572
4882
|
model,
|
|
4573
|
-
includes,
|
|
4574
4883
|
schemas,
|
|
4575
4884
|
pagination,
|
|
4576
4885
|
args
|
|
@@ -4582,7 +4891,24 @@ function constructFinalSql(spec) {
|
|
|
4582
4891
|
const includeSpec = extractIncludeSpec(args);
|
|
4583
4892
|
const hasIncludes = hasNestedIncludes(includeSpec);
|
|
4584
4893
|
const hasPagination = isNotNullish(pagination.take);
|
|
4585
|
-
const
|
|
4894
|
+
const takeValue = typeof pagination.take === "number" ? pagination.take : null;
|
|
4895
|
+
const isLargeTake = takeValue !== null && takeValue > 50;
|
|
4896
|
+
const shouldUseArrayAgg = dialect === "postgres" && hasIncludes && method === "findMany" && hasPagination && isLargeTake && canUseArrayAggForAll(includeSpec, model, schemas);
|
|
4897
|
+
if (shouldUseArrayAgg) {
|
|
4898
|
+
const aaResult = buildArrayAggSql(spec);
|
|
4899
|
+
if (aaResult.sql) {
|
|
4900
|
+
const baseSqlResult = finalizeSql(aaResult.sql, params, dialect);
|
|
4901
|
+
return {
|
|
4902
|
+
sql: baseSqlResult.sql,
|
|
4903
|
+
params: baseSqlResult.params,
|
|
4904
|
+
paramMappings: baseSqlResult.paramMappings,
|
|
4905
|
+
requiresReduction: true,
|
|
4906
|
+
includeSpec: aaResult.includeSpec,
|
|
4907
|
+
isArrayAgg: true
|
|
4908
|
+
};
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
const shouldUseFlatJoin = dialect === "postgres" && hasPagination && hasIncludes && canUseFlatJoinForAll(includeSpec, model, schemas);
|
|
4586
4912
|
if (shouldUseFlatJoin) {
|
|
4587
4913
|
const flatResult = buildFlatJoinSql(spec);
|
|
4588
4914
|
if (flatResult.sql) {
|
|
@@ -4628,12 +4954,13 @@ function constructFinalSql(spec) {
|
|
|
4628
4954
|
pushWhere(parts, conditions);
|
|
4629
4955
|
let finalOrderBy = orderBy;
|
|
4630
4956
|
if (dialect === "postgres" && isNonEmptyArray(distinct)) {
|
|
4631
|
-
|
|
4632
|
-
|
|
4957
|
+
const currentEntries = getOrderByEntries(spec);
|
|
4958
|
+
const mergedEntries = ensurePostgresDistinctOrderEntries({
|
|
4959
|
+
entries: currentEntries.length > 0 ? currentEntries : [],
|
|
4633
4960
|
distinct: [...distinct],
|
|
4634
|
-
fromAlias: from.alias,
|
|
4635
4961
|
model
|
|
4636
4962
|
});
|
|
4963
|
+
finalOrderBy = renderOrderBySql(mergedEntries, from.alias, dialect, model);
|
|
4637
4964
|
}
|
|
4638
4965
|
if (isNonEmptyString(finalOrderBy))
|
|
4639
4966
|
parts.push(SQL_TEMPLATES.ORDER_BY, finalOrderBy);
|
|
@@ -4659,11 +4986,11 @@ function mapFirstOrderByByField(existing) {
|
|
|
4659
4986
|
return m;
|
|
4660
4987
|
}
|
|
4661
4988
|
function buildPostgresDistinctOrderBy(distinctFields, existing) {
|
|
4662
|
-
var
|
|
4989
|
+
var _a3;
|
|
4663
4990
|
const firstByField = mapFirstOrderByByField(existing);
|
|
4664
4991
|
const next = [];
|
|
4665
4992
|
for (const f of distinctFields) {
|
|
4666
|
-
next.push((
|
|
4993
|
+
next.push((_a3 = firstByField.get(f)) != null ? _a3 : { [f]: "asc" });
|
|
4667
4994
|
}
|
|
4668
4995
|
const distinctSet = new Set(distinctFields);
|
|
4669
4996
|
for (const obj of existing) {
|
|
@@ -5489,10 +5816,10 @@ function isPrismaMethod(v) {
|
|
|
5489
5816
|
return v === "findMany" || v === "findFirst" || v === "findUnique" || v === "aggregate" || v === "groupBy" || v === "count";
|
|
5490
5817
|
}
|
|
5491
5818
|
function resolveMethod(directive) {
|
|
5492
|
-
var
|
|
5819
|
+
var _a3, _b;
|
|
5493
5820
|
const m = directive == null ? void 0 : directive.method;
|
|
5494
5821
|
if (isPrismaMethod(m)) return m;
|
|
5495
|
-
const pm = (_b = (
|
|
5822
|
+
const pm = (_b = (_a3 = directive == null ? void 0 : directive.query) == null ? void 0 : _a3.processed) == null ? void 0 : _b.method;
|
|
5496
5823
|
if (isPrismaMethod(pm)) return pm;
|
|
5497
5824
|
return "findMany";
|
|
5498
5825
|
}
|
|
@@ -5653,7 +5980,7 @@ function extractIncludeSpec2(processed, modelDef) {
|
|
|
5653
5980
|
return includeSpec;
|
|
5654
5981
|
}
|
|
5655
5982
|
function buildAndNormalizeSql(args) {
|
|
5656
|
-
var
|
|
5983
|
+
var _a3;
|
|
5657
5984
|
const {
|
|
5658
5985
|
method,
|
|
5659
5986
|
processed,
|
|
@@ -5679,13 +6006,15 @@ function buildAndNormalizeSql(args) {
|
|
|
5679
6006
|
sqlResult.paramMappings,
|
|
5680
6007
|
dialect
|
|
5681
6008
|
);
|
|
5682
|
-
const includeSpec = (
|
|
6009
|
+
const includeSpec = (_a3 = sqlResult.includeSpec && isPlainObject(sqlResult.includeSpec) ? sqlResult.includeSpec : null) != null ? _a3 : extractIncludeSpec2(processed, modelDef);
|
|
5683
6010
|
const requiresReduction = sqlResult.requiresReduction === true;
|
|
6011
|
+
const isArrayAgg = sqlResult.isArrayAgg === true;
|
|
5684
6012
|
return {
|
|
5685
6013
|
sql: normalized.sql,
|
|
5686
6014
|
paramMappings: normalized.paramMappings,
|
|
5687
6015
|
requiresReduction,
|
|
5688
|
-
includeSpec
|
|
6016
|
+
includeSpec,
|
|
6017
|
+
isArrayAgg
|
|
5689
6018
|
};
|
|
5690
6019
|
}
|
|
5691
6020
|
function finalizeDirective(args) {
|
|
@@ -5696,11 +6025,12 @@ function finalizeDirective(args) {
|
|
|
5696
6025
|
normalizedMappings,
|
|
5697
6026
|
dialect,
|
|
5698
6027
|
requiresReduction,
|
|
5699
|
-
includeSpec
|
|
6028
|
+
includeSpec,
|
|
6029
|
+
isArrayAgg
|
|
5700
6030
|
} = args;
|
|
5701
6031
|
const params = normalizedMappings.map((m) => {
|
|
5702
|
-
var
|
|
5703
|
-
return (
|
|
6032
|
+
var _a3;
|
|
6033
|
+
return (_a3 = m.value) != null ? _a3 : void 0;
|
|
5704
6034
|
});
|
|
5705
6035
|
validateParamConsistencyByDialect(normalizedSql, params, dialect);
|
|
5706
6036
|
const { staticParams, dynamicKeys, paramOrder } = buildParamsFromMappings(normalizedMappings);
|
|
@@ -5713,6 +6043,7 @@ function finalizeDirective(args) {
|
|
|
5713
6043
|
paramMappings: normalizedMappings,
|
|
5714
6044
|
requiresReduction,
|
|
5715
6045
|
includeSpec,
|
|
6046
|
+
isArrayAgg,
|
|
5716
6047
|
originalDirective: directive
|
|
5717
6048
|
};
|
|
5718
6049
|
}
|
|
@@ -5746,7 +6077,8 @@ function generateSQL(directive) {
|
|
|
5746
6077
|
normalizedMappings: built.paramMappings,
|
|
5747
6078
|
dialect,
|
|
5748
6079
|
requiresReduction: built.requiresReduction,
|
|
5749
|
-
includeSpec: built.includeSpec
|
|
6080
|
+
includeSpec: built.includeSpec,
|
|
6081
|
+
isArrayAgg: built.isArrayAgg
|
|
5750
6082
|
});
|
|
5751
6083
|
}
|
|
5752
6084
|
|
|
@@ -6353,7 +6685,8 @@ function buildSQLFull(model, models, method, args, dialect) {
|
|
|
6353
6685
|
return __spreadProps(__spreadValues({}, sqlResult), {
|
|
6354
6686
|
paramMappings: result.paramMappings,
|
|
6355
6687
|
requiresReduction: result.requiresReduction,
|
|
6356
|
-
includeSpec: result.includeSpec
|
|
6688
|
+
includeSpec: result.includeSpec,
|
|
6689
|
+
isArrayAgg: result.isArrayAgg
|
|
6357
6690
|
});
|
|
6358
6691
|
}
|
|
6359
6692
|
function buildSQLWithCache(model, models, method, args, dialect) {
|
|
@@ -6366,7 +6699,8 @@ function buildSQLWithCache(model, models, method, args, dialect) {
|
|
|
6366
6699
|
params: [...cached.params],
|
|
6367
6700
|
paramMappings: cached.paramMappings,
|
|
6368
6701
|
requiresReduction: cached.requiresReduction,
|
|
6369
|
-
includeSpec: cached.includeSpec
|
|
6702
|
+
includeSpec: cached.includeSpec,
|
|
6703
|
+
isArrayAgg: cached.isArrayAgg
|
|
6370
6704
|
};
|
|
6371
6705
|
}
|
|
6372
6706
|
queryCacheStats.miss();
|
|
@@ -6384,7 +6718,8 @@ function buildSQLWithCache(model, models, method, args, dialect) {
|
|
|
6384
6718
|
params: [...result.params],
|
|
6385
6719
|
paramMappings: result.paramMappings,
|
|
6386
6720
|
requiresReduction: result.requiresReduction,
|
|
6387
|
-
includeSpec: result.includeSpec
|
|
6721
|
+
includeSpec: result.includeSpec,
|
|
6722
|
+
isArrayAgg: result.isArrayAgg
|
|
6388
6723
|
});
|
|
6389
6724
|
return result;
|
|
6390
6725
|
}
|
|
@@ -6458,10 +6793,10 @@ function getRowTransformer(method) {
|
|
|
6458
6793
|
|
|
6459
6794
|
// src/result-transformers.ts
|
|
6460
6795
|
function transformQueryResults(method, results) {
|
|
6461
|
-
var
|
|
6796
|
+
var _a3, _b;
|
|
6462
6797
|
if (method === "findFirst" || method === "findUnique") {
|
|
6463
6798
|
if (Array.isArray(results)) {
|
|
6464
|
-
return (
|
|
6799
|
+
return (_a3 = results[0]) != null ? _a3 : null;
|
|
6465
6800
|
}
|
|
6466
6801
|
}
|
|
6467
6802
|
if (method === "aggregate") {
|
|
@@ -6708,9 +7043,9 @@ function wrapQueryForMethod(method, cteName, resultAlias) {
|
|
|
6708
7043
|
}
|
|
6709
7044
|
}
|
|
6710
7045
|
function isAllCountQueries(queries, keys) {
|
|
6711
|
-
var
|
|
7046
|
+
var _a3;
|
|
6712
7047
|
for (const key of keys) {
|
|
6713
|
-
if (((
|
|
7048
|
+
if (((_a3 = queries[key]) == null ? void 0 : _a3.method) !== "count") return false;
|
|
6714
7049
|
}
|
|
6715
7050
|
return true;
|
|
6716
7051
|
}
|
|
@@ -6949,8 +7284,8 @@ function buildMergedCountBatchSql(queries, keys, aliasesByKey, modelMap, models,
|
|
|
6949
7284
|
const fromSql = rewrittenSubs.join(" CROSS JOIN ");
|
|
6950
7285
|
const sql = `SELECT ${selectParts.join(", ")} FROM ${fromSql}`;
|
|
6951
7286
|
const aliases = keys.map((k) => {
|
|
6952
|
-
var
|
|
6953
|
-
return (
|
|
7287
|
+
var _a3;
|
|
7288
|
+
return (_a3 = aliasesByKey.get(k)) != null ? _a3 : "";
|
|
6954
7289
|
});
|
|
6955
7290
|
return { sql, params: finalParams, keys, aliases };
|
|
6956
7291
|
}
|
|
@@ -7318,11 +7653,11 @@ function parseBatchValue(rawValue, method, modelName, modelMap) {
|
|
|
7318
7653
|
}
|
|
7319
7654
|
}
|
|
7320
7655
|
function parseBatchResults(row, keys, queries, aliases, modelMap) {
|
|
7321
|
-
var
|
|
7656
|
+
var _a3;
|
|
7322
7657
|
const results = {};
|
|
7323
7658
|
for (let i = 0; i < keys.length; i++) {
|
|
7324
7659
|
const key = keys[i];
|
|
7325
|
-
const columnKey = (
|
|
7660
|
+
const columnKey = (_a3 = aliases == null ? void 0 : aliases[i]) != null ? _a3 : key;
|
|
7326
7661
|
const rawValue = row[columnKey];
|
|
7327
7662
|
const query = queries[key];
|
|
7328
7663
|
results[key] = parseBatchValue(
|
|
@@ -7420,37 +7755,20 @@ function createTransactionExecutor(deps) {
|
|
|
7420
7755
|
}
|
|
7421
7756
|
|
|
7422
7757
|
// src/builder/shared/key-utils.ts
|
|
7423
|
-
function
|
|
7758
|
+
function buildKey(row, fields) {
|
|
7424
7759
|
if (fields.length === 0) return null;
|
|
7425
7760
|
if (fields.length === 1) {
|
|
7426
7761
|
const val = row[fields[0]];
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
if (t === "number") return Number.isFinite(val) ? `n:${val}` : null;
|
|
7431
|
-
if (t === "boolean") return val ? "b:1" : "b:0";
|
|
7432
|
-
if (t === "bigint") return `i:${val}`;
|
|
7433
|
-
return `o:${val}`;
|
|
7434
|
-
}
|
|
7435
|
-
const parts = new Array(fields.length);
|
|
7762
|
+
return val == null ? null : val;
|
|
7763
|
+
}
|
|
7764
|
+
let key = "";
|
|
7436
7765
|
for (let i = 0; i < fields.length; i++) {
|
|
7437
7766
|
const val = row[fields[i]];
|
|
7438
7767
|
if (val == null) return null;
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
parts[i] = `s:${val}`;
|
|
7442
|
-
} else if (t === "number") {
|
|
7443
|
-
if (!Number.isFinite(val)) return null;
|
|
7444
|
-
parts[i] = `n:${val}`;
|
|
7445
|
-
} else if (t === "boolean") {
|
|
7446
|
-
parts[i] = val ? "b:1" : "b:0";
|
|
7447
|
-
} else if (t === "bigint") {
|
|
7448
|
-
parts[i] = `i:${val}`;
|
|
7449
|
-
} else {
|
|
7450
|
-
parts[i] = `o:${val}`;
|
|
7451
|
-
}
|
|
7768
|
+
if (i > 0) key += "";
|
|
7769
|
+
key += typeof val === "string" ? val : String(val);
|
|
7452
7770
|
}
|
|
7453
|
-
return
|
|
7771
|
+
return key;
|
|
7454
7772
|
}
|
|
7455
7773
|
|
|
7456
7774
|
// src/builder/select/reducer.ts
|
|
@@ -7467,6 +7785,14 @@ function buildRelationScalarCols(relModel, relPath, includeAllScalars, selectedS
|
|
|
7467
7785
|
}
|
|
7468
7786
|
return out;
|
|
7469
7787
|
}
|
|
7788
|
+
function extractChildLimit(relArgs) {
|
|
7789
|
+
if (!isPlainObject(relArgs)) return void 0;
|
|
7790
|
+
const obj = relArgs;
|
|
7791
|
+
if ("take" in obj && typeof obj.take === "number" && obj.take > 0) {
|
|
7792
|
+
return obj.take;
|
|
7793
|
+
}
|
|
7794
|
+
return void 0;
|
|
7795
|
+
}
|
|
7470
7796
|
function buildReducerConfig(parentModel, includeSpec, allModels, prefix = "", depth = 0) {
|
|
7471
7797
|
if (depth > 10) {
|
|
7472
7798
|
throw new Error(
|
|
@@ -7489,7 +7815,7 @@ function buildReducerConfig(parentModel, includeSpec, allModels, prefix = "", de
|
|
|
7489
7815
|
`Related model '${field.relatedModel}' not found for relation '${incName}'`
|
|
7490
7816
|
);
|
|
7491
7817
|
}
|
|
7492
|
-
const
|
|
7818
|
+
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
7493
7819
|
const primaryKeyFields = getPrimaryKeyFields(relatedModel);
|
|
7494
7820
|
const scalarSel = extractScalarSelection(incValue, relatedModel);
|
|
7495
7821
|
const relPath = prefix ? `${prefix}.${incName}` : incName;
|
|
@@ -7511,14 +7837,16 @@ function buildReducerConfig(parentModel, includeSpec, allModels, prefix = "", de
|
|
|
7511
7837
|
scalarSel.includeAllScalars,
|
|
7512
7838
|
scalarSel.selectedScalarFields
|
|
7513
7839
|
);
|
|
7840
|
+
const childLimit = isList ? extractChildLimit(incValue) : void 0;
|
|
7514
7841
|
includedRelations.push({
|
|
7515
7842
|
name: incName,
|
|
7516
|
-
cardinality:
|
|
7843
|
+
cardinality: isList ? "many" : "one",
|
|
7517
7844
|
relatedModel,
|
|
7518
7845
|
primaryKeyFields,
|
|
7519
7846
|
includeAllScalars: scalarSel.includeAllScalars,
|
|
7520
7847
|
selectedScalarFields: scalarSel.selectedScalarFields,
|
|
7521
7848
|
nestedIncludes,
|
|
7849
|
+
childLimit,
|
|
7522
7850
|
path: relPath,
|
|
7523
7851
|
keyCols,
|
|
7524
7852
|
scalarCols
|
|
@@ -7550,7 +7878,7 @@ function initNestedPlaceholders(obj, nested) {
|
|
|
7550
7878
|
}
|
|
7551
7879
|
}
|
|
7552
7880
|
function materializeRelationObject(row, rel) {
|
|
7553
|
-
const relKey =
|
|
7881
|
+
const relKey = buildKey(row, rel.keyCols);
|
|
7554
7882
|
if (relKey == null) return null;
|
|
7555
7883
|
const obj = {};
|
|
7556
7884
|
for (const c of rel.scalarCols) {
|
|
@@ -7566,7 +7894,7 @@ function processNestedRelations(obj, rel, row, manyStore) {
|
|
|
7566
7894
|
}
|
|
7567
7895
|
}
|
|
7568
7896
|
function processRelation(parentObj, rel, row, manyStore) {
|
|
7569
|
-
const relKey =
|
|
7897
|
+
const relKey = buildKey(row, rel.keyCols);
|
|
7570
7898
|
if (relKey == null) return;
|
|
7571
7899
|
if (rel.cardinality === "one") {
|
|
7572
7900
|
let current = parentObj[rel.name];
|
|
@@ -7580,6 +7908,9 @@ function processRelation(parentObj, rel, row, manyStore) {
|
|
|
7580
7908
|
return;
|
|
7581
7909
|
}
|
|
7582
7910
|
const arr = parentObj[rel.name];
|
|
7911
|
+
if (rel.childLimit && arr.length >= rel.childLimit) {
|
|
7912
|
+
return;
|
|
7913
|
+
}
|
|
7583
7914
|
const idx = getIndexForParent(manyStore, parentObj, rel.path);
|
|
7584
7915
|
const existing = idx.get(relKey);
|
|
7585
7916
|
if (existing) {
|
|
@@ -7613,7 +7944,7 @@ function reduceFlatRows(rows, config) {
|
|
|
7613
7944
|
const manyStore = /* @__PURE__ */ new WeakMap();
|
|
7614
7945
|
for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
|
|
7615
7946
|
const row = rows[rowIdx];
|
|
7616
|
-
const parentKey =
|
|
7947
|
+
const parentKey = buildKey(row, parentKeyCols);
|
|
7617
7948
|
if (parentKey == null) continue;
|
|
7618
7949
|
let record = resultMap.get(parentKey);
|
|
7619
7950
|
if (!record) {
|
|
@@ -7638,9 +7969,7 @@ function reduceFlatRows(rows, config) {
|
|
|
7638
7969
|
}
|
|
7639
7970
|
|
|
7640
7971
|
// src/builder/select/segment-planner.ts
|
|
7641
|
-
|
|
7642
|
-
var MAX_ESTIMATED_ROWS = Number.MAX_SAFE_INTEGER / 1e3;
|
|
7643
|
-
function isList(field) {
|
|
7972
|
+
function isListField(field) {
|
|
7644
7973
|
return typeof field.type === "string" && field.type.endsWith("[]");
|
|
7645
7974
|
}
|
|
7646
7975
|
function resolveRelation(model, relName, allModels) {
|
|
@@ -7650,47 +7979,6 @@ function resolveRelation(model, relName, allModels) {
|
|
|
7650
7979
|
if (!relModel) return null;
|
|
7651
7980
|
return { field, relModel };
|
|
7652
7981
|
}
|
|
7653
|
-
function effectiveFanout(stats) {
|
|
7654
|
-
return 1 + stats.coverage * (stats.avg - 1);
|
|
7655
|
-
}
|
|
7656
|
-
function estimateFlatRows(parentCount, relations, stats) {
|
|
7657
|
-
var _a;
|
|
7658
|
-
let rows = parentCount;
|
|
7659
|
-
for (const rel of relations) {
|
|
7660
|
-
const relStats = (_a = stats == null ? void 0 : stats[rel.modelName]) == null ? void 0 : _a[rel.relName];
|
|
7661
|
-
const fanout = relStats ? effectiveFanout(relStats) : 10;
|
|
7662
|
-
const next = rows * fanout;
|
|
7663
|
-
if (next > MAX_ESTIMATED_ROWS) {
|
|
7664
|
-
return MAX_ESTIMATED_ROWS;
|
|
7665
|
-
}
|
|
7666
|
-
rows = next;
|
|
7667
|
-
}
|
|
7668
|
-
return Math.ceil(rows);
|
|
7669
|
-
}
|
|
7670
|
-
function collectOneToManyRelations(entries, model, allModels) {
|
|
7671
|
-
const out = [];
|
|
7672
|
-
for (const entry of entries) {
|
|
7673
|
-
const resolved = resolveRelation(model, entry.name, allModels);
|
|
7674
|
-
if (!resolved) continue;
|
|
7675
|
-
if (!isList(resolved.field)) continue;
|
|
7676
|
-
out.push({
|
|
7677
|
-
name: entry.name,
|
|
7678
|
-
relArgs: entry.value,
|
|
7679
|
-
field: resolved.field,
|
|
7680
|
-
relModel: resolved.relModel,
|
|
7681
|
-
hasPagination: hasChildPagination(entry.value)
|
|
7682
|
-
});
|
|
7683
|
-
}
|
|
7684
|
-
return out;
|
|
7685
|
-
}
|
|
7686
|
-
function getParentCount(method, args) {
|
|
7687
|
-
if (method === "findFirst" || method === "findUnique") return 1;
|
|
7688
|
-
if ((args == null ? void 0 : args.take) !== void 0 && (args == null ? void 0 : args.take) !== null) {
|
|
7689
|
-
const take = typeof args.take === "number" ? Math.abs(args.take) : null;
|
|
7690
|
-
if (take !== null) return take;
|
|
7691
|
-
}
|
|
7692
|
-
return null;
|
|
7693
|
-
}
|
|
7694
7982
|
function buildWhereInSegment(name, relArgs, field, relModel) {
|
|
7695
7983
|
const keys = resolveRelationKeys(field, "whereIn");
|
|
7696
7984
|
if (keys.childKeys.length !== 1) return null;
|
|
@@ -7700,7 +7988,7 @@ function buildWhereInSegment(name, relArgs, field, relModel) {
|
|
|
7700
7988
|
childModelName: relModel.name,
|
|
7701
7989
|
fkFieldName: keys.childKeys[0],
|
|
7702
7990
|
parentKeyFieldName: keys.parentKeys[0],
|
|
7703
|
-
isList:
|
|
7991
|
+
isList: isListField(field)
|
|
7704
7992
|
};
|
|
7705
7993
|
}
|
|
7706
7994
|
function deepClone(obj) {
|
|
@@ -7734,74 +8022,154 @@ function removeRelationsFromArgs(args, names) {
|
|
|
7734
8022
|
}
|
|
7735
8023
|
return filtered;
|
|
7736
8024
|
}
|
|
8025
|
+
function ensureParentKeysInSelect(args, segments) {
|
|
8026
|
+
if (!(args == null ? void 0 : args.select)) return { args, injectedKeys: [] };
|
|
8027
|
+
const injected = [];
|
|
8028
|
+
const newSelect = __spreadValues({}, args.select);
|
|
8029
|
+
for (const seg of segments) {
|
|
8030
|
+
if (!newSelect[seg.parentKeyFieldName]) {
|
|
8031
|
+
newSelect[seg.parentKeyFieldName] = true;
|
|
8032
|
+
injected.push(seg.parentKeyFieldName);
|
|
8033
|
+
}
|
|
8034
|
+
}
|
|
8035
|
+
if (injected.length === 0) return { args, injectedKeys: [] };
|
|
8036
|
+
return { args: __spreadProps(__spreadValues({}, args), { select: newSelect }), injectedKeys: injected };
|
|
8037
|
+
}
|
|
7737
8038
|
function planQueryStrategy(params) {
|
|
7738
|
-
const { model,
|
|
8039
|
+
const { model, args, allModels } = params;
|
|
8040
|
+
const emptyPlan = {
|
|
8041
|
+
filteredArgs: args,
|
|
8042
|
+
whereInSegments: [],
|
|
8043
|
+
injectedParentKeys: []
|
|
8044
|
+
};
|
|
7739
8045
|
const entries = extractRelationEntries(args, model);
|
|
7740
8046
|
if (entries.length === 0) {
|
|
7741
|
-
return
|
|
7742
|
-
}
|
|
7743
|
-
const oneToManyRels = collectOneToManyRelations(entries, model, allModels);
|
|
7744
|
-
const unpaginatedOneToMany = oneToManyRels.filter((r) => !r.hasPagination);
|
|
7745
|
-
if (unpaginatedOneToMany.length === 0) {
|
|
7746
|
-
return { filteredArgs: args, whereInSegments: [] };
|
|
8047
|
+
return emptyPlan;
|
|
7747
8048
|
}
|
|
7748
|
-
const parentCount = getParentCount(method, args);
|
|
7749
8049
|
const whereInSegments = [];
|
|
7750
8050
|
const toRemove = /* @__PURE__ */ new Set();
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
rel.field,
|
|
7757
|
-
rel.relModel
|
|
7758
|
-
);
|
|
7759
|
-
if (segment) {
|
|
7760
|
-
whereInSegments.push(segment);
|
|
7761
|
-
toRemove.add(rel.name);
|
|
7762
|
-
}
|
|
8051
|
+
for (const entry of entries) {
|
|
8052
|
+
const resolved = resolveRelation(model, entry.name, allModels);
|
|
8053
|
+
if (!resolved) continue;
|
|
8054
|
+
if (isListField(resolved.field) && hasChildPagination(entry.value)) {
|
|
8055
|
+
continue;
|
|
7763
8056
|
}
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
8057
|
+
const segment = buildWhereInSegment(
|
|
8058
|
+
entry.name,
|
|
8059
|
+
entry.value,
|
|
8060
|
+
resolved.field,
|
|
8061
|
+
resolved.relModel
|
|
8062
|
+
);
|
|
8063
|
+
if (segment) {
|
|
8064
|
+
whereInSegments.push(segment);
|
|
8065
|
+
toRemove.add(entry.name);
|
|
8066
|
+
}
|
|
8067
|
+
}
|
|
8068
|
+
if (toRemove.size === 0) {
|
|
8069
|
+
return emptyPlan;
|
|
8070
|
+
}
|
|
8071
|
+
const filteredArgs = removeRelationsFromArgs(args, toRemove);
|
|
8072
|
+
const { args: finalArgs, injectedKeys } = ensureParentKeysInSelect(
|
|
8073
|
+
filteredArgs,
|
|
8074
|
+
whereInSegments
|
|
8075
|
+
);
|
|
8076
|
+
return {
|
|
8077
|
+
filteredArgs: finalArgs,
|
|
8078
|
+
whereInSegments,
|
|
8079
|
+
injectedParentKeys: injectedKeys
|
|
8080
|
+
};
|
|
8081
|
+
}
|
|
8082
|
+
|
|
8083
|
+
// src/builder/select/array-agg-reducer.ts
|
|
8084
|
+
function buildArrayAggReducerConfig(parentModel, includeSpec, allModels) {
|
|
8085
|
+
const modelMap = new Map(allModels.map((m) => [m.name, m]));
|
|
8086
|
+
const parentJsonSet = getJsonFieldSet(parentModel);
|
|
8087
|
+
const parentScalarFields = getScalarFieldNames(parentModel);
|
|
8088
|
+
const relations = [];
|
|
8089
|
+
for (const [relName, relValue] of Object.entries(includeSpec)) {
|
|
8090
|
+
if (relValue === false) continue;
|
|
8091
|
+
const field = parentModel.fields.find((f) => f.name === relName);
|
|
8092
|
+
if (!field || !field.isRelation || !field.relatedModel) continue;
|
|
8093
|
+
const relModel = modelMap.get(field.relatedModel);
|
|
8094
|
+
if (!relModel) continue;
|
|
8095
|
+
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
8096
|
+
const indices = getFieldIndices(relModel);
|
|
8097
|
+
const scalarSel = extractScalarSelection(relValue, relModel);
|
|
8098
|
+
const pkFields = getPrimaryKeyFields(relModel);
|
|
8099
|
+
const relJsonSet = getJsonFieldSet(relModel);
|
|
8100
|
+
const selectedFields = scalarSel.includeAllScalars ? Array.from(indices.scalarFields.keys()) : [.../* @__PURE__ */ new Set([...pkFields, ...scalarSel.selectedScalarFields])];
|
|
8101
|
+
const scalarCols = selectedFields.map((fieldName) => {
|
|
8102
|
+
const f = indices.scalarFields.get(fieldName);
|
|
8103
|
+
if (!f) return null;
|
|
8104
|
+
return {
|
|
8105
|
+
fieldName: f.name,
|
|
8106
|
+
colName: `${relName}.${f.name}`,
|
|
8107
|
+
isJson: relJsonSet.has(f.name)
|
|
8108
|
+
};
|
|
8109
|
+
}).filter(Boolean);
|
|
8110
|
+
relations.push({
|
|
8111
|
+
name: relName,
|
|
8112
|
+
isList,
|
|
8113
|
+
scalarFields: scalarCols,
|
|
8114
|
+
pkFieldName: pkFields[0]
|
|
8115
|
+
});
|
|
8116
|
+
}
|
|
8117
|
+
return {
|
|
8118
|
+
parentModel,
|
|
8119
|
+
parentScalarFields,
|
|
8120
|
+
parentJsonSet,
|
|
8121
|
+
relations
|
|
8122
|
+
};
|
|
8123
|
+
}
|
|
8124
|
+
function reduceArrayAggRows(rows, config) {
|
|
8125
|
+
var _a3;
|
|
8126
|
+
if (rows.length === 0) return [];
|
|
8127
|
+
const { parentScalarFields, parentJsonSet, relations } = config;
|
|
8128
|
+
const results = new Array(rows.length);
|
|
8129
|
+
for (let i = 0; i < rows.length; i++) {
|
|
8130
|
+
const row = rows[i];
|
|
8131
|
+
const record = {};
|
|
8132
|
+
for (const fieldName of parentScalarFields) {
|
|
8133
|
+
if (!(fieldName in row)) continue;
|
|
8134
|
+
record[fieldName] = maybeParseJson(
|
|
8135
|
+
row[fieldName],
|
|
8136
|
+
parentJsonSet,
|
|
8137
|
+
fieldName
|
|
7772
8138
|
);
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
8139
|
+
}
|
|
8140
|
+
for (const rel of relations) {
|
|
8141
|
+
const firstCol = rel.scalarFields[0];
|
|
8142
|
+
if (!firstCol) {
|
|
8143
|
+
record[rel.name] = rel.isList ? [] : null;
|
|
8144
|
+
continue;
|
|
7776
8145
|
}
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
toRemove.add(rel.name);
|
|
8146
|
+
const arr = row[firstCol.colName];
|
|
8147
|
+
if (!Array.isArray(arr) || arr.length === 0) {
|
|
8148
|
+
record[rel.name] = rel.isList ? [] : null;
|
|
8149
|
+
continue;
|
|
8150
|
+
}
|
|
8151
|
+
const len = arr.length;
|
|
8152
|
+
const children = new Array(len);
|
|
8153
|
+
for (let j = 0; j < len; j++) {
|
|
8154
|
+
const child = {};
|
|
8155
|
+
for (const col2 of rel.scalarFields) {
|
|
8156
|
+
const values = row[col2.colName];
|
|
8157
|
+
child[col2.fieldName] = parseJsonIfNeeded(
|
|
8158
|
+
col2.isJson,
|
|
8159
|
+
Array.isArray(values) ? values[j] : null
|
|
8160
|
+
);
|
|
7793
8161
|
}
|
|
8162
|
+
children[j] = child;
|
|
7794
8163
|
}
|
|
8164
|
+
record[rel.name] = rel.isList ? children : (_a3 = children[0]) != null ? _a3 : null;
|
|
7795
8165
|
}
|
|
8166
|
+
results[i] = record;
|
|
7796
8167
|
}
|
|
7797
|
-
|
|
7798
|
-
return { filteredArgs: args, whereInSegments: [] };
|
|
7799
|
-
}
|
|
7800
|
-
const filteredArgs = removeRelationsFromArgs(args, toRemove);
|
|
7801
|
-
return { filteredArgs, whereInSegments };
|
|
8168
|
+
return results;
|
|
7802
8169
|
}
|
|
7803
8170
|
|
|
7804
8171
|
// src/builder/shared/where-in-executor-base.ts
|
|
8172
|
+
var MAX_RECURSIVE_DEPTH = 10;
|
|
7805
8173
|
function getParamLimit(dialect) {
|
|
7806
8174
|
return dialect === "postgres" ? 32e3 : 900;
|
|
7807
8175
|
}
|
|
@@ -7854,8 +8222,14 @@ function stitchResults(parentRows, segment, childRows, stripFk) {
|
|
|
7854
8222
|
}
|
|
7855
8223
|
}
|
|
7856
8224
|
}
|
|
7857
|
-
function
|
|
8225
|
+
function executeSingleSegment(segment, parentRows, allModels, modelMap, dialect, execute, depth) {
|
|
7858
8226
|
return __async(this, null, function* () {
|
|
8227
|
+
if (depth > MAX_RECURSIVE_DEPTH) {
|
|
8228
|
+
for (const parent of parentRows) {
|
|
8229
|
+
parent[segment.relationName] = segment.isList ? [] : null;
|
|
8230
|
+
}
|
|
8231
|
+
return;
|
|
8232
|
+
}
|
|
7859
8233
|
const parentIds = parentRows.map((r) => r[segment.parentKeyFieldName]).filter((v) => v != null);
|
|
7860
8234
|
if (parentIds.length === 0) {
|
|
7861
8235
|
for (const parent of parentRows) {
|
|
@@ -7875,23 +8249,41 @@ function executeSegmentBase(segment, parentRows, allModels, modelMap, dialect, e
|
|
|
7875
8249
|
}
|
|
7876
8250
|
const allChildRows = [];
|
|
7877
8251
|
let needsStripFk = false;
|
|
8252
|
+
let nestedSegments = [];
|
|
7878
8253
|
for (const chunk of chunks) {
|
|
7879
8254
|
const childArgs = buildChildArgs(
|
|
7880
8255
|
segment.relArgs,
|
|
7881
8256
|
segment.fkFieldName,
|
|
7882
8257
|
chunk
|
|
7883
8258
|
);
|
|
7884
|
-
const
|
|
8259
|
+
const childPlan = planQueryStrategy({
|
|
8260
|
+
model: childModel,
|
|
8261
|
+
args: childArgs,
|
|
8262
|
+
allModels});
|
|
8263
|
+
if (nestedSegments.length === 0 && childPlan.whereInSegments.length > 0) {
|
|
8264
|
+
nestedSegments = childPlan.whereInSegments;
|
|
8265
|
+
}
|
|
8266
|
+
const stripFk = ensureFkInSelect(
|
|
8267
|
+
childPlan.filteredArgs,
|
|
8268
|
+
segment.fkFieldName
|
|
8269
|
+
);
|
|
7885
8270
|
if (stripFk) needsStripFk = true;
|
|
7886
8271
|
const result = buildSQL(
|
|
7887
8272
|
childModel,
|
|
7888
8273
|
allModels,
|
|
7889
8274
|
"findMany",
|
|
7890
|
-
|
|
8275
|
+
childPlan.filteredArgs,
|
|
7891
8276
|
dialect
|
|
7892
8277
|
);
|
|
7893
8278
|
let rows = yield execute(result.sql, result.params);
|
|
7894
|
-
if (result.
|
|
8279
|
+
if (result.isArrayAgg && result.includeSpec) {
|
|
8280
|
+
const config = buildArrayAggReducerConfig(
|
|
8281
|
+
childModel,
|
|
8282
|
+
result.includeSpec,
|
|
8283
|
+
allModels
|
|
8284
|
+
);
|
|
8285
|
+
rows = reduceArrayAggRows(rows, config);
|
|
8286
|
+
} else if (result.requiresReduction && result.includeSpec) {
|
|
7895
8287
|
const config = buildReducerConfig(
|
|
7896
8288
|
childModel,
|
|
7897
8289
|
result.includeSpec,
|
|
@@ -7903,28 +8295,440 @@ function executeSegmentBase(segment, parentRows, allModels, modelMap, dialect, e
|
|
|
7903
8295
|
allChildRows.push(row);
|
|
7904
8296
|
}
|
|
7905
8297
|
}
|
|
8298
|
+
if (nestedSegments.length > 0 && allChildRows.length > 0) {
|
|
8299
|
+
for (const row of allChildRows) {
|
|
8300
|
+
for (const nestedSeg of nestedSegments) {
|
|
8301
|
+
row[nestedSeg.relationName] = nestedSeg.isList ? [] : null;
|
|
8302
|
+
}
|
|
8303
|
+
}
|
|
8304
|
+
yield resolveSegmentsIntelligent(
|
|
8305
|
+
nestedSegments,
|
|
8306
|
+
allChildRows,
|
|
8307
|
+
allModels,
|
|
8308
|
+
modelMap,
|
|
8309
|
+
dialect,
|
|
8310
|
+
execute,
|
|
8311
|
+
depth + 1
|
|
8312
|
+
);
|
|
8313
|
+
}
|
|
7906
8314
|
stitchResults(parentRows, segment, allChildRows, needsStripFk);
|
|
7907
8315
|
});
|
|
7908
8316
|
}
|
|
8317
|
+
function resolveSegmentsIntelligent(segments, parentRows, allModels, modelMap, dialect, execute, depth) {
|
|
8318
|
+
return __async(this, null, function* () {
|
|
8319
|
+
if (depth > MAX_RECURSIVE_DEPTH) return;
|
|
8320
|
+
if (segments.length === 0) return;
|
|
8321
|
+
if (segments.length === 1) {
|
|
8322
|
+
yield executeSingleSegment(
|
|
8323
|
+
segments[0],
|
|
8324
|
+
parentRows,
|
|
8325
|
+
allModels,
|
|
8326
|
+
modelMap,
|
|
8327
|
+
dialect,
|
|
8328
|
+
execute,
|
|
8329
|
+
depth
|
|
8330
|
+
);
|
|
8331
|
+
return;
|
|
8332
|
+
}
|
|
8333
|
+
yield Promise.all(
|
|
8334
|
+
segments.map(
|
|
8335
|
+
(seg) => executeSingleSegment(
|
|
8336
|
+
seg,
|
|
8337
|
+
parentRows,
|
|
8338
|
+
allModels,
|
|
8339
|
+
modelMap,
|
|
8340
|
+
dialect,
|
|
8341
|
+
execute,
|
|
8342
|
+
depth
|
|
8343
|
+
)
|
|
8344
|
+
)
|
|
8345
|
+
);
|
|
8346
|
+
});
|
|
8347
|
+
}
|
|
8348
|
+
function executeSegmentBase(segment, parentRows, allModels, modelMap, dialect, execute, depth = 0) {
|
|
8349
|
+
return __async(this, null, function* () {
|
|
8350
|
+
yield executeSingleSegment(
|
|
8351
|
+
segment,
|
|
8352
|
+
parentRows,
|
|
8353
|
+
allModels,
|
|
8354
|
+
modelMap,
|
|
8355
|
+
dialect,
|
|
8356
|
+
execute,
|
|
8357
|
+
depth
|
|
8358
|
+
);
|
|
8359
|
+
});
|
|
8360
|
+
}
|
|
7909
8361
|
|
|
7910
8362
|
// src/builder/where-in-executor.ts
|
|
8363
|
+
var ADAPTIVE_PARENT_THRESHOLD = 15;
|
|
8364
|
+
var ADAPTIVE_DEPTH_THRESHOLD = 2;
|
|
8365
|
+
function measureRelArgsDepth(relArgs) {
|
|
8366
|
+
if (!relArgs || relArgs === true || typeof relArgs !== "object") return 0;
|
|
8367
|
+
const args = relArgs;
|
|
8368
|
+
const nested = args.include || args.select;
|
|
8369
|
+
if (!nested || typeof nested !== "object") return 0;
|
|
8370
|
+
let maxChildDepth = 0;
|
|
8371
|
+
for (const val of Object.values(nested)) {
|
|
8372
|
+
if (val === false) continue;
|
|
8373
|
+
if (val === true) {
|
|
8374
|
+
maxChildDepth = Math.max(maxChildDepth, 1);
|
|
8375
|
+
continue;
|
|
8376
|
+
}
|
|
8377
|
+
if (val && typeof val === "object") {
|
|
8378
|
+
maxChildDepth = Math.max(maxChildDepth, 1 + measureRelArgsDepth(val));
|
|
8379
|
+
}
|
|
8380
|
+
}
|
|
8381
|
+
return maxChildDepth;
|
|
8382
|
+
}
|
|
8383
|
+
function measureSegmentNestingDepth(segments) {
|
|
8384
|
+
let maxDepth = 0;
|
|
8385
|
+
for (const seg of segments) {
|
|
8386
|
+
const depth = 1 + measureRelArgsDepth(seg.relArgs);
|
|
8387
|
+
maxDepth = Math.max(maxDepth, depth);
|
|
8388
|
+
}
|
|
8389
|
+
return maxDepth;
|
|
8390
|
+
}
|
|
8391
|
+
function shouldAdaptivelySwitch(actualParentCount, segments) {
|
|
8392
|
+
if (actualParentCount > ADAPTIVE_PARENT_THRESHOLD) return false;
|
|
8393
|
+
if (segments.length === 0) return false;
|
|
8394
|
+
const depth = measureSegmentNestingDepth(segments);
|
|
8395
|
+
return depth >= ADAPTIVE_DEPTH_THRESHOLD;
|
|
8396
|
+
}
|
|
8397
|
+
function executeCorrelatedFallback(parentRows, parentModel, allModels, dialect, execute, originalArgs, method, segments) {
|
|
8398
|
+
return __async(this, null, function* () {
|
|
8399
|
+
const pkField = getPrimaryKeyField(parentModel);
|
|
8400
|
+
const pks = parentRows.map((r) => r[pkField]).filter(Boolean);
|
|
8401
|
+
if (pks.length === 0) {
|
|
8402
|
+
for (const parent of parentRows) {
|
|
8403
|
+
for (const seg of segments) {
|
|
8404
|
+
parent[seg.relationName] = seg.isList ? [] : null;
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
8407
|
+
return;
|
|
8408
|
+
}
|
|
8409
|
+
const fallbackArgs = __spreadValues({}, originalArgs);
|
|
8410
|
+
delete fallbackArgs.take;
|
|
8411
|
+
delete fallbackArgs.skip;
|
|
8412
|
+
delete fallbackArgs.cursor;
|
|
8413
|
+
fallbackArgs.where = { [pkField]: { in: pks } };
|
|
8414
|
+
if (originalArgs.orderBy) {
|
|
8415
|
+
fallbackArgs.orderBy = originalArgs.orderBy;
|
|
8416
|
+
}
|
|
8417
|
+
const result = buildSQL(
|
|
8418
|
+
parentModel,
|
|
8419
|
+
allModels,
|
|
8420
|
+
method,
|
|
8421
|
+
fallbackArgs,
|
|
8422
|
+
dialect
|
|
8423
|
+
);
|
|
8424
|
+
let rows = yield execute(result.sql, result.params);
|
|
8425
|
+
if (result.isArrayAgg && result.includeSpec) {
|
|
8426
|
+
const config = buildArrayAggReducerConfig(
|
|
8427
|
+
parentModel,
|
|
8428
|
+
result.includeSpec,
|
|
8429
|
+
allModels
|
|
8430
|
+
);
|
|
8431
|
+
rows = reduceArrayAggRows(rows, config);
|
|
8432
|
+
} else if (result.requiresReduction && result.includeSpec) {
|
|
8433
|
+
const config = buildReducerConfig(
|
|
8434
|
+
parentModel,
|
|
8435
|
+
result.includeSpec,
|
|
8436
|
+
allModels
|
|
8437
|
+
);
|
|
8438
|
+
rows = reduceFlatRows(rows, config);
|
|
8439
|
+
}
|
|
8440
|
+
const rowsByPk = /* @__PURE__ */ new Map();
|
|
8441
|
+
for (const row of rows) {
|
|
8442
|
+
rowsByPk.set(row[pkField], row);
|
|
8443
|
+
}
|
|
8444
|
+
for (const parent of parentRows) {
|
|
8445
|
+
const pk = parent[pkField];
|
|
8446
|
+
const fullRow = rowsByPk.get(pk);
|
|
8447
|
+
if (fullRow) {
|
|
8448
|
+
for (const seg of segments) {
|
|
8449
|
+
parent[seg.relationName] = fullRow[seg.relationName];
|
|
8450
|
+
}
|
|
8451
|
+
} else {
|
|
8452
|
+
for (const seg of segments) {
|
|
8453
|
+
parent[seg.relationName] = seg.isList ? [] : null;
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8456
|
+
}
|
|
8457
|
+
});
|
|
8458
|
+
}
|
|
7911
8459
|
function executeWhereInSegments(params) {
|
|
7912
8460
|
return __async(this, null, function* () {
|
|
7913
|
-
const {
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
8461
|
+
const {
|
|
8462
|
+
segments,
|
|
8463
|
+
parentRows,
|
|
8464
|
+
parentModel,
|
|
8465
|
+
allModels,
|
|
8466
|
+
modelMap,
|
|
8467
|
+
dialect,
|
|
8468
|
+
execute,
|
|
8469
|
+
originalArgs,
|
|
8470
|
+
method
|
|
8471
|
+
} = params;
|
|
8472
|
+
if (originalArgs && method && parentModel && shouldAdaptivelySwitch(parentRows.length, segments)) {
|
|
8473
|
+
yield executeCorrelatedFallback(
|
|
8474
|
+
parentRows,
|
|
8475
|
+
parentModel,
|
|
8476
|
+
allModels,
|
|
8477
|
+
dialect,
|
|
8478
|
+
execute,
|
|
8479
|
+
originalArgs,
|
|
8480
|
+
method,
|
|
8481
|
+
segments
|
|
8482
|
+
);
|
|
8483
|
+
return;
|
|
8484
|
+
}
|
|
8485
|
+
if (segments.length === 1) {
|
|
7917
8486
|
yield executeSegmentBase(
|
|
7918
|
-
|
|
8487
|
+
segments[0],
|
|
8488
|
+
parentRows,
|
|
8489
|
+
allModels,
|
|
8490
|
+
modelMap,
|
|
8491
|
+
dialect,
|
|
8492
|
+
execute,
|
|
8493
|
+
0
|
|
8494
|
+
);
|
|
8495
|
+
return;
|
|
8496
|
+
}
|
|
8497
|
+
yield Promise.all(
|
|
8498
|
+
segments.map(
|
|
8499
|
+
(segment) => executeSegmentBase(
|
|
8500
|
+
segment,
|
|
8501
|
+
parentRows,
|
|
8502
|
+
allModels,
|
|
8503
|
+
modelMap,
|
|
8504
|
+
dialect,
|
|
8505
|
+
execute,
|
|
8506
|
+
0
|
|
8507
|
+
)
|
|
8508
|
+
)
|
|
8509
|
+
);
|
|
8510
|
+
});
|
|
8511
|
+
}
|
|
8512
|
+
|
|
8513
|
+
// src/builder/select/streaming-where-in-executor.ts
|
|
8514
|
+
var MAX_RECURSIVE_DEPTH2 = 10;
|
|
8515
|
+
function buildParentKeyIndex(parentRows, parentKeyFieldName) {
|
|
8516
|
+
const index = /* @__PURE__ */ new Map();
|
|
8517
|
+
for (const parent of parentRows) {
|
|
8518
|
+
const keyVal = parent[parentKeyFieldName];
|
|
8519
|
+
if (keyVal == null) continue;
|
|
8520
|
+
let arr = index.get(keyVal);
|
|
8521
|
+
if (!arr) {
|
|
8522
|
+
arr = [];
|
|
8523
|
+
index.set(keyVal, arr);
|
|
8524
|
+
}
|
|
8525
|
+
arr.push(parent);
|
|
8526
|
+
}
|
|
8527
|
+
return index;
|
|
8528
|
+
}
|
|
8529
|
+
function stitchChildrenToParents(children, segment, parentKeyIndex) {
|
|
8530
|
+
for (const child of children) {
|
|
8531
|
+
const childKey = child[segment.fkFieldName];
|
|
8532
|
+
const matchingParents = parentKeyIndex.get(childKey);
|
|
8533
|
+
if (!matchingParents) continue;
|
|
8534
|
+
for (const parent of matchingParents) {
|
|
8535
|
+
if (segment.isList) {
|
|
8536
|
+
if (!Array.isArray(parent[segment.relationName])) {
|
|
8537
|
+
parent[segment.relationName] = [];
|
|
8538
|
+
}
|
|
8539
|
+
parent[segment.relationName].push(child);
|
|
8540
|
+
} else {
|
|
8541
|
+
parent[segment.relationName] = child;
|
|
8542
|
+
}
|
|
8543
|
+
}
|
|
8544
|
+
}
|
|
8545
|
+
}
|
|
8546
|
+
function ensureFkInSelect2(childArgs, fkFieldName) {
|
|
8547
|
+
if (!childArgs.select) return false;
|
|
8548
|
+
if (childArgs.select[fkFieldName]) return false;
|
|
8549
|
+
childArgs.select = __spreadProps(__spreadValues({}, childArgs.select), { [fkFieldName]: true });
|
|
8550
|
+
return true;
|
|
8551
|
+
}
|
|
8552
|
+
function executeWhereInSegmentsStreaming(params) {
|
|
8553
|
+
return __async(this, null, function* () {
|
|
8554
|
+
const {
|
|
8555
|
+
segments,
|
|
8556
|
+
parentSql,
|
|
8557
|
+
parentParams,
|
|
8558
|
+
parentModel,
|
|
8559
|
+
allModels,
|
|
8560
|
+
modelMap,
|
|
8561
|
+
dialect,
|
|
8562
|
+
execute
|
|
8563
|
+
} = params;
|
|
8564
|
+
if (segments.length === 0) {
|
|
8565
|
+
throw new Error("executeWhereInSegmentsStreaming requires segments");
|
|
8566
|
+
}
|
|
8567
|
+
if (dialect !== "postgres") {
|
|
8568
|
+
throw new Error("Streaming WHERE IN requires postgres dialect");
|
|
8569
|
+
}
|
|
8570
|
+
const parentRows = yield execute(parentSql, parentParams);
|
|
8571
|
+
if (parentRows.length === 0) return [];
|
|
8572
|
+
for (const row of parentRows) {
|
|
8573
|
+
for (const seg of segments) {
|
|
8574
|
+
row[seg.relationName] = seg.isList ? [] : null;
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
yield resolveSegments(
|
|
8578
|
+
segments,
|
|
8579
|
+
parentRows,
|
|
8580
|
+
allModels,
|
|
8581
|
+
modelMap,
|
|
8582
|
+
dialect,
|
|
8583
|
+
execute,
|
|
8584
|
+
0
|
|
8585
|
+
);
|
|
8586
|
+
return parentRows;
|
|
8587
|
+
});
|
|
8588
|
+
}
|
|
8589
|
+
function executeWithPreFetchedParents(params) {
|
|
8590
|
+
return __async(this, null, function* () {
|
|
8591
|
+
const {
|
|
8592
|
+
segments,
|
|
8593
|
+
parentRows,
|
|
8594
|
+
parentModel,
|
|
8595
|
+
allModels,
|
|
8596
|
+
modelMap,
|
|
8597
|
+
dialect,
|
|
8598
|
+
execute
|
|
8599
|
+
} = params;
|
|
8600
|
+
if (segments.length === 0) return parentRows;
|
|
8601
|
+
if (parentRows.length === 0) return [];
|
|
8602
|
+
for (const row of parentRows) {
|
|
8603
|
+
for (const seg of segments) {
|
|
8604
|
+
row[seg.relationName] = seg.isList ? [] : null;
|
|
8605
|
+
}
|
|
8606
|
+
}
|
|
8607
|
+
yield resolveSegments(
|
|
8608
|
+
segments,
|
|
8609
|
+
parentRows,
|
|
8610
|
+
allModels,
|
|
8611
|
+
modelMap,
|
|
8612
|
+
dialect,
|
|
8613
|
+
execute,
|
|
8614
|
+
0
|
|
8615
|
+
);
|
|
8616
|
+
return parentRows;
|
|
8617
|
+
});
|
|
8618
|
+
}
|
|
8619
|
+
function resolveSegments(segments, parentRows, allModels, modelMap, dialect, execute, depth) {
|
|
8620
|
+
return __async(this, null, function* () {
|
|
8621
|
+
if (depth > MAX_RECURSIVE_DEPTH2) return;
|
|
8622
|
+
if (segments.length === 0) return;
|
|
8623
|
+
if (segments.length === 1) {
|
|
8624
|
+
yield resolveSingleSegment(
|
|
8625
|
+
segments[0],
|
|
7919
8626
|
parentRows,
|
|
7920
8627
|
allModels,
|
|
7921
8628
|
modelMap,
|
|
7922
8629
|
dialect,
|
|
7923
|
-
execute
|
|
8630
|
+
execute,
|
|
8631
|
+
depth
|
|
8632
|
+
);
|
|
8633
|
+
return;
|
|
8634
|
+
}
|
|
8635
|
+
yield Promise.all(
|
|
8636
|
+
segments.map(
|
|
8637
|
+
(seg) => resolveSingleSegment(
|
|
8638
|
+
seg,
|
|
8639
|
+
parentRows,
|
|
8640
|
+
allModels,
|
|
8641
|
+
modelMap,
|
|
8642
|
+
dialect,
|
|
8643
|
+
execute,
|
|
8644
|
+
depth
|
|
8645
|
+
)
|
|
8646
|
+
)
|
|
8647
|
+
);
|
|
8648
|
+
});
|
|
8649
|
+
}
|
|
8650
|
+
function resolveSingleSegment(segment, parentRows, allModels, modelMap, dialect, execute, depth) {
|
|
8651
|
+
return __async(this, null, function* () {
|
|
8652
|
+
const childModel = modelMap.get(segment.childModelName);
|
|
8653
|
+
if (!childModel) {
|
|
8654
|
+
return;
|
|
8655
|
+
}
|
|
8656
|
+
const parentIds = parentRows.map((r) => r[segment.parentKeyFieldName]).filter((v) => v != null);
|
|
8657
|
+
if (parentIds.length === 0) {
|
|
8658
|
+
return;
|
|
8659
|
+
}
|
|
8660
|
+
const uniqueIds = [...new Set(parentIds)];
|
|
8661
|
+
const childArgs = buildChildArgs2(
|
|
8662
|
+
segment.relArgs,
|
|
8663
|
+
segment.fkFieldName,
|
|
8664
|
+
uniqueIds
|
|
8665
|
+
);
|
|
8666
|
+
const needsStripFk = ensureFkInSelect2(childArgs, segment.fkFieldName);
|
|
8667
|
+
const childPlan = planQueryStrategy({
|
|
8668
|
+
model: childModel,
|
|
8669
|
+
args: childArgs,
|
|
8670
|
+
allModels});
|
|
8671
|
+
const result = buildSQL(
|
|
8672
|
+
childModel,
|
|
8673
|
+
allModels,
|
|
8674
|
+
"findMany",
|
|
8675
|
+
childPlan.filteredArgs,
|
|
8676
|
+
dialect
|
|
8677
|
+
);
|
|
8678
|
+
let children = yield execute(result.sql, result.params);
|
|
8679
|
+
if (result.isArrayAgg && result.includeSpec) {
|
|
8680
|
+
const config = buildArrayAggReducerConfig(
|
|
8681
|
+
childModel,
|
|
8682
|
+
result.includeSpec,
|
|
8683
|
+
allModels
|
|
8684
|
+
);
|
|
8685
|
+
children = reduceArrayAggRows(children, config);
|
|
8686
|
+
} else if (result.requiresReduction && result.includeSpec) {
|
|
8687
|
+
const config = buildReducerConfig(childModel, result.includeSpec, allModels);
|
|
8688
|
+
children = reduceFlatRows(children, config);
|
|
8689
|
+
}
|
|
8690
|
+
if (childPlan.whereInSegments.length > 0 && children.length > 0) {
|
|
8691
|
+
for (const child of children) {
|
|
8692
|
+
for (const nestedSeg of childPlan.whereInSegments) {
|
|
8693
|
+
child[nestedSeg.relationName] = nestedSeg.isList ? [] : null;
|
|
8694
|
+
}
|
|
8695
|
+
}
|
|
8696
|
+
yield resolveSegments(
|
|
8697
|
+
childPlan.whereInSegments,
|
|
8698
|
+
children,
|
|
8699
|
+
allModels,
|
|
8700
|
+
modelMap,
|
|
8701
|
+
dialect,
|
|
8702
|
+
execute,
|
|
8703
|
+
depth + 1
|
|
7924
8704
|
);
|
|
8705
|
+
if (childPlan.injectedParentKeys.length > 0) {
|
|
8706
|
+
for (const child of children) {
|
|
8707
|
+
for (const key of childPlan.injectedParentKeys) {
|
|
8708
|
+
delete child[key];
|
|
8709
|
+
}
|
|
8710
|
+
}
|
|
8711
|
+
}
|
|
8712
|
+
}
|
|
8713
|
+
const parentKeyIndex = buildParentKeyIndex(
|
|
8714
|
+
parentRows,
|
|
8715
|
+
segment.parentKeyFieldName
|
|
8716
|
+
);
|
|
8717
|
+
stitchChildrenToParents(children, segment, parentKeyIndex);
|
|
8718
|
+
if (needsStripFk) {
|
|
8719
|
+
for (const child of children) {
|
|
8720
|
+
delete child[segment.fkFieldName];
|
|
8721
|
+
}
|
|
7925
8722
|
}
|
|
7926
8723
|
});
|
|
7927
8724
|
}
|
|
8725
|
+
function buildChildArgs2(relArgs, fkFieldName, parentIds) {
|
|
8726
|
+
const base = relArgs === true || typeof relArgs !== "object" || relArgs === null ? {} : __spreadValues({}, relArgs);
|
|
8727
|
+
const existingWhere = base.where;
|
|
8728
|
+
const inCondition = { [fkFieldName]: { in: parentIds } };
|
|
8729
|
+
base.where = existingWhere ? { AND: [existingWhere, inCondition] } : inCondition;
|
|
8730
|
+
return base;
|
|
8731
|
+
}
|
|
7928
8732
|
|
|
7929
8733
|
// src/builder/select/core-reducer.ts
|
|
7930
8734
|
var getOrCreateRelationMap = (relationMaps, parent) => {
|
|
@@ -7967,10 +8771,6 @@ var createChildObject = (row, rel) => {
|
|
|
7967
8771
|
}
|
|
7968
8772
|
return child;
|
|
7969
8773
|
};
|
|
7970
|
-
var extractChildKey = (row, rel) => {
|
|
7971
|
-
const cols = rel.primaryKeyFields.map((f) => `${rel.path}.${f}`);
|
|
7972
|
-
return buildCompositeKey(row, cols);
|
|
7973
|
-
};
|
|
7974
8774
|
var attachChildToParent = (parent, child, rel) => {
|
|
7975
8775
|
if (rel.cardinality === "many") {
|
|
7976
8776
|
parent[rel.name].push(child);
|
|
@@ -7978,17 +8778,25 @@ var attachChildToParent = (parent, child, rel) => {
|
|
|
7978
8778
|
parent[rel.name] = child;
|
|
7979
8779
|
}
|
|
7980
8780
|
};
|
|
8781
|
+
function prepareRelations(relations) {
|
|
8782
|
+
return relations.map((rel) => ({
|
|
8783
|
+
rel,
|
|
8784
|
+
prefixedPkFields: rel.primaryKeyFields.map((f) => `${rel.path}.${f}`),
|
|
8785
|
+
nested: rel.nestedIncludes ? prepareRelations(rel.nestedIncludes.includedRelations) : null
|
|
8786
|
+
}));
|
|
8787
|
+
}
|
|
7981
8788
|
var createRelationProcessor = (relationMaps) => {
|
|
7982
|
-
const processRelation2 = (parent,
|
|
7983
|
-
const
|
|
7984
|
-
|
|
8789
|
+
const processRelation2 = (parent, prepared, row) => {
|
|
8790
|
+
const { rel, prefixedPkFields, nested } = prepared;
|
|
8791
|
+
const childKey = buildKey(row, prefixedPkFields);
|
|
8792
|
+
if (childKey == null) return;
|
|
7985
8793
|
const relMap = getOrCreateRelationMap(relationMaps, parent);
|
|
7986
8794
|
const childMap = getOrCreateChildMap(relMap, rel.path);
|
|
7987
8795
|
if (childMap.has(childKey)) {
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
for (const
|
|
7991
|
-
processRelation2(existing,
|
|
8796
|
+
if (nested) {
|
|
8797
|
+
const existing = childMap.get(childKey);
|
|
8798
|
+
for (const nestedPrepared of nested) {
|
|
8799
|
+
processRelation2(existing, nestedPrepared, row);
|
|
7992
8800
|
}
|
|
7993
8801
|
}
|
|
7994
8802
|
return;
|
|
@@ -7996,9 +8804,9 @@ var createRelationProcessor = (relationMaps) => {
|
|
|
7996
8804
|
const child = createChildObject(row, rel);
|
|
7997
8805
|
childMap.set(childKey, child);
|
|
7998
8806
|
attachChildToParent(parent, child, rel);
|
|
7999
|
-
if (
|
|
8000
|
-
for (const
|
|
8001
|
-
processRelation2(child,
|
|
8807
|
+
if (nested) {
|
|
8808
|
+
for (const nestedPrepared of nested) {
|
|
8809
|
+
processRelation2(child, nestedPrepared, row);
|
|
8002
8810
|
}
|
|
8003
8811
|
}
|
|
8004
8812
|
};
|
|
@@ -8011,31 +8819,28 @@ var createCoreReducer = (config) => {
|
|
|
8011
8819
|
const jsonSet = getJsonFieldSet(config.parentModel);
|
|
8012
8820
|
const parentPkFields = getPrimaryKeyFields(config.parentModel);
|
|
8013
8821
|
const includedRelations = config.includedRelations;
|
|
8014
|
-
const
|
|
8822
|
+
const preparedRelations = prepareRelations(includedRelations);
|
|
8015
8823
|
const processRelation2 = createRelationProcessor(relationMaps);
|
|
8016
8824
|
const processRow = (row) => {
|
|
8017
|
-
const parentKey =
|
|
8018
|
-
if (
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
})();
|
|
8029
|
-
for (const rel of includedRelations) {
|
|
8030
|
-
processRelation2(parent, rel, row);
|
|
8825
|
+
const parentKey = buildKey(row, parentPkFields);
|
|
8826
|
+
if (parentKey == null) return null;
|
|
8827
|
+
let parent;
|
|
8828
|
+
if (parentMap.has(parentKey)) {
|
|
8829
|
+
parent = parentMap.get(parentKey);
|
|
8830
|
+
} else {
|
|
8831
|
+
parent = createParentObject(row, scalarFields, jsonSet, includedRelations);
|
|
8832
|
+
parentMap.set(parentKey, parent);
|
|
8833
|
+
}
|
|
8834
|
+
for (const prepared of preparedRelations) {
|
|
8835
|
+
processRelation2(parent, prepared, row);
|
|
8031
8836
|
}
|
|
8032
8837
|
return parentKey;
|
|
8033
8838
|
};
|
|
8034
8839
|
return {
|
|
8035
8840
|
processRow,
|
|
8036
8841
|
getParent: (key) => {
|
|
8037
|
-
var
|
|
8038
|
-
return (
|
|
8842
|
+
var _a3;
|
|
8843
|
+
return (_a3 = parentMap.get(key)) != null ? _a3 : null;
|
|
8039
8844
|
},
|
|
8040
8845
|
getAllParents: () => Array.from(parentMap.values()),
|
|
8041
8846
|
getParentMap: () => parentMap
|
|
@@ -8095,135 +8900,9 @@ function createProgressiveReducer(config) {
|
|
|
8095
8900
|
};
|
|
8096
8901
|
}
|
|
8097
8902
|
|
|
8098
|
-
// src/builder/select/streaming-where-in-executor.ts
|
|
8099
|
-
function executeWhereInSegmentsStreaming(params) {
|
|
8100
|
-
return __async(this, null, function* () {
|
|
8101
|
-
const {
|
|
8102
|
-
segments,
|
|
8103
|
-
parentSql,
|
|
8104
|
-
parentParams,
|
|
8105
|
-
parentModel,
|
|
8106
|
-
allModels,
|
|
8107
|
-
modelMap,
|
|
8108
|
-
dialect,
|
|
8109
|
-
execute,
|
|
8110
|
-
batchSize = 100,
|
|
8111
|
-
maxConcurrency = 10
|
|
8112
|
-
} = params;
|
|
8113
|
-
if (segments.length === 0) {
|
|
8114
|
-
throw new Error("executeWhereInSegmentsStreaming requires segments");
|
|
8115
|
-
}
|
|
8116
|
-
if (dialect !== "postgres") {
|
|
8117
|
-
throw new Error("Streaming WHERE IN requires postgres dialect");
|
|
8118
|
-
}
|
|
8119
|
-
const parentMap = /* @__PURE__ */ new Map();
|
|
8120
|
-
const batches = /* @__PURE__ */ new Map();
|
|
8121
|
-
const inFlightMap = /* @__PURE__ */ new Map();
|
|
8122
|
-
for (const seg of segments) {
|
|
8123
|
-
batches.set(seg.relationName, []);
|
|
8124
|
-
}
|
|
8125
|
-
const pkField = getPrimaryKeyField(parentModel);
|
|
8126
|
-
const parentRows = yield execute(parentSql, parentParams);
|
|
8127
|
-
for (const row of parentRows) {
|
|
8128
|
-
const pk = row[pkField];
|
|
8129
|
-
parentMap.set(pk, __spreadValues({}, row));
|
|
8130
|
-
for (const seg of segments) {
|
|
8131
|
-
row[seg.relationName] = seg.isList ? [] : null;
|
|
8132
|
-
}
|
|
8133
|
-
for (const seg of segments) {
|
|
8134
|
-
const batch = batches.get(seg.relationName);
|
|
8135
|
-
const parentKey = row[seg.parentKeyFieldName];
|
|
8136
|
-
batch.push(parentKey);
|
|
8137
|
-
if (batch.length >= batchSize) {
|
|
8138
|
-
const idsToFetch = [...batch];
|
|
8139
|
-
batch.length = 0;
|
|
8140
|
-
const promise = fetchAndAttachChildren(
|
|
8141
|
-
seg,
|
|
8142
|
-
idsToFetch,
|
|
8143
|
-
parentMap,
|
|
8144
|
-
allModels,
|
|
8145
|
-
modelMap,
|
|
8146
|
-
dialect,
|
|
8147
|
-
execute
|
|
8148
|
-
);
|
|
8149
|
-
inFlightMap.set(promise, seg.relationName);
|
|
8150
|
-
promise.finally(() => {
|
|
8151
|
-
inFlightMap.delete(promise);
|
|
8152
|
-
});
|
|
8153
|
-
if (inFlightMap.size >= maxConcurrency) {
|
|
8154
|
-
yield Promise.race(inFlightMap.keys());
|
|
8155
|
-
}
|
|
8156
|
-
}
|
|
8157
|
-
}
|
|
8158
|
-
}
|
|
8159
|
-
for (const seg of segments) {
|
|
8160
|
-
const batch = batches.get(seg.relationName);
|
|
8161
|
-
if (batch.length > 0) {
|
|
8162
|
-
const promise = fetchAndAttachChildren(
|
|
8163
|
-
seg,
|
|
8164
|
-
batch,
|
|
8165
|
-
parentMap,
|
|
8166
|
-
allModels,
|
|
8167
|
-
modelMap,
|
|
8168
|
-
dialect,
|
|
8169
|
-
execute
|
|
8170
|
-
);
|
|
8171
|
-
inFlightMap.set(promise, seg.relationName);
|
|
8172
|
-
promise.finally(() => {
|
|
8173
|
-
inFlightMap.delete(promise);
|
|
8174
|
-
});
|
|
8175
|
-
}
|
|
8176
|
-
}
|
|
8177
|
-
yield Promise.all(inFlightMap.keys());
|
|
8178
|
-
return Array.from(parentMap.values());
|
|
8179
|
-
});
|
|
8180
|
-
}
|
|
8181
|
-
function fetchAndAttachChildren(segment, parentIds, parentMap, allModels, modelMap, dialect, execute) {
|
|
8182
|
-
return __async(this, null, function* () {
|
|
8183
|
-
const childModel = modelMap.get(segment.childModelName);
|
|
8184
|
-
if (!childModel) return;
|
|
8185
|
-
const childArgs = buildChildArgs2(
|
|
8186
|
-
segment.relArgs,
|
|
8187
|
-
segment.fkFieldName,
|
|
8188
|
-
parentIds
|
|
8189
|
-
);
|
|
8190
|
-
const result = buildSQL(
|
|
8191
|
-
childModel,
|
|
8192
|
-
allModels,
|
|
8193
|
-
"findMany",
|
|
8194
|
-
childArgs,
|
|
8195
|
-
dialect
|
|
8196
|
-
);
|
|
8197
|
-
let children = yield execute(result.sql, result.params);
|
|
8198
|
-
if (result.requiresReduction && result.includeSpec) {
|
|
8199
|
-
const config = buildReducerConfig(childModel, result.includeSpec, allModels);
|
|
8200
|
-
children = reduceFlatRows(children, config);
|
|
8201
|
-
}
|
|
8202
|
-
for (const child of children) {
|
|
8203
|
-
const fkValue = child[segment.fkFieldName];
|
|
8204
|
-
const parent = parentMap.get(fkValue);
|
|
8205
|
-
if (!parent) continue;
|
|
8206
|
-
if (segment.isList) {
|
|
8207
|
-
if (!Array.isArray(parent[segment.relationName])) {
|
|
8208
|
-
parent[segment.relationName] = [];
|
|
8209
|
-
}
|
|
8210
|
-
parent[segment.relationName].push(child);
|
|
8211
|
-
} else {
|
|
8212
|
-
parent[segment.relationName] = child;
|
|
8213
|
-
}
|
|
8214
|
-
}
|
|
8215
|
-
});
|
|
8216
|
-
}
|
|
8217
|
-
function buildChildArgs2(relArgs, fkFieldName, parentIds) {
|
|
8218
|
-
const base = relArgs === true || typeof relArgs !== "object" || relArgs === null ? {} : __spreadValues({}, relArgs);
|
|
8219
|
-
const existingWhere = base.where;
|
|
8220
|
-
const inCondition = { [fkFieldName]: { in: parentIds } };
|
|
8221
|
-
base.where = existingWhere ? { AND: [existingWhere, inCondition] } : inCondition;
|
|
8222
|
-
return base;
|
|
8223
|
-
}
|
|
8224
|
-
|
|
8225
8903
|
// src/generated-runtime.ts
|
|
8226
8904
|
var SQLITE_STMT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
8905
|
+
var STMT_CACHE_LIMIT = 1e3;
|
|
8227
8906
|
function getOrPrepareStatement(client, sql) {
|
|
8228
8907
|
let cache = SQLITE_STMT_CACHE.get(client);
|
|
8229
8908
|
if (!cache) {
|
|
@@ -8231,13 +8910,16 @@ function getOrPrepareStatement(client, sql) {
|
|
|
8231
8910
|
SQLITE_STMT_CACHE.set(client, cache);
|
|
8232
8911
|
}
|
|
8233
8912
|
let stmt = cache.get(sql);
|
|
8234
|
-
if (
|
|
8235
|
-
|
|
8913
|
+
if (stmt) {
|
|
8914
|
+
cache.delete(sql);
|
|
8236
8915
|
cache.set(sql, stmt);
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8916
|
+
return stmt;
|
|
8917
|
+
}
|
|
8918
|
+
stmt = client.prepare(sql);
|
|
8919
|
+
cache.set(sql, stmt);
|
|
8920
|
+
if (cache.size > STMT_CACHE_LIMIT) {
|
|
8921
|
+
const firstKey = cache.keys().next().value;
|
|
8922
|
+
cache.delete(firstKey);
|
|
8241
8923
|
}
|
|
8242
8924
|
return stmt;
|
|
8243
8925
|
}
|
|
@@ -8247,22 +8929,44 @@ function shouldSqliteUseGet(method) {
|
|
|
8247
8929
|
function normalizeParams(params) {
|
|
8248
8930
|
return params.map((p) => normalizeValue(p));
|
|
8249
8931
|
}
|
|
8250
|
-
function executePostgresQuery(client, sql, params, method, requiresReduction, includeSpec, model, allModels) {
|
|
8932
|
+
function executePostgresQuery(client, sql, params, method, requiresReduction, includeSpec, model, allModels, isArrayAgg) {
|
|
8251
8933
|
return __async(this, null, function* () {
|
|
8252
8934
|
const normalizedParams = normalizeParams(params);
|
|
8253
|
-
|
|
8935
|
+
if (isArrayAgg && includeSpec) {
|
|
8936
|
+
const config = buildArrayAggReducerConfig(model, includeSpec, allModels);
|
|
8937
|
+
const results2 = [];
|
|
8938
|
+
yield client.unsafe(sql, normalizedParams).forEach((row) => {
|
|
8939
|
+
results2.push(row);
|
|
8940
|
+
});
|
|
8941
|
+
return reduceArrayAggRows(results2, config);
|
|
8942
|
+
}
|
|
8254
8943
|
if (requiresReduction && includeSpec) {
|
|
8255
8944
|
const config = buildReducerConfig(model, includeSpec, allModels);
|
|
8256
8945
|
const reducer = createStreamingReducer(config);
|
|
8257
8946
|
yield client.unsafe(sql, normalizedParams).forEach((row) => {
|
|
8258
|
-
reducer.processRow(
|
|
8947
|
+
reducer.processRow(row);
|
|
8259
8948
|
});
|
|
8260
8949
|
return reducer.getResults();
|
|
8261
8950
|
}
|
|
8951
|
+
const needsTransform = method === "groupBy" || method === "aggregate" || method === "count";
|
|
8952
|
+
if (!needsTransform) {
|
|
8953
|
+
const results2 = [];
|
|
8954
|
+
yield client.unsafe(sql, normalizedParams).forEach((row) => {
|
|
8955
|
+
results2.push(row);
|
|
8956
|
+
});
|
|
8957
|
+
return results2;
|
|
8958
|
+
}
|
|
8959
|
+
const rowTransformer = getRowTransformer(method);
|
|
8262
8960
|
const results = [];
|
|
8263
|
-
|
|
8264
|
-
|
|
8265
|
-
|
|
8961
|
+
if (rowTransformer) {
|
|
8962
|
+
yield client.unsafe(sql, normalizedParams).forEach((row) => {
|
|
8963
|
+
results.push(rowTransformer(row));
|
|
8964
|
+
});
|
|
8965
|
+
} else {
|
|
8966
|
+
yield client.unsafe(sql, normalizedParams).forEach((row) => {
|
|
8967
|
+
results.push(row);
|
|
8968
|
+
});
|
|
8969
|
+
}
|
|
8266
8970
|
return results;
|
|
8267
8971
|
});
|
|
8268
8972
|
}
|
|
@@ -8396,6 +9100,6 @@ function generateSQLByModel(directives) {
|
|
|
8396
9100
|
return byModel;
|
|
8397
9101
|
}
|
|
8398
9102
|
|
|
8399
|
-
export { buildBatchCountSql, buildBatchSql, buildReducerConfig, buildSQL, createPrismaSQL, createProgressiveReducer, createStreamingReducer, createToSQL, createTransactionExecutor, executePostgresQuery, executeRaw, executeSqliteQuery, executeWhereInSegments, executeWhereInSegmentsStreaming, extractCountValue, generateAllSQL, generateSQL2 as generateSQL, generateSQLByModel, getOrPrepareStatement, getRowTransformer, normalizeParams, normalizeValue, parseBatchCountResults, parseBatchResults, planQueryStrategy, reduceFlatRows, shouldSqliteUseGet, transformAggregateRow, transformQueryResults };
|
|
9103
|
+
export { buildArrayAggReducerConfig, buildBatchCountSql, buildBatchSql, buildReducerConfig, buildSQL, createPrismaSQL, createProgressiveReducer, createStreamingReducer, createToSQL, createTransactionExecutor, executePostgresQuery, executeRaw, executeSqliteQuery, executeWhereInSegments, executeWhereInSegmentsStreaming, executeWithPreFetchedParents, extractCountValue, generateAllSQL, generateSQL2 as generateSQL, generateSQLByModel, getOrPrepareStatement, getPrimaryKeyField, getRowTransformer, normalizeParams, normalizeValue, parseBatchCountResults, parseBatchResults, planQueryStrategy, reduceArrayAggRows, reduceFlatRows, shouldSqliteUseGet, transformAggregateRow, transformQueryResults };
|
|
8400
9104
|
//# sourceMappingURL=index.js.map
|
|
8401
9105
|
//# sourceMappingURL=index.js.map
|