metal-orm 1.0.16 → 1.0.18
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/README.md +37 -40
- package/dist/decorators/index.cjs +344 -69
- package/dist/decorators/index.cjs.map +1 -1
- package/dist/decorators/index.d.cts +1 -1
- package/dist/decorators/index.d.ts +1 -1
- package/dist/decorators/index.js +344 -69
- package/dist/decorators/index.js.map +1 -1
- package/dist/index.cjs +567 -181
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -30
- package/dist/index.d.ts +66 -30
- package/dist/index.js +559 -181
- package/dist/index.js.map +1 -1
- package/dist/{select-BKZrMRCQ.d.cts → select-BuMpVcVt.d.cts} +265 -74
- package/dist/{select-BKZrMRCQ.d.ts → select-BuMpVcVt.d.ts} +265 -74
- package/package.json +5 -1
- package/src/codegen/naming-strategy.ts +15 -10
- package/src/core/ast/aggregate-functions.ts +50 -4
- package/src/core/ast/builders.ts +23 -3
- package/src/core/ast/expression-builders.ts +36 -16
- package/src/core/ast/expression-nodes.ts +17 -9
- package/src/core/ast/join-node.ts +5 -3
- package/src/core/ast/join.ts +16 -16
- package/src/core/ast/query.ts +44 -29
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +18 -0
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +11 -0
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +9 -0
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
- package/src/core/ddl/introspect/functions/postgres.ts +2 -6
- package/src/core/dialect/abstract.ts +12 -8
- package/src/core/dialect/base/sql-dialect.ts +58 -46
- package/src/core/dialect/mssql/functions.ts +24 -15
- package/src/core/dialect/mssql/index.ts +53 -28
- package/src/core/dialect/postgres/functions.ts +33 -24
- package/src/core/dialect/sqlite/functions.ts +19 -12
- package/src/core/dialect/sqlite/index.ts +22 -13
- package/src/core/functions/datetime.ts +2 -1
- package/src/core/functions/numeric.ts +2 -1
- package/src/core/functions/standard-strategy.ts +52 -12
- package/src/core/functions/text.ts +2 -1
- package/src/core/functions/types.ts +8 -8
- package/src/index.ts +5 -4
- package/src/orm/domain-event-bus.ts +43 -25
- package/src/orm/entity-meta.ts +40 -0
- package/src/orm/execution-context.ts +6 -0
- package/src/orm/hydration-context.ts +6 -4
- package/src/orm/orm-session.ts +35 -24
- package/src/orm/orm.ts +10 -10
- package/src/orm/query-logger.ts +15 -0
- package/src/orm/runtime-types.ts +60 -2
- package/src/orm/transaction-runner.ts +7 -0
- package/src/orm/unit-of-work.ts +1 -0
- package/src/query-builder/column-selector.ts +9 -7
- package/src/query-builder/insert-query-state.ts +13 -3
- package/src/query-builder/query-ast-service.ts +59 -38
- package/src/query-builder/relation-conditions.ts +38 -34
- package/src/query-builder/relation-manager.ts +8 -3
- package/src/query-builder/relation-service.ts +59 -46
- package/src/query-builder/select-helpers.ts +50 -0
- package/src/query-builder/select-query-state.ts +19 -7
- package/src/query-builder/select.ts +339 -167
- package/src/query-builder/update-query-state.ts +31 -9
- package/src/schema/column.ts +75 -39
- package/src/schema/types.ts +17 -6
|
@@ -332,6 +332,15 @@ var isWindowFunctionNode = (node) => node?.type === "WindowFunction";
|
|
|
332
332
|
var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isWindowFunctionNode(node);
|
|
333
333
|
|
|
334
334
|
// src/core/ast/expression-builders.ts
|
|
335
|
+
var valueToOperand = (value) => {
|
|
336
|
+
if (isOperandNode(value)) {
|
|
337
|
+
return value;
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
type: "Literal",
|
|
341
|
+
value
|
|
342
|
+
};
|
|
343
|
+
};
|
|
335
344
|
var toNode = (col) => {
|
|
336
345
|
if (isOperandNode(col)) return col;
|
|
337
346
|
const def = col;
|
|
@@ -341,10 +350,10 @@ var toLiteralNode = (value) => ({
|
|
|
341
350
|
type: "Literal",
|
|
342
351
|
value
|
|
343
352
|
});
|
|
353
|
+
var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
344
354
|
var toOperand = (val) => {
|
|
345
|
-
if (val
|
|
346
|
-
|
|
347
|
-
return { type: "Literal", value: val };
|
|
355
|
+
if (isLiteralValue(val)) {
|
|
356
|
+
return valueToOperand(val);
|
|
348
357
|
}
|
|
349
358
|
return toNode(val);
|
|
350
359
|
};
|
|
@@ -385,6 +394,24 @@ var notExists = (subquery) => ({
|
|
|
385
394
|
subquery
|
|
386
395
|
});
|
|
387
396
|
|
|
397
|
+
// src/core/sql/sql.ts
|
|
398
|
+
var JOIN_KINDS = {
|
|
399
|
+
/** INNER JOIN type */
|
|
400
|
+
INNER: "INNER",
|
|
401
|
+
/** LEFT JOIN type */
|
|
402
|
+
LEFT: "LEFT",
|
|
403
|
+
/** RIGHT JOIN type */
|
|
404
|
+
RIGHT: "RIGHT",
|
|
405
|
+
/** CROSS JOIN type */
|
|
406
|
+
CROSS: "CROSS"
|
|
407
|
+
};
|
|
408
|
+
var ORDER_DIRECTIONS = {
|
|
409
|
+
/** Ascending order */
|
|
410
|
+
ASC: "ASC",
|
|
411
|
+
/** Descending order */
|
|
412
|
+
DESC: "DESC"
|
|
413
|
+
};
|
|
414
|
+
|
|
388
415
|
// src/core/ast/aggregate-functions.ts
|
|
389
416
|
var buildAggregate = (name) => (col) => ({
|
|
390
417
|
type: "Function",
|
|
@@ -394,14 +421,41 @@ var buildAggregate = (name) => (col) => ({
|
|
|
394
421
|
var count = buildAggregate("COUNT");
|
|
395
422
|
var sum = buildAggregate("SUM");
|
|
396
423
|
var avg = buildAggregate("AVG");
|
|
424
|
+
var min = buildAggregate("MIN");
|
|
425
|
+
var max = buildAggregate("MAX");
|
|
426
|
+
|
|
427
|
+
// src/core/ast/builders.ts
|
|
428
|
+
var buildColumnNode = (table, column) => {
|
|
429
|
+
if (column.type === "Column") {
|
|
430
|
+
return column;
|
|
431
|
+
}
|
|
432
|
+
const def = column;
|
|
433
|
+
const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
|
|
434
|
+
return {
|
|
435
|
+
type: "Column",
|
|
436
|
+
table: baseTable,
|
|
437
|
+
name: def.name
|
|
438
|
+
};
|
|
439
|
+
};
|
|
440
|
+
var derivedTable = (query, alias, columnAliases) => ({
|
|
441
|
+
type: "DerivedTable",
|
|
442
|
+
query,
|
|
443
|
+
alias,
|
|
444
|
+
columnAliases
|
|
445
|
+
});
|
|
397
446
|
|
|
398
447
|
// src/core/functions/standard-strategy.ts
|
|
399
|
-
var StandardFunctionStrategy = class {
|
|
448
|
+
var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
400
449
|
constructor() {
|
|
401
450
|
this.renderers = /* @__PURE__ */ new Map();
|
|
402
451
|
this.registerStandard();
|
|
403
452
|
}
|
|
404
453
|
registerStandard() {
|
|
454
|
+
this.add("COUNT", ({ compiledArgs }) => `COUNT(${compiledArgs.join(", ")})`);
|
|
455
|
+
this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
|
|
456
|
+
this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
|
|
457
|
+
this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
|
|
458
|
+
this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
|
|
405
459
|
this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
|
|
406
460
|
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
407
461
|
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
@@ -428,6 +482,7 @@ var StandardFunctionStrategy = class {
|
|
|
428
482
|
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
429
483
|
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
430
484
|
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
485
|
+
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
431
486
|
}
|
|
432
487
|
add(name, renderer) {
|
|
433
488
|
this.renderers.set(name, renderer);
|
|
@@ -435,6 +490,36 @@ var StandardFunctionStrategy = class {
|
|
|
435
490
|
getRenderer(name) {
|
|
436
491
|
return this.renderers.get(name);
|
|
437
492
|
}
|
|
493
|
+
renderGroupConcat(ctx) {
|
|
494
|
+
const arg = ctx.compiledArgs[0];
|
|
495
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
496
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
497
|
+
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
498
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
499
|
+
}
|
|
500
|
+
buildOrderByExpression(ctx) {
|
|
501
|
+
const orderBy = ctx.node.orderBy;
|
|
502
|
+
if (!orderBy || orderBy.length === 0) {
|
|
503
|
+
return "";
|
|
504
|
+
}
|
|
505
|
+
const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
|
|
506
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
507
|
+
}
|
|
508
|
+
formatGroupConcatSeparator(ctx) {
|
|
509
|
+
if (!ctx.node.separator) {
|
|
510
|
+
return "";
|
|
511
|
+
}
|
|
512
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
513
|
+
}
|
|
514
|
+
getGroupConcatSeparatorOperand(ctx) {
|
|
515
|
+
return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
516
|
+
}
|
|
517
|
+
static {
|
|
518
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
519
|
+
type: "Literal",
|
|
520
|
+
value: ","
|
|
521
|
+
};
|
|
522
|
+
}
|
|
438
523
|
};
|
|
439
524
|
|
|
440
525
|
// src/core/dialect/abstract.ts
|
|
@@ -781,7 +866,11 @@ var Dialect = class _Dialect {
|
|
|
781
866
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
782
867
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
783
868
|
if (renderer) {
|
|
784
|
-
return renderer({
|
|
869
|
+
return renderer({
|
|
870
|
+
node: fnNode,
|
|
871
|
+
compiledArgs,
|
|
872
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx)
|
|
873
|
+
});
|
|
785
874
|
}
|
|
786
875
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
787
876
|
}
|
|
@@ -1044,7 +1133,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1044
1133
|
return this.returningStrategy.compileReturning(returning, ctx);
|
|
1045
1134
|
}
|
|
1046
1135
|
compileInsertColumnList(columns) {
|
|
1047
|
-
return columns.map((column) =>
|
|
1136
|
+
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
1048
1137
|
}
|
|
1049
1138
|
compileInsertValues(values, ctx) {
|
|
1050
1139
|
return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
@@ -1070,7 +1159,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1070
1159
|
compileUpdateAssignments(assignments, ctx) {
|
|
1071
1160
|
return assignments.map((assignment) => {
|
|
1072
1161
|
const col = assignment.column;
|
|
1073
|
-
const target =
|
|
1162
|
+
const target = this.quoteIdentifier(col.name);
|
|
1074
1163
|
const value = this.compileOperand(assignment.value, ctx);
|
|
1075
1164
|
return `${target} = ${value}`;
|
|
1076
1165
|
}).join(", ");
|
|
@@ -1102,12 +1191,29 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1102
1191
|
if (tableSource.type === "FunctionTable") {
|
|
1103
1192
|
return this.compileFunctionTable(tableSource, ctx);
|
|
1104
1193
|
}
|
|
1194
|
+
if (tableSource.type === "DerivedTable") {
|
|
1195
|
+
return this.compileDerivedTable(tableSource, ctx);
|
|
1196
|
+
}
|
|
1105
1197
|
return this.compileTableSource(tableSource);
|
|
1106
1198
|
}
|
|
1107
1199
|
compileFunctionTable(fn, ctx) {
|
|
1108
1200
|
return FunctionTableFormatter.format(fn, ctx, this);
|
|
1109
1201
|
}
|
|
1202
|
+
compileDerivedTable(table, ctx) {
|
|
1203
|
+
if (!table.alias) {
|
|
1204
|
+
throw new Error("Derived tables must have an alias.");
|
|
1205
|
+
}
|
|
1206
|
+
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
1207
|
+
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
1208
|
+
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
1209
|
+
}
|
|
1110
1210
|
compileTableSource(table) {
|
|
1211
|
+
if (table.type === "FunctionTable") {
|
|
1212
|
+
return this.compileFunctionTable(table);
|
|
1213
|
+
}
|
|
1214
|
+
if (table.type === "DerivedTable") {
|
|
1215
|
+
return this.compileDerivedTable(table);
|
|
1216
|
+
}
|
|
1111
1217
|
const base = this.compileTableName(table);
|
|
1112
1218
|
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
1113
1219
|
}
|
|
@@ -1204,6 +1310,14 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1204
1310
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1205
1311
|
return `DATE_TRUNC('${partClean}', ${date})`;
|
|
1206
1312
|
});
|
|
1313
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1314
|
+
const arg = ctx.compiledArgs[0];
|
|
1315
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1316
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1317
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1318
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1319
|
+
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
1320
|
+
});
|
|
1207
1321
|
}
|
|
1208
1322
|
};
|
|
1209
1323
|
|
|
@@ -1448,6 +1562,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1448
1562
|
}
|
|
1449
1563
|
return `date(${date}, 'start of ${partClean}')`;
|
|
1450
1564
|
});
|
|
1565
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1566
|
+
const arg = ctx.compiledArgs[0];
|
|
1567
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1568
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1569
|
+
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
1570
|
+
});
|
|
1451
1571
|
}
|
|
1452
1572
|
};
|
|
1453
1573
|
|
|
@@ -1482,6 +1602,12 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
1482
1602
|
const columns = this.formatReturningColumns(returning);
|
|
1483
1603
|
return ` RETURNING ${columns}`;
|
|
1484
1604
|
}
|
|
1605
|
+
formatReturningColumns(returning) {
|
|
1606
|
+
return returning.map((column) => {
|
|
1607
|
+
const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
|
|
1608
|
+
return `${this.quoteIdentifier(column.name)}${alias}`;
|
|
1609
|
+
}).join(", ");
|
|
1610
|
+
}
|
|
1485
1611
|
supportsReturning() {
|
|
1486
1612
|
return true;
|
|
1487
1613
|
}
|
|
@@ -1564,6 +1690,14 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1564
1690
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1565
1691
|
return `DATETRUNC(${partClean}, ${date})`;
|
|
1566
1692
|
});
|
|
1693
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1694
|
+
const arg = ctx.compiledArgs[0];
|
|
1695
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1696
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1697
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1698
|
+
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
1699
|
+
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
1700
|
+
});
|
|
1567
1701
|
}
|
|
1568
1702
|
};
|
|
1569
1703
|
|
|
@@ -1640,6 +1774,9 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1640
1774
|
return `UPDATE ${table} SET ${assignments}${whereClause};`;
|
|
1641
1775
|
}
|
|
1642
1776
|
compileDeleteAst(ast, ctx) {
|
|
1777
|
+
if (ast.from.type !== "Table") {
|
|
1778
|
+
throw new Error("DELETE only supports base tables in the MSSQL dialect.");
|
|
1779
|
+
}
|
|
1643
1780
|
const table = this.quoteIdentifier(ast.from.name);
|
|
1644
1781
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
1645
1782
|
return `DELETE FROM ${table}${whereClause};`;
|
|
@@ -1663,9 +1800,9 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1663
1800
|
return expr;
|
|
1664
1801
|
}).join(", ");
|
|
1665
1802
|
const distinct = ast.distinct ? "DISTINCT " : "";
|
|
1666
|
-
const from =
|
|
1803
|
+
const from = this.compileTableSource(ast.from, ctx);
|
|
1667
1804
|
const joins = ast.joins.map((j) => {
|
|
1668
|
-
const table = this.
|
|
1805
|
+
const table = this.compileTableSource(j.table, ctx);
|
|
1669
1806
|
const cond = this.compileExpression(j.condition, ctx);
|
|
1670
1807
|
return `${j.kind} JOIN ${table} ON ${cond}`;
|
|
1671
1808
|
}).join(" ");
|
|
@@ -1695,6 +1832,21 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1695
1832
|
}
|
|
1696
1833
|
return pagination;
|
|
1697
1834
|
}
|
|
1835
|
+
compileTableSource(table, ctx) {
|
|
1836
|
+
if (table.type === "FunctionTable") {
|
|
1837
|
+
return FunctionTableFormatter.format(table, ctx, this);
|
|
1838
|
+
}
|
|
1839
|
+
if (table.type === "DerivedTable") {
|
|
1840
|
+
return this.compileDerivedTable(table, ctx);
|
|
1841
|
+
}
|
|
1842
|
+
const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
|
|
1843
|
+
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
1844
|
+
}
|
|
1845
|
+
compileDerivedTable(table, ctx) {
|
|
1846
|
+
const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
1847
|
+
const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
1848
|
+
return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
|
|
1849
|
+
}
|
|
1698
1850
|
compileCtes(ast, ctx) {
|
|
1699
1851
|
if (!ast.ctes || ast.ctes.length === 0) return "";
|
|
1700
1852
|
const defs = ast.ctes.map((cte) => {
|
|
@@ -1823,6 +1975,17 @@ var SelectQueryState = class _SelectQueryState {
|
|
|
1823
1975
|
joins: [...this.ast.joins ?? [], join]
|
|
1824
1976
|
});
|
|
1825
1977
|
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Replaces the FROM clause.
|
|
1980
|
+
* @param from - Table source for the FROM clause
|
|
1981
|
+
* @returns New SelectQueryState with updated FROM
|
|
1982
|
+
*/
|
|
1983
|
+
withFrom(from) {
|
|
1984
|
+
return this.clone({
|
|
1985
|
+
...this.ast,
|
|
1986
|
+
from
|
|
1987
|
+
});
|
|
1988
|
+
}
|
|
1826
1989
|
/**
|
|
1827
1990
|
* Adds a WHERE clause to the query
|
|
1828
1991
|
* @param predicate - WHERE predicate expression
|
|
@@ -1933,24 +2096,6 @@ var createJoinNode = (kind, tableName, condition, relationName) => ({
|
|
|
1933
2096
|
meta: relationName ? { relationName } : void 0
|
|
1934
2097
|
});
|
|
1935
2098
|
|
|
1936
|
-
// src/core/sql/sql.ts
|
|
1937
|
-
var JOIN_KINDS = {
|
|
1938
|
-
/** INNER JOIN type */
|
|
1939
|
-
INNER: "INNER",
|
|
1940
|
-
/** LEFT JOIN type */
|
|
1941
|
-
LEFT: "LEFT",
|
|
1942
|
-
/** RIGHT JOIN type */
|
|
1943
|
-
RIGHT: "RIGHT",
|
|
1944
|
-
/** CROSS JOIN type */
|
|
1945
|
-
CROSS: "CROSS"
|
|
1946
|
-
};
|
|
1947
|
-
var ORDER_DIRECTIONS = {
|
|
1948
|
-
/** Ascending order */
|
|
1949
|
-
ASC: "ASC",
|
|
1950
|
-
/** Descending order */
|
|
1951
|
-
DESC: "DESC"
|
|
1952
|
-
};
|
|
1953
|
-
|
|
1954
2099
|
// src/query-builder/hydration-manager.ts
|
|
1955
2100
|
var HydrationManager = class _HydrationManager {
|
|
1956
2101
|
/**
|
|
@@ -2333,19 +2478,6 @@ var buildDefaultHydrationPlan = (table) => ({
|
|
|
2333
2478
|
relations: []
|
|
2334
2479
|
});
|
|
2335
2480
|
|
|
2336
|
-
// src/core/ast/builders.ts
|
|
2337
|
-
var buildColumnNode = (table, column) => {
|
|
2338
|
-
if (column.type === "Column") {
|
|
2339
|
-
return column;
|
|
2340
|
-
}
|
|
2341
|
-
const def = column;
|
|
2342
|
-
return {
|
|
2343
|
-
type: "Column",
|
|
2344
|
-
table: def.table || table.name,
|
|
2345
|
-
name: def.name
|
|
2346
|
-
};
|
|
2347
|
-
};
|
|
2348
|
-
|
|
2349
2481
|
// src/query-builder/raw-column-parser.ts
|
|
2350
2482
|
var parseRawColumn = (col, tableName, ctes) => {
|
|
2351
2483
|
if (col.includes("(")) {
|
|
@@ -2385,6 +2517,8 @@ var QueryAstService = class {
|
|
|
2385
2517
|
const existingAliases = new Set(
|
|
2386
2518
|
this.state.ast.columns.map((c) => c.alias || c.name)
|
|
2387
2519
|
);
|
|
2520
|
+
const from = this.state.ast.from;
|
|
2521
|
+
const rootTableName = from.type === "Table" && from.alias ? from.alias : this.table.name;
|
|
2388
2522
|
const newCols = Object.entries(columns).reduce((acc, [alias, val]) => {
|
|
2389
2523
|
if (existingAliases.has(alias)) return acc;
|
|
2390
2524
|
if (isExpressionSelectionNode(val)) {
|
|
@@ -2392,9 +2526,10 @@ var QueryAstService = class {
|
|
|
2392
2526
|
return acc;
|
|
2393
2527
|
}
|
|
2394
2528
|
const colDef = val;
|
|
2529
|
+
const resolvedTable = colDef.table && colDef.table === this.table.name && from.type === "Table" && from.alias ? from.alias : colDef.table || rootTableName;
|
|
2395
2530
|
acc.push({
|
|
2396
2531
|
type: "Column",
|
|
2397
|
-
table:
|
|
2532
|
+
table: resolvedTable,
|
|
2398
2533
|
name: colDef.name,
|
|
2399
2534
|
alias
|
|
2400
2535
|
});
|
|
@@ -2409,7 +2544,9 @@ var QueryAstService = class {
|
|
|
2409
2544
|
* @returns Column selection result with updated state and added columns
|
|
2410
2545
|
*/
|
|
2411
2546
|
selectRaw(cols) {
|
|
2412
|
-
const
|
|
2547
|
+
const from = this.state.ast.from;
|
|
2548
|
+
const defaultTable = from.type === "Table" && from.alias ? from.alias : this.table.name;
|
|
2549
|
+
const newCols = cols.map((col) => parseRawColumn(col, defaultTable, this.state.ast.ctes));
|
|
2413
2550
|
const nextState = this.state.withColumns(newCols);
|
|
2414
2551
|
return { state: nextState, addedColumns: newCols };
|
|
2415
2552
|
}
|
|
@@ -2445,6 +2582,14 @@ var QueryAstService = class {
|
|
|
2445
2582
|
};
|
|
2446
2583
|
return this.state.withSetOperation(op);
|
|
2447
2584
|
}
|
|
2585
|
+
/**
|
|
2586
|
+
* Replaces the FROM clause for the current query.
|
|
2587
|
+
* @param from - Table source to use in the FROM clause
|
|
2588
|
+
* @returns Updated query state with new FROM
|
|
2589
|
+
*/
|
|
2590
|
+
withFrom(from) {
|
|
2591
|
+
return this.state.withFrom(from);
|
|
2592
|
+
}
|
|
2448
2593
|
/**
|
|
2449
2594
|
* Selects a subquery as a column
|
|
2450
2595
|
* @param alias - Alias for the subquery
|
|
@@ -2478,7 +2623,9 @@ var QueryAstService = class {
|
|
|
2478
2623
|
* @returns Updated query state with GROUP BY clause
|
|
2479
2624
|
*/
|
|
2480
2625
|
withGroupBy(col) {
|
|
2481
|
-
const
|
|
2626
|
+
const from = this.state.ast.from;
|
|
2627
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
2628
|
+
const node = buildColumnNode(tableRef, col);
|
|
2482
2629
|
return this.state.withGroupBy([node]);
|
|
2483
2630
|
}
|
|
2484
2631
|
/**
|
|
@@ -2497,7 +2644,9 @@ var QueryAstService = class {
|
|
|
2497
2644
|
* @returns Updated query state with ORDER BY clause
|
|
2498
2645
|
*/
|
|
2499
2646
|
withOrderBy(col, direction) {
|
|
2500
|
-
const
|
|
2647
|
+
const from = this.state.ast.from;
|
|
2648
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
2649
|
+
const node = buildColumnNode(tableRef, col);
|
|
2501
2650
|
return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
|
|
2502
2651
|
}
|
|
2503
2652
|
/**
|
|
@@ -2601,7 +2750,8 @@ var RelationProjectionHelper = class {
|
|
|
2601
2750
|
var assertNever = (value) => {
|
|
2602
2751
|
throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
|
|
2603
2752
|
};
|
|
2604
|
-
var baseRelationCondition = (root, relation) => {
|
|
2753
|
+
var baseRelationCondition = (root, relation, rootAlias) => {
|
|
2754
|
+
const rootTable = rootAlias || root.name;
|
|
2605
2755
|
const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
|
|
2606
2756
|
const localKey = relation.localKey || defaultLocalKey;
|
|
2607
2757
|
switch (relation.type) {
|
|
@@ -2609,12 +2759,12 @@ var baseRelationCondition = (root, relation) => {
|
|
|
2609
2759
|
case RelationKinds.HasOne:
|
|
2610
2760
|
return eq(
|
|
2611
2761
|
{ type: "Column", table: relation.target.name, name: relation.foreignKey },
|
|
2612
|
-
{ type: "Column", table:
|
|
2762
|
+
{ type: "Column", table: rootTable, name: localKey }
|
|
2613
2763
|
);
|
|
2614
2764
|
case RelationKinds.BelongsTo:
|
|
2615
2765
|
return eq(
|
|
2616
2766
|
{ type: "Column", table: relation.target.name, name: localKey },
|
|
2617
|
-
{ type: "Column", table:
|
|
2767
|
+
{ type: "Column", table: rootTable, name: relation.foreignKey }
|
|
2618
2768
|
);
|
|
2619
2769
|
case RelationKinds.BelongsToMany:
|
|
2620
2770
|
throw new Error("BelongsToMany relations do not support the standard join condition builder");
|
|
@@ -2622,12 +2772,13 @@ var baseRelationCondition = (root, relation) => {
|
|
|
2622
2772
|
return assertNever(relation);
|
|
2623
2773
|
}
|
|
2624
2774
|
};
|
|
2625
|
-
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) => {
|
|
2775
|
+
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
|
|
2626
2776
|
const rootKey = relation.localKey || findPrimaryKey(root);
|
|
2627
2777
|
const targetKey = relation.targetKey || findPrimaryKey(relation.target);
|
|
2778
|
+
const rootTable = rootAlias || root.name;
|
|
2628
2779
|
const pivotCondition = eq(
|
|
2629
2780
|
{ type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
|
|
2630
|
-
{ type: "Column", table:
|
|
2781
|
+
{ type: "Column", table: rootTable, name: rootKey }
|
|
2631
2782
|
);
|
|
2632
2783
|
const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
|
|
2633
2784
|
let targetCondition = eq(
|
|
@@ -2645,12 +2796,12 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) =>
|
|
|
2645
2796
|
);
|
|
2646
2797
|
return [pivotJoin, targetJoin];
|
|
2647
2798
|
};
|
|
2648
|
-
var buildRelationJoinCondition = (root, relation, extra) => {
|
|
2649
|
-
const base = baseRelationCondition(root, relation);
|
|
2799
|
+
var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
|
|
2800
|
+
const base = baseRelationCondition(root, relation, rootAlias);
|
|
2650
2801
|
return extra ? and(base, extra) : base;
|
|
2651
2802
|
};
|
|
2652
|
-
var buildRelationCorrelation = (root, relation) => {
|
|
2653
|
-
return baseRelationCondition(root, relation);
|
|
2803
|
+
var buildRelationCorrelation = (root, relation, rootAlias) => {
|
|
2804
|
+
return baseRelationCondition(root, relation, rootAlias);
|
|
2654
2805
|
};
|
|
2655
2806
|
|
|
2656
2807
|
// src/core/ast/join-metadata.ts
|
|
@@ -2694,7 +2845,7 @@ var RelationService = class {
|
|
|
2694
2845
|
match(relationName, predicate) {
|
|
2695
2846
|
const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
|
|
2696
2847
|
const pk = findPrimaryKey(this.table);
|
|
2697
|
-
const distinctCols = [{ type: "Column", table: this.
|
|
2848
|
+
const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
|
|
2698
2849
|
const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
|
|
2699
2850
|
const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
|
|
2700
2851
|
return { state: nextState, hydration: joined.hydration };
|
|
@@ -2781,9 +2932,13 @@ var RelationService = class {
|
|
|
2781
2932
|
* @param ast - Query AST to modify
|
|
2782
2933
|
* @returns Modified query AST with relation correlation
|
|
2783
2934
|
*/
|
|
2784
|
-
applyRelationCorrelation(relationName, ast) {
|
|
2935
|
+
applyRelationCorrelation(relationName, ast, additionalCorrelation) {
|
|
2785
2936
|
const relation = this.getRelation(relationName);
|
|
2786
|
-
const
|
|
2937
|
+
const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
|
|
2938
|
+
let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
|
|
2939
|
+
if (additionalCorrelation) {
|
|
2940
|
+
correlation = and(correlation, additionalCorrelation);
|
|
2941
|
+
}
|
|
2787
2942
|
const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
|
|
2788
2943
|
return {
|
|
2789
2944
|
...ast,
|
|
@@ -2800,17 +2955,19 @@ var RelationService = class {
|
|
|
2800
2955
|
*/
|
|
2801
2956
|
withJoin(state, relationName, joinKind, extraCondition) {
|
|
2802
2957
|
const relation = this.getRelation(relationName);
|
|
2958
|
+
const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
|
|
2803
2959
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
2804
2960
|
const joins = buildBelongsToManyJoins(
|
|
2805
2961
|
this.table,
|
|
2806
2962
|
relationName,
|
|
2807
2963
|
relation,
|
|
2808
2964
|
joinKind,
|
|
2809
|
-
extraCondition
|
|
2965
|
+
extraCondition,
|
|
2966
|
+
rootAlias
|
|
2810
2967
|
);
|
|
2811
2968
|
return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
|
|
2812
2969
|
}
|
|
2813
|
-
const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
|
|
2970
|
+
const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
|
|
2814
2971
|
const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
|
|
2815
2972
|
return this.astService(state).withJoin(joinNode);
|
|
2816
2973
|
}
|
|
@@ -2849,6 +3006,11 @@ var RelationService = class {
|
|
|
2849
3006
|
astService(state = this.state) {
|
|
2850
3007
|
return this.createQueryAstService(this.table, state);
|
|
2851
3008
|
}
|
|
3009
|
+
rootTableName() {
|
|
3010
|
+
const from = this.state.ast.from;
|
|
3011
|
+
if (from.type === "Table" && from.alias) return from.alias;
|
|
3012
|
+
return this.table.name;
|
|
3013
|
+
}
|
|
2852
3014
|
};
|
|
2853
3015
|
|
|
2854
3016
|
// src/query-builder/select-query-builder-deps.ts
|
|
@@ -2923,7 +3085,9 @@ var ColumnSelector = class {
|
|
|
2923
3085
|
* @returns Updated query context with DISTINCT clause
|
|
2924
3086
|
*/
|
|
2925
3087
|
distinct(context, columns) {
|
|
2926
|
-
const
|
|
3088
|
+
const from = context.state.ast.from;
|
|
3089
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
|
|
3090
|
+
const nodes = columns.map((col) => buildColumnNode(tableRef, col));
|
|
2927
3091
|
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
2928
3092
|
const nextState = astService.withDistinct(nodes);
|
|
2929
3093
|
return { state: nextState, hydration: context.hydration };
|
|
@@ -2980,8 +3144,8 @@ var RelationManager = class {
|
|
|
2980
3144
|
* @param ast - Query AST to modify
|
|
2981
3145
|
* @returns Modified query AST with relation correlation
|
|
2982
3146
|
*/
|
|
2983
|
-
applyRelationCorrelation(context, relationName, ast) {
|
|
2984
|
-
return this.createService(context).applyRelationCorrelation(relationName, ast);
|
|
3147
|
+
applyRelationCorrelation(context, relationName, ast, additionalCorrelation) {
|
|
3148
|
+
return this.createService(context).applyRelationCorrelation(relationName, ast, additionalCorrelation);
|
|
2985
3149
|
}
|
|
2986
3150
|
/**
|
|
2987
3151
|
* Creates a relation service instance
|
|
@@ -4028,9 +4192,30 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4028
4192
|
clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
|
|
4029
4193
|
return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
|
|
4030
4194
|
}
|
|
4195
|
+
/**
|
|
4196
|
+
* Applies an alias to the root FROM table.
|
|
4197
|
+
* @param alias - Alias to apply
|
|
4198
|
+
*/
|
|
4199
|
+
as(alias) {
|
|
4200
|
+
const from = this.context.state.ast.from;
|
|
4201
|
+
if (from.type !== "Table") {
|
|
4202
|
+
throw new Error("Cannot alias non-table FROM sources");
|
|
4203
|
+
}
|
|
4204
|
+
const nextFrom = { ...from, alias };
|
|
4205
|
+
const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
|
|
4206
|
+
return this.clone(nextContext);
|
|
4207
|
+
}
|
|
4031
4208
|
resolveQueryNode(query) {
|
|
4032
4209
|
return typeof query.getAST === "function" ? query.getAST() : query;
|
|
4033
4210
|
}
|
|
4211
|
+
applyCorrelation(ast, correlation) {
|
|
4212
|
+
if (!correlation) return ast;
|
|
4213
|
+
const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
|
|
4214
|
+
return {
|
|
4215
|
+
...ast,
|
|
4216
|
+
where: combinedWhere
|
|
4217
|
+
};
|
|
4218
|
+
}
|
|
4034
4219
|
createChildBuilder(table) {
|
|
4035
4220
|
return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
|
|
4036
4221
|
}
|
|
@@ -4059,6 +4244,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4059
4244
|
select(columns) {
|
|
4060
4245
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
4061
4246
|
}
|
|
4247
|
+
/**
|
|
4248
|
+
* Selects columns from the root table by name (typed).
|
|
4249
|
+
* @param cols - Column names on the root table
|
|
4250
|
+
*/
|
|
4251
|
+
selectColumns(...cols) {
|
|
4252
|
+
const selection = {};
|
|
4253
|
+
for (const key of cols) {
|
|
4254
|
+
const col = this.env.table.columns[key];
|
|
4255
|
+
if (!col) {
|
|
4256
|
+
throw new Error(`Column '${key}' not found on table '${this.env.table.name}'`);
|
|
4257
|
+
}
|
|
4258
|
+
selection[key] = col;
|
|
4259
|
+
}
|
|
4260
|
+
return this.select(selection);
|
|
4261
|
+
}
|
|
4062
4262
|
/**
|
|
4063
4263
|
|
|
4064
4264
|
* Selects raw column expressions
|
|
@@ -4107,6 +4307,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4107
4307
|
const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
|
|
4108
4308
|
return this.clone(nextContext);
|
|
4109
4309
|
}
|
|
4310
|
+
/**
|
|
4311
|
+
* Replaces the FROM clause with a derived table (subquery with alias)
|
|
4312
|
+
* @param subquery - Subquery to use as the FROM source
|
|
4313
|
+
* @param alias - Alias for the derived table
|
|
4314
|
+
* @param columnAliases - Optional column alias list
|
|
4315
|
+
* @returns New query builder instance with updated FROM
|
|
4316
|
+
*/
|
|
4317
|
+
fromSubquery(subquery, alias, columnAliases) {
|
|
4318
|
+
const subAst = this.resolveQueryNode(subquery);
|
|
4319
|
+
const fromNode = derivedTable(subAst, alias, columnAliases);
|
|
4320
|
+
const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
|
|
4321
|
+
return this.clone(nextContext);
|
|
4322
|
+
}
|
|
4110
4323
|
/**
|
|
4111
4324
|
|
|
4112
4325
|
* Selects a subquery as a column
|
|
@@ -4122,6 +4335,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4122
4335
|
const query = this.resolveQueryNode(sub);
|
|
4123
4336
|
return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
|
|
4124
4337
|
}
|
|
4338
|
+
/**
|
|
4339
|
+
* Adds a JOIN against a derived table (subquery with alias)
|
|
4340
|
+
* @param subquery - Subquery to join
|
|
4341
|
+
* @param alias - Alias for the derived table
|
|
4342
|
+
* @param condition - Join condition expression
|
|
4343
|
+
* @param joinKind - Join kind (defaults to INNER)
|
|
4344
|
+
* @param columnAliases - Optional column alias list for the derived table
|
|
4345
|
+
* @returns New query builder instance with the derived-table join
|
|
4346
|
+
*/
|
|
4347
|
+
joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
|
|
4348
|
+
const subAst = this.resolveQueryNode(subquery);
|
|
4349
|
+
const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
|
|
4350
|
+
const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
|
|
4351
|
+
return this.clone(nextContext);
|
|
4352
|
+
}
|
|
4125
4353
|
/**
|
|
4126
4354
|
|
|
4127
4355
|
* Adds an INNER JOIN to the query
|
|
@@ -4219,6 +4447,47 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4219
4447
|
nextLazy.add(relationName);
|
|
4220
4448
|
return this.clone(this.context, nextLazy);
|
|
4221
4449
|
}
|
|
4450
|
+
/**
|
|
4451
|
+
* Selects columns for a related table in a single hop.
|
|
4452
|
+
*/
|
|
4453
|
+
selectRelationColumns(relationName, ...cols) {
|
|
4454
|
+
const relation = this.env.table.relations[relationName];
|
|
4455
|
+
if (!relation) {
|
|
4456
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4457
|
+
}
|
|
4458
|
+
const target = relation.target;
|
|
4459
|
+
for (const col of cols) {
|
|
4460
|
+
if (!target.columns[col]) {
|
|
4461
|
+
throw new Error(
|
|
4462
|
+
`Column '${col}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4466
|
+
return this.include(relationName, { columns: cols });
|
|
4467
|
+
}
|
|
4468
|
+
/**
|
|
4469
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
4470
|
+
*/
|
|
4471
|
+
includePick(relationName, cols) {
|
|
4472
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
4473
|
+
}
|
|
4474
|
+
/**
|
|
4475
|
+
* Selects columns for the root table and relations from a single config object.
|
|
4476
|
+
*/
|
|
4477
|
+
selectColumnsDeep(config) {
|
|
4478
|
+
let qb = this;
|
|
4479
|
+
if (config.root?.length) {
|
|
4480
|
+
qb = qb.selectColumns(...config.root);
|
|
4481
|
+
}
|
|
4482
|
+
for (const key of Object.keys(config)) {
|
|
4483
|
+
if (key === "root") continue;
|
|
4484
|
+
const relName = key;
|
|
4485
|
+
const cols = config[relName];
|
|
4486
|
+
if (!cols || !cols.length) continue;
|
|
4487
|
+
qb = qb.selectRelationColumns(relName, ...cols);
|
|
4488
|
+
}
|
|
4489
|
+
return qb;
|
|
4490
|
+
}
|
|
4222
4491
|
getLazyRelations() {
|
|
4223
4492
|
return Array.from(this.lazyRelations);
|
|
4224
4493
|
}
|
|
@@ -4380,9 +4649,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4380
4649
|
* @returns New query builder instance with the WHERE EXISTS condition
|
|
4381
4650
|
|
|
4382
4651
|
*/
|
|
4383
|
-
whereExists(subquery) {
|
|
4652
|
+
whereExists(subquery, correlate) {
|
|
4384
4653
|
const subAst = this.resolveQueryNode(subquery);
|
|
4385
|
-
|
|
4654
|
+
const correlated = this.applyCorrelation(subAst, correlate);
|
|
4655
|
+
return this.where(exists(correlated));
|
|
4386
4656
|
}
|
|
4387
4657
|
/**
|
|
4388
4658
|
|
|
@@ -4393,9 +4663,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4393
4663
|
* @returns New query builder instance with the WHERE NOT EXISTS condition
|
|
4394
4664
|
|
|
4395
4665
|
*/
|
|
4396
|
-
whereNotExists(subquery) {
|
|
4666
|
+
whereNotExists(subquery, correlate) {
|
|
4397
4667
|
const subAst = this.resolveQueryNode(subquery);
|
|
4398
|
-
|
|
4668
|
+
const correlated = this.applyCorrelation(subAst, correlate);
|
|
4669
|
+
return this.where(notExists(correlated));
|
|
4399
4670
|
}
|
|
4400
4671
|
/**
|
|
4401
4672
|
|
|
@@ -4408,17 +4679,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4408
4679
|
* @returns New query builder instance with the relationship existence check
|
|
4409
4680
|
|
|
4410
4681
|
*/
|
|
4411
|
-
whereHas(relationName,
|
|
4682
|
+
whereHas(relationName, callbackOrOptions, maybeOptions) {
|
|
4412
4683
|
const relation = this.env.table.relations[relationName];
|
|
4413
4684
|
if (!relation) {
|
|
4414
4685
|
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4415
4686
|
}
|
|
4687
|
+
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
4688
|
+
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
4416
4689
|
let subQb = this.createChildBuilder(relation.target);
|
|
4417
4690
|
if (callback) {
|
|
4418
4691
|
subQb = callback(subQb);
|
|
4419
4692
|
}
|
|
4420
4693
|
const subAst = subQb.getAST();
|
|
4421
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
|
|
4694
|
+
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
4422
4695
|
return this.where(exists(finalSubAst));
|
|
4423
4696
|
}
|
|
4424
4697
|
/**
|
|
@@ -4432,17 +4705,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4432
4705
|
* @returns New query builder instance with the relationship non-existence check
|
|
4433
4706
|
|
|
4434
4707
|
*/
|
|
4435
|
-
whereHasNot(relationName,
|
|
4708
|
+
whereHasNot(relationName, callbackOrOptions, maybeOptions) {
|
|
4436
4709
|
const relation = this.env.table.relations[relationName];
|
|
4437
4710
|
if (!relation) {
|
|
4438
4711
|
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4439
4712
|
}
|
|
4713
|
+
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
4714
|
+
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
4440
4715
|
let subQb = this.createChildBuilder(relation.target);
|
|
4441
4716
|
if (callback) {
|
|
4442
4717
|
subQb = callback(subQb);
|
|
4443
4718
|
}
|
|
4444
4719
|
const subAst = subQb.getAST();
|
|
4445
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
|
|
4720
|
+
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
4446
4721
|
return this.where(notExists(finalSubAst));
|
|
4447
4722
|
}
|
|
4448
4723
|
/**
|