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