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/generator.js
CHANGED
|
@@ -2312,7 +2312,7 @@ var require_package = __commonJS({
|
|
|
2312
2312
|
"package.json"(exports$1, module) {
|
|
2313
2313
|
module.exports = {
|
|
2314
2314
|
name: "prisma-sql",
|
|
2315
|
-
version: "1.
|
|
2315
|
+
version: "1.68.0",
|
|
2316
2316
|
description: "Convert Prisma queries to optimized SQL with type safety. 2-7x faster than Prisma Client.",
|
|
2317
2317
|
main: "dist/index.cjs",
|
|
2318
2318
|
module: "dist/index.js",
|
|
@@ -2793,6 +2793,8 @@ var LIMITS = Object.freeze({
|
|
|
2793
2793
|
MAX_STRING_LENGTH: 1e4,
|
|
2794
2794
|
MAX_HAVING_DEPTH: 50
|
|
2795
2795
|
});
|
|
2796
|
+
var _a;
|
|
2797
|
+
var DEBUG_PARAMS = typeof process !== "undefined" && ((_a = process.env) == null ? void 0 : _a.DEBUG_PARAMS) === "1";
|
|
2796
2798
|
|
|
2797
2799
|
// src/builder/shared/validators/type-guards.ts
|
|
2798
2800
|
function isNotNullish(value) {
|
|
@@ -3336,7 +3338,7 @@ function normalizeField(field) {
|
|
|
3336
3338
|
return field;
|
|
3337
3339
|
}
|
|
3338
3340
|
function getFieldIndices(model) {
|
|
3339
|
-
var
|
|
3341
|
+
var _a3;
|
|
3340
3342
|
let cached = FIELD_INDICES_CACHE.get(model);
|
|
3341
3343
|
if (cached) return cached;
|
|
3342
3344
|
const scalarFields = /* @__PURE__ */ new Map();
|
|
@@ -3355,7 +3357,7 @@ function getFieldIndices(model) {
|
|
|
3355
3357
|
} else {
|
|
3356
3358
|
scalarFields.set(field.name, field);
|
|
3357
3359
|
scalarNames.push(field.name);
|
|
3358
|
-
const fieldType = String((
|
|
3360
|
+
const fieldType = String((_a3 = field.type) != null ? _a3 : "").toLowerCase();
|
|
3359
3361
|
if (fieldType === "json") {
|
|
3360
3362
|
jsonFields.add(field.name);
|
|
3361
3363
|
}
|
|
@@ -3453,13 +3455,13 @@ function getModelByName(schemas, name) {
|
|
|
3453
3455
|
return schemas.find((m) => m.name === name);
|
|
3454
3456
|
}
|
|
3455
3457
|
function normalizeIntLike(name, v, opts = {}) {
|
|
3456
|
-
var
|
|
3458
|
+
var _a3, _b;
|
|
3457
3459
|
if (!isNotNullish(v)) return void 0;
|
|
3458
3460
|
if (isDynamicParameter(v)) return v;
|
|
3459
3461
|
if (typeof v !== "number" || !Number.isFinite(v) || !Number.isInteger(v)) {
|
|
3460
3462
|
throw new Error(`${name} must be an integer`);
|
|
3461
3463
|
}
|
|
3462
|
-
const min = (
|
|
3464
|
+
const min = (_a3 = opts.min) != null ? _a3 : 0;
|
|
3463
3465
|
const allowZero = (_b = opts.allowZero) != null ? _b : true;
|
|
3464
3466
|
if (!allowZero && v === 0) {
|
|
3465
3467
|
throw new Error(`${name} must be > 0`);
|
|
@@ -3481,7 +3483,9 @@ function scopeName(scope, dynamicName) {
|
|
|
3481
3483
|
function addAutoScoped(params, value, scope) {
|
|
3482
3484
|
if (isDynamicParameter(value)) {
|
|
3483
3485
|
const dn = extractDynamicName(value);
|
|
3484
|
-
|
|
3486
|
+
if (DEBUG_PARAMS) {
|
|
3487
|
+
console.log(`[PARAM] ${scope} = ${JSON.stringify(value)}`);
|
|
3488
|
+
}
|
|
3485
3489
|
return params.add(void 0, scopeName(scope, dn));
|
|
3486
3490
|
}
|
|
3487
3491
|
return params.add(value);
|
|
@@ -3922,7 +3926,7 @@ function assertCursorAndOrderFieldsScalar(model, cursor, orderEntries) {
|
|
|
3922
3926
|
}
|
|
3923
3927
|
}
|
|
3924
3928
|
function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect, model) {
|
|
3925
|
-
var
|
|
3929
|
+
var _a3;
|
|
3926
3930
|
assertSafeTableRef(tableName);
|
|
3927
3931
|
assertSafeAlias(alias);
|
|
3928
3932
|
const d = dialect != null ? dialect : getGlobalDialect();
|
|
@@ -3937,6 +3941,33 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
3937
3941
|
}
|
|
3938
3942
|
if (cursorEntries.length === 0)
|
|
3939
3943
|
throw new Error("cursor must have at least one field with defined value");
|
|
3944
|
+
const orderEntries = normalizeAndValidateOrderBy(
|
|
3945
|
+
orderBy,
|
|
3946
|
+
model,
|
|
3947
|
+
parseOrderByValue
|
|
3948
|
+
);
|
|
3949
|
+
if (cursorEntries.length === 1 && orderEntries.length === 0) {
|
|
3950
|
+
const [field, value] = cursorEntries[0];
|
|
3951
|
+
const ph = addAutoScoped(params, value, `cursor.${field}`);
|
|
3952
|
+
const c = col(alias, field, model);
|
|
3953
|
+
return {
|
|
3954
|
+
cte: "",
|
|
3955
|
+
condition: `${c} >= ${ph}`
|
|
3956
|
+
};
|
|
3957
|
+
}
|
|
3958
|
+
if (cursorEntries.length === 1 && orderEntries.length === 1) {
|
|
3959
|
+
const [cursorField, cursorValue] = cursorEntries[0];
|
|
3960
|
+
const orderEntry = orderEntries[0];
|
|
3961
|
+
if (orderEntry.field === cursorField) {
|
|
3962
|
+
const ph = addAutoScoped(params, cursorValue, `cursor.${cursorField}`);
|
|
3963
|
+
const c = col(alias, cursorField, model);
|
|
3964
|
+
const op = orderEntry.direction === "asc" ? ">=" : "<=";
|
|
3965
|
+
return {
|
|
3966
|
+
cte: "",
|
|
3967
|
+
condition: `${c} ${op} ${ph}`
|
|
3968
|
+
};
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3940
3971
|
const { cteName, srcAlias } = buildCursorNames(alias);
|
|
3941
3972
|
assertSafeAlias(cteName);
|
|
3942
3973
|
assertSafeAlias(srcAlias);
|
|
@@ -3945,49 +3976,52 @@ function buildCursorCondition(cursor, orderBy, tableName, alias, params, dialect
|
|
|
3945
3976
|
model,
|
|
3946
3977
|
parseValue: parseOrderByValue
|
|
3947
3978
|
});
|
|
3948
|
-
let
|
|
3979
|
+
let finalOrderEntries = normalizeAndValidateOrderBy(
|
|
3949
3980
|
orderBy,
|
|
3950
3981
|
model,
|
|
3951
3982
|
parseOrderByValue
|
|
3952
3983
|
);
|
|
3953
|
-
if (
|
|
3954
|
-
|
|
3984
|
+
if (finalOrderEntries.length === 0) {
|
|
3985
|
+
finalOrderEntries = cursorEntries.map(([field]) => ({
|
|
3955
3986
|
field,
|
|
3956
3987
|
direction: "asc"
|
|
3957
3988
|
}));
|
|
3958
3989
|
} else {
|
|
3959
|
-
|
|
3990
|
+
finalOrderEntries = ensureCursorFieldsInOrder(
|
|
3991
|
+
finalOrderEntries,
|
|
3992
|
+
cursorEntries
|
|
3993
|
+
);
|
|
3960
3994
|
}
|
|
3961
|
-
assertCursorAndOrderFieldsScalar(model, cursor,
|
|
3995
|
+
assertCursorAndOrderFieldsScalar(model, cursor, finalOrderEntries);
|
|
3962
3996
|
const { whereSql: cursorWhereSql } = buildCursorFilterParts(
|
|
3963
3997
|
cursor,
|
|
3964
3998
|
srcAlias,
|
|
3965
3999
|
params,
|
|
3966
4000
|
model
|
|
3967
4001
|
);
|
|
3968
|
-
const cursorOrderBy =
|
|
4002
|
+
const cursorOrderBy = finalOrderEntries.map(
|
|
3969
4003
|
(e) => srcAlias + "." + quoteColumn(model, e.field) + " " + e.direction.toUpperCase()
|
|
3970
4004
|
).join(", ");
|
|
3971
4005
|
const selectList = buildCursorCteSelectList(
|
|
3972
4006
|
cursorEntries,
|
|
3973
|
-
|
|
4007
|
+
finalOrderEntries,
|
|
3974
4008
|
model
|
|
3975
4009
|
);
|
|
3976
4010
|
const cte = cteName + " AS (\n SELECT " + selectList + " FROM " + tableName + " " + srcAlias + "\n WHERE " + cursorWhereSql + "\n ORDER BY " + cursorOrderBy + "\n LIMIT 1\n )";
|
|
3977
4011
|
const existsExpr = "EXISTS (SELECT 1 FROM " + cteName + ")";
|
|
3978
4012
|
const orClauses = [];
|
|
3979
|
-
for (let level = 0; level <
|
|
4013
|
+
for (let level = 0; level < finalOrderEntries.length; level++) {
|
|
3980
4014
|
const andParts = [];
|
|
3981
4015
|
for (let i = 0; i < level; i++) {
|
|
3982
|
-
const e2 =
|
|
4016
|
+
const e2 = finalOrderEntries[i];
|
|
3983
4017
|
const c2 = col(alias, e2.field, model);
|
|
3984
4018
|
const cursorField2 = cteName + "." + quoteColumn(model, e2.field);
|
|
3985
4019
|
andParts.push(buildCursorEqualityExpr(c2, cursorField2));
|
|
3986
4020
|
}
|
|
3987
|
-
const e =
|
|
4021
|
+
const e = finalOrderEntries[level];
|
|
3988
4022
|
const c = col(alias, e.field, model);
|
|
3989
4023
|
const cursorField = cteName + "." + quoteColumn(model, e.field);
|
|
3990
|
-
const nulls = (
|
|
4024
|
+
const nulls = (_a3 = e.nulls) != null ? _a3 : defaultNullsFor(d, e.direction);
|
|
3991
4025
|
andParts.push(buildCursorInequalityExpr(c, e.direction, nulls, cursorField));
|
|
3992
4026
|
orClauses.push("(" + andParts.join(SQL_SEPARATORS.CONDITION_AND) + ")");
|
|
3993
4027
|
}
|
|
@@ -4533,6 +4567,16 @@ function handleJsonWildcard(expr, op, val, params, wildcards, dialect) {
|
|
|
4533
4567
|
|
|
4534
4568
|
// src/builder/where/relations.ts
|
|
4535
4569
|
var NO_JOINS = [];
|
|
4570
|
+
var SCHEMA_MAP_CACHE = /* @__PURE__ */ new WeakMap();
|
|
4571
|
+
function getSchemaByName(schemas) {
|
|
4572
|
+
let map = SCHEMA_MAP_CACHE.get(schemas);
|
|
4573
|
+
if (!map) {
|
|
4574
|
+
map = /* @__PURE__ */ new Map();
|
|
4575
|
+
for (const m of schemas) map.set(m.name, m);
|
|
4576
|
+
SCHEMA_MAP_CACHE.set(schemas, map);
|
|
4577
|
+
}
|
|
4578
|
+
return map;
|
|
4579
|
+
}
|
|
4536
4580
|
function isListRelation(fieldType) {
|
|
4537
4581
|
return typeof fieldType === "string" && fieldType.endsWith("[]");
|
|
4538
4582
|
}
|
|
@@ -4732,7 +4776,8 @@ function buildRelation(fieldName, value, ctx, whereBuilder) {
|
|
|
4732
4776
|
modelName: ctx.model.name
|
|
4733
4777
|
});
|
|
4734
4778
|
}
|
|
4735
|
-
const
|
|
4779
|
+
const schemaMap = getSchemaByName(ctx.schemaModels);
|
|
4780
|
+
const relModel = schemaMap.get(field.relatedModel);
|
|
4736
4781
|
if (!isNotNullish(relModel)) {
|
|
4737
4782
|
throw createError(
|
|
4738
4783
|
`Related model '${field.relatedModel}' not found in schema. Available models: ${ctx.schemaModels.map((m) => m.name).join(", ")}`,
|
|
@@ -5063,6 +5108,8 @@ function createAliasGenerator(maxAliases = 1e4) {
|
|
|
5063
5108
|
};
|
|
5064
5109
|
}
|
|
5065
5110
|
var MAX_PARAM_INDEX = Number.MAX_SAFE_INTEGER - 1e3;
|
|
5111
|
+
var _a2;
|
|
5112
|
+
var IS_PRODUCTION2 = typeof process !== "undefined" && ((_a2 = process.env) == null ? void 0 : _a2.NODE_ENV) === "production";
|
|
5066
5113
|
function assertSameLength(params, mappings) {
|
|
5067
5114
|
if (params.length !== mappings.length) {
|
|
5068
5115
|
throw new Error(
|
|
@@ -5122,6 +5169,11 @@ function validateMappings(mappings) {
|
|
|
5122
5169
|
}
|
|
5123
5170
|
}
|
|
5124
5171
|
function validateState(params, mappings, index) {
|
|
5172
|
+
if (IS_PRODUCTION2) {
|
|
5173
|
+
assertSameLength(params, mappings);
|
|
5174
|
+
assertValidNextIndex(index);
|
|
5175
|
+
return;
|
|
5176
|
+
}
|
|
5125
5177
|
assertSameLength(params, mappings);
|
|
5126
5178
|
assertValidNextIndex(index);
|
|
5127
5179
|
if (mappings.length === 0) return;
|
|
@@ -5276,10 +5328,10 @@ function toPublicResult(clause, joins, params) {
|
|
|
5276
5328
|
|
|
5277
5329
|
// src/builder/where.ts
|
|
5278
5330
|
function buildWhereClause(where, options) {
|
|
5279
|
-
var
|
|
5331
|
+
var _a3, _b, _c, _d, _e;
|
|
5280
5332
|
assertSafeAlias(options.alias);
|
|
5281
5333
|
const dialect = options.dialect || getGlobalDialect();
|
|
5282
|
-
const params = (
|
|
5334
|
+
const params = (_a3 = options.params) != null ? _a3 : createParamStore(1, dialect);
|
|
5283
5335
|
const ctx = {
|
|
5284
5336
|
alias: options.alias,
|
|
5285
5337
|
model: options.model,
|
|
@@ -5338,8 +5390,8 @@ function buildDefaultScalarFields(model, alias) {
|
|
|
5338
5390
|
return out;
|
|
5339
5391
|
}
|
|
5340
5392
|
function getDefaultSelectCached(model, alias) {
|
|
5341
|
-
var
|
|
5342
|
-
return (
|
|
5393
|
+
var _a3;
|
|
5394
|
+
return (_a3 = DEFAULT_SELECT_CACHE.get(model)) == null ? void 0 : _a3.get(alias);
|
|
5343
5395
|
}
|
|
5344
5396
|
function cacheDefaultSelect(model, alias, sql) {
|
|
5345
5397
|
let cache = DEFAULT_SELECT_CACHE.get(model);
|
|
@@ -5436,7 +5488,8 @@ function buildRelationSelect(relArgs, relModel, relAlias) {
|
|
|
5436
5488
|
}
|
|
5437
5489
|
|
|
5438
5490
|
// src/builder/shared/relation-key-utils.ts
|
|
5439
|
-
|
|
5491
|
+
var RELATION_KEYS_CACHE = /* @__PURE__ */ new WeakMap();
|
|
5492
|
+
function computeRelationKeys(field, context) {
|
|
5440
5493
|
const fkFields = normalizeKeyList(field.foreignKey);
|
|
5441
5494
|
if (fkFields.length === 0) {
|
|
5442
5495
|
throw new Error(
|
|
@@ -5454,6 +5507,13 @@ function resolveRelationKeys(field, context = "include") {
|
|
|
5454
5507
|
const parentKeys = field.isForeignKeyLocal ? fkFields : refFields;
|
|
5455
5508
|
return { childKeys, parentKeys };
|
|
5456
5509
|
}
|
|
5510
|
+
function resolveRelationKeys(field, context = "include") {
|
|
5511
|
+
let cached = RELATION_KEYS_CACHE.get(field);
|
|
5512
|
+
if (cached) return cached;
|
|
5513
|
+
cached = computeRelationKeys(field, context);
|
|
5514
|
+
RELATION_KEYS_CACHE.set(field, cached);
|
|
5515
|
+
return cached;
|
|
5516
|
+
}
|
|
5457
5517
|
|
|
5458
5518
|
// src/builder/shared/relation-extraction-utils.ts
|
|
5459
5519
|
function extractRelationEntries(args, model) {
|
|
@@ -5483,6 +5543,18 @@ function extractRelationEntries(args, model) {
|
|
|
5483
5543
|
var MAX_INCLUDE_DEPTH = 5;
|
|
5484
5544
|
var MAX_INCLUDES_PER_LEVEL = 10;
|
|
5485
5545
|
var MAX_TOTAL_SUBQUERIES = 100;
|
|
5546
|
+
var FIELD_BY_NAME_CACHE2 = /* @__PURE__ */ new WeakMap();
|
|
5547
|
+
function getFieldMap(model) {
|
|
5548
|
+
let map = FIELD_BY_NAME_CACHE2.get(model);
|
|
5549
|
+
if (!map) {
|
|
5550
|
+
map = /* @__PURE__ */ new Map();
|
|
5551
|
+
for (const f of model.fields) {
|
|
5552
|
+
map.set(f.name, f);
|
|
5553
|
+
}
|
|
5554
|
+
FIELD_BY_NAME_CACHE2.set(model, map);
|
|
5555
|
+
}
|
|
5556
|
+
return map;
|
|
5557
|
+
}
|
|
5486
5558
|
function buildIncludeScope(includePath) {
|
|
5487
5559
|
if (includePath.length === 0) return "include";
|
|
5488
5560
|
let scope = "include";
|
|
@@ -5502,7 +5574,8 @@ function getRelationTableReference(relModel, dialect) {
|
|
|
5502
5574
|
);
|
|
5503
5575
|
}
|
|
5504
5576
|
function resolveRelationOrThrow(model, schemaByName, relName) {
|
|
5505
|
-
const
|
|
5577
|
+
const fieldMap = getFieldMap(model);
|
|
5578
|
+
const field = fieldMap.get(relName);
|
|
5506
5579
|
if (!isNotNullish(field)) {
|
|
5507
5580
|
throw new Error(
|
|
5508
5581
|
`Unknown relation '${relName}' on model ${model.name}. Available relation fields: ${model.fields.filter((f) => f.isRelation).map((f) => f.name).join(", ")}`
|
|
@@ -5619,11 +5692,22 @@ function finalizeOrderByForInclude(args) {
|
|
|
5619
5692
|
}
|
|
5620
5693
|
function buildSelectWithNestedIncludes(relArgs, relModel, relAlias, ctx) {
|
|
5621
5694
|
let relSelect = buildRelationSelect(relArgs, relModel, relAlias);
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5695
|
+
let nestedIncludes = [];
|
|
5696
|
+
if (isPlainObject(relArgs)) {
|
|
5697
|
+
const prevModel = ctx.model;
|
|
5698
|
+
const prevParentAlias = ctx.parentAlias;
|
|
5699
|
+
const prevDepth = ctx.depth;
|
|
5700
|
+
ctx.model = relModel;
|
|
5701
|
+
ctx.parentAlias = relAlias;
|
|
5702
|
+
ctx.depth = prevDepth + 1;
|
|
5703
|
+
try {
|
|
5704
|
+
nestedIncludes = buildIncludeSqlInternal(relArgs, ctx);
|
|
5705
|
+
} finally {
|
|
5706
|
+
ctx.model = prevModel;
|
|
5707
|
+
ctx.parentAlias = prevParentAlias;
|
|
5708
|
+
ctx.depth = prevDepth;
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5627
5711
|
if (isNonEmptyArray(nestedIncludes)) {
|
|
5628
5712
|
const emptyJson = ctx.dialect === "postgres" ? `'[]'::json` : `json('[]')`;
|
|
5629
5713
|
const nestedSelects = nestedIncludes.map(
|
|
@@ -6020,16 +6104,22 @@ function buildIncludeSqlInternal(args, ctx) {
|
|
|
6020
6104
|
`Circular include detected: ${Array.from(ctx.visitSet).join(" -> ")} -> ${relationPath}. Relation '${relationPath}' creates an infinite loop.`
|
|
6021
6105
|
);
|
|
6022
6106
|
}
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
|
|
6032
|
-
|
|
6107
|
+
ctx.includePath.push(relName);
|
|
6108
|
+
ctx.visitSet.add(relationPath);
|
|
6109
|
+
try {
|
|
6110
|
+
includes.push(
|
|
6111
|
+
buildSingleInclude(
|
|
6112
|
+
relName,
|
|
6113
|
+
relArgs,
|
|
6114
|
+
resolved.field,
|
|
6115
|
+
resolved.relModel,
|
|
6116
|
+
ctx
|
|
6117
|
+
)
|
|
6118
|
+
);
|
|
6119
|
+
} finally {
|
|
6120
|
+
ctx.includePath.pop();
|
|
6121
|
+
ctx.visitSet.delete(relationPath);
|
|
6122
|
+
}
|
|
6033
6123
|
}
|
|
6034
6124
|
return includes;
|
|
6035
6125
|
}
|
|
@@ -6313,10 +6403,19 @@ function canUseNestedFlatJoin(relArgs, depth) {
|
|
|
6313
6403
|
}
|
|
6314
6404
|
return true;
|
|
6315
6405
|
}
|
|
6316
|
-
function canUseFlatJoinForAll(includeSpec) {
|
|
6317
|
-
|
|
6406
|
+
function canUseFlatJoinForAll(includeSpec, parentModel, schemas) {
|
|
6407
|
+
const modelMap = new Map(schemas.map((m) => [m.name, m]));
|
|
6408
|
+
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
6318
6409
|
if (value === false) continue;
|
|
6410
|
+
const field = parentModel.fields.find((f) => f.name === relName);
|
|
6411
|
+
if (!field || !field.isRelation) continue;
|
|
6319
6412
|
if (!canUseNestedFlatJoin(value, 0)) return false;
|
|
6413
|
+
const relModel = modelMap.get(field.relatedModel);
|
|
6414
|
+
if (!relModel) continue;
|
|
6415
|
+
const nestedSpec = extractNestedIncludeSpec(value, relModel);
|
|
6416
|
+
if (Object.keys(nestedSpec).length > 0) {
|
|
6417
|
+
if (!canUseFlatJoinForAll(nestedSpec, relModel, schemas)) return false;
|
|
6418
|
+
}
|
|
6320
6419
|
}
|
|
6321
6420
|
return true;
|
|
6322
6421
|
}
|
|
@@ -6413,7 +6512,7 @@ function buildFlatJoinSql(spec) {
|
|
|
6413
6512
|
if (Object.keys(includeSpec).length === 0) {
|
|
6414
6513
|
return { sql: "", requiresReduction: false, includeSpec: {} };
|
|
6415
6514
|
}
|
|
6416
|
-
if (!canUseFlatJoinForAll(includeSpec)) {
|
|
6515
|
+
if (!canUseFlatJoinForAll(includeSpec, model, schemas)) {
|
|
6417
6516
|
return { sql: "", requiresReduction: false, includeSpec: {} };
|
|
6418
6517
|
}
|
|
6419
6518
|
const baseJoins = whereJoins.length > 0 ? whereJoins.join(" ") : "";
|
|
@@ -6459,6 +6558,217 @@ function buildFlatJoinSql(spec) {
|
|
|
6459
6558
|
`.trim();
|
|
6460
6559
|
return { sql, requiresReduction: true, includeSpec };
|
|
6461
6560
|
}
|
|
6561
|
+
|
|
6562
|
+
// src/builder/select/array-agg.ts
|
|
6563
|
+
function canUseArrayAggForAll(includeSpec, parentModel, schemas) {
|
|
6564
|
+
const modelMap = new Map(schemas.map((m) => [m.name, m]));
|
|
6565
|
+
for (const [relName, value] of Object.entries(includeSpec)) {
|
|
6566
|
+
if (value === false) continue;
|
|
6567
|
+
const field = parentModel.fields.find((f) => f.name === relName);
|
|
6568
|
+
if (!field || !field.isRelation) continue;
|
|
6569
|
+
if (isPlainObject(value) && hasChildPagination(value)) return false;
|
|
6570
|
+
const relModel = modelMap.get(field.relatedModel);
|
|
6571
|
+
if (!relModel) continue;
|
|
6572
|
+
const nestedSpec = extractNestedIncludeSpec(value, relModel);
|
|
6573
|
+
if (Object.keys(nestedSpec).length > 0) return false;
|
|
6574
|
+
}
|
|
6575
|
+
return true;
|
|
6576
|
+
}
|
|
6577
|
+
function getRelationModel2(parentModel, relationName, schemas) {
|
|
6578
|
+
const field = parentModel.fields.find((f) => f.name === relationName);
|
|
6579
|
+
if (!(field == null ? void 0 : field.isRelation) || !field.relatedModel) {
|
|
6580
|
+
throw new Error(`Invalid relation ${relationName} on ${parentModel.name}`);
|
|
6581
|
+
}
|
|
6582
|
+
const relModel = schemas.find((m) => m.name === field.relatedModel);
|
|
6583
|
+
if (!relModel) {
|
|
6584
|
+
throw new Error(`Related model ${field.relatedModel} not found`);
|
|
6585
|
+
}
|
|
6586
|
+
return relModel;
|
|
6587
|
+
}
|
|
6588
|
+
function buildSubqueryRawSelect2(model, alias) {
|
|
6589
|
+
const cols = [];
|
|
6590
|
+
for (const f of model.fields) {
|
|
6591
|
+
if (f.isRelation) continue;
|
|
6592
|
+
cols.push(`${alias}.${quoteColumn(model, f.name)}`);
|
|
6593
|
+
}
|
|
6594
|
+
return cols.length > 0 ? cols.join(SQL_SEPARATORS.FIELD_LIST) : "*";
|
|
6595
|
+
}
|
|
6596
|
+
function readWhereInput2(relArgs) {
|
|
6597
|
+
if (!isPlainObject(relArgs)) return {};
|
|
6598
|
+
const obj = relArgs;
|
|
6599
|
+
if (!("where" in obj)) return {};
|
|
6600
|
+
const w = obj.where;
|
|
6601
|
+
return isPlainObject(w) ? w : {};
|
|
6602
|
+
}
|
|
6603
|
+
function buildArrayAggRelation(args) {
|
|
6604
|
+
const {
|
|
6605
|
+
relationName,
|
|
6606
|
+
relArgs,
|
|
6607
|
+
field,
|
|
6608
|
+
relModel,
|
|
6609
|
+
parentModel,
|
|
6610
|
+
parentAlias,
|
|
6611
|
+
schemas,
|
|
6612
|
+
dialect,
|
|
6613
|
+
aliasCounter,
|
|
6614
|
+
params
|
|
6615
|
+
} = args;
|
|
6616
|
+
const isList = typeof field.type === "string" && field.type.endsWith("[]");
|
|
6617
|
+
const { childKeys: relKeyFields, parentKeys: parentKeyFields } = resolveRelationKeys(field, "include");
|
|
6618
|
+
if (relKeyFields.length === 0) return null;
|
|
6619
|
+
const innerAlias = `__aa_r${aliasCounter.count++}`;
|
|
6620
|
+
const joinAlias = `__aa_j${aliasCounter.count++}`;
|
|
6621
|
+
const indices = getFieldIndices(relModel);
|
|
6622
|
+
const scalarSel = extractScalarSelection(relArgs, relModel);
|
|
6623
|
+
const pkFields = getPrimaryKeyFields(relModel);
|
|
6624
|
+
const selectedFields = scalarSel.includeAllScalars ? Array.from(indices.scalarFields.keys()) : [.../* @__PURE__ */ new Set([...pkFields, ...scalarSel.selectedScalarFields])];
|
|
6625
|
+
const pkOrderExpr = pkFields.map((f) => `${innerAlias}.${quoteColumn(relModel, f)}`).join(SQL_SEPARATORS.FIELD_LIST);
|
|
6626
|
+
const pkFilterExpr = `${innerAlias}.${quoteColumn(relModel, pkFields[0])}`;
|
|
6627
|
+
const fkSelectParts = relKeyFields.map(
|
|
6628
|
+
(f, i) => `${innerAlias}.${quoteColumn(relModel, f)} AS "__fk${i}"`
|
|
6629
|
+
);
|
|
6630
|
+
const aggParts = selectedFields.map((fieldName) => {
|
|
6631
|
+
const f = indices.scalarFields.get(fieldName);
|
|
6632
|
+
if (!f) return null;
|
|
6633
|
+
const colRef = `${innerAlias}.${quoteColumn(relModel, fieldName)}`;
|
|
6634
|
+
const alias = `"${relationName}.${f.name}"`;
|
|
6635
|
+
return `array_agg(${colRef} ORDER BY ${pkOrderExpr}) FILTER (WHERE ${pkFilterExpr} IS NOT NULL) AS ${alias}`;
|
|
6636
|
+
}).filter(Boolean);
|
|
6637
|
+
const fkGroupByParts = relKeyFields.map(
|
|
6638
|
+
(f) => `${innerAlias}.${quoteColumn(relModel, f)}`
|
|
6639
|
+
);
|
|
6640
|
+
const relTable = buildTableReference(
|
|
6641
|
+
SQL_TEMPLATES.PUBLIC_SCHEMA,
|
|
6642
|
+
relModel.tableName,
|
|
6643
|
+
dialect
|
|
6644
|
+
);
|
|
6645
|
+
const whereInput = readWhereInput2(relArgs);
|
|
6646
|
+
let whereJoinsSql = "";
|
|
6647
|
+
let whereClauseSql = "";
|
|
6648
|
+
if (Object.keys(whereInput).length > 0) {
|
|
6649
|
+
const aliasGen = createAliasGenerator();
|
|
6650
|
+
const whereResult = buildWhereClause(whereInput, {
|
|
6651
|
+
alias: innerAlias,
|
|
6652
|
+
schemaModels: schemas,
|
|
6653
|
+
model: relModel,
|
|
6654
|
+
params,
|
|
6655
|
+
isSubquery: true,
|
|
6656
|
+
aliasGen,
|
|
6657
|
+
dialect
|
|
6658
|
+
});
|
|
6659
|
+
if (whereResult.joins.length > 0) {
|
|
6660
|
+
whereJoinsSql = " " + whereResult.joins.join(" ");
|
|
6661
|
+
}
|
|
6662
|
+
if (isValidWhereClause(whereResult.clause)) {
|
|
6663
|
+
whereClauseSql = ` ${SQL_TEMPLATES.WHERE} ${whereResult.clause}`;
|
|
6664
|
+
}
|
|
6665
|
+
}
|
|
6666
|
+
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)}`;
|
|
6667
|
+
const onParts = parentKeyFields.map(
|
|
6668
|
+
(f, i) => `${joinAlias}."__fk${i}" = ${parentAlias}.${quoteColumn(parentModel, f)}`
|
|
6669
|
+
);
|
|
6670
|
+
const onCondition = onParts.length === 1 ? onParts[0] : `(${onParts.join(" AND ")})`;
|
|
6671
|
+
const joinSql = `LEFT JOIN (${subquery}) ${joinAlias} ON ${onCondition}`;
|
|
6672
|
+
const selectExprs = selectedFields.map((fieldName) => {
|
|
6673
|
+
const f = indices.scalarFields.get(fieldName);
|
|
6674
|
+
if (!f) return null;
|
|
6675
|
+
return `${joinAlias}."${relationName}.${f.name}"`;
|
|
6676
|
+
}).filter(Boolean);
|
|
6677
|
+
return {
|
|
6678
|
+
joinSql,
|
|
6679
|
+
selectExprs,
|
|
6680
|
+
relationName,
|
|
6681
|
+
isList,
|
|
6682
|
+
scalarFieldNames: selectedFields
|
|
6683
|
+
};
|
|
6684
|
+
}
|
|
6685
|
+
function buildArrayAggSql(spec) {
|
|
6686
|
+
const {
|
|
6687
|
+
select: select2,
|
|
6688
|
+
from,
|
|
6689
|
+
whereClause,
|
|
6690
|
+
whereJoins,
|
|
6691
|
+
orderBy,
|
|
6692
|
+
dialect,
|
|
6693
|
+
model,
|
|
6694
|
+
schemas,
|
|
6695
|
+
args,
|
|
6696
|
+
params
|
|
6697
|
+
} = spec;
|
|
6698
|
+
const entries = extractRelationEntries(args, model);
|
|
6699
|
+
const includeSpec = {};
|
|
6700
|
+
for (const e of entries) {
|
|
6701
|
+
includeSpec[e.name] = e.value;
|
|
6702
|
+
}
|
|
6703
|
+
if (Object.keys(includeSpec).length === 0) {
|
|
6704
|
+
return {
|
|
6705
|
+
sql: "",
|
|
6706
|
+
requiresReduction: false,
|
|
6707
|
+
includeSpec: {},
|
|
6708
|
+
isArrayAgg: false
|
|
6709
|
+
};
|
|
6710
|
+
}
|
|
6711
|
+
if (!canUseArrayAggForAll(includeSpec, model, schemas)) {
|
|
6712
|
+
return {
|
|
6713
|
+
sql: "",
|
|
6714
|
+
requiresReduction: false,
|
|
6715
|
+
includeSpec: {},
|
|
6716
|
+
isArrayAgg: false
|
|
6717
|
+
};
|
|
6718
|
+
}
|
|
6719
|
+
const baseJoins = whereJoins.length > 0 ? whereJoins.join(" ") : "";
|
|
6720
|
+
const baseWhere = whereClause && whereClause !== "1=1" ? `WHERE ${whereClause}` : "";
|
|
6721
|
+
const baseOrderBy = orderBy ? `ORDER BY ${orderBy}` : "";
|
|
6722
|
+
const subqueryScalarCols = buildSubqueryRawSelect2(model, from.alias);
|
|
6723
|
+
let baseSubquery = `SELECT ${subqueryScalarCols} FROM ${from.table} ${from.alias}` + (baseJoins ? ` ${baseJoins}` : "") + (baseWhere ? ` ${baseWhere}` : "") + (baseOrderBy ? ` ${baseOrderBy}` : "");
|
|
6724
|
+
baseSubquery = appendPagination(baseSubquery.trim(), spec);
|
|
6725
|
+
const aliasCounter = { count: 0 };
|
|
6726
|
+
const joins = [];
|
|
6727
|
+
const arraySelectExprs = [];
|
|
6728
|
+
for (const [relName, relValue] of Object.entries(includeSpec)) {
|
|
6729
|
+
if (relValue === false) continue;
|
|
6730
|
+
const field = model.fields.find((f) => f.name === relName);
|
|
6731
|
+
if (!field || !isValidRelationField(field)) continue;
|
|
6732
|
+
const relModel = getRelationModel2(model, relName, schemas);
|
|
6733
|
+
const built = buildArrayAggRelation({
|
|
6734
|
+
relationName: relName,
|
|
6735
|
+
relArgs: relValue,
|
|
6736
|
+
field,
|
|
6737
|
+
relModel,
|
|
6738
|
+
parentModel: model,
|
|
6739
|
+
parentAlias: from.alias,
|
|
6740
|
+
schemas,
|
|
6741
|
+
dialect,
|
|
6742
|
+
aliasCounter,
|
|
6743
|
+
params
|
|
6744
|
+
});
|
|
6745
|
+
if (!built) continue;
|
|
6746
|
+
joins.push(built.joinSql);
|
|
6747
|
+
arraySelectExprs.push(...built.selectExprs);
|
|
6748
|
+
}
|
|
6749
|
+
if (joins.length === 0) {
|
|
6750
|
+
return {
|
|
6751
|
+
sql: "",
|
|
6752
|
+
requiresReduction: false,
|
|
6753
|
+
includeSpec: {},
|
|
6754
|
+
isArrayAgg: false
|
|
6755
|
+
};
|
|
6756
|
+
}
|
|
6757
|
+
const baseSelect = (select2 != null ? select2 : "").trim();
|
|
6758
|
+
const allSelects = [baseSelect, ...arraySelectExprs].filter((s) => s && s.trim().length > 0).join(SQL_SEPARATORS.FIELD_LIST);
|
|
6759
|
+
if (!allSelects) {
|
|
6760
|
+
throw new Error("Array-agg SELECT requires at least one selected field");
|
|
6761
|
+
}
|
|
6762
|
+
const pkField = getPrimaryKeyField(model);
|
|
6763
|
+
const pkOrder = `${from.alias}.${quoteColumn(model, pkField)} ASC`;
|
|
6764
|
+
const sql = `
|
|
6765
|
+
SELECT ${allSelects}
|
|
6766
|
+
FROM (${baseSubquery}) ${from.alias}
|
|
6767
|
+
${joins.join(" ")}
|
|
6768
|
+
ORDER BY ${pkOrder}
|
|
6769
|
+
`.trim();
|
|
6770
|
+
return { sql, requiresReduction: true, includeSpec, isArrayAgg: true };
|
|
6771
|
+
}
|
|
6462
6772
|
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;
|
|
6463
6773
|
function buildWhereSql(conditions) {
|
|
6464
6774
|
if (!isNonEmptyArray(conditions)) return "";
|
|
@@ -6546,47 +6856,45 @@ function buildOutputColumns(scalarNames, includeNames, hasCount) {
|
|
|
6546
6856
|
}
|
|
6547
6857
|
return formatted;
|
|
6548
6858
|
}
|
|
6549
|
-
function
|
|
6550
|
-
|
|
6551
|
-
const
|
|
6552
|
-
const
|
|
6553
|
-
const
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
function extractDistinctOrderEntries(spec) {
|
|
6561
|
-
if (isNotNullish(spec.args.orderBy)) {
|
|
6562
|
-
const normalized = normalizeOrderByInput(
|
|
6563
|
-
spec.args.orderBy,
|
|
6564
|
-
parseOrderByValue
|
|
6565
|
-
);
|
|
6566
|
-
const entries = [];
|
|
6567
|
-
for (const item of normalized) {
|
|
6568
|
-
for (const field in item) {
|
|
6569
|
-
if (!Object.prototype.hasOwnProperty.call(item, field)) continue;
|
|
6570
|
-
const value = item[field];
|
|
6571
|
-
if (typeof value === "string") {
|
|
6572
|
-
entries.push({ field, direction: value });
|
|
6573
|
-
continue;
|
|
6574
|
-
}
|
|
6575
|
-
const obj = value;
|
|
6576
|
-
entries.push({ field, direction: obj.direction, nulls: obj.nulls });
|
|
6859
|
+
function getOrderByEntries(spec) {
|
|
6860
|
+
if (!isNotNullish(spec.args.orderBy)) return [];
|
|
6861
|
+
const normalized = normalizeOrderByInput(spec.args.orderBy, parseOrderByValue);
|
|
6862
|
+
const entries = [];
|
|
6863
|
+
for (const item of normalized) {
|
|
6864
|
+
for (const field in item) {
|
|
6865
|
+
if (!Object.prototype.hasOwnProperty.call(item, field)) continue;
|
|
6866
|
+
const value = item[field];
|
|
6867
|
+
if (typeof value === "string") {
|
|
6868
|
+
entries.push({ field, direction: value });
|
|
6869
|
+
continue;
|
|
6577
6870
|
}
|
|
6871
|
+
const obj = value;
|
|
6872
|
+
entries.push({ field, direction: obj.direction, nulls: obj.nulls });
|
|
6578
6873
|
}
|
|
6579
|
-
if (entries.length > 0) return entries;
|
|
6580
6874
|
}
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6875
|
+
return entries;
|
|
6876
|
+
}
|
|
6877
|
+
function renderOrderBySql(entries, alias, dialect, model) {
|
|
6878
|
+
if (entries.length === 0) return "";
|
|
6879
|
+
const out = [];
|
|
6880
|
+
for (const e of entries) {
|
|
6881
|
+
const dir = e.direction.toUpperCase();
|
|
6882
|
+
const c = col(alias, e.field, model);
|
|
6883
|
+
if (dialect === "postgres") {
|
|
6884
|
+
const nulls = isNotNullish(e.nulls) ? ` NULLS ${e.nulls.toUpperCase()}` : "";
|
|
6885
|
+
out.push(c + " " + dir + nulls);
|
|
6886
|
+
} else if (isNotNullish(e.nulls)) {
|
|
6887
|
+
const isNullExpr = `(${c} IS NULL)`;
|
|
6888
|
+
const nullRankDir = e.nulls === "first" ? "DESC" : "ASC";
|
|
6889
|
+
out.push(isNullExpr + " " + nullRankDir);
|
|
6890
|
+
out.push(c + " " + dir);
|
|
6891
|
+
} else {
|
|
6892
|
+
out.push(c + " " + dir);
|
|
6893
|
+
}
|
|
6586
6894
|
}
|
|
6587
|
-
return
|
|
6895
|
+
return out.join(SQL_SEPARATORS.ORDER_BY);
|
|
6588
6896
|
}
|
|
6589
|
-
function
|
|
6897
|
+
function renderOrderBySimple(entries, alias) {
|
|
6590
6898
|
if (entries.length === 0) return "";
|
|
6591
6899
|
const out = [];
|
|
6592
6900
|
for (const e of entries) {
|
|
@@ -6597,40 +6905,73 @@ function buildFieldNameOrderBy(entries, alias) {
|
|
|
6597
6905
|
const nullRankDir = e.nulls === "first" ? "DESC" : "ASC";
|
|
6598
6906
|
out.push(isNullExpr + " " + nullRankDir);
|
|
6599
6907
|
out.push(c + " " + dir);
|
|
6600
|
-
|
|
6908
|
+
} else {
|
|
6909
|
+
out.push(c + " " + dir);
|
|
6601
6910
|
}
|
|
6602
|
-
out.push(c + " " + dir);
|
|
6603
6911
|
}
|
|
6604
6912
|
return out.join(SQL_SEPARATORS.ORDER_BY);
|
|
6605
6913
|
}
|
|
6914
|
+
function ensureIdTiebreakerEntries(entries, model) {
|
|
6915
|
+
var _a3, _b;
|
|
6916
|
+
const idField = (_b = (_a3 = model == null ? void 0 : model.fields) == null ? void 0 : _a3.find) == null ? void 0 : _b.call(
|
|
6917
|
+
_a3,
|
|
6918
|
+
(f) => f.name === "id" && !f.isRelation
|
|
6919
|
+
);
|
|
6920
|
+
if (!idField) return entries;
|
|
6921
|
+
if (entries.some((e) => e.field === "id")) return entries;
|
|
6922
|
+
return [...entries, { field: "id", direction: "asc" }];
|
|
6923
|
+
}
|
|
6924
|
+
function ensurePostgresDistinctOrderEntries(args) {
|
|
6925
|
+
const { entries, distinct, model } = args;
|
|
6926
|
+
const distinctEntries = [...distinct].map((f) => ({
|
|
6927
|
+
field: f,
|
|
6928
|
+
direction: "asc"
|
|
6929
|
+
}));
|
|
6930
|
+
const canKeepAsIs = entries.length >= distinctEntries.length && distinctEntries.every((de, i) => entries[i].field === de.field);
|
|
6931
|
+
const merged = canKeepAsIs ? entries : [...distinctEntries, ...entries];
|
|
6932
|
+
return ensureIdTiebreakerEntries(merged, model);
|
|
6933
|
+
}
|
|
6934
|
+
function extractDistinctOrderEntries(spec) {
|
|
6935
|
+
const entries = getOrderByEntries(spec);
|
|
6936
|
+
if (entries.length > 0) return entries;
|
|
6937
|
+
if (isNotNullish(spec.distinct) && isNonEmptyArray(spec.distinct)) {
|
|
6938
|
+
return [...spec.distinct].map((f) => ({
|
|
6939
|
+
field: f,
|
|
6940
|
+
direction: "asc"
|
|
6941
|
+
}));
|
|
6942
|
+
}
|
|
6943
|
+
return [];
|
|
6944
|
+
}
|
|
6606
6945
|
function buildSqliteDistinctQuery(spec, selectWithIncludes, countJoins) {
|
|
6607
|
-
var
|
|
6608
|
-
const { includes, from, whereClause, whereJoins,
|
|
6946
|
+
var _a3, _b;
|
|
6947
|
+
const { includes, from, whereClause, whereJoins, distinct, model } = spec;
|
|
6609
6948
|
if (!isNotNullish(distinct) || !isNonEmptyArray(distinct)) {
|
|
6610
6949
|
throw new Error("buildSqliteDistinctQuery requires distinct fields");
|
|
6611
6950
|
}
|
|
6612
6951
|
const scalarNames = parseSimpleScalarSelect(spec.select, from.alias);
|
|
6613
6952
|
const includeNames = includes.map((i) => i.name);
|
|
6614
|
-
const hasCount = Boolean((_b = (
|
|
6953
|
+
const hasCount = Boolean((_b = (_a3 = spec.args) == null ? void 0 : _a3.select) == null ? void 0 : _b._count);
|
|
6615
6954
|
const outerSelectCols = buildOutputColumns(
|
|
6616
6955
|
scalarNames,
|
|
6617
6956
|
includeNames,
|
|
6618
6957
|
hasCount
|
|
6619
6958
|
);
|
|
6620
6959
|
const distinctCols = buildDistinctColumns([...distinct], from.alias, model);
|
|
6621
|
-
const
|
|
6622
|
-
const
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
const
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6960
|
+
const baseEntries = getOrderByEntries(spec);
|
|
6961
|
+
const fallbackEntries = [...distinct].map((f) => ({
|
|
6962
|
+
field: f,
|
|
6963
|
+
direction: "asc"
|
|
6964
|
+
}));
|
|
6965
|
+
const resolvedEntries = baseEntries.length > 0 ? baseEntries : fallbackEntries;
|
|
6966
|
+
const windowEntries = ensureIdTiebreakerEntries(resolvedEntries, model);
|
|
6967
|
+
const windowOrder = renderOrderBySql(
|
|
6968
|
+
windowEntries,
|
|
6969
|
+
from.alias,
|
|
6970
|
+
"sqlite",
|
|
6630
6971
|
model
|
|
6631
|
-
|
|
6972
|
+
);
|
|
6632
6973
|
const outerEntries = extractDistinctOrderEntries(spec);
|
|
6633
|
-
const outerOrder =
|
|
6974
|
+
const outerOrder = renderOrderBySimple(outerEntries, '"__tp_distinct"');
|
|
6634
6975
|
const joins = buildJoinsSql(whereJoins, countJoins);
|
|
6635
6976
|
const conditions = [];
|
|
6636
6977
|
if (whereClause && whereClause !== "1=1") conditions.push(whereClause);
|
|
@@ -6681,12 +7022,12 @@ function resolveCountSelect(countSelectRaw, model) {
|
|
|
6681
7022
|
return null;
|
|
6682
7023
|
}
|
|
6683
7024
|
function buildIncludeColumns(spec) {
|
|
6684
|
-
var
|
|
7025
|
+
var _a3, _b;
|
|
6685
7026
|
const { select: select2, includes, dialect, model, schemas, from, params } = spec;
|
|
6686
7027
|
const baseSelect = (select2 != null ? select2 : "").trim();
|
|
6687
7028
|
let countCols = "";
|
|
6688
7029
|
let countJoins = [];
|
|
6689
|
-
const countSelectRaw = (_b = (
|
|
7030
|
+
const countSelectRaw = (_b = (_a3 = spec.args) == null ? void 0 : _a3.select) == null ? void 0 : _b._count;
|
|
6690
7031
|
if (countSelectRaw) {
|
|
6691
7032
|
const resolvedCountSelect = resolveCountSelect(countSelectRaw, model);
|
|
6692
7033
|
if (resolvedCountSelect && Object.keys(resolvedCountSelect).length > 0) {
|
|
@@ -6845,37 +7186,6 @@ function extractIncludeSpec(args) {
|
|
|
6845
7186
|
function hasNestedIncludes(includeSpec) {
|
|
6846
7187
|
return Object.keys(includeSpec).length > 0;
|
|
6847
7188
|
}
|
|
6848
|
-
function splitOrderByTerms(orderBy) {
|
|
6849
|
-
const raw = orderBy.trim();
|
|
6850
|
-
if (raw.length === 0) return [];
|
|
6851
|
-
return raw.split(SQL_SEPARATORS.ORDER_BY).map((s) => s.trim()).filter((s) => s.length > 0);
|
|
6852
|
-
}
|
|
6853
|
-
function hasIdInOrderBy(orderBy, fromAlias) {
|
|
6854
|
-
const lower = orderBy.toLowerCase();
|
|
6855
|
-
const aliasLower = fromAlias.toLowerCase();
|
|
6856
|
-
return lower.includes(`${aliasLower}.id `) || lower.includes(`${aliasLower}."id"`);
|
|
6857
|
-
}
|
|
6858
|
-
function ensureIdTiebreakerOrderBy(orderBy, fromAlias, model) {
|
|
6859
|
-
var _a, _b;
|
|
6860
|
-
const idField = (_b = (_a = model == null ? void 0 : model.fields) == null ? void 0 : _a.find) == null ? void 0 : _b.call(
|
|
6861
|
-
_a,
|
|
6862
|
-
(f) => f.name === "id" && !f.isRelation
|
|
6863
|
-
);
|
|
6864
|
-
if (!idField) return orderBy;
|
|
6865
|
-
if (hasIdInOrderBy(orderBy, fromAlias)) return orderBy;
|
|
6866
|
-
const t = col(fromAlias, "id", model) + " ASC";
|
|
6867
|
-
return isNonEmptyString(orderBy) ? orderBy + ", " + t : t;
|
|
6868
|
-
}
|
|
6869
|
-
function ensurePostgresDistinctOrderBy(args) {
|
|
6870
|
-
const { orderBy, distinct, fromAlias, model } = args;
|
|
6871
|
-
const distinctTerms = distinct.map((f) => col(fromAlias, f, model) + " ASC");
|
|
6872
|
-
const existing = splitOrderByTerms(orderBy);
|
|
6873
|
-
const canKeepAsIs = existing.length >= distinctTerms.length && distinctTerms.every(
|
|
6874
|
-
(term, i) => existing[i].toLowerCase().startsWith(term.split(" ASC")[0].toLowerCase())
|
|
6875
|
-
);
|
|
6876
|
-
const merged = canKeepAsIs ? orderBy : [...distinctTerms, ...existing].join(SQL_SEPARATORS.ORDER_BY);
|
|
6877
|
-
return ensureIdTiebreakerOrderBy(merged, fromAlias, model);
|
|
6878
|
-
}
|
|
6879
7189
|
function constructFinalSql(spec) {
|
|
6880
7190
|
const {
|
|
6881
7191
|
select: select2,
|
|
@@ -6890,7 +7200,6 @@ function constructFinalSql(spec) {
|
|
|
6890
7200
|
params,
|
|
6891
7201
|
dialect,
|
|
6892
7202
|
model,
|
|
6893
|
-
includes,
|
|
6894
7203
|
schemas,
|
|
6895
7204
|
pagination,
|
|
6896
7205
|
args
|
|
@@ -6902,7 +7211,24 @@ function constructFinalSql(spec) {
|
|
|
6902
7211
|
const includeSpec = extractIncludeSpec(args);
|
|
6903
7212
|
const hasIncludes = hasNestedIncludes(includeSpec);
|
|
6904
7213
|
const hasPagination = isNotNullish(pagination.take);
|
|
6905
|
-
const
|
|
7214
|
+
const takeValue = typeof pagination.take === "number" ? pagination.take : null;
|
|
7215
|
+
const isLargeTake = takeValue !== null && takeValue > 50;
|
|
7216
|
+
const shouldUseArrayAgg = dialect === "postgres" && hasIncludes && method === "findMany" && hasPagination && isLargeTake && canUseArrayAggForAll(includeSpec, model, schemas);
|
|
7217
|
+
if (shouldUseArrayAgg) {
|
|
7218
|
+
const aaResult = buildArrayAggSql(spec);
|
|
7219
|
+
if (aaResult.sql) {
|
|
7220
|
+
const baseSqlResult = finalizeSql(aaResult.sql, params, dialect);
|
|
7221
|
+
return {
|
|
7222
|
+
sql: baseSqlResult.sql,
|
|
7223
|
+
params: baseSqlResult.params,
|
|
7224
|
+
paramMappings: baseSqlResult.paramMappings,
|
|
7225
|
+
requiresReduction: true,
|
|
7226
|
+
includeSpec: aaResult.includeSpec,
|
|
7227
|
+
isArrayAgg: true
|
|
7228
|
+
};
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
const shouldUseFlatJoin = dialect === "postgres" && hasPagination && hasIncludes && canUseFlatJoinForAll(includeSpec, model, schemas);
|
|
6906
7232
|
if (shouldUseFlatJoin) {
|
|
6907
7233
|
const flatResult = buildFlatJoinSql(spec);
|
|
6908
7234
|
if (flatResult.sql) {
|
|
@@ -6948,12 +7274,13 @@ function constructFinalSql(spec) {
|
|
|
6948
7274
|
pushWhere(parts, conditions);
|
|
6949
7275
|
let finalOrderBy = orderBy;
|
|
6950
7276
|
if (dialect === "postgres" && isNonEmptyArray(distinct)) {
|
|
6951
|
-
|
|
6952
|
-
|
|
7277
|
+
const currentEntries = getOrderByEntries(spec);
|
|
7278
|
+
const mergedEntries = ensurePostgresDistinctOrderEntries({
|
|
7279
|
+
entries: currentEntries.length > 0 ? currentEntries : [],
|
|
6953
7280
|
distinct: [...distinct],
|
|
6954
|
-
fromAlias: from.alias,
|
|
6955
7281
|
model
|
|
6956
7282
|
});
|
|
7283
|
+
finalOrderBy = renderOrderBySql(mergedEntries, from.alias, dialect, model);
|
|
6957
7284
|
}
|
|
6958
7285
|
if (isNonEmptyString(finalOrderBy))
|
|
6959
7286
|
parts.push(SQL_TEMPLATES.ORDER_BY, finalOrderBy);
|
|
@@ -6979,11 +7306,11 @@ function mapFirstOrderByByField(existing) {
|
|
|
6979
7306
|
return m;
|
|
6980
7307
|
}
|
|
6981
7308
|
function buildPostgresDistinctOrderBy(distinctFields, existing) {
|
|
6982
|
-
var
|
|
7309
|
+
var _a3;
|
|
6983
7310
|
const firstByField = mapFirstOrderByByField(existing);
|
|
6984
7311
|
const next = [];
|
|
6985
7312
|
for (const f of distinctFields) {
|
|
6986
|
-
next.push((
|
|
7313
|
+
next.push((_a3 = firstByField.get(f)) != null ? _a3 : { [f]: "asc" });
|
|
6987
7314
|
}
|
|
6988
7315
|
const distinctSet = new Set(distinctFields);
|
|
6989
7316
|
for (const obj of existing) {
|
|
@@ -7809,10 +8136,10 @@ function isPrismaMethod(v) {
|
|
|
7809
8136
|
return v === "findMany" || v === "findFirst" || v === "findUnique" || v === "aggregate" || v === "groupBy" || v === "count";
|
|
7810
8137
|
}
|
|
7811
8138
|
function resolveMethod(directive) {
|
|
7812
|
-
var
|
|
8139
|
+
var _a3, _b;
|
|
7813
8140
|
const m = directive == null ? void 0 : directive.method;
|
|
7814
8141
|
if (isPrismaMethod(m)) return m;
|
|
7815
|
-
const pm = (_b = (
|
|
8142
|
+
const pm = (_b = (_a3 = directive == null ? void 0 : directive.query) == null ? void 0 : _a3.processed) == null ? void 0 : _b.method;
|
|
7816
8143
|
if (isPrismaMethod(pm)) return pm;
|
|
7817
8144
|
return "findMany";
|
|
7818
8145
|
}
|
|
@@ -7973,7 +8300,7 @@ function extractIncludeSpec2(processed, modelDef) {
|
|
|
7973
8300
|
return includeSpec;
|
|
7974
8301
|
}
|
|
7975
8302
|
function buildAndNormalizeSql(args) {
|
|
7976
|
-
var
|
|
8303
|
+
var _a3;
|
|
7977
8304
|
const {
|
|
7978
8305
|
method,
|
|
7979
8306
|
processed,
|
|
@@ -7999,13 +8326,15 @@ function buildAndNormalizeSql(args) {
|
|
|
7999
8326
|
sqlResult.paramMappings,
|
|
8000
8327
|
dialect
|
|
8001
8328
|
);
|
|
8002
|
-
const includeSpec = (
|
|
8329
|
+
const includeSpec = (_a3 = sqlResult.includeSpec && isPlainObject(sqlResult.includeSpec) ? sqlResult.includeSpec : null) != null ? _a3 : extractIncludeSpec2(processed, modelDef);
|
|
8003
8330
|
const requiresReduction = sqlResult.requiresReduction === true;
|
|
8331
|
+
const isArrayAgg = sqlResult.isArrayAgg === true;
|
|
8004
8332
|
return {
|
|
8005
8333
|
sql: normalized.sql,
|
|
8006
8334
|
paramMappings: normalized.paramMappings,
|
|
8007
8335
|
requiresReduction,
|
|
8008
|
-
includeSpec
|
|
8336
|
+
includeSpec,
|
|
8337
|
+
isArrayAgg
|
|
8009
8338
|
};
|
|
8010
8339
|
}
|
|
8011
8340
|
function finalizeDirective(args) {
|
|
@@ -8016,11 +8345,12 @@ function finalizeDirective(args) {
|
|
|
8016
8345
|
normalizedMappings,
|
|
8017
8346
|
dialect,
|
|
8018
8347
|
requiresReduction,
|
|
8019
|
-
includeSpec
|
|
8348
|
+
includeSpec,
|
|
8349
|
+
isArrayAgg
|
|
8020
8350
|
} = args;
|
|
8021
8351
|
const params = normalizedMappings.map((m) => {
|
|
8022
|
-
var
|
|
8023
|
-
return (
|
|
8352
|
+
var _a3;
|
|
8353
|
+
return (_a3 = m.value) != null ? _a3 : void 0;
|
|
8024
8354
|
});
|
|
8025
8355
|
validateParamConsistencyByDialect(normalizedSql, params, dialect);
|
|
8026
8356
|
const { staticParams, dynamicKeys, paramOrder } = buildParamsFromMappings(normalizedMappings);
|
|
@@ -8033,6 +8363,7 @@ function finalizeDirective(args) {
|
|
|
8033
8363
|
paramMappings: normalizedMappings,
|
|
8034
8364
|
requiresReduction,
|
|
8035
8365
|
includeSpec,
|
|
8366
|
+
isArrayAgg,
|
|
8036
8367
|
originalDirective: directive
|
|
8037
8368
|
};
|
|
8038
8369
|
}
|
|
@@ -8066,7 +8397,8 @@ function generateSQL(directive) {
|
|
|
8066
8397
|
normalizedMappings: built.paramMappings,
|
|
8067
8398
|
dialect,
|
|
8068
8399
|
requiresReduction: built.requiresReduction,
|
|
8069
|
-
includeSpec: built.includeSpec
|
|
8400
|
+
includeSpec: built.includeSpec,
|
|
8401
|
+
isArrayAgg: built.isArrayAgg
|
|
8070
8402
|
});
|
|
8071
8403
|
}
|
|
8072
8404
|
|
|
@@ -8721,7 +9053,8 @@ function processModelDirectives(modelName, result, config) {
|
|
|
8721
9053
|
dynamicKeys: sqlDirective.dynamicKeys,
|
|
8722
9054
|
paramMappings: sqlDirective.paramMappings,
|
|
8723
9055
|
requiresReduction: sqlDirective.requiresReduction || false,
|
|
8724
|
-
includeSpec: sqlDirective.includeSpec || {}
|
|
9056
|
+
includeSpec: sqlDirective.includeSpec || {},
|
|
9057
|
+
isArrayAgg: sqlDirective.isArrayAgg || false
|
|
8725
9058
|
});
|
|
8726
9059
|
} catch (error) {
|
|
8727
9060
|
if (!config.skipInvalid) throw error;
|
|
@@ -8749,9 +9082,9 @@ function processAllModelDirectives(directiveResults, config) {
|
|
|
8749
9082
|
}
|
|
8750
9083
|
function generateClient(options) {
|
|
8751
9084
|
return __async(this, null, function* () {
|
|
8752
|
-
var
|
|
9085
|
+
var _a3;
|
|
8753
9086
|
const { datamodel, outputDir, config, datasourceUrl } = options;
|
|
8754
|
-
const runtimeImportPath = (
|
|
9087
|
+
const runtimeImportPath = (_a3 = options.runtimeImportPath) != null ? _a3 : "prisma-sql";
|
|
8755
9088
|
setGlobalDialect(config.dialect);
|
|
8756
9089
|
const models = convertDMMFToModels(datamodel);
|
|
8757
9090
|
const directiveResults = processAllDirectives(
|
|
@@ -8831,8 +9164,6 @@ function generateClient(options) {
|
|
|
8831
9164
|
}
|
|
8832
9165
|
function generateImports(runtimeImportPath) {
|
|
8833
9166
|
return `import {
|
|
8834
|
-
transformAggregateRow,
|
|
8835
|
-
extractCountValue,
|
|
8836
9167
|
buildSQL,
|
|
8837
9168
|
buildBatchSql,
|
|
8838
9169
|
parseBatchResults,
|
|
@@ -8844,7 +9175,6 @@ function generateImports(runtimeImportPath) {
|
|
|
8844
9175
|
planQueryStrategy,
|
|
8845
9176
|
executeWhereInSegments,
|
|
8846
9177
|
buildReducerConfig,
|
|
8847
|
-
reduceFlatRows,
|
|
8848
9178
|
type PrismaMethod,
|
|
8849
9179
|
type Model,
|
|
8850
9180
|
type BatchQuery,
|
|
@@ -8852,13 +9182,11 @@ function generateImports(runtimeImportPath) {
|
|
|
8852
9182
|
type TransactionQuery,
|
|
8853
9183
|
type TransactionOptions,
|
|
8854
9184
|
getOrPrepareStatement,
|
|
8855
|
-
shouldSqliteUseGet,
|
|
8856
9185
|
normalizeParams,
|
|
8857
9186
|
executePostgresQuery,
|
|
8858
9187
|
executeSqliteQuery,
|
|
8859
9188
|
executeRaw,
|
|
8860
|
-
} from ${JSON.stringify(runtimeImportPath)}
|
|
8861
|
-
import { RELATION_STATS } from './planner.generated'`;
|
|
9189
|
+
} from ${JSON.stringify(runtimeImportPath)}`;
|
|
8862
9190
|
}
|
|
8863
9191
|
function generateCoreTypes() {
|
|
8864
9192
|
return `class DeferredQuery {
|
|
@@ -8987,6 +9315,7 @@ const QUERIES: Record<string, Record<string, Record<string, {
|
|
|
8987
9315
|
paramMappings: any[]
|
|
8988
9316
|
requiresReduction: boolean
|
|
8989
9317
|
includeSpec: Record<string, any>
|
|
9318
|
+
isArrayAgg: boolean
|
|
8990
9319
|
}>>> = ${formatQueries(queries)}
|
|
8991
9320
|
|
|
8992
9321
|
const DIALECT = ${JSON.stringify(dialect)}
|
|
@@ -9209,9 +9538,10 @@ function generateExtension(runtimeImportPath) {
|
|
|
9209
9538
|
requiresReduction: boolean,
|
|
9210
9539
|
includeSpec: Record<string, any> | undefined,
|
|
9211
9540
|
model: any | undefined,
|
|
9541
|
+
isArrayAgg?: boolean,
|
|
9212
9542
|
): Promise<unknown[]> {
|
|
9213
9543
|
if (DIALECT === 'postgres') {
|
|
9214
|
-
return executePostgresQuery(client, sql, params, method, requiresReduction, includeSpec, model, MODELS)
|
|
9544
|
+
return executePostgresQuery(client, sql, params, method, requiresReduction, includeSpec, model, MODELS, isArrayAgg)
|
|
9215
9545
|
}
|
|
9216
9546
|
|
|
9217
9547
|
return executeSqliteQuery(client, sql, params, method, requiresReduction, includeSpec, model, MODELS)
|
|
@@ -9282,7 +9612,6 @@ function generateExtension(runtimeImportPath) {
|
|
|
9282
9612
|
method,
|
|
9283
9613
|
args: transformedArgs,
|
|
9284
9614
|
allModels: MODELS,
|
|
9285
|
-
relationStats: RELATION_STATS as any,
|
|
9286
9615
|
dialect: DIALECT,
|
|
9287
9616
|
})
|
|
9288
9617
|
|
|
@@ -9293,6 +9622,7 @@ function generateExtension(runtimeImportPath) {
|
|
|
9293
9622
|
let prebaked = false
|
|
9294
9623
|
let requiresReduction = false
|
|
9295
9624
|
let includeSpec: Record<string, any> | undefined
|
|
9625
|
+
let isArrayAgg = false
|
|
9296
9626
|
|
|
9297
9627
|
if (prebakedQuery) {
|
|
9298
9628
|
sql = prebakedQuery.sql
|
|
@@ -9300,17 +9630,19 @@ function generateExtension(runtimeImportPath) {
|
|
|
9300
9630
|
prebaked = true
|
|
9301
9631
|
requiresReduction = prebakedQuery.requiresReduction || false
|
|
9302
9632
|
includeSpec = prebakedQuery.includeSpec
|
|
9633
|
+
isArrayAgg = prebakedQuery.isArrayAgg || false
|
|
9303
9634
|
} else {
|
|
9304
9635
|
const result = buildSQL(model, MODELS, method, plan.filteredArgs, DIALECT)
|
|
9305
9636
|
sql = result.sql
|
|
9306
9637
|
params = result.params as unknown[]
|
|
9307
9638
|
requiresReduction = result.requiresReduction || false
|
|
9308
9639
|
includeSpec = result.includeSpec
|
|
9640
|
+
isArrayAgg = result.isArrayAgg || false
|
|
9309
9641
|
}
|
|
9310
9642
|
|
|
9311
9643
|
if (debug) {
|
|
9312
9644
|
const strategy = DIALECT === 'postgres'
|
|
9313
|
-
? (requiresReduction ? 'STREAMING REDUCTION' : 'STREAMING')
|
|
9645
|
+
? (isArrayAgg ? 'ARRAY AGG' : requiresReduction ? 'STREAMING REDUCTION' : 'STREAMING')
|
|
9314
9646
|
: (requiresReduction ? 'BUFFERED REDUCTION' : 'DIRECT')
|
|
9315
9647
|
|
|
9316
9648
|
const whereInMode = plan.whereInSegments.length > 0
|
|
@@ -9323,63 +9655,75 @@ function generateExtension(runtimeImportPath) {
|
|
|
9323
9655
|
console.log(' Params:', params)
|
|
9324
9656
|
}
|
|
9325
9657
|
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9658
|
+
if (plan.whereInSegments.length > 0) {
|
|
9659
|
+
if (DIALECT === 'postgres') {
|
|
9660
|
+
const { executeWhereInSegmentsStreaming } = await import(${JSON.stringify(runtimeImportPath)})
|
|
9661
|
+
|
|
9662
|
+
const results = await executeWhereInSegmentsStreaming({
|
|
9663
|
+
segments: plan.whereInSegments,
|
|
9664
|
+
parentSql: sql,
|
|
9665
|
+
parentParams: normalizeParams(params),
|
|
9666
|
+
parentModel: model,
|
|
9667
|
+
allModels: MODELS,
|
|
9668
|
+
modelMap: MODEL_MAP,
|
|
9669
|
+
dialect: DIALECT,
|
|
9670
|
+
execute: async (sql: string, params: unknown[]) => {
|
|
9671
|
+
const results: any[] = []
|
|
9672
|
+
await client.unsafe(sql, normalizeParams(params)).forEach((row: any) => {
|
|
9673
|
+
results.push(row)
|
|
9674
|
+
})
|
|
9675
|
+
return results
|
|
9676
|
+
},
|
|
9677
|
+
})
|
|
9329
9678
|
|
|
9330
|
-
|
|
9331
|
-
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
})
|
|
9679
|
+
if (plan.injectedParentKeys.length > 0) {
|
|
9680
|
+
for (const row of results) {
|
|
9681
|
+
for (const key of plan.injectedParentKeys) {
|
|
9682
|
+
delete row[key]
|
|
9683
|
+
}
|
|
9684
|
+
}
|
|
9685
|
+
}
|
|
9338
9686
|
|
|
9339
|
-
|
|
9687
|
+
const duration = Date.now() - startTime
|
|
9688
|
+
onQuery?.({ model: modelName, method, sql, params, duration, prebaked })
|
|
9340
9689
|
|
|
9341
|
-
|
|
9342
|
-
|
|
9690
|
+
return transformQueryResults(method, results)
|
|
9691
|
+
} else {
|
|
9692
|
+
const parentRows = await executeQuery(sql, params, method, requiresReduction, includeSpec, model, isArrayAgg) as any[]
|
|
9343
9693
|
|
|
9344
|
-
|
|
9345
|
-
if (DIALECT === 'postgres') {
|
|
9346
|
-
const { executeWhereInSegmentsStreaming } = await import(${JSON.stringify(runtimeImportPath)})
|
|
9347
|
-
|
|
9348
|
-
const streamResults = await executeWhereInSegmentsStreaming({
|
|
9349
|
-
segments: plan.whereInSegments,
|
|
9350
|
-
parentSql: sql,
|
|
9351
|
-
parentParams: params,
|
|
9352
|
-
parentModel: model,
|
|
9353
|
-
allModels: MODELS,
|
|
9354
|
-
modelMap: MODEL_MAP,
|
|
9355
|
-
dialect: DIALECT,
|
|
9356
|
-
execute: async (sql: string, params: unknown[]) => {
|
|
9357
|
-
const results: any[] = []
|
|
9358
|
-
await client.unsafe(sql, normalizeParams(params)).forEach((row: any) => {
|
|
9359
|
-
results.push(row)
|
|
9360
|
-
})
|
|
9361
|
-
return results
|
|
9362
|
-
},
|
|
9363
|
-
batchSize: 100,
|
|
9364
|
-
maxConcurrency: 10
|
|
9365
|
-
})
|
|
9366
|
-
|
|
9367
|
-
transformed = Array.isArray(transformed) ? streamResults : streamResults[0]
|
|
9368
|
-
} else {
|
|
9694
|
+
if (parentRows.length > 0) {
|
|
9369
9695
|
await executeWhereInSegments({
|
|
9370
9696
|
segments: plan.whereInSegments,
|
|
9371
|
-
parentRows
|
|
9697
|
+
parentRows,
|
|
9372
9698
|
parentModel: model,
|
|
9373
9699
|
allModels: MODELS,
|
|
9374
9700
|
modelMap: MODEL_MAP,
|
|
9375
9701
|
dialect: DIALECT,
|
|
9376
9702
|
execute: executeWhereInQuery,
|
|
9377
9703
|
})
|
|
9704
|
+
|
|
9705
|
+
if (plan.injectedParentKeys.length > 0) {
|
|
9706
|
+
for (const row of parentRows) {
|
|
9707
|
+
for (const key of plan.injectedParentKeys) {
|
|
9708
|
+
delete row[key]
|
|
9709
|
+
}
|
|
9710
|
+
}
|
|
9711
|
+
}
|
|
9378
9712
|
}
|
|
9713
|
+
|
|
9714
|
+
const duration = Date.now() - startTime
|
|
9715
|
+
onQuery?.({ model: modelName, method, sql, params, duration, prebaked })
|
|
9716
|
+
|
|
9717
|
+
return transformQueryResults(method, parentRows)
|
|
9379
9718
|
}
|
|
9380
9719
|
}
|
|
9381
9720
|
|
|
9382
|
-
|
|
9721
|
+
const results = await executeQuery(sql, params, method, requiresReduction, includeSpec, model, isArrayAgg)
|
|
9722
|
+
|
|
9723
|
+
const duration = Date.now() - startTime
|
|
9724
|
+
onQuery?.({ model: modelName, method, sql, params, duration, prebaked })
|
|
9725
|
+
|
|
9726
|
+
return transformQueryResults(method, results)
|
|
9383
9727
|
} catch (error) {
|
|
9384
9728
|
const msg = error instanceof Error ? error.message : String(error)
|
|
9385
9729
|
console.warn(\`[prisma-sql] \${modelName}.\${method} acceleration failed: \${msg}\`)
|
|
@@ -9420,7 +9764,6 @@ function generateExtension(runtimeImportPath) {
|
|
|
9420
9764
|
method: 'findMany',
|
|
9421
9765
|
args: transformedArgs,
|
|
9422
9766
|
allModels: MODELS,
|
|
9423
|
-
relationStats: RELATION_STATS as any,
|
|
9424
9767
|
dialect: DIALECT,
|
|
9425
9768
|
})
|
|
9426
9769
|
|
|
@@ -9431,23 +9774,39 @@ function generateExtension(runtimeImportPath) {
|
|
|
9431
9774
|
let params: unknown[]
|
|
9432
9775
|
let requiresReduction = false
|
|
9433
9776
|
let includeSpec: Record<string, any> | undefined
|
|
9777
|
+
let isArrayAgg = false
|
|
9434
9778
|
|
|
9435
9779
|
if (prebakedQuery) {
|
|
9436
9780
|
sql = prebakedQuery.sql
|
|
9437
9781
|
params = resolveParamsFromMappings(plan.filteredArgs, prebakedQuery.paramMappings)
|
|
9438
9782
|
requiresReduction = prebakedQuery.requiresReduction
|
|
9439
9783
|
includeSpec = prebakedQuery.includeSpec
|
|
9784
|
+
isArrayAgg = prebakedQuery.isArrayAgg || false
|
|
9440
9785
|
} else {
|
|
9441
9786
|
const result = buildSQL(model, MODELS, 'findMany', plan.filteredArgs, DIALECT)
|
|
9442
9787
|
sql = result.sql
|
|
9443
9788
|
params = result.params as unknown[]
|
|
9444
9789
|
requiresReduction = result.requiresReduction || false
|
|
9445
9790
|
includeSpec = result.includeSpec
|
|
9791
|
+
isArrayAgg = result.isArrayAgg || false
|
|
9446
9792
|
}
|
|
9447
9793
|
|
|
9448
9794
|
const normalizedParams = normalizeParams(params)
|
|
9449
9795
|
|
|
9450
|
-
if (
|
|
9796
|
+
if (isArrayAgg && includeSpec) {
|
|
9797
|
+
const { buildArrayAggReducerConfig, reduceArrayAggRows } = await import(${JSON.stringify(runtimeImportPath)})
|
|
9798
|
+
const config = buildArrayAggReducerConfig(model, includeSpec, MODELS)
|
|
9799
|
+
const results: any[] = []
|
|
9800
|
+
|
|
9801
|
+
await client.unsafe(sql, normalizedParams).forEach((row: any) => {
|
|
9802
|
+
results.push(row)
|
|
9803
|
+
})
|
|
9804
|
+
|
|
9805
|
+
const reduced = reduceArrayAggRows(results, config)
|
|
9806
|
+
for (const item of reduced) {
|
|
9807
|
+
yield item
|
|
9808
|
+
}
|
|
9809
|
+
} else if (requiresReduction && includeSpec) {
|
|
9451
9810
|
const { createProgressiveReducer } = await import(${JSON.stringify(runtimeImportPath)})
|
|
9452
9811
|
const config = buildReducerConfig(model, includeSpec, MODELS)
|
|
9453
9812
|
const reducer = createProgressiveReducer(config)
|
|
@@ -9710,8 +10069,7 @@ function generateCode(models, queries, dialect, datamodel, runtimeImportPath) {
|
|
|
9710
10069
|
generateDataConstants(cleanModels, mappings, fieldTypes, queries, dialect),
|
|
9711
10070
|
generateTransformLogic(),
|
|
9712
10071
|
generateExtension(runtimeImportPath),
|
|
9713
|
-
generateTypeExports()
|
|
9714
|
-
`export * from './planner.generated'`
|
|
10072
|
+
generateTypeExports()
|
|
9715
10073
|
].join("\n\n");
|
|
9716
10074
|
}
|
|
9717
10075
|
function formatQueries(queries) {
|
|
@@ -9731,6 +10089,7 @@ function formatQueries(queries) {
|
|
|
9731
10089
|
paramMappings: ${JSON.stringify(query.paramMappings)},
|
|
9732
10090
|
requiresReduction: ${query.requiresReduction || false},
|
|
9733
10091
|
includeSpec: ${JSON.stringify(query.includeSpec || {})},
|
|
10092
|
+
isArrayAgg: ${query.isArrayAgg || false},
|
|
9734
10093
|
}`);
|
|
9735
10094
|
}
|
|
9736
10095
|
methodEntries.push(` ${JSON.stringify(method)}: {
|
|
@@ -9756,9 +10115,9 @@ function getDialectFromProvider(provider) {
|
|
|
9756
10115
|
);
|
|
9757
10116
|
}
|
|
9758
10117
|
function getOutputDir(options) {
|
|
9759
|
-
var
|
|
10118
|
+
var _a3, _b;
|
|
9760
10119
|
const schemaDir = dirname(options.schemaPath);
|
|
9761
|
-
if ((
|
|
10120
|
+
if ((_a3 = options.generator.output) == null ? void 0 : _a3.value) {
|
|
9762
10121
|
return resolve(schemaDir, options.generator.output.value);
|
|
9763
10122
|
}
|
|
9764
10123
|
const clientGenerator = options.otherGenerators.find(
|