metal-orm 1.0.12 → 1.0.13
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 +17 -15
- package/dist/decorators/index.cjs +302 -32
- 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 +302 -32
- package/dist/decorators/index.js.map +1 -1
- package/dist/index.cjs +583 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -2
- package/dist/index.d.ts +18 -2
- package/dist/index.js +583 -130
- package/dist/index.js.map +1 -1
- package/dist/{select-BKlr2ivY.d.cts → select-CCp1oz9p.d.cts} +114 -1
- package/dist/{select-BKlr2ivY.d.ts → select-CCp1oz9p.d.ts} +114 -1
- package/package.json +3 -2
- package/src/core/ast/query.ts +40 -22
- package/src/core/dialect/abstract.ts +122 -37
- package/src/core/dialect/base/sql-dialect.ts +51 -8
- package/src/core/dialect/mssql/index.ts +125 -80
- package/src/core/dialect/postgres/index.ts +5 -6
- package/src/core/dialect/sqlite/index.ts +5 -6
- package/src/orm/execute.ts +25 -16
- package/src/orm/orm-context.ts +60 -55
- package/src/orm/query-logger.ts +38 -0
- package/src/orm/relations/belongs-to.ts +42 -26
- package/src/orm/relations/has-many.ts +41 -25
- package/src/orm/relations/many-to-many.ts +43 -27
- package/src/orm/unit-of-work.ts +60 -23
- package/src/query-builder/hydration-manager.ts +229 -25
- package/src/query-builder/query-ast-service.ts +27 -12
- package/src/query-builder/select-query-state.ts +24 -12
- package/src/query-builder/select.ts +58 -14
|
@@ -721,6 +721,20 @@ interface CommonTableExpressionNode {
|
|
|
721
721
|
/** Whether the CTE is recursive */
|
|
722
722
|
recursive: boolean;
|
|
723
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Supported set operation kinds for compound SELECT queries
|
|
726
|
+
*/
|
|
727
|
+
type SetOperationKind = 'UNION' | 'UNION ALL' | 'INTERSECT' | 'EXCEPT';
|
|
728
|
+
/**
|
|
729
|
+
* AST node representing a set operation (UNION, INTERSECT, etc.)
|
|
730
|
+
*/
|
|
731
|
+
interface SetOperationNode {
|
|
732
|
+
type: 'SetOperation';
|
|
733
|
+
/** Operator to combine queries */
|
|
734
|
+
operator: SetOperationKind;
|
|
735
|
+
/** Right-hand query in the compound expression */
|
|
736
|
+
query: SelectQueryNode;
|
|
737
|
+
}
|
|
724
738
|
/**
|
|
725
739
|
* AST node representing a complete SELECT query
|
|
726
740
|
*/
|
|
@@ -750,6 +764,8 @@ interface SelectQueryNode {
|
|
|
750
764
|
meta?: QueryMetadata;
|
|
751
765
|
/** Optional DISTINCT clause */
|
|
752
766
|
distinct?: ColumnNode[];
|
|
767
|
+
/** Optional set operations chaining this query with others */
|
|
768
|
+
setOps?: SetOperationNode[];
|
|
753
769
|
}
|
|
754
770
|
interface InsertQueryNode {
|
|
755
771
|
type: 'InsertQuery';
|
|
@@ -832,6 +848,7 @@ declare abstract class Dialect implements SelectCompiler, InsertCompiler, Update
|
|
|
832
848
|
compileInsert(ast: InsertQueryNode): CompiledQuery;
|
|
833
849
|
compileUpdate(ast: UpdateQueryNode): CompiledQuery;
|
|
834
850
|
compileDelete(ast: DeleteQueryNode): CompiledQuery;
|
|
851
|
+
supportsReturning(): boolean;
|
|
835
852
|
/**
|
|
836
853
|
* Compiles SELECT query AST to SQL (to be implemented by concrete dialects)
|
|
837
854
|
* @param ast - Query AST
|
|
@@ -877,6 +894,31 @@ declare abstract class Dialect implements SelectCompiler, InsertCompiler, Update
|
|
|
877
894
|
* @returns Formatted placeholder string
|
|
878
895
|
*/
|
|
879
896
|
protected formatPlaceholder(index: number): string;
|
|
897
|
+
/**
|
|
898
|
+
* Whether the current dialect supports a given set operation.
|
|
899
|
+
* Override in concrete dialects to restrict support.
|
|
900
|
+
*/
|
|
901
|
+
protected supportsSetOperation(kind: SetOperationKind): boolean;
|
|
902
|
+
/**
|
|
903
|
+
* Validates set-operation semantics:
|
|
904
|
+
* - Ensures the dialect supports requested operators.
|
|
905
|
+
* - Enforces that only the outermost compound query may have ORDER/LIMIT/OFFSET.
|
|
906
|
+
* @param ast - Query to validate
|
|
907
|
+
* @param isOutermost - Whether this node is the outermost compound query
|
|
908
|
+
*/
|
|
909
|
+
protected validateSetOperations(ast: SelectQueryNode, isOutermost?: boolean): void;
|
|
910
|
+
/**
|
|
911
|
+
* Hoists CTEs from set-operation operands to the outermost query so WITH appears once.
|
|
912
|
+
* @param ast - Query AST
|
|
913
|
+
* @returns Normalized AST without inner CTEs and a list of hoisted CTEs
|
|
914
|
+
*/
|
|
915
|
+
private hoistCtes;
|
|
916
|
+
/**
|
|
917
|
+
* Normalizes a SELECT AST before compilation (validation + CTE hoisting).
|
|
918
|
+
* @param ast - Query AST
|
|
919
|
+
* @returns Normalized query AST
|
|
920
|
+
*/
|
|
921
|
+
protected normalizeSelectAst(ast: SelectQueryNode): SelectQueryNode;
|
|
880
922
|
private readonly expressionCompilers;
|
|
881
923
|
private readonly operandCompilers;
|
|
882
924
|
protected constructor();
|
|
@@ -999,6 +1041,12 @@ declare class SelectQueryState {
|
|
|
999
1041
|
* @returns New SelectQueryState with CTE
|
|
1000
1042
|
*/
|
|
1001
1043
|
withCte(cte: CommonTableExpressionNode): SelectQueryState;
|
|
1044
|
+
/**
|
|
1045
|
+
* Adds a set operation (UNION/INTERSECT/EXCEPT) to the query
|
|
1046
|
+
* @param op - Set operation node to add
|
|
1047
|
+
* @returns New SelectQueryState with set operation
|
|
1048
|
+
*/
|
|
1049
|
+
withSetOperation(op: SetOperationNode): SelectQueryState;
|
|
1002
1050
|
}
|
|
1003
1051
|
|
|
1004
1052
|
/**
|
|
@@ -1101,6 +1149,31 @@ declare class HydrationManager {
|
|
|
1101
1149
|
* @returns Hydration plan or undefined if none exists
|
|
1102
1150
|
*/
|
|
1103
1151
|
getPlan(): HydrationPlan | undefined;
|
|
1152
|
+
/**
|
|
1153
|
+
* Attaches hydration metadata to a query AST node.
|
|
1154
|
+
*/
|
|
1155
|
+
private attachHydrationMeta;
|
|
1156
|
+
/**
|
|
1157
|
+
* Determines whether the query needs pagination rewriting to keep LIMIT/OFFSET
|
|
1158
|
+
* applied to parent rows when eager-loading multiplicative relations.
|
|
1159
|
+
*/
|
|
1160
|
+
private requiresParentPagination;
|
|
1161
|
+
private hasMultiplyingRelations;
|
|
1162
|
+
/**
|
|
1163
|
+
* Rewrites the query using CTEs so LIMIT/OFFSET target distinct parent rows
|
|
1164
|
+
* instead of the joined result set.
|
|
1165
|
+
*
|
|
1166
|
+
* The strategy:
|
|
1167
|
+
* - Hoist the original query (minus limit/offset) into a base CTE.
|
|
1168
|
+
* - Select distinct parent ids from that base CTE with the original ordering and pagination.
|
|
1169
|
+
* - Join the base CTE against the paged ids to retrieve the joined rows for just that page.
|
|
1170
|
+
*/
|
|
1171
|
+
private wrapForParentPagination;
|
|
1172
|
+
private nextCteName;
|
|
1173
|
+
private getProjectionNames;
|
|
1174
|
+
private buildProjectionAliasMap;
|
|
1175
|
+
private mapOrderBy;
|
|
1176
|
+
private buildPagingColumns;
|
|
1104
1177
|
}
|
|
1105
1178
|
|
|
1106
1179
|
/**
|
|
@@ -1149,6 +1222,13 @@ declare class QueryAstService {
|
|
|
1149
1222
|
* @returns Updated query state with CTE
|
|
1150
1223
|
*/
|
|
1151
1224
|
withCte(name: string, query: SelectQueryNode, columns?: string[], recursive?: boolean): SelectQueryState;
|
|
1225
|
+
/**
|
|
1226
|
+
* Adds a set operation (UNION/UNION ALL/INTERSECT/EXCEPT) to the query
|
|
1227
|
+
* @param operator - Set operator
|
|
1228
|
+
* @param query - Right-hand side query
|
|
1229
|
+
* @returns Updated query state with set operation
|
|
1230
|
+
*/
|
|
1231
|
+
withSetOperation(operator: SetOperationKind, query: SelectQueryNode): SelectQueryState;
|
|
1152
1232
|
/**
|
|
1153
1233
|
* Selects a subquery as a column
|
|
1154
1234
|
* @param alias - Alias for the subquery
|
|
@@ -1408,6 +1488,12 @@ interface HasDomainEvents {
|
|
|
1408
1488
|
type DomainEventHandler$1<Context> = (event: any, ctx: Context) => Promise<void> | void;
|
|
1409
1489
|
declare const addDomainEvent: (entity: HasDomainEvents, event: any) => void;
|
|
1410
1490
|
|
|
1491
|
+
interface QueryLogEntry {
|
|
1492
|
+
sql: string;
|
|
1493
|
+
params?: unknown[];
|
|
1494
|
+
}
|
|
1495
|
+
type QueryLogger = (entry: QueryLogEntry) => void;
|
|
1496
|
+
|
|
1411
1497
|
interface OrmInterceptor {
|
|
1412
1498
|
beforeFlush?(ctx: OrmContext): Promise<void> | void;
|
|
1413
1499
|
afterFlush?(ctx: OrmContext): Promise<void> | void;
|
|
@@ -1418,10 +1504,12 @@ interface OrmContextOptions {
|
|
|
1418
1504
|
executor: DbExecutor;
|
|
1419
1505
|
interceptors?: OrmInterceptor[];
|
|
1420
1506
|
domainEventHandlers?: Record<string, DomainEventHandler[]>;
|
|
1507
|
+
queryLogger?: QueryLogger;
|
|
1421
1508
|
}
|
|
1422
1509
|
declare class OrmContext {
|
|
1423
1510
|
private readonly options;
|
|
1424
1511
|
private readonly identityMap;
|
|
1512
|
+
private readonly executorWithLogging;
|
|
1425
1513
|
private readonly unitOfWork;
|
|
1426
1514
|
private readonly relationChanges;
|
|
1427
1515
|
private readonly interceptors;
|
|
@@ -1468,6 +1556,7 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1468
1556
|
private createChildBuilder;
|
|
1469
1557
|
private applyAst;
|
|
1470
1558
|
private applyJoin;
|
|
1559
|
+
private applySetOperation;
|
|
1471
1560
|
/**
|
|
1472
1561
|
* Selects specific columns for the query
|
|
1473
1562
|
* @param columns - Record of column definitions, function nodes, case expressions, or window functions
|
|
@@ -1593,6 +1682,30 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1593
1682
|
* @returns New query builder instance with the OFFSET clause
|
|
1594
1683
|
*/
|
|
1595
1684
|
offset(n: number): SelectQueryBuilder<T, TTable>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Combines this query with another using UNION
|
|
1687
|
+
* @param query - Query to union with
|
|
1688
|
+
* @returns New query builder instance with the set operation
|
|
1689
|
+
*/
|
|
1690
|
+
union(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1691
|
+
/**
|
|
1692
|
+
* Combines this query with another using UNION ALL
|
|
1693
|
+
* @param query - Query to union with
|
|
1694
|
+
* @returns New query builder instance with the set operation
|
|
1695
|
+
*/
|
|
1696
|
+
unionAll(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1697
|
+
/**
|
|
1698
|
+
* Combines this query with another using INTERSECT
|
|
1699
|
+
* @param query - Query to intersect with
|
|
1700
|
+
* @returns New query builder instance with the set operation
|
|
1701
|
+
*/
|
|
1702
|
+
intersect(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1703
|
+
/**
|
|
1704
|
+
* Combines this query with another using EXCEPT
|
|
1705
|
+
* @param query - Query to subtract
|
|
1706
|
+
* @returns New query builder instance with the set operation
|
|
1707
|
+
*/
|
|
1708
|
+
except(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1596
1709
|
/**
|
|
1597
1710
|
* Adds a WHERE EXISTS condition to the query
|
|
1598
1711
|
* @param subquery - Subquery to check for existence
|
|
@@ -1656,4 +1769,4 @@ declare const createColumn: (table: string, name: string) => ColumnNode;
|
|
|
1656
1769
|
*/
|
|
1657
1770
|
declare const createLiteral: (val: string | number) => LiteralNode;
|
|
1658
1771
|
|
|
1659
|
-
export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
|
|
1772
|
+
export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type QueryLogEntry as an, type QueryLogger as ao, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
|
|
@@ -721,6 +721,20 @@ interface CommonTableExpressionNode {
|
|
|
721
721
|
/** Whether the CTE is recursive */
|
|
722
722
|
recursive: boolean;
|
|
723
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Supported set operation kinds for compound SELECT queries
|
|
726
|
+
*/
|
|
727
|
+
type SetOperationKind = 'UNION' | 'UNION ALL' | 'INTERSECT' | 'EXCEPT';
|
|
728
|
+
/**
|
|
729
|
+
* AST node representing a set operation (UNION, INTERSECT, etc.)
|
|
730
|
+
*/
|
|
731
|
+
interface SetOperationNode {
|
|
732
|
+
type: 'SetOperation';
|
|
733
|
+
/** Operator to combine queries */
|
|
734
|
+
operator: SetOperationKind;
|
|
735
|
+
/** Right-hand query in the compound expression */
|
|
736
|
+
query: SelectQueryNode;
|
|
737
|
+
}
|
|
724
738
|
/**
|
|
725
739
|
* AST node representing a complete SELECT query
|
|
726
740
|
*/
|
|
@@ -750,6 +764,8 @@ interface SelectQueryNode {
|
|
|
750
764
|
meta?: QueryMetadata;
|
|
751
765
|
/** Optional DISTINCT clause */
|
|
752
766
|
distinct?: ColumnNode[];
|
|
767
|
+
/** Optional set operations chaining this query with others */
|
|
768
|
+
setOps?: SetOperationNode[];
|
|
753
769
|
}
|
|
754
770
|
interface InsertQueryNode {
|
|
755
771
|
type: 'InsertQuery';
|
|
@@ -832,6 +848,7 @@ declare abstract class Dialect implements SelectCompiler, InsertCompiler, Update
|
|
|
832
848
|
compileInsert(ast: InsertQueryNode): CompiledQuery;
|
|
833
849
|
compileUpdate(ast: UpdateQueryNode): CompiledQuery;
|
|
834
850
|
compileDelete(ast: DeleteQueryNode): CompiledQuery;
|
|
851
|
+
supportsReturning(): boolean;
|
|
835
852
|
/**
|
|
836
853
|
* Compiles SELECT query AST to SQL (to be implemented by concrete dialects)
|
|
837
854
|
* @param ast - Query AST
|
|
@@ -877,6 +894,31 @@ declare abstract class Dialect implements SelectCompiler, InsertCompiler, Update
|
|
|
877
894
|
* @returns Formatted placeholder string
|
|
878
895
|
*/
|
|
879
896
|
protected formatPlaceholder(index: number): string;
|
|
897
|
+
/**
|
|
898
|
+
* Whether the current dialect supports a given set operation.
|
|
899
|
+
* Override in concrete dialects to restrict support.
|
|
900
|
+
*/
|
|
901
|
+
protected supportsSetOperation(kind: SetOperationKind): boolean;
|
|
902
|
+
/**
|
|
903
|
+
* Validates set-operation semantics:
|
|
904
|
+
* - Ensures the dialect supports requested operators.
|
|
905
|
+
* - Enforces that only the outermost compound query may have ORDER/LIMIT/OFFSET.
|
|
906
|
+
* @param ast - Query to validate
|
|
907
|
+
* @param isOutermost - Whether this node is the outermost compound query
|
|
908
|
+
*/
|
|
909
|
+
protected validateSetOperations(ast: SelectQueryNode, isOutermost?: boolean): void;
|
|
910
|
+
/**
|
|
911
|
+
* Hoists CTEs from set-operation operands to the outermost query so WITH appears once.
|
|
912
|
+
* @param ast - Query AST
|
|
913
|
+
* @returns Normalized AST without inner CTEs and a list of hoisted CTEs
|
|
914
|
+
*/
|
|
915
|
+
private hoistCtes;
|
|
916
|
+
/**
|
|
917
|
+
* Normalizes a SELECT AST before compilation (validation + CTE hoisting).
|
|
918
|
+
* @param ast - Query AST
|
|
919
|
+
* @returns Normalized query AST
|
|
920
|
+
*/
|
|
921
|
+
protected normalizeSelectAst(ast: SelectQueryNode): SelectQueryNode;
|
|
880
922
|
private readonly expressionCompilers;
|
|
881
923
|
private readonly operandCompilers;
|
|
882
924
|
protected constructor();
|
|
@@ -999,6 +1041,12 @@ declare class SelectQueryState {
|
|
|
999
1041
|
* @returns New SelectQueryState with CTE
|
|
1000
1042
|
*/
|
|
1001
1043
|
withCte(cte: CommonTableExpressionNode): SelectQueryState;
|
|
1044
|
+
/**
|
|
1045
|
+
* Adds a set operation (UNION/INTERSECT/EXCEPT) to the query
|
|
1046
|
+
* @param op - Set operation node to add
|
|
1047
|
+
* @returns New SelectQueryState with set operation
|
|
1048
|
+
*/
|
|
1049
|
+
withSetOperation(op: SetOperationNode): SelectQueryState;
|
|
1002
1050
|
}
|
|
1003
1051
|
|
|
1004
1052
|
/**
|
|
@@ -1101,6 +1149,31 @@ declare class HydrationManager {
|
|
|
1101
1149
|
* @returns Hydration plan or undefined if none exists
|
|
1102
1150
|
*/
|
|
1103
1151
|
getPlan(): HydrationPlan | undefined;
|
|
1152
|
+
/**
|
|
1153
|
+
* Attaches hydration metadata to a query AST node.
|
|
1154
|
+
*/
|
|
1155
|
+
private attachHydrationMeta;
|
|
1156
|
+
/**
|
|
1157
|
+
* Determines whether the query needs pagination rewriting to keep LIMIT/OFFSET
|
|
1158
|
+
* applied to parent rows when eager-loading multiplicative relations.
|
|
1159
|
+
*/
|
|
1160
|
+
private requiresParentPagination;
|
|
1161
|
+
private hasMultiplyingRelations;
|
|
1162
|
+
/**
|
|
1163
|
+
* Rewrites the query using CTEs so LIMIT/OFFSET target distinct parent rows
|
|
1164
|
+
* instead of the joined result set.
|
|
1165
|
+
*
|
|
1166
|
+
* The strategy:
|
|
1167
|
+
* - Hoist the original query (minus limit/offset) into a base CTE.
|
|
1168
|
+
* - Select distinct parent ids from that base CTE with the original ordering and pagination.
|
|
1169
|
+
* - Join the base CTE against the paged ids to retrieve the joined rows for just that page.
|
|
1170
|
+
*/
|
|
1171
|
+
private wrapForParentPagination;
|
|
1172
|
+
private nextCteName;
|
|
1173
|
+
private getProjectionNames;
|
|
1174
|
+
private buildProjectionAliasMap;
|
|
1175
|
+
private mapOrderBy;
|
|
1176
|
+
private buildPagingColumns;
|
|
1104
1177
|
}
|
|
1105
1178
|
|
|
1106
1179
|
/**
|
|
@@ -1149,6 +1222,13 @@ declare class QueryAstService {
|
|
|
1149
1222
|
* @returns Updated query state with CTE
|
|
1150
1223
|
*/
|
|
1151
1224
|
withCte(name: string, query: SelectQueryNode, columns?: string[], recursive?: boolean): SelectQueryState;
|
|
1225
|
+
/**
|
|
1226
|
+
* Adds a set operation (UNION/UNION ALL/INTERSECT/EXCEPT) to the query
|
|
1227
|
+
* @param operator - Set operator
|
|
1228
|
+
* @param query - Right-hand side query
|
|
1229
|
+
* @returns Updated query state with set operation
|
|
1230
|
+
*/
|
|
1231
|
+
withSetOperation(operator: SetOperationKind, query: SelectQueryNode): SelectQueryState;
|
|
1152
1232
|
/**
|
|
1153
1233
|
* Selects a subquery as a column
|
|
1154
1234
|
* @param alias - Alias for the subquery
|
|
@@ -1408,6 +1488,12 @@ interface HasDomainEvents {
|
|
|
1408
1488
|
type DomainEventHandler$1<Context> = (event: any, ctx: Context) => Promise<void> | void;
|
|
1409
1489
|
declare const addDomainEvent: (entity: HasDomainEvents, event: any) => void;
|
|
1410
1490
|
|
|
1491
|
+
interface QueryLogEntry {
|
|
1492
|
+
sql: string;
|
|
1493
|
+
params?: unknown[];
|
|
1494
|
+
}
|
|
1495
|
+
type QueryLogger = (entry: QueryLogEntry) => void;
|
|
1496
|
+
|
|
1411
1497
|
interface OrmInterceptor {
|
|
1412
1498
|
beforeFlush?(ctx: OrmContext): Promise<void> | void;
|
|
1413
1499
|
afterFlush?(ctx: OrmContext): Promise<void> | void;
|
|
@@ -1418,10 +1504,12 @@ interface OrmContextOptions {
|
|
|
1418
1504
|
executor: DbExecutor;
|
|
1419
1505
|
interceptors?: OrmInterceptor[];
|
|
1420
1506
|
domainEventHandlers?: Record<string, DomainEventHandler[]>;
|
|
1507
|
+
queryLogger?: QueryLogger;
|
|
1421
1508
|
}
|
|
1422
1509
|
declare class OrmContext {
|
|
1423
1510
|
private readonly options;
|
|
1424
1511
|
private readonly identityMap;
|
|
1512
|
+
private readonly executorWithLogging;
|
|
1425
1513
|
private readonly unitOfWork;
|
|
1426
1514
|
private readonly relationChanges;
|
|
1427
1515
|
private readonly interceptors;
|
|
@@ -1468,6 +1556,7 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1468
1556
|
private createChildBuilder;
|
|
1469
1557
|
private applyAst;
|
|
1470
1558
|
private applyJoin;
|
|
1559
|
+
private applySetOperation;
|
|
1471
1560
|
/**
|
|
1472
1561
|
* Selects specific columns for the query
|
|
1473
1562
|
* @param columns - Record of column definitions, function nodes, case expressions, or window functions
|
|
@@ -1593,6 +1682,30 @@ declare class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1593
1682
|
* @returns New query builder instance with the OFFSET clause
|
|
1594
1683
|
*/
|
|
1595
1684
|
offset(n: number): SelectQueryBuilder<T, TTable>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Combines this query with another using UNION
|
|
1687
|
+
* @param query - Query to union with
|
|
1688
|
+
* @returns New query builder instance with the set operation
|
|
1689
|
+
*/
|
|
1690
|
+
union(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1691
|
+
/**
|
|
1692
|
+
* Combines this query with another using UNION ALL
|
|
1693
|
+
* @param query - Query to union with
|
|
1694
|
+
* @returns New query builder instance with the set operation
|
|
1695
|
+
*/
|
|
1696
|
+
unionAll(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1697
|
+
/**
|
|
1698
|
+
* Combines this query with another using INTERSECT
|
|
1699
|
+
* @param query - Query to intersect with
|
|
1700
|
+
* @returns New query builder instance with the set operation
|
|
1701
|
+
*/
|
|
1702
|
+
intersect(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1703
|
+
/**
|
|
1704
|
+
* Combines this query with another using EXCEPT
|
|
1705
|
+
* @param query - Query to subtract
|
|
1706
|
+
* @returns New query builder instance with the set operation
|
|
1707
|
+
*/
|
|
1708
|
+
except(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable>;
|
|
1596
1709
|
/**
|
|
1597
1710
|
* Adds a WHERE EXISTS condition to the query
|
|
1598
1711
|
* @param subquery - Subquery to check for existence
|
|
@@ -1656,4 +1769,4 @@ declare const createColumn: (table: string, name: string) => ColumnNode;
|
|
|
1656
1769
|
*/
|
|
1657
1770
|
declare const createLiteral: (val: string | number) => LiteralNode;
|
|
1658
1771
|
|
|
1659
|
-
export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
|
|
1772
|
+
export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type QueryLogEntry as an, type QueryLogger as ao, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metal-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"build": "tsup",
|
|
22
22
|
"check": "tsc --noEmit",
|
|
23
23
|
"test": "vitest",
|
|
24
|
-
"test:ui": "vitest --ui"
|
|
24
|
+
"test:ui": "vitest --ui",
|
|
25
|
+
"show-sql": "node scripts/show-sql.mjs"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"mysql2": "^3.9.0",
|
package/src/core/ast/query.ts
CHANGED
|
@@ -94,23 +94,39 @@ export interface QueryMetadata {
|
|
|
94
94
|
/**
|
|
95
95
|
* AST node representing a Common Table Expression (CTE)
|
|
96
96
|
*/
|
|
97
|
-
export interface CommonTableExpressionNode {
|
|
98
|
-
type: 'CommonTableExpression';
|
|
99
|
-
/** CTE name */
|
|
100
|
-
name: string;
|
|
101
|
-
/** Optional column names */
|
|
102
|
-
columns?: string[];
|
|
103
|
-
/** CTE query */
|
|
104
|
-
query: SelectQueryNode;
|
|
105
|
-
/** Whether the CTE is recursive */
|
|
106
|
-
recursive: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
*
|
|
111
|
-
*/
|
|
112
|
-
export
|
|
113
|
-
|
|
97
|
+
export interface CommonTableExpressionNode {
|
|
98
|
+
type: 'CommonTableExpression';
|
|
99
|
+
/** CTE name */
|
|
100
|
+
name: string;
|
|
101
|
+
/** Optional column names */
|
|
102
|
+
columns?: string[];
|
|
103
|
+
/** CTE query */
|
|
104
|
+
query: SelectQueryNode;
|
|
105
|
+
/** Whether the CTE is recursive */
|
|
106
|
+
recursive: boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Supported set operation kinds for compound SELECT queries
|
|
111
|
+
*/
|
|
112
|
+
export type SetOperationKind = 'UNION' | 'UNION ALL' | 'INTERSECT' | 'EXCEPT';
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* AST node representing a set operation (UNION, INTERSECT, etc.)
|
|
116
|
+
*/
|
|
117
|
+
export interface SetOperationNode {
|
|
118
|
+
type: 'SetOperation';
|
|
119
|
+
/** Operator to combine queries */
|
|
120
|
+
operator: SetOperationKind;
|
|
121
|
+
/** Right-hand query in the compound expression */
|
|
122
|
+
query: SelectQueryNode;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* AST node representing a complete SELECT query
|
|
127
|
+
*/
|
|
128
|
+
export interface SelectQueryNode {
|
|
129
|
+
type: 'SelectQuery';
|
|
114
130
|
/** Optional CTEs (WITH clauses) */
|
|
115
131
|
ctes?: CommonTableExpressionNode[];
|
|
116
132
|
/** FROM clause table */
|
|
@@ -131,11 +147,13 @@ export interface SelectQueryNode {
|
|
|
131
147
|
limit?: number;
|
|
132
148
|
/** Optional OFFSET clause */
|
|
133
149
|
offset?: number;
|
|
134
|
-
/** Optional query metadata */
|
|
135
|
-
meta?: QueryMetadata;
|
|
136
|
-
/** Optional DISTINCT clause */
|
|
137
|
-
distinct?: ColumnNode[];
|
|
138
|
-
|
|
150
|
+
/** Optional query metadata */
|
|
151
|
+
meta?: QueryMetadata;
|
|
152
|
+
/** Optional DISTINCT clause */
|
|
153
|
+
distinct?: ColumnNode[];
|
|
154
|
+
/** Optional set operations chaining this query with others */
|
|
155
|
+
setOps?: SetOperationNode[];
|
|
156
|
+
}
|
|
139
157
|
|
|
140
158
|
export interface InsertQueryNode {
|
|
141
159
|
type: 'InsertQuery';
|