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
package/dist/index.cjs
CHANGED
|
@@ -84,6 +84,7 @@ __export(index_exports, {
|
|
|
84
84
|
columnOperand: () => columnOperand,
|
|
85
85
|
concat: () => concat,
|
|
86
86
|
concatWs: () => concatWs,
|
|
87
|
+
correlateBy: () => correlateBy,
|
|
87
88
|
cos: () => cos,
|
|
88
89
|
cot: () => cot,
|
|
89
90
|
count: () => count,
|
|
@@ -112,6 +113,7 @@ __export(index_exports, {
|
|
|
112
113
|
diffSchema: () => diffSchema,
|
|
113
114
|
endOfMonth: () => endOfMonth,
|
|
114
115
|
eq: () => eq,
|
|
116
|
+
esel: () => esel,
|
|
115
117
|
executeHydrated: () => executeHydrated,
|
|
116
118
|
executeHydratedWithContexts: () => executeHydratedWithContexts,
|
|
117
119
|
exists: () => exists,
|
|
@@ -123,6 +125,7 @@ __export(index_exports, {
|
|
|
123
125
|
generateCreateTableSql: () => generateCreateTableSql,
|
|
124
126
|
generateSchemaSql: () => generateSchemaSql,
|
|
125
127
|
getSchemaIntrospector: () => getSchemaIntrospector,
|
|
128
|
+
groupConcat: () => groupConcat,
|
|
126
129
|
gt: () => gt,
|
|
127
130
|
gte: () => gte,
|
|
128
131
|
hasMany: () => hasMany,
|
|
@@ -137,6 +140,7 @@ __export(index_exports, {
|
|
|
137
140
|
isNotNull: () => isNotNull,
|
|
138
141
|
isNull: () => isNull,
|
|
139
142
|
isOperandNode: () => isOperandNode,
|
|
143
|
+
isValueOperandInput: () => isValueOperandInput,
|
|
140
144
|
isWindowFunctionNode: () => isWindowFunctionNode,
|
|
141
145
|
jsonPath: () => jsonPath,
|
|
142
146
|
lag: () => lag,
|
|
@@ -159,6 +163,8 @@ __export(index_exports, {
|
|
|
159
163
|
lt: () => lt,
|
|
160
164
|
lte: () => lte,
|
|
161
165
|
ltrim: () => ltrim,
|
|
166
|
+
max: () => max,
|
|
167
|
+
min: () => min,
|
|
162
168
|
mod: () => mod,
|
|
163
169
|
month: () => month,
|
|
164
170
|
neq: () => neq,
|
|
@@ -169,6 +175,7 @@ __export(index_exports, {
|
|
|
169
175
|
now: () => now,
|
|
170
176
|
ntile: () => ntile,
|
|
171
177
|
or: () => or,
|
|
178
|
+
outerRef: () => outerRef,
|
|
172
179
|
pi: () => pi,
|
|
173
180
|
position: () => position,
|
|
174
181
|
pow: () => pow,
|
|
@@ -189,6 +196,7 @@ __export(index_exports, {
|
|
|
189
196
|
rowsToQueryResult: () => rowsToQueryResult,
|
|
190
197
|
rpad: () => rpad,
|
|
191
198
|
rtrim: () => rtrim,
|
|
199
|
+
sel: () => sel,
|
|
192
200
|
sign: () => sign,
|
|
193
201
|
sin: () => sin,
|
|
194
202
|
space: () => space,
|
|
@@ -273,6 +281,30 @@ var col = {
|
|
|
273
281
|
* Creates a UUID column definition
|
|
274
282
|
*/
|
|
275
283
|
uuid: () => ({ name: "", type: "UUID" }),
|
|
284
|
+
/**
|
|
285
|
+
* Creates a binary large object column definition
|
|
286
|
+
*/
|
|
287
|
+
blob: () => ({ name: "", type: "BLOB" }),
|
|
288
|
+
/**
|
|
289
|
+
* Creates a fixed-length binary column definition
|
|
290
|
+
*/
|
|
291
|
+
binary: (length2) => ({
|
|
292
|
+
name: "",
|
|
293
|
+
type: "BINARY",
|
|
294
|
+
args: length2 !== void 0 ? [length2] : void 0
|
|
295
|
+
}),
|
|
296
|
+
/**
|
|
297
|
+
* Creates a variable-length binary column definition
|
|
298
|
+
*/
|
|
299
|
+
varbinary: (length2) => ({
|
|
300
|
+
name: "",
|
|
301
|
+
type: "VARBINARY",
|
|
302
|
+
args: length2 !== void 0 ? [length2] : void 0
|
|
303
|
+
}),
|
|
304
|
+
/**
|
|
305
|
+
* Creates a Postgres bytea column definition
|
|
306
|
+
*/
|
|
307
|
+
bytea: () => ({ name: "", type: "BYTEA" }),
|
|
276
308
|
/**
|
|
277
309
|
* Creates a timestamp column definition
|
|
278
310
|
*/
|
|
@@ -422,10 +454,13 @@ var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressi
|
|
|
422
454
|
|
|
423
455
|
// src/core/ast/expression-builders.ts
|
|
424
456
|
var valueToOperand = (value) => {
|
|
425
|
-
if (value
|
|
426
|
-
return
|
|
457
|
+
if (isOperandNode(value)) {
|
|
458
|
+
return value;
|
|
427
459
|
}
|
|
428
|
-
return
|
|
460
|
+
return {
|
|
461
|
+
type: "Literal",
|
|
462
|
+
value
|
|
463
|
+
};
|
|
429
464
|
};
|
|
430
465
|
var toNode = (col2) => {
|
|
431
466
|
if (isOperandNode(col2)) return col2;
|
|
@@ -436,14 +471,20 @@ var toLiteralNode = (value) => ({
|
|
|
436
471
|
type: "Literal",
|
|
437
472
|
value
|
|
438
473
|
});
|
|
474
|
+
var isLiteralValue = (value) => value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
475
|
+
var isValueOperandInput = (value) => isOperandNode(value) || isLiteralValue(value);
|
|
439
476
|
var toOperand = (val) => {
|
|
440
|
-
if (val
|
|
441
|
-
|
|
442
|
-
return { type: "Literal", value: val };
|
|
477
|
+
if (isLiteralValue(val)) {
|
|
478
|
+
return valueToOperand(val);
|
|
443
479
|
}
|
|
444
480
|
return toNode(val);
|
|
445
481
|
};
|
|
446
482
|
var columnOperand = (col2) => toNode(col2);
|
|
483
|
+
var outerRef = (col2) => ({
|
|
484
|
+
...columnOperand(col2),
|
|
485
|
+
scope: "outer"
|
|
486
|
+
});
|
|
487
|
+
var correlateBy = (table, column) => outerRef({ name: column, table });
|
|
447
488
|
var createBinaryExpression = (operator, left2, right2, escape) => {
|
|
448
489
|
const node = {
|
|
449
490
|
type: "BinaryExpression",
|
|
@@ -585,6 +626,62 @@ var windowFunction = (name, args = [], partitionBy, orderBy) => {
|
|
|
585
626
|
return buildWindowFunction(name, nodeArgs, partitionNodes, orderNodes);
|
|
586
627
|
};
|
|
587
628
|
|
|
629
|
+
// src/core/sql/sql.ts
|
|
630
|
+
var SQL_OPERATORS = {
|
|
631
|
+
/** Equality operator */
|
|
632
|
+
EQUALS: "=",
|
|
633
|
+
/** Not equals operator */
|
|
634
|
+
NOT_EQUALS: "!=",
|
|
635
|
+
/** Greater than operator */
|
|
636
|
+
GREATER_THAN: ">",
|
|
637
|
+
/** Greater than or equal operator */
|
|
638
|
+
GREATER_OR_EQUAL: ">=",
|
|
639
|
+
/** Less than operator */
|
|
640
|
+
LESS_THAN: "<",
|
|
641
|
+
/** Less than or equal operator */
|
|
642
|
+
LESS_OR_EQUAL: "<=",
|
|
643
|
+
/** LIKE pattern matching operator */
|
|
644
|
+
LIKE: "LIKE",
|
|
645
|
+
/** NOT LIKE pattern matching operator */
|
|
646
|
+
NOT_LIKE: "NOT LIKE",
|
|
647
|
+
/** IN membership operator */
|
|
648
|
+
IN: "IN",
|
|
649
|
+
/** NOT IN membership operator */
|
|
650
|
+
NOT_IN: "NOT IN",
|
|
651
|
+
/** BETWEEN range operator */
|
|
652
|
+
BETWEEN: "BETWEEN",
|
|
653
|
+
/** NOT BETWEEN range operator */
|
|
654
|
+
NOT_BETWEEN: "NOT BETWEEN",
|
|
655
|
+
/** IS NULL null check operator */
|
|
656
|
+
IS_NULL: "IS NULL",
|
|
657
|
+
/** IS NOT NULL null check operator */
|
|
658
|
+
IS_NOT_NULL: "IS NOT NULL",
|
|
659
|
+
/** Logical AND operator */
|
|
660
|
+
AND: "AND",
|
|
661
|
+
/** Logical OR operator */
|
|
662
|
+
OR: "OR",
|
|
663
|
+
/** EXISTS operator */
|
|
664
|
+
EXISTS: "EXISTS",
|
|
665
|
+
/** NOT EXISTS operator */
|
|
666
|
+
NOT_EXISTS: "NOT EXISTS"
|
|
667
|
+
};
|
|
668
|
+
var JOIN_KINDS = {
|
|
669
|
+
/** INNER JOIN type */
|
|
670
|
+
INNER: "INNER",
|
|
671
|
+
/** LEFT JOIN type */
|
|
672
|
+
LEFT: "LEFT",
|
|
673
|
+
/** RIGHT JOIN type */
|
|
674
|
+
RIGHT: "RIGHT",
|
|
675
|
+
/** CROSS JOIN type */
|
|
676
|
+
CROSS: "CROSS"
|
|
677
|
+
};
|
|
678
|
+
var ORDER_DIRECTIONS = {
|
|
679
|
+
/** Ascending order */
|
|
680
|
+
ASC: "ASC",
|
|
681
|
+
/** Descending order */
|
|
682
|
+
DESC: "DESC"
|
|
683
|
+
};
|
|
684
|
+
|
|
588
685
|
// src/core/ast/aggregate-functions.ts
|
|
589
686
|
var buildAggregate = (name) => (col2) => ({
|
|
590
687
|
type: "Function",
|
|
@@ -594,6 +691,20 @@ var buildAggregate = (name) => (col2) => ({
|
|
|
594
691
|
var count = buildAggregate("COUNT");
|
|
595
692
|
var sum = buildAggregate("SUM");
|
|
596
693
|
var avg = buildAggregate("AVG");
|
|
694
|
+
var min = buildAggregate("MIN");
|
|
695
|
+
var max = buildAggregate("MAX");
|
|
696
|
+
var toOrderByNode = (order) => ({
|
|
697
|
+
type: "OrderBy",
|
|
698
|
+
column: columnOperand(order.column),
|
|
699
|
+
direction: order.direction ?? ORDER_DIRECTIONS.ASC
|
|
700
|
+
});
|
|
701
|
+
var groupConcat = (col2, options) => ({
|
|
702
|
+
type: "Function",
|
|
703
|
+
name: "GROUP_CONCAT",
|
|
704
|
+
args: [columnOperand(col2)],
|
|
705
|
+
orderBy: options?.orderBy?.map(toOrderByNode),
|
|
706
|
+
separator: options?.separator !== void 0 ? valueToOperand(options.separator) : void 0
|
|
707
|
+
});
|
|
597
708
|
|
|
598
709
|
// src/core/ast/expression-visitor.ts
|
|
599
710
|
var expressionDispatchers = /* @__PURE__ */ new Map();
|
|
@@ -684,13 +795,57 @@ var toTableRef = (table) => ({
|
|
|
684
795
|
alias: table.alias
|
|
685
796
|
});
|
|
686
797
|
|
|
798
|
+
// src/core/ast/builders.ts
|
|
799
|
+
var buildColumnNode = (table, column) => {
|
|
800
|
+
if (column.type === "Column") {
|
|
801
|
+
return column;
|
|
802
|
+
}
|
|
803
|
+
const def = column;
|
|
804
|
+
const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
|
|
805
|
+
return {
|
|
806
|
+
type: "Column",
|
|
807
|
+
table: baseTable,
|
|
808
|
+
name: def.name
|
|
809
|
+
};
|
|
810
|
+
};
|
|
811
|
+
var buildColumnNodes = (table, names) => names.map((name) => ({
|
|
812
|
+
type: "Column",
|
|
813
|
+
table: table.alias || table.name,
|
|
814
|
+
name
|
|
815
|
+
}));
|
|
816
|
+
var createTableNode = (table) => ({
|
|
817
|
+
type: "Table",
|
|
818
|
+
name: table.name
|
|
819
|
+
});
|
|
820
|
+
var fnTable = (name, args = [], alias, opts) => ({
|
|
821
|
+
type: "FunctionTable",
|
|
822
|
+
name,
|
|
823
|
+
args,
|
|
824
|
+
alias,
|
|
825
|
+
lateral: opts?.lateral,
|
|
826
|
+
withOrdinality: opts?.withOrdinality,
|
|
827
|
+
columnAliases: opts?.columnAliases,
|
|
828
|
+
schema: opts?.schema
|
|
829
|
+
});
|
|
830
|
+
var derivedTable = (query, alias, columnAliases) => ({
|
|
831
|
+
type: "DerivedTable",
|
|
832
|
+
query,
|
|
833
|
+
alias,
|
|
834
|
+
columnAliases
|
|
835
|
+
});
|
|
836
|
+
|
|
687
837
|
// src/core/functions/standard-strategy.ts
|
|
688
|
-
var StandardFunctionStrategy = class {
|
|
838
|
+
var StandardFunctionStrategy = class _StandardFunctionStrategy {
|
|
689
839
|
constructor() {
|
|
690
840
|
this.renderers = /* @__PURE__ */ new Map();
|
|
691
841
|
this.registerStandard();
|
|
692
842
|
}
|
|
693
843
|
registerStandard() {
|
|
844
|
+
this.add("COUNT", ({ compiledArgs }) => `COUNT(${compiledArgs.join(", ")})`);
|
|
845
|
+
this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
|
|
846
|
+
this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
|
|
847
|
+
this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
|
|
848
|
+
this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
|
|
694
849
|
this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
|
|
695
850
|
this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
|
|
696
851
|
this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
|
|
@@ -717,6 +872,7 @@ var StandardFunctionStrategy = class {
|
|
|
717
872
|
this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
|
|
718
873
|
this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
|
|
719
874
|
this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
|
|
875
|
+
this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
|
|
720
876
|
}
|
|
721
877
|
add(name, renderer) {
|
|
722
878
|
this.renderers.set(name, renderer);
|
|
@@ -724,6 +880,36 @@ var StandardFunctionStrategy = class {
|
|
|
724
880
|
getRenderer(name) {
|
|
725
881
|
return this.renderers.get(name);
|
|
726
882
|
}
|
|
883
|
+
renderGroupConcat(ctx) {
|
|
884
|
+
const arg = ctx.compiledArgs[0];
|
|
885
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
886
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
887
|
+
const separatorClause = this.formatGroupConcatSeparator(ctx);
|
|
888
|
+
return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
|
|
889
|
+
}
|
|
890
|
+
buildOrderByExpression(ctx) {
|
|
891
|
+
const orderBy = ctx.node.orderBy;
|
|
892
|
+
if (!orderBy || orderBy.length === 0) {
|
|
893
|
+
return "";
|
|
894
|
+
}
|
|
895
|
+
const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
|
|
896
|
+
return `ORDER BY ${parts.join(", ")}`;
|
|
897
|
+
}
|
|
898
|
+
formatGroupConcatSeparator(ctx) {
|
|
899
|
+
if (!ctx.node.separator) {
|
|
900
|
+
return "";
|
|
901
|
+
}
|
|
902
|
+
return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
|
|
903
|
+
}
|
|
904
|
+
getGroupConcatSeparatorOperand(ctx) {
|
|
905
|
+
return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
|
|
906
|
+
}
|
|
907
|
+
static {
|
|
908
|
+
this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
|
|
909
|
+
type: "Literal",
|
|
910
|
+
value: ","
|
|
911
|
+
};
|
|
912
|
+
}
|
|
727
913
|
};
|
|
728
914
|
|
|
729
915
|
// src/core/dialect/abstract.ts
|
|
@@ -1070,7 +1256,11 @@ var Dialect = class _Dialect {
|
|
|
1070
1256
|
const compiledArgs = fnNode.args.map((arg) => this.compileOperand(arg, ctx));
|
|
1071
1257
|
const renderer = this.functionStrategy.getRenderer(fnNode.name);
|
|
1072
1258
|
if (renderer) {
|
|
1073
|
-
return renderer({
|
|
1259
|
+
return renderer({
|
|
1260
|
+
node: fnNode,
|
|
1261
|
+
compiledArgs,
|
|
1262
|
+
compileOperand: (operand) => this.compileOperand(operand, ctx)
|
|
1263
|
+
});
|
|
1074
1264
|
}
|
|
1075
1265
|
return `${fnNode.name}(${compiledArgs.join(", ")})`;
|
|
1076
1266
|
}
|
|
@@ -1333,7 +1523,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1333
1523
|
return this.returningStrategy.compileReturning(returning, ctx);
|
|
1334
1524
|
}
|
|
1335
1525
|
compileInsertColumnList(columns) {
|
|
1336
|
-
return columns.map((column) =>
|
|
1526
|
+
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
1337
1527
|
}
|
|
1338
1528
|
compileInsertValues(values, ctx) {
|
|
1339
1529
|
return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
|
|
@@ -1359,7 +1549,7 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1359
1549
|
compileUpdateAssignments(assignments, ctx) {
|
|
1360
1550
|
return assignments.map((assignment) => {
|
|
1361
1551
|
const col2 = assignment.column;
|
|
1362
|
-
const target =
|
|
1552
|
+
const target = this.quoteIdentifier(col2.name);
|
|
1363
1553
|
const value = this.compileOperand(assignment.value, ctx);
|
|
1364
1554
|
return `${target} = ${value}`;
|
|
1365
1555
|
}).join(", ");
|
|
@@ -1391,12 +1581,29 @@ var SqlDialectBase = class extends Dialect {
|
|
|
1391
1581
|
if (tableSource.type === "FunctionTable") {
|
|
1392
1582
|
return this.compileFunctionTable(tableSource, ctx);
|
|
1393
1583
|
}
|
|
1584
|
+
if (tableSource.type === "DerivedTable") {
|
|
1585
|
+
return this.compileDerivedTable(tableSource, ctx);
|
|
1586
|
+
}
|
|
1394
1587
|
return this.compileTableSource(tableSource);
|
|
1395
1588
|
}
|
|
1396
1589
|
compileFunctionTable(fn4, ctx) {
|
|
1397
1590
|
return FunctionTableFormatter.format(fn4, ctx, this);
|
|
1398
1591
|
}
|
|
1592
|
+
compileDerivedTable(table, ctx) {
|
|
1593
|
+
if (!table.alias) {
|
|
1594
|
+
throw new Error("Derived tables must have an alias.");
|
|
1595
|
+
}
|
|
1596
|
+
const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
1597
|
+
const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
1598
|
+
return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
|
|
1599
|
+
}
|
|
1399
1600
|
compileTableSource(table) {
|
|
1601
|
+
if (table.type === "FunctionTable") {
|
|
1602
|
+
return this.compileFunctionTable(table);
|
|
1603
|
+
}
|
|
1604
|
+
if (table.type === "DerivedTable") {
|
|
1605
|
+
return this.compileDerivedTable(table);
|
|
1606
|
+
}
|
|
1400
1607
|
const base = this.compileTableName(table);
|
|
1401
1608
|
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
1402
1609
|
}
|
|
@@ -1493,6 +1700,14 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1493
1700
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1494
1701
|
return `DATE_TRUNC('${partClean}', ${date})`;
|
|
1495
1702
|
});
|
|
1703
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1704
|
+
const arg = ctx.compiledArgs[0];
|
|
1705
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
1706
|
+
const orderSegment = orderClause ? ` ${orderClause}` : "";
|
|
1707
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1708
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1709
|
+
return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
|
|
1710
|
+
});
|
|
1496
1711
|
}
|
|
1497
1712
|
};
|
|
1498
1713
|
|
|
@@ -1737,6 +1952,12 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1737
1952
|
}
|
|
1738
1953
|
return `date(${date}, 'start of ${partClean}')`;
|
|
1739
1954
|
});
|
|
1955
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
1956
|
+
const arg = ctx.compiledArgs[0];
|
|
1957
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
1958
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
1959
|
+
return `GROUP_CONCAT(${arg}, ${separator})`;
|
|
1960
|
+
});
|
|
1740
1961
|
}
|
|
1741
1962
|
};
|
|
1742
1963
|
|
|
@@ -1771,6 +1992,12 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
1771
1992
|
const columns = this.formatReturningColumns(returning);
|
|
1772
1993
|
return ` RETURNING ${columns}`;
|
|
1773
1994
|
}
|
|
1995
|
+
formatReturningColumns(returning) {
|
|
1996
|
+
return returning.map((column) => {
|
|
1997
|
+
const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
|
|
1998
|
+
return `${this.quoteIdentifier(column.name)}${alias}`;
|
|
1999
|
+
}).join(", ");
|
|
2000
|
+
}
|
|
1774
2001
|
supportsReturning() {
|
|
1775
2002
|
return true;
|
|
1776
2003
|
}
|
|
@@ -1853,6 +2080,14 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
1853
2080
|
const partClean = String(partArg.value).replace(/['"]/g, "").toLowerCase();
|
|
1854
2081
|
return `DATETRUNC(${partClean}, ${date})`;
|
|
1855
2082
|
});
|
|
2083
|
+
this.add("GROUP_CONCAT", (ctx) => {
|
|
2084
|
+
const arg = ctx.compiledArgs[0];
|
|
2085
|
+
const separatorOperand = this.getGroupConcatSeparatorOperand(ctx);
|
|
2086
|
+
const separator = ctx.compileOperand(separatorOperand);
|
|
2087
|
+
const orderClause = this.buildOrderByExpression(ctx);
|
|
2088
|
+
const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
|
|
2089
|
+
return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
|
|
2090
|
+
});
|
|
1856
2091
|
}
|
|
1857
2092
|
};
|
|
1858
2093
|
|
|
@@ -1929,6 +2164,9 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1929
2164
|
return `UPDATE ${table} SET ${assignments}${whereClause};`;
|
|
1930
2165
|
}
|
|
1931
2166
|
compileDeleteAst(ast, ctx) {
|
|
2167
|
+
if (ast.from.type !== "Table") {
|
|
2168
|
+
throw new Error("DELETE only supports base tables in the MSSQL dialect.");
|
|
2169
|
+
}
|
|
1932
2170
|
const table = this.quoteIdentifier(ast.from.name);
|
|
1933
2171
|
const whereClause = this.compileWhere(ast.where, ctx);
|
|
1934
2172
|
return `DELETE FROM ${table}${whereClause};`;
|
|
@@ -1952,9 +2190,9 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1952
2190
|
return expr;
|
|
1953
2191
|
}).join(", ");
|
|
1954
2192
|
const distinct = ast.distinct ? "DISTINCT " : "";
|
|
1955
|
-
const from =
|
|
2193
|
+
const from = this.compileTableSource(ast.from, ctx);
|
|
1956
2194
|
const joins = ast.joins.map((j) => {
|
|
1957
|
-
const table = this.
|
|
2195
|
+
const table = this.compileTableSource(j.table, ctx);
|
|
1958
2196
|
const cond = this.compileExpression(j.condition, ctx);
|
|
1959
2197
|
return `${j.kind} JOIN ${table} ON ${cond}`;
|
|
1960
2198
|
}).join(" ");
|
|
@@ -1984,6 +2222,21 @@ var SqlServerDialect = class extends Dialect {
|
|
|
1984
2222
|
}
|
|
1985
2223
|
return pagination;
|
|
1986
2224
|
}
|
|
2225
|
+
compileTableSource(table, ctx) {
|
|
2226
|
+
if (table.type === "FunctionTable") {
|
|
2227
|
+
return FunctionTableFormatter.format(table, ctx, this);
|
|
2228
|
+
}
|
|
2229
|
+
if (table.type === "DerivedTable") {
|
|
2230
|
+
return this.compileDerivedTable(table, ctx);
|
|
2231
|
+
}
|
|
2232
|
+
const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
|
|
2233
|
+
return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
|
|
2234
|
+
}
|
|
2235
|
+
compileDerivedTable(table, ctx) {
|
|
2236
|
+
const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
|
|
2237
|
+
const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
|
|
2238
|
+
return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
|
|
2239
|
+
}
|
|
1987
2240
|
compileCtes(ast, ctx) {
|
|
1988
2241
|
if (!ast.ctes || ast.ctes.length === 0) return "";
|
|
1989
2242
|
const defs = ast.ctes.map((cte) => {
|
|
@@ -2112,6 +2365,17 @@ var SelectQueryState = class _SelectQueryState {
|
|
|
2112
2365
|
joins: [...this.ast.joins ?? [], join]
|
|
2113
2366
|
});
|
|
2114
2367
|
}
|
|
2368
|
+
/**
|
|
2369
|
+
* Replaces the FROM clause.
|
|
2370
|
+
* @param from - Table source for the FROM clause
|
|
2371
|
+
* @returns New SelectQueryState with updated FROM
|
|
2372
|
+
*/
|
|
2373
|
+
withFrom(from) {
|
|
2374
|
+
return this.clone({
|
|
2375
|
+
...this.ast,
|
|
2376
|
+
from
|
|
2377
|
+
});
|
|
2378
|
+
}
|
|
2115
2379
|
/**
|
|
2116
2380
|
* Adds a WHERE clause to the query
|
|
2117
2381
|
* @param predicate - WHERE predicate expression
|
|
@@ -2222,62 +2486,6 @@ var createJoinNode = (kind, tableName, condition, relationName) => ({
|
|
|
2222
2486
|
meta: relationName ? { relationName } : void 0
|
|
2223
2487
|
});
|
|
2224
2488
|
|
|
2225
|
-
// src/core/sql/sql.ts
|
|
2226
|
-
var SQL_OPERATORS = {
|
|
2227
|
-
/** Equality operator */
|
|
2228
|
-
EQUALS: "=",
|
|
2229
|
-
/** Not equals operator */
|
|
2230
|
-
NOT_EQUALS: "!=",
|
|
2231
|
-
/** Greater than operator */
|
|
2232
|
-
GREATER_THAN: ">",
|
|
2233
|
-
/** Greater than or equal operator */
|
|
2234
|
-
GREATER_OR_EQUAL: ">=",
|
|
2235
|
-
/** Less than operator */
|
|
2236
|
-
LESS_THAN: "<",
|
|
2237
|
-
/** Less than or equal operator */
|
|
2238
|
-
LESS_OR_EQUAL: "<=",
|
|
2239
|
-
/** LIKE pattern matching operator */
|
|
2240
|
-
LIKE: "LIKE",
|
|
2241
|
-
/** NOT LIKE pattern matching operator */
|
|
2242
|
-
NOT_LIKE: "NOT LIKE",
|
|
2243
|
-
/** IN membership operator */
|
|
2244
|
-
IN: "IN",
|
|
2245
|
-
/** NOT IN membership operator */
|
|
2246
|
-
NOT_IN: "NOT IN",
|
|
2247
|
-
/** BETWEEN range operator */
|
|
2248
|
-
BETWEEN: "BETWEEN",
|
|
2249
|
-
/** NOT BETWEEN range operator */
|
|
2250
|
-
NOT_BETWEEN: "NOT BETWEEN",
|
|
2251
|
-
/** IS NULL null check operator */
|
|
2252
|
-
IS_NULL: "IS NULL",
|
|
2253
|
-
/** IS NOT NULL null check operator */
|
|
2254
|
-
IS_NOT_NULL: "IS NOT NULL",
|
|
2255
|
-
/** Logical AND operator */
|
|
2256
|
-
AND: "AND",
|
|
2257
|
-
/** Logical OR operator */
|
|
2258
|
-
OR: "OR",
|
|
2259
|
-
/** EXISTS operator */
|
|
2260
|
-
EXISTS: "EXISTS",
|
|
2261
|
-
/** NOT EXISTS operator */
|
|
2262
|
-
NOT_EXISTS: "NOT EXISTS"
|
|
2263
|
-
};
|
|
2264
|
-
var JOIN_KINDS = {
|
|
2265
|
-
/** INNER JOIN type */
|
|
2266
|
-
INNER: "INNER",
|
|
2267
|
-
/** LEFT JOIN type */
|
|
2268
|
-
LEFT: "LEFT",
|
|
2269
|
-
/** RIGHT JOIN type */
|
|
2270
|
-
RIGHT: "RIGHT",
|
|
2271
|
-
/** CROSS JOIN type */
|
|
2272
|
-
CROSS: "CROSS"
|
|
2273
|
-
};
|
|
2274
|
-
var ORDER_DIRECTIONS = {
|
|
2275
|
-
/** Ascending order */
|
|
2276
|
-
ASC: "ASC",
|
|
2277
|
-
/** Descending order */
|
|
2278
|
-
DESC: "DESC"
|
|
2279
|
-
};
|
|
2280
|
-
|
|
2281
2489
|
// src/query-builder/hydration-manager.ts
|
|
2282
2490
|
var HydrationManager = class _HydrationManager {
|
|
2283
2491
|
/**
|
|
@@ -2660,38 +2868,6 @@ var buildDefaultHydrationPlan = (table) => ({
|
|
|
2660
2868
|
relations: []
|
|
2661
2869
|
});
|
|
2662
2870
|
|
|
2663
|
-
// src/core/ast/builders.ts
|
|
2664
|
-
var buildColumnNode = (table, column) => {
|
|
2665
|
-
if (column.type === "Column") {
|
|
2666
|
-
return column;
|
|
2667
|
-
}
|
|
2668
|
-
const def = column;
|
|
2669
|
-
return {
|
|
2670
|
-
type: "Column",
|
|
2671
|
-
table: def.table || table.name,
|
|
2672
|
-
name: def.name
|
|
2673
|
-
};
|
|
2674
|
-
};
|
|
2675
|
-
var buildColumnNodes = (table, names) => names.map((name) => ({
|
|
2676
|
-
type: "Column",
|
|
2677
|
-
table: table.name,
|
|
2678
|
-
name
|
|
2679
|
-
}));
|
|
2680
|
-
var createTableNode = (table) => ({
|
|
2681
|
-
type: "Table",
|
|
2682
|
-
name: table.name
|
|
2683
|
-
});
|
|
2684
|
-
var fnTable = (name, args = [], alias, opts) => ({
|
|
2685
|
-
type: "FunctionTable",
|
|
2686
|
-
name,
|
|
2687
|
-
args,
|
|
2688
|
-
alias,
|
|
2689
|
-
lateral: opts?.lateral,
|
|
2690
|
-
withOrdinality: opts?.withOrdinality,
|
|
2691
|
-
columnAliases: opts?.columnAliases,
|
|
2692
|
-
schema: opts?.schema
|
|
2693
|
-
});
|
|
2694
|
-
|
|
2695
2871
|
// src/query-builder/raw-column-parser.ts
|
|
2696
2872
|
var parseRawColumn = (col2, tableName, ctes) => {
|
|
2697
2873
|
if (col2.includes("(")) {
|
|
@@ -2731,6 +2907,8 @@ var QueryAstService = class {
|
|
|
2731
2907
|
const existingAliases = new Set(
|
|
2732
2908
|
this.state.ast.columns.map((c) => c.alias || c.name)
|
|
2733
2909
|
);
|
|
2910
|
+
const from = this.state.ast.from;
|
|
2911
|
+
const rootTableName = from.type === "Table" && from.alias ? from.alias : this.table.name;
|
|
2734
2912
|
const newCols = Object.entries(columns).reduce((acc, [alias, val]) => {
|
|
2735
2913
|
if (existingAliases.has(alias)) return acc;
|
|
2736
2914
|
if (isExpressionSelectionNode(val)) {
|
|
@@ -2738,9 +2916,10 @@ var QueryAstService = class {
|
|
|
2738
2916
|
return acc;
|
|
2739
2917
|
}
|
|
2740
2918
|
const colDef = val;
|
|
2919
|
+
const resolvedTable = colDef.table && colDef.table === this.table.name && from.type === "Table" && from.alias ? from.alias : colDef.table || rootTableName;
|
|
2741
2920
|
acc.push({
|
|
2742
2921
|
type: "Column",
|
|
2743
|
-
table:
|
|
2922
|
+
table: resolvedTable,
|
|
2744
2923
|
name: colDef.name,
|
|
2745
2924
|
alias
|
|
2746
2925
|
});
|
|
@@ -2755,7 +2934,9 @@ var QueryAstService = class {
|
|
|
2755
2934
|
* @returns Column selection result with updated state and added columns
|
|
2756
2935
|
*/
|
|
2757
2936
|
selectRaw(cols) {
|
|
2758
|
-
const
|
|
2937
|
+
const from = this.state.ast.from;
|
|
2938
|
+
const defaultTable = from.type === "Table" && from.alias ? from.alias : this.table.name;
|
|
2939
|
+
const newCols = cols.map((col2) => parseRawColumn(col2, defaultTable, this.state.ast.ctes));
|
|
2759
2940
|
const nextState = this.state.withColumns(newCols);
|
|
2760
2941
|
return { state: nextState, addedColumns: newCols };
|
|
2761
2942
|
}
|
|
@@ -2791,6 +2972,14 @@ var QueryAstService = class {
|
|
|
2791
2972
|
};
|
|
2792
2973
|
return this.state.withSetOperation(op);
|
|
2793
2974
|
}
|
|
2975
|
+
/**
|
|
2976
|
+
* Replaces the FROM clause for the current query.
|
|
2977
|
+
* @param from - Table source to use in the FROM clause
|
|
2978
|
+
* @returns Updated query state with new FROM
|
|
2979
|
+
*/
|
|
2980
|
+
withFrom(from) {
|
|
2981
|
+
return this.state.withFrom(from);
|
|
2982
|
+
}
|
|
2794
2983
|
/**
|
|
2795
2984
|
* Selects a subquery as a column
|
|
2796
2985
|
* @param alias - Alias for the subquery
|
|
@@ -2824,7 +3013,9 @@ var QueryAstService = class {
|
|
|
2824
3013
|
* @returns Updated query state with GROUP BY clause
|
|
2825
3014
|
*/
|
|
2826
3015
|
withGroupBy(col2) {
|
|
2827
|
-
const
|
|
3016
|
+
const from = this.state.ast.from;
|
|
3017
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
3018
|
+
const node = buildColumnNode(tableRef, col2);
|
|
2828
3019
|
return this.state.withGroupBy([node]);
|
|
2829
3020
|
}
|
|
2830
3021
|
/**
|
|
@@ -2843,7 +3034,9 @@ var QueryAstService = class {
|
|
|
2843
3034
|
* @returns Updated query state with ORDER BY clause
|
|
2844
3035
|
*/
|
|
2845
3036
|
withOrderBy(col2, direction) {
|
|
2846
|
-
const
|
|
3037
|
+
const from = this.state.ast.from;
|
|
3038
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
|
|
3039
|
+
const node = buildColumnNode(tableRef, col2);
|
|
2847
3040
|
return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
|
|
2848
3041
|
}
|
|
2849
3042
|
/**
|
|
@@ -2947,7 +3140,8 @@ var RelationProjectionHelper = class {
|
|
|
2947
3140
|
var assertNever = (value) => {
|
|
2948
3141
|
throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
|
|
2949
3142
|
};
|
|
2950
|
-
var baseRelationCondition = (root, relation) => {
|
|
3143
|
+
var baseRelationCondition = (root, relation, rootAlias) => {
|
|
3144
|
+
const rootTable = rootAlias || root.name;
|
|
2951
3145
|
const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
|
|
2952
3146
|
const localKey = relation.localKey || defaultLocalKey;
|
|
2953
3147
|
switch (relation.type) {
|
|
@@ -2955,12 +3149,12 @@ var baseRelationCondition = (root, relation) => {
|
|
|
2955
3149
|
case RelationKinds.HasOne:
|
|
2956
3150
|
return eq(
|
|
2957
3151
|
{ type: "Column", table: relation.target.name, name: relation.foreignKey },
|
|
2958
|
-
{ type: "Column", table:
|
|
3152
|
+
{ type: "Column", table: rootTable, name: localKey }
|
|
2959
3153
|
);
|
|
2960
3154
|
case RelationKinds.BelongsTo:
|
|
2961
3155
|
return eq(
|
|
2962
3156
|
{ type: "Column", table: relation.target.name, name: localKey },
|
|
2963
|
-
{ type: "Column", table:
|
|
3157
|
+
{ type: "Column", table: rootTable, name: relation.foreignKey }
|
|
2964
3158
|
);
|
|
2965
3159
|
case RelationKinds.BelongsToMany:
|
|
2966
3160
|
throw new Error("BelongsToMany relations do not support the standard join condition builder");
|
|
@@ -2968,12 +3162,13 @@ var baseRelationCondition = (root, relation) => {
|
|
|
2968
3162
|
return assertNever(relation);
|
|
2969
3163
|
}
|
|
2970
3164
|
};
|
|
2971
|
-
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) => {
|
|
3165
|
+
var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
|
|
2972
3166
|
const rootKey = relation.localKey || findPrimaryKey(root);
|
|
2973
3167
|
const targetKey = relation.targetKey || findPrimaryKey(relation.target);
|
|
3168
|
+
const rootTable = rootAlias || root.name;
|
|
2974
3169
|
const pivotCondition = eq(
|
|
2975
3170
|
{ type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
|
|
2976
|
-
{ type: "Column", table:
|
|
3171
|
+
{ type: "Column", table: rootTable, name: rootKey }
|
|
2977
3172
|
);
|
|
2978
3173
|
const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
|
|
2979
3174
|
let targetCondition = eq(
|
|
@@ -2991,12 +3186,12 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) =>
|
|
|
2991
3186
|
);
|
|
2992
3187
|
return [pivotJoin, targetJoin];
|
|
2993
3188
|
};
|
|
2994
|
-
var buildRelationJoinCondition = (root, relation, extra) => {
|
|
2995
|
-
const base = baseRelationCondition(root, relation);
|
|
3189
|
+
var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
|
|
3190
|
+
const base = baseRelationCondition(root, relation, rootAlias);
|
|
2996
3191
|
return extra ? and(base, extra) : base;
|
|
2997
3192
|
};
|
|
2998
|
-
var buildRelationCorrelation = (root, relation) => {
|
|
2999
|
-
return baseRelationCondition(root, relation);
|
|
3193
|
+
var buildRelationCorrelation = (root, relation, rootAlias) => {
|
|
3194
|
+
return baseRelationCondition(root, relation, rootAlias);
|
|
3000
3195
|
};
|
|
3001
3196
|
|
|
3002
3197
|
// src/core/ast/join-metadata.ts
|
|
@@ -3040,7 +3235,7 @@ var RelationService = class {
|
|
|
3040
3235
|
match(relationName, predicate) {
|
|
3041
3236
|
const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
|
|
3042
3237
|
const pk = findPrimaryKey(this.table);
|
|
3043
|
-
const distinctCols = [{ type: "Column", table: this.
|
|
3238
|
+
const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
|
|
3044
3239
|
const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
|
|
3045
3240
|
const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
|
|
3046
3241
|
return { state: nextState, hydration: joined.hydration };
|
|
@@ -3127,9 +3322,13 @@ var RelationService = class {
|
|
|
3127
3322
|
* @param ast - Query AST to modify
|
|
3128
3323
|
* @returns Modified query AST with relation correlation
|
|
3129
3324
|
*/
|
|
3130
|
-
applyRelationCorrelation(relationName, ast) {
|
|
3325
|
+
applyRelationCorrelation(relationName, ast, additionalCorrelation) {
|
|
3131
3326
|
const relation = this.getRelation(relationName);
|
|
3132
|
-
const
|
|
3327
|
+
const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
|
|
3328
|
+
let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
|
|
3329
|
+
if (additionalCorrelation) {
|
|
3330
|
+
correlation = and(correlation, additionalCorrelation);
|
|
3331
|
+
}
|
|
3133
3332
|
const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
|
|
3134
3333
|
return {
|
|
3135
3334
|
...ast,
|
|
@@ -3146,17 +3345,19 @@ var RelationService = class {
|
|
|
3146
3345
|
*/
|
|
3147
3346
|
withJoin(state, relationName, joinKind, extraCondition) {
|
|
3148
3347
|
const relation = this.getRelation(relationName);
|
|
3348
|
+
const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
|
|
3149
3349
|
if (relation.type === RelationKinds.BelongsToMany) {
|
|
3150
3350
|
const joins = buildBelongsToManyJoins(
|
|
3151
3351
|
this.table,
|
|
3152
3352
|
relationName,
|
|
3153
3353
|
relation,
|
|
3154
3354
|
joinKind,
|
|
3155
|
-
extraCondition
|
|
3355
|
+
extraCondition,
|
|
3356
|
+
rootAlias
|
|
3156
3357
|
);
|
|
3157
3358
|
return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
|
|
3158
3359
|
}
|
|
3159
|
-
const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
|
|
3360
|
+
const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
|
|
3160
3361
|
const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
|
|
3161
3362
|
return this.astService(state).withJoin(joinNode);
|
|
3162
3363
|
}
|
|
@@ -3195,6 +3396,11 @@ var RelationService = class {
|
|
|
3195
3396
|
astService(state = this.state) {
|
|
3196
3397
|
return this.createQueryAstService(this.table, state);
|
|
3197
3398
|
}
|
|
3399
|
+
rootTableName() {
|
|
3400
|
+
const from = this.state.ast.from;
|
|
3401
|
+
if (from.type === "Table" && from.alias) return from.alias;
|
|
3402
|
+
return this.table.name;
|
|
3403
|
+
}
|
|
3198
3404
|
};
|
|
3199
3405
|
|
|
3200
3406
|
// src/query-builder/select-query-builder-deps.ts
|
|
@@ -3269,7 +3475,9 @@ var ColumnSelector = class {
|
|
|
3269
3475
|
* @returns Updated query context with DISTINCT clause
|
|
3270
3476
|
*/
|
|
3271
3477
|
distinct(context, columns) {
|
|
3272
|
-
const
|
|
3478
|
+
const from = context.state.ast.from;
|
|
3479
|
+
const tableRef = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
|
|
3480
|
+
const nodes = columns.map((col2) => buildColumnNode(tableRef, col2));
|
|
3273
3481
|
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
3274
3482
|
const nextState = astService.withDistinct(nodes);
|
|
3275
3483
|
return { state: nextState, hydration: context.hydration };
|
|
@@ -3326,8 +3534,8 @@ var RelationManager = class {
|
|
|
3326
3534
|
* @param ast - Query AST to modify
|
|
3327
3535
|
* @returns Modified query AST with relation correlation
|
|
3328
3536
|
*/
|
|
3329
|
-
applyRelationCorrelation(context, relationName, ast) {
|
|
3330
|
-
return this.createService(context).applyRelationCorrelation(relationName, ast);
|
|
3537
|
+
applyRelationCorrelation(context, relationName, ast, additionalCorrelation) {
|
|
3538
|
+
return this.createService(context).applyRelationCorrelation(relationName, ast, additionalCorrelation);
|
|
3331
3539
|
}
|
|
3332
3540
|
/**
|
|
3333
3541
|
* Creates a relation service instance
|
|
@@ -4374,9 +4582,30 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4374
4582
|
clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
|
|
4375
4583
|
return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
|
|
4376
4584
|
}
|
|
4585
|
+
/**
|
|
4586
|
+
* Applies an alias to the root FROM table.
|
|
4587
|
+
* @param alias - Alias to apply
|
|
4588
|
+
*/
|
|
4589
|
+
as(alias) {
|
|
4590
|
+
const from = this.context.state.ast.from;
|
|
4591
|
+
if (from.type !== "Table") {
|
|
4592
|
+
throw new Error("Cannot alias non-table FROM sources");
|
|
4593
|
+
}
|
|
4594
|
+
const nextFrom = { ...from, alias };
|
|
4595
|
+
const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
|
|
4596
|
+
return this.clone(nextContext);
|
|
4597
|
+
}
|
|
4377
4598
|
resolveQueryNode(query) {
|
|
4378
4599
|
return typeof query.getAST === "function" ? query.getAST() : query;
|
|
4379
4600
|
}
|
|
4601
|
+
applyCorrelation(ast, correlation) {
|
|
4602
|
+
if (!correlation) return ast;
|
|
4603
|
+
const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
|
|
4604
|
+
return {
|
|
4605
|
+
...ast,
|
|
4606
|
+
where: combinedWhere
|
|
4607
|
+
};
|
|
4608
|
+
}
|
|
4380
4609
|
createChildBuilder(table) {
|
|
4381
4610
|
return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
|
|
4382
4611
|
}
|
|
@@ -4405,6 +4634,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4405
4634
|
select(columns) {
|
|
4406
4635
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
4407
4636
|
}
|
|
4637
|
+
/**
|
|
4638
|
+
* Selects columns from the root table by name (typed).
|
|
4639
|
+
* @param cols - Column names on the root table
|
|
4640
|
+
*/
|
|
4641
|
+
selectColumns(...cols) {
|
|
4642
|
+
const selection = {};
|
|
4643
|
+
for (const key of cols) {
|
|
4644
|
+
const col2 = this.env.table.columns[key];
|
|
4645
|
+
if (!col2) {
|
|
4646
|
+
throw new Error(`Column '${key}' not found on table '${this.env.table.name}'`);
|
|
4647
|
+
}
|
|
4648
|
+
selection[key] = col2;
|
|
4649
|
+
}
|
|
4650
|
+
return this.select(selection);
|
|
4651
|
+
}
|
|
4408
4652
|
/**
|
|
4409
4653
|
|
|
4410
4654
|
* Selects raw column expressions
|
|
@@ -4453,6 +4697,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4453
4697
|
const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
|
|
4454
4698
|
return this.clone(nextContext);
|
|
4455
4699
|
}
|
|
4700
|
+
/**
|
|
4701
|
+
* Replaces the FROM clause with a derived table (subquery with alias)
|
|
4702
|
+
* @param subquery - Subquery to use as the FROM source
|
|
4703
|
+
* @param alias - Alias for the derived table
|
|
4704
|
+
* @param columnAliases - Optional column alias list
|
|
4705
|
+
* @returns New query builder instance with updated FROM
|
|
4706
|
+
*/
|
|
4707
|
+
fromSubquery(subquery, alias, columnAliases) {
|
|
4708
|
+
const subAst = this.resolveQueryNode(subquery);
|
|
4709
|
+
const fromNode = derivedTable(subAst, alias, columnAliases);
|
|
4710
|
+
const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
|
|
4711
|
+
return this.clone(nextContext);
|
|
4712
|
+
}
|
|
4456
4713
|
/**
|
|
4457
4714
|
|
|
4458
4715
|
* Selects a subquery as a column
|
|
@@ -4468,6 +4725,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4468
4725
|
const query = this.resolveQueryNode(sub);
|
|
4469
4726
|
return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
|
|
4470
4727
|
}
|
|
4728
|
+
/**
|
|
4729
|
+
* Adds a JOIN against a derived table (subquery with alias)
|
|
4730
|
+
* @param subquery - Subquery to join
|
|
4731
|
+
* @param alias - Alias for the derived table
|
|
4732
|
+
* @param condition - Join condition expression
|
|
4733
|
+
* @param joinKind - Join kind (defaults to INNER)
|
|
4734
|
+
* @param columnAliases - Optional column alias list for the derived table
|
|
4735
|
+
* @returns New query builder instance with the derived-table join
|
|
4736
|
+
*/
|
|
4737
|
+
joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
|
|
4738
|
+
const subAst = this.resolveQueryNode(subquery);
|
|
4739
|
+
const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
|
|
4740
|
+
const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
|
|
4741
|
+
return this.clone(nextContext);
|
|
4742
|
+
}
|
|
4471
4743
|
/**
|
|
4472
4744
|
|
|
4473
4745
|
* Adds an INNER JOIN to the query
|
|
@@ -4565,6 +4837,47 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4565
4837
|
nextLazy.add(relationName);
|
|
4566
4838
|
return this.clone(this.context, nextLazy);
|
|
4567
4839
|
}
|
|
4840
|
+
/**
|
|
4841
|
+
* Selects columns for a related table in a single hop.
|
|
4842
|
+
*/
|
|
4843
|
+
selectRelationColumns(relationName, ...cols) {
|
|
4844
|
+
const relation = this.env.table.relations[relationName];
|
|
4845
|
+
if (!relation) {
|
|
4846
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4847
|
+
}
|
|
4848
|
+
const target = relation.target;
|
|
4849
|
+
for (const col2 of cols) {
|
|
4850
|
+
if (!target.columns[col2]) {
|
|
4851
|
+
throw new Error(
|
|
4852
|
+
`Column '${col2}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
4853
|
+
);
|
|
4854
|
+
}
|
|
4855
|
+
}
|
|
4856
|
+
return this.include(relationName, { columns: cols });
|
|
4857
|
+
}
|
|
4858
|
+
/**
|
|
4859
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
4860
|
+
*/
|
|
4861
|
+
includePick(relationName, cols) {
|
|
4862
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
4863
|
+
}
|
|
4864
|
+
/**
|
|
4865
|
+
* Selects columns for the root table and relations from a single config object.
|
|
4866
|
+
*/
|
|
4867
|
+
selectColumnsDeep(config) {
|
|
4868
|
+
let qb = this;
|
|
4869
|
+
if (config.root?.length) {
|
|
4870
|
+
qb = qb.selectColumns(...config.root);
|
|
4871
|
+
}
|
|
4872
|
+
for (const key of Object.keys(config)) {
|
|
4873
|
+
if (key === "root") continue;
|
|
4874
|
+
const relName = key;
|
|
4875
|
+
const cols = config[relName];
|
|
4876
|
+
if (!cols || !cols.length) continue;
|
|
4877
|
+
qb = qb.selectRelationColumns(relName, ...cols);
|
|
4878
|
+
}
|
|
4879
|
+
return qb;
|
|
4880
|
+
}
|
|
4568
4881
|
getLazyRelations() {
|
|
4569
4882
|
return Array.from(this.lazyRelations);
|
|
4570
4883
|
}
|
|
@@ -4726,9 +5039,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4726
5039
|
* @returns New query builder instance with the WHERE EXISTS condition
|
|
4727
5040
|
|
|
4728
5041
|
*/
|
|
4729
|
-
whereExists(subquery) {
|
|
5042
|
+
whereExists(subquery, correlate) {
|
|
4730
5043
|
const subAst = this.resolveQueryNode(subquery);
|
|
4731
|
-
|
|
5044
|
+
const correlated = this.applyCorrelation(subAst, correlate);
|
|
5045
|
+
return this.where(exists(correlated));
|
|
4732
5046
|
}
|
|
4733
5047
|
/**
|
|
4734
5048
|
|
|
@@ -4739,9 +5053,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4739
5053
|
* @returns New query builder instance with the WHERE NOT EXISTS condition
|
|
4740
5054
|
|
|
4741
5055
|
*/
|
|
4742
|
-
whereNotExists(subquery) {
|
|
5056
|
+
whereNotExists(subquery, correlate) {
|
|
4743
5057
|
const subAst = this.resolveQueryNode(subquery);
|
|
4744
|
-
|
|
5058
|
+
const correlated = this.applyCorrelation(subAst, correlate);
|
|
5059
|
+
return this.where(notExists(correlated));
|
|
4745
5060
|
}
|
|
4746
5061
|
/**
|
|
4747
5062
|
|
|
@@ -4754,17 +5069,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4754
5069
|
* @returns New query builder instance with the relationship existence check
|
|
4755
5070
|
|
|
4756
5071
|
*/
|
|
4757
|
-
whereHas(relationName,
|
|
5072
|
+
whereHas(relationName, callbackOrOptions, maybeOptions) {
|
|
4758
5073
|
const relation = this.env.table.relations[relationName];
|
|
4759
5074
|
if (!relation) {
|
|
4760
5075
|
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4761
5076
|
}
|
|
5077
|
+
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
5078
|
+
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
4762
5079
|
let subQb = this.createChildBuilder(relation.target);
|
|
4763
5080
|
if (callback) {
|
|
4764
5081
|
subQb = callback(subQb);
|
|
4765
5082
|
}
|
|
4766
5083
|
const subAst = subQb.getAST();
|
|
4767
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
|
|
5084
|
+
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
4768
5085
|
return this.where(exists(finalSubAst));
|
|
4769
5086
|
}
|
|
4770
5087
|
/**
|
|
@@ -4778,17 +5095,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4778
5095
|
* @returns New query builder instance with the relationship non-existence check
|
|
4779
5096
|
|
|
4780
5097
|
*/
|
|
4781
|
-
whereHasNot(relationName,
|
|
5098
|
+
whereHasNot(relationName, callbackOrOptions, maybeOptions) {
|
|
4782
5099
|
const relation = this.env.table.relations[relationName];
|
|
4783
5100
|
if (!relation) {
|
|
4784
5101
|
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
4785
5102
|
}
|
|
5103
|
+
const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
|
|
5104
|
+
const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
|
|
4786
5105
|
let subQb = this.createChildBuilder(relation.target);
|
|
4787
5106
|
if (callback) {
|
|
4788
5107
|
subQb = callback(subQb);
|
|
4789
5108
|
}
|
|
4790
5109
|
const subAst = subQb.getAST();
|
|
4791
|
-
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
|
|
5110
|
+
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
4792
5111
|
return this.where(notExists(finalSubAst));
|
|
4793
5112
|
}
|
|
4794
5113
|
/**
|
|
@@ -4840,6 +5159,54 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
4840
5159
|
var createColumn = (table, name) => ({ type: "Column", table, name });
|
|
4841
5160
|
var createLiteral = (val) => ({ type: "Literal", value: val });
|
|
4842
5161
|
|
|
5162
|
+
// src/orm/entity-metadata.ts
|
|
5163
|
+
var metadataMap = /* @__PURE__ */ new Map();
|
|
5164
|
+
var getEntityMetadata = (target) => {
|
|
5165
|
+
return metadataMap.get(target);
|
|
5166
|
+
};
|
|
5167
|
+
|
|
5168
|
+
// src/decorators/bootstrap.ts
|
|
5169
|
+
var getTableDefFromEntity = (ctor) => {
|
|
5170
|
+
const meta = getEntityMetadata(ctor);
|
|
5171
|
+
if (!meta) return void 0;
|
|
5172
|
+
return meta.table;
|
|
5173
|
+
};
|
|
5174
|
+
var selectFromEntity = (ctor) => {
|
|
5175
|
+
const table = getTableDefFromEntity(ctor);
|
|
5176
|
+
if (!table) {
|
|
5177
|
+
throw new Error("Entity metadata has not been bootstrapped");
|
|
5178
|
+
}
|
|
5179
|
+
return new SelectQueryBuilder(table);
|
|
5180
|
+
};
|
|
5181
|
+
|
|
5182
|
+
// src/query-builder/select-helpers.ts
|
|
5183
|
+
function sel(table, ...cols) {
|
|
5184
|
+
const selection = {};
|
|
5185
|
+
for (const col2 of cols) {
|
|
5186
|
+
const def = table.columns[col2];
|
|
5187
|
+
if (!def) {
|
|
5188
|
+
throw new Error(`Column '${col2}' not found on table '${table.name}'`);
|
|
5189
|
+
}
|
|
5190
|
+
selection[col2] = def;
|
|
5191
|
+
}
|
|
5192
|
+
return selection;
|
|
5193
|
+
}
|
|
5194
|
+
function esel(entity, ...props) {
|
|
5195
|
+
const table = getTableDefFromEntity(entity);
|
|
5196
|
+
if (!table) {
|
|
5197
|
+
throw new Error(`No table definition registered for entity '${entity.name}'`);
|
|
5198
|
+
}
|
|
5199
|
+
const selection = {};
|
|
5200
|
+
for (const prop of props) {
|
|
5201
|
+
const col2 = table.columns[prop];
|
|
5202
|
+
if (!col2) {
|
|
5203
|
+
throw new Error(`No column '${prop}' found for entity '${entity.name}'`);
|
|
5204
|
+
}
|
|
5205
|
+
selection[prop] = col2;
|
|
5206
|
+
}
|
|
5207
|
+
return selection;
|
|
5208
|
+
}
|
|
5209
|
+
|
|
4843
5210
|
// src/query-builder/insert-query-state.ts
|
|
4844
5211
|
var InsertQueryState = class _InsertQueryState {
|
|
4845
5212
|
constructor(table, ast) {
|
|
@@ -4858,7 +5225,15 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
4858
5225
|
if (!rows.length) return this;
|
|
4859
5226
|
const definedColumns = this.ast.columns.length ? this.ast.columns : buildColumnNodes(this.table, Object.keys(rows[0]));
|
|
4860
5227
|
const newRows = rows.map(
|
|
4861
|
-
(row) => definedColumns.map((column) =>
|
|
5228
|
+
(row, rowIndex) => definedColumns.map((column) => {
|
|
5229
|
+
const rawValue = row[column.name];
|
|
5230
|
+
if (!isValueOperandInput(rawValue)) {
|
|
5231
|
+
throw new Error(
|
|
5232
|
+
`Invalid insert value for column "${column.name}" in row ${rowIndex}: only primitives, null, or OperandNodes are allowed`
|
|
5233
|
+
);
|
|
5234
|
+
}
|
|
5235
|
+
return valueToOperand(rawValue);
|
|
5236
|
+
})
|
|
4862
5237
|
);
|
|
4863
5238
|
return this.clone({
|
|
4864
5239
|
...this.ast,
|
|
@@ -4909,6 +5284,17 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
4909
5284
|
};
|
|
4910
5285
|
|
|
4911
5286
|
// src/query-builder/update-query-state.ts
|
|
5287
|
+
var isUpdateValue = (value) => {
|
|
5288
|
+
if (value === null) return true;
|
|
5289
|
+
switch (typeof value) {
|
|
5290
|
+
case "string":
|
|
5291
|
+
case "number":
|
|
5292
|
+
case "boolean":
|
|
5293
|
+
return true;
|
|
5294
|
+
default:
|
|
5295
|
+
return isOperandNode(value);
|
|
5296
|
+
}
|
|
5297
|
+
};
|
|
4912
5298
|
var UpdateQueryState = class _UpdateQueryState {
|
|
4913
5299
|
constructor(table, ast) {
|
|
4914
5300
|
this.table = table;
|
|
@@ -4922,14 +5308,21 @@ var UpdateQueryState = class _UpdateQueryState {
|
|
|
4922
5308
|
return new _UpdateQueryState(this.table, nextAst);
|
|
4923
5309
|
}
|
|
4924
5310
|
withSet(values) {
|
|
4925
|
-
const assignments = Object.entries(values).map(([column,
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
}
|
|
4931
|
-
|
|
4932
|
-
|
|
5311
|
+
const assignments = Object.entries(values).map(([column, rawValue]) => {
|
|
5312
|
+
if (!isUpdateValue(rawValue)) {
|
|
5313
|
+
throw new Error(
|
|
5314
|
+
`Invalid update value for column "${column}": only primitives, null, or OperandNodes are allowed`
|
|
5315
|
+
);
|
|
5316
|
+
}
|
|
5317
|
+
return {
|
|
5318
|
+
column: {
|
|
5319
|
+
type: "Column",
|
|
5320
|
+
table: this.table.name,
|
|
5321
|
+
name: column
|
|
5322
|
+
},
|
|
5323
|
+
value: valueToOperand(rawValue)
|
|
5324
|
+
};
|
|
5325
|
+
});
|
|
4933
5326
|
return this.clone({
|
|
4934
5327
|
...this.ast,
|
|
4935
5328
|
set: assignments
|
|
@@ -6138,7 +6531,7 @@ var DefaultNamingStrategy = class {
|
|
|
6138
6531
|
* @returns Capitalized table name (handles schema-qualified names)
|
|
6139
6532
|
*/
|
|
6140
6533
|
tableToSymbol(table) {
|
|
6141
|
-
const tableName = typeof table === "string" ? table : table.name;
|
|
6534
|
+
const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.name;
|
|
6142
6535
|
if (tableName.includes(".")) {
|
|
6143
6536
|
return tableName.split(".").map((part) => this.capitalize(part)).join("");
|
|
6144
6537
|
}
|
|
@@ -6197,8 +6590,8 @@ var TypeScriptGenerator = class {
|
|
|
6197
6590
|
return `${key}: ${this.printOperand(operand)}`;
|
|
6198
6591
|
});
|
|
6199
6592
|
lines.push(`db.select({`);
|
|
6200
|
-
selections.forEach((
|
|
6201
|
-
lines.push(` ${
|
|
6593
|
+
selections.forEach((sel2, index) => {
|
|
6594
|
+
lines.push(` ${sel2}${index < selections.length - 1 ? "," : ""}`);
|
|
6202
6595
|
});
|
|
6203
6596
|
lines.push(`})`);
|
|
6204
6597
|
lines.push(`.from(${this.namingStrategy.tableToSymbol(ast.from)})`);
|
|
@@ -6481,26 +6874,6 @@ var TypeScriptGenerator = class {
|
|
|
6481
6874
|
}
|
|
6482
6875
|
};
|
|
6483
6876
|
|
|
6484
|
-
// src/orm/entity-metadata.ts
|
|
6485
|
-
var metadataMap = /* @__PURE__ */ new Map();
|
|
6486
|
-
var getEntityMetadata = (target) => {
|
|
6487
|
-
return metadataMap.get(target);
|
|
6488
|
-
};
|
|
6489
|
-
|
|
6490
|
-
// src/decorators/bootstrap.ts
|
|
6491
|
-
var getTableDefFromEntity = (ctor) => {
|
|
6492
|
-
const meta = getEntityMetadata(ctor);
|
|
6493
|
-
if (!meta) return void 0;
|
|
6494
|
-
return meta.table;
|
|
6495
|
-
};
|
|
6496
|
-
var selectFromEntity = (ctor) => {
|
|
6497
|
-
const table = getTableDefFromEntity(ctor);
|
|
6498
|
-
if (!table) {
|
|
6499
|
-
throw new Error("Entity metadata has not been bootstrapped");
|
|
6500
|
-
}
|
|
6501
|
-
return new SelectQueryBuilder(table);
|
|
6502
|
-
};
|
|
6503
|
-
|
|
6504
6877
|
// src/orm/identity-map.ts
|
|
6505
6878
|
var IdentityMap = class {
|
|
6506
6879
|
constructor() {
|
|
@@ -6713,6 +7086,7 @@ var UnitOfWork = class {
|
|
|
6713
7086
|
extractColumns(table, entity) {
|
|
6714
7087
|
const payload = {};
|
|
6715
7088
|
for (const column of Object.keys(table.columns)) {
|
|
7089
|
+
if (entity[column] === void 0) continue;
|
|
6716
7090
|
payload[column] = entity[column];
|
|
6717
7091
|
}
|
|
6718
7092
|
return payload;
|
|
@@ -6767,24 +7141,30 @@ var UnitOfWork = class {
|
|
|
6767
7141
|
var DomainEventBus = class {
|
|
6768
7142
|
constructor(initialHandlers) {
|
|
6769
7143
|
this.handlers = /* @__PURE__ */ new Map();
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
7144
|
+
if (initialHandlers) {
|
|
7145
|
+
for (const key in initialHandlers) {
|
|
7146
|
+
const type = key;
|
|
7147
|
+
const list = initialHandlers[type] ?? [];
|
|
7148
|
+
this.handlers.set(type, [...list]);
|
|
7149
|
+
}
|
|
7150
|
+
}
|
|
6774
7151
|
}
|
|
6775
|
-
|
|
6776
|
-
const
|
|
7152
|
+
on(type, handler) {
|
|
7153
|
+
const key = type;
|
|
7154
|
+
const existing = this.handlers.get(key) ?? [];
|
|
6777
7155
|
existing.push(handler);
|
|
6778
|
-
this.handlers.set(
|
|
7156
|
+
this.handlers.set(key, existing);
|
|
7157
|
+
}
|
|
7158
|
+
register(type, handler) {
|
|
7159
|
+
this.on(type, handler);
|
|
6779
7160
|
}
|
|
6780
7161
|
async dispatch(trackedEntities, ctx) {
|
|
6781
7162
|
for (const tracked of trackedEntities) {
|
|
6782
7163
|
const entity = tracked.entity;
|
|
6783
|
-
if (!entity.domainEvents
|
|
7164
|
+
if (!entity.domainEvents?.length) continue;
|
|
6784
7165
|
for (const event of entity.domainEvents) {
|
|
6785
|
-
const
|
|
6786
|
-
|
|
6787
|
-
if (!handlers) continue;
|
|
7166
|
+
const handlers = this.handlers.get(event.type);
|
|
7167
|
+
if (!handlers?.length) continue;
|
|
6788
7168
|
for (const handler of handlers) {
|
|
6789
7169
|
await handler(event, ctx);
|
|
6790
7170
|
}
|
|
@@ -6792,11 +7172,6 @@ var DomainEventBus = class {
|
|
|
6792
7172
|
entity.domainEvents = [];
|
|
6793
7173
|
}
|
|
6794
7174
|
}
|
|
6795
|
-
getEventName(event) {
|
|
6796
|
-
if (!event) return "Unknown";
|
|
6797
|
-
if (typeof event === "string") return event;
|
|
6798
|
-
return event.constructor?.name ?? "Unknown";
|
|
6799
|
-
}
|
|
6800
7175
|
};
|
|
6801
7176
|
var addDomainEvent = (entity, event) => {
|
|
6802
7177
|
if (!entity.domainEvents) {
|
|
@@ -7038,8 +7413,8 @@ var OrmSession = class {
|
|
|
7038
7413
|
registerInterceptor(interceptor) {
|
|
7039
7414
|
this.interceptors.push(interceptor);
|
|
7040
7415
|
}
|
|
7041
|
-
registerDomainEventHandler(
|
|
7042
|
-
this.domainEvents.
|
|
7416
|
+
registerDomainEventHandler(type, handler) {
|
|
7417
|
+
this.domainEvents.on(type, handler);
|
|
7043
7418
|
}
|
|
7044
7419
|
async find(entityClass, id) {
|
|
7045
7420
|
const table = getTableDefFromEntity(entityClass);
|
|
@@ -7051,7 +7426,11 @@ var OrmSession = class {
|
|
|
7051
7426
|
if (!column) {
|
|
7052
7427
|
throw new Error("Entity table does not expose a primary key");
|
|
7053
7428
|
}
|
|
7054
|
-
const
|
|
7429
|
+
const columnSelections = Object.values(table.columns).reduce((acc, col2) => {
|
|
7430
|
+
acc[col2.name] = col2;
|
|
7431
|
+
return acc;
|
|
7432
|
+
}, {});
|
|
7433
|
+
const qb = selectFromEntity(entityClass).select(columnSelections).where(eq(column, id)).limit(1);
|
|
7055
7434
|
const rows = await executeHydrated(this, qb);
|
|
7056
7435
|
return rows[0] ?? null;
|
|
7057
7436
|
}
|
|
@@ -7163,7 +7542,6 @@ var Orm = class {
|
|
|
7163
7542
|
const executor = this.executorFactory.createExecutor(options?.tx);
|
|
7164
7543
|
return new OrmSession({ orm: this, executor });
|
|
7165
7544
|
}
|
|
7166
|
-
// Nice convenience:
|
|
7167
7545
|
async transaction(fn4) {
|
|
7168
7546
|
const executor = this.executorFactory.createTransactionalExecutor();
|
|
7169
7547
|
const session = new OrmSession({ orm: this, executor });
|
|
@@ -7327,6 +7705,7 @@ function createMssqlExecutor(client) {
|
|
|
7327
7705
|
columnOperand,
|
|
7328
7706
|
concat,
|
|
7329
7707
|
concatWs,
|
|
7708
|
+
correlateBy,
|
|
7330
7709
|
cos,
|
|
7331
7710
|
cot,
|
|
7332
7711
|
count,
|
|
@@ -7355,6 +7734,7 @@ function createMssqlExecutor(client) {
|
|
|
7355
7734
|
diffSchema,
|
|
7356
7735
|
endOfMonth,
|
|
7357
7736
|
eq,
|
|
7737
|
+
esel,
|
|
7358
7738
|
executeHydrated,
|
|
7359
7739
|
executeHydratedWithContexts,
|
|
7360
7740
|
exists,
|
|
@@ -7366,6 +7746,7 @@ function createMssqlExecutor(client) {
|
|
|
7366
7746
|
generateCreateTableSql,
|
|
7367
7747
|
generateSchemaSql,
|
|
7368
7748
|
getSchemaIntrospector,
|
|
7749
|
+
groupConcat,
|
|
7369
7750
|
gt,
|
|
7370
7751
|
gte,
|
|
7371
7752
|
hasMany,
|
|
@@ -7380,6 +7761,7 @@ function createMssqlExecutor(client) {
|
|
|
7380
7761
|
isNotNull,
|
|
7381
7762
|
isNull,
|
|
7382
7763
|
isOperandNode,
|
|
7764
|
+
isValueOperandInput,
|
|
7383
7765
|
isWindowFunctionNode,
|
|
7384
7766
|
jsonPath,
|
|
7385
7767
|
lag,
|
|
@@ -7402,6 +7784,8 @@ function createMssqlExecutor(client) {
|
|
|
7402
7784
|
lt,
|
|
7403
7785
|
lte,
|
|
7404
7786
|
ltrim,
|
|
7787
|
+
max,
|
|
7788
|
+
min,
|
|
7405
7789
|
mod,
|
|
7406
7790
|
month,
|
|
7407
7791
|
neq,
|
|
@@ -7412,6 +7796,7 @@ function createMssqlExecutor(client) {
|
|
|
7412
7796
|
now,
|
|
7413
7797
|
ntile,
|
|
7414
7798
|
or,
|
|
7799
|
+
outerRef,
|
|
7415
7800
|
pi,
|
|
7416
7801
|
position,
|
|
7417
7802
|
pow,
|
|
@@ -7432,6 +7817,7 @@ function createMssqlExecutor(client) {
|
|
|
7432
7817
|
rowsToQueryResult,
|
|
7433
7818
|
rpad,
|
|
7434
7819
|
rtrim,
|
|
7820
|
+
sel,
|
|
7435
7821
|
sign,
|
|
7436
7822
|
sin,
|
|
7437
7823
|
space,
|