linkgress-orm 0.4.60 → 0.4.62
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/entity/entity-base.d.ts +1 -1
- package/dist/entity/entity-builder.d.ts +3 -3
- package/dist/entity/entity-builder.js +3 -3
- package/dist/migration/check-constraint-sql.d.ts +2 -2
- package/dist/query/conditions.d.ts +16 -1
- package/dist/query/conditions.d.ts.map +1 -1
- package/dist/query/conditions.js +9 -1
- package/dist/query/conditions.js.map +1 -1
- package/dist/query/cte-root-query.d.ts +66 -0
- package/dist/query/cte-root-query.d.ts.map +1 -1
- package/dist/query/cte-root-query.js +135 -18
- package/dist/query/cte-root-query.js.map +1 -1
- package/dist/query/grouped-query.d.ts +7 -0
- package/dist/query/grouped-query.d.ts.map +1 -1
- package/dist/query/grouped-query.js +7 -1
- package/dist/query/grouped-query.js.map +1 -1
- package/dist/query/query-builder.d.ts +14 -0
- package/dist/query/query-builder.d.ts.map +1 -1
- package/dist/query/query-builder.js +64 -9
- package/dist/query/query-builder.js.map +1 -1
- package/dist/query/union-builder.d.ts +7 -0
- package/dist/query/union-builder.d.ts.map +1 -1
- package/dist/query/union-builder.js +66 -0
- package/dist/query/union-builder.js.map +1 -1
- package/package.json +1 -1
|
@@ -710,6 +710,16 @@ class SelectQueryBuilder {
|
|
|
710
710
|
}
|
|
711
711
|
return this;
|
|
712
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* The CTEs attached to this query through `.with(...)` (or auto-attached by
|
|
715
|
+
* `joinFilter(cte, ...)`). Read by {@link UnionQueryBuilder.buildSql}, which
|
|
716
|
+
* hoists them to statement level so a CTE declared on one union leg is
|
|
717
|
+
* visible to all of them.
|
|
718
|
+
* @internal
|
|
719
|
+
*/
|
|
720
|
+
_getAttachedCtes() {
|
|
721
|
+
return this.ctes;
|
|
722
|
+
}
|
|
713
723
|
/**
|
|
714
724
|
* Limit results
|
|
715
725
|
*/
|
|
@@ -1345,6 +1355,9 @@ class SelectQueryBuilder {
|
|
|
1345
1355
|
allParams: context.params,
|
|
1346
1356
|
collectionStrategy: this.collectionStrategy,
|
|
1347
1357
|
executor: this.executor,
|
|
1358
|
+
// CTEs the union already declared ahead of the whole statement — this leg
|
|
1359
|
+
// must not re-declare them (nor re-push their params).
|
|
1360
|
+
hoistedCteNames: context.hoistedCteNames,
|
|
1348
1361
|
};
|
|
1349
1362
|
const mockRow = this._createMockRow();
|
|
1350
1363
|
const selectionResult = this.selector(mockRow);
|
|
@@ -4185,7 +4198,7 @@ ${joinClauses.join('\n')}`;
|
|
|
4185
4198
|
let whereClause = '';
|
|
4186
4199
|
if (this.whereCond) {
|
|
4187
4200
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
4188
|
-
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
4201
|
+
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
4189
4202
|
whereClause = `WHERE ${sql}`;
|
|
4190
4203
|
context.paramCounter = newParamCounter; // Use returned counter (handles both params and placeholders)
|
|
4191
4204
|
context.allParams.push(...params);
|
|
@@ -4321,8 +4334,14 @@ ${joinClauses.join('\n')}`;
|
|
|
4321
4334
|
* @internal
|
|
4322
4335
|
*/
|
|
4323
4336
|
buildQueryCore(selection, context, includeOrderLimitOffset = true) {
|
|
4324
|
-
// Handle user-defined CTEs first - their params need to come before main query params
|
|
4337
|
+
// Handle user-defined CTEs first - their params need to come before main query params.
|
|
4338
|
+
// A CTE the enclosing builder already hoisted to statement level (UNION) has had both
|
|
4339
|
+
// its params and its WITH entry contributed there; pushing them again would duplicate
|
|
4340
|
+
// the params and shift every placeholder in this leg.
|
|
4325
4341
|
for (const cte of this.ctes) {
|
|
4342
|
+
if (context.hoistedCteNames?.has(cte.name)) {
|
|
4343
|
+
continue;
|
|
4344
|
+
}
|
|
4326
4345
|
context.allParams.push(...cte.params);
|
|
4327
4346
|
context.paramCounter += cte.params.length;
|
|
4328
4347
|
}
|
|
@@ -4532,7 +4551,7 @@ ${joinClauses.join('\n')}`;
|
|
|
4532
4551
|
let whereClause = '';
|
|
4533
4552
|
if (this.whereCond) {
|
|
4534
4553
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
4535
|
-
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
4554
|
+
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
4536
4555
|
whereClause = `WHERE ${sql}`;
|
|
4537
4556
|
context.paramCounter = newParamCounter;
|
|
4538
4557
|
context.allParams.push(...params);
|
|
@@ -4569,6 +4588,10 @@ ${joinClauses.join('\n')}`;
|
|
|
4569
4588
|
let finalQuery = '';
|
|
4570
4589
|
const allCtes = [];
|
|
4571
4590
|
for (const cte of this.ctes) {
|
|
4591
|
+
// Hoisted to statement level by the enclosing UNION - declared there, not here.
|
|
4592
|
+
if (context.hoistedCteNames?.has(cte.name)) {
|
|
4593
|
+
continue;
|
|
4594
|
+
}
|
|
4572
4595
|
allCtes.push(`"${cte.name}" AS ${cte.materialized ? 'MATERIALIZED ' : ''}(${cte.query})`);
|
|
4573
4596
|
}
|
|
4574
4597
|
if (context.ctes.size > 0) {
|
|
@@ -5194,7 +5217,7 @@ ${joinClauses.join('\n')}`;
|
|
|
5194
5217
|
let whereClause = '';
|
|
5195
5218
|
if (this.whereCond) {
|
|
5196
5219
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
5197
|
-
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
5220
|
+
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
5198
5221
|
whereClause = `WHERE ${sql}`;
|
|
5199
5222
|
context.paramCounter = newParamCounter; // Use returned counter (handles both params and placeholders)
|
|
5200
5223
|
context.allParams.push(...params);
|
|
@@ -5251,6 +5274,18 @@ ${joinClauses.join('\n')}`;
|
|
|
5251
5274
|
* Build aggregate query (count or exists)
|
|
5252
5275
|
*/
|
|
5253
5276
|
buildAggregateQuery(context, type) {
|
|
5277
|
+
// User-defined CTEs first, exactly as buildQuery does: their params occupy the
|
|
5278
|
+
// opening slots of the statement because DbCte bodies carry placeholders numbered
|
|
5279
|
+
// from $1. Without this, `.with(cte).count()` / `.exists()` dropped the WITH clause
|
|
5280
|
+
// entirely and PostgreSQL answered `relation "<cte>" does not exist` (42P01) for any
|
|
5281
|
+
// query whose WHERE referenced the CTE.
|
|
5282
|
+
for (const cte of this.ctes) {
|
|
5283
|
+
if (context.hoistedCteNames?.has(cte.name)) {
|
|
5284
|
+
continue;
|
|
5285
|
+
}
|
|
5286
|
+
context.allParams.push(...cte.params);
|
|
5287
|
+
context.paramCounter += cte.params.length;
|
|
5288
|
+
}
|
|
5254
5289
|
// Detect navigation property joins from WHERE condition
|
|
5255
5290
|
const joins = [];
|
|
5256
5291
|
this.detectAndAddJoinsFromCondition(this.whereCond, joins);
|
|
@@ -5258,7 +5293,7 @@ ${joinClauses.join('\n')}`;
|
|
|
5258
5293
|
let whereClause = '';
|
|
5259
5294
|
if (this.whereCond) {
|
|
5260
5295
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
5261
|
-
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
5296
|
+
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
5262
5297
|
whereClause = `WHERE ${sql}`;
|
|
5263
5298
|
context.paramCounter = newParamCounter; // Use returned counter (handles both params and placeholders)
|
|
5264
5299
|
context.allParams.push(...params);
|
|
@@ -5314,9 +5349,24 @@ ${joinClauses.join('\n')}`;
|
|
|
5314
5349
|
const selectClause = type === 'count'
|
|
5315
5350
|
? 'SELECT COUNT(*) as count'
|
|
5316
5351
|
: 'SELECT EXISTS(SELECT 1';
|
|
5352
|
+
// WITH clause - same assembly as buildQuery, so an aggregate can reference the
|
|
5353
|
+
// CTEs attached to the query it is aggregating.
|
|
5354
|
+
const allCtes = [];
|
|
5355
|
+
for (const cte of this.ctes) {
|
|
5356
|
+
if (context.hoistedCteNames?.has(cte.name)) {
|
|
5357
|
+
continue;
|
|
5358
|
+
}
|
|
5359
|
+
allCtes.push(`"${cte.name}" AS ${cte.materialized ? 'MATERIALIZED ' : ''}(${cte.query})`);
|
|
5360
|
+
}
|
|
5361
|
+
if (context.ctes.size > 0) {
|
|
5362
|
+
for (const [cteName, { sql: cteSql }] of context.ctes.entries()) {
|
|
5363
|
+
allCtes.push(`"${cteName}" AS (${cteSql})`);
|
|
5364
|
+
}
|
|
5365
|
+
}
|
|
5366
|
+
const withClause = allCtes.length > 0 ? `WITH ${allCtes.join(', ')}\n` : '';
|
|
5317
5367
|
const sql = type === 'count'
|
|
5318
|
-
? `${selectClause}\n${fromClause}\n${whereClause}`.trim()
|
|
5319
|
-
: `${selectClause}\n${fromClause}\n${whereClause})`.trim();
|
|
5368
|
+
? `${withClause}${selectClause}\n${fromClause}\n${whereClause}`.trim()
|
|
5369
|
+
: `${withClause}${selectClause}\n${fromClause}\n${whereClause})`.trim();
|
|
5320
5370
|
return {
|
|
5321
5371
|
sql,
|
|
5322
5372
|
params: context.allParams,
|
|
@@ -5355,6 +5405,11 @@ ${joinClauses.join('\n')}`;
|
|
|
5355
5405
|
paramCounter: outerContext.paramCounter,
|
|
5356
5406
|
allParams: outerContext.params,
|
|
5357
5407
|
placeholders: outerContext.placeholders, // Pass placeholders through for prepared statements
|
|
5408
|
+
// CTEs an enclosing builder already declared at statement level stay
|
|
5409
|
+
// declared for anything NESTED in this subquery too. Without this the
|
|
5410
|
+
// signal dies at the subquery boundary and a CTE-rooted subquery one
|
|
5411
|
+
// level deeper re-declares (and re-materializes) a CTE it was handed.
|
|
5412
|
+
hoistedCteNames: outerContext.hoistedCteNames,
|
|
5358
5413
|
executor: this.executor,
|
|
5359
5414
|
};
|
|
5360
5415
|
// Analyze the selector to extract nested queries
|
|
@@ -6089,7 +6144,7 @@ class CollectionQueryBuilder {
|
|
|
6089
6144
|
}
|
|
6090
6145
|
if (this.whereCond) {
|
|
6091
6146
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
6092
|
-
const { sql: condSql, params, placeholders, paramCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
6147
|
+
const { sql: condSql, params, placeholders, paramCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
6093
6148
|
context.paramCounter = paramCounter;
|
|
6094
6149
|
context.params.push(...params);
|
|
6095
6150
|
if (placeholders) {
|
|
@@ -6610,7 +6665,7 @@ class CollectionQueryBuilder {
|
|
|
6610
6665
|
let whereParams;
|
|
6611
6666
|
if (this.whereCond) {
|
|
6612
6667
|
const condBuilder = new conditions_1.ConditionBuilder();
|
|
6613
|
-
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders);
|
|
6668
|
+
const { sql, params, placeholders, paramCounter: newParamCounter } = condBuilder.build(this.whereCond, context.paramCounter, context.placeholders, context.hoistedCteNames);
|
|
6614
6669
|
whereClause = sql;
|
|
6615
6670
|
whereParams = params;
|
|
6616
6671
|
context.paramCounter = newParamCounter; // Use returned counter (handles both params and placeholders)
|