metal-orm 1.0.38 → 1.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +230 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -24
- package/dist/index.d.ts +71 -24
- package/dist/index.js +225 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/scripts/generate-entities.mjs +3 -3
- package/src/codegen/typescript.ts +60 -3
- package/src/core/ast/aggregate-functions.ts +15 -15
- package/src/core/ast/expression-builders.ts +357 -316
- package/src/core/ast/expression-nodes.ts +208 -186
- package/src/core/ast/expression-visitor.ts +40 -30
- package/src/core/ast/query.ts +142 -132
- package/src/core/ast/window-functions.ts +86 -86
- package/src/core/dialect/abstract.ts +505 -479
- package/src/core/dialect/base/groupby-compiler.ts +6 -6
- package/src/core/dialect/base/orderby-compiler.ts +20 -6
- package/src/core/dialect/base/sql-dialect.ts +154 -136
- package/src/core/dialect/mssql/index.ts +172 -161
- package/src/core/functions/standard-strategy.ts +46 -37
- package/src/query-builder/hydration-manager.ts +93 -79
- package/src/query-builder/query-ast-service.ts +207 -170
- package/src/query-builder/select-query-state.ts +169 -162
- package/src/query-builder/select.ts +15 -23
|
@@ -1,79 +1,86 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
*
|
|
40
|
-
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
import {
|
|
3
|
+
SelectQueryNode,
|
|
4
|
+
CommonTableExpressionNode,
|
|
5
|
+
OrderByNode,
|
|
6
|
+
SetOperationNode,
|
|
7
|
+
TableSourceNode,
|
|
8
|
+
OrderingTerm
|
|
9
|
+
} from '../core/ast/query.js';
|
|
10
|
+
import {
|
|
11
|
+
ColumnNode,
|
|
12
|
+
ExpressionNode,
|
|
13
|
+
FunctionNode,
|
|
14
|
+
ScalarSubqueryNode,
|
|
15
|
+
CaseExpressionNode,
|
|
16
|
+
WindowFunctionNode
|
|
17
|
+
} from '../core/ast/expression.js';
|
|
18
|
+
import { JoinNode } from '../core/ast/join.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Node types that can be used in query projections
|
|
22
|
+
*/
|
|
23
|
+
export type ProjectionNode =
|
|
24
|
+
| ColumnNode
|
|
25
|
+
| FunctionNode
|
|
26
|
+
| ScalarSubqueryNode
|
|
27
|
+
| CaseExpressionNode
|
|
28
|
+
| WindowFunctionNode;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Manages the state of a SELECT query being built
|
|
32
|
+
*/
|
|
33
|
+
export class SelectQueryState {
|
|
34
|
+
/**
|
|
35
|
+
* Table definition for the query
|
|
36
|
+
*/
|
|
37
|
+
public readonly table: TableDef;
|
|
38
|
+
/**
|
|
39
|
+
* Abstract Syntax Tree (AST) representation of the query
|
|
40
|
+
*/
|
|
41
|
+
public readonly ast: SelectQueryNode;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new SelectQueryState instance
|
|
45
|
+
* @param table - Table definition
|
|
46
|
+
* @param ast - Optional existing AST
|
|
47
|
+
*/
|
|
48
|
+
constructor(table: TableDef, ast?: SelectQueryNode) {
|
|
49
|
+
this.table = table;
|
|
50
|
+
this.ast = ast ?? {
|
|
51
|
+
type: 'SelectQuery',
|
|
52
|
+
from: { type: 'Table', name: table.name },
|
|
53
|
+
columns: [],
|
|
54
|
+
joins: []
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new SelectQueryState with updated AST
|
|
60
|
+
* @param nextAst - Updated AST
|
|
61
|
+
* @returns New SelectQueryState instance
|
|
62
|
+
*/
|
|
63
|
+
private clone(nextAst: SelectQueryNode): SelectQueryState {
|
|
64
|
+
return new SelectQueryState(this.table, nextAst);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Adds columns to the query
|
|
69
|
+
* @param newCols - Columns to add
|
|
70
|
+
* @returns New SelectQueryState with added columns
|
|
71
|
+
*/
|
|
72
|
+
withColumns(newCols: ProjectionNode[]): SelectQueryState {
|
|
73
|
+
return this.clone({
|
|
74
|
+
...this.ast,
|
|
75
|
+
columns: [...(this.ast.columns ?? []), ...newCols]
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Adds a join to the query
|
|
81
|
+
* @param join - Join node to add
|
|
82
|
+
* @returns New SelectQueryState with added join
|
|
83
|
+
*/
|
|
77
84
|
withJoin(join: JoinNode): SelectQueryState {
|
|
78
85
|
return this.clone({
|
|
79
86
|
...this.ast,
|
|
@@ -92,92 +99,92 @@ export class SelectQueryState {
|
|
|
92
99
|
from
|
|
93
100
|
});
|
|
94
101
|
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Adds a WHERE clause to the query
|
|
98
|
-
* @param predicate - WHERE predicate expression
|
|
99
|
-
* @returns New SelectQueryState with WHERE clause
|
|
100
|
-
*/
|
|
101
|
-
withWhere(predicate: ExpressionNode): SelectQueryState {
|
|
102
|
-
return this.clone({
|
|
103
|
-
...this.ast,
|
|
104
|
-
where: predicate
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Adds a HAVING clause to the query
|
|
110
|
-
* @param predicate - HAVING predicate expression
|
|
111
|
-
* @returns New SelectQueryState with HAVING clause
|
|
112
|
-
*/
|
|
113
|
-
withHaving(predicate: ExpressionNode): SelectQueryState {
|
|
114
|
-
return this.clone({
|
|
115
|
-
...this.ast,
|
|
116
|
-
having: predicate
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Adds GROUP BY columns to the query
|
|
122
|
-
* @param columns -
|
|
123
|
-
* @returns New SelectQueryState with GROUP BY clause
|
|
124
|
-
*/
|
|
125
|
-
withGroupBy(columns:
|
|
126
|
-
return this.clone({
|
|
127
|
-
...this.ast,
|
|
128
|
-
groupBy: [...(this.ast.groupBy ?? []), ...columns]
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Adds ORDER BY clauses to the query
|
|
134
|
-
* @param orderBy - ORDER BY nodes
|
|
135
|
-
* @returns New SelectQueryState with ORDER BY clause
|
|
136
|
-
*/
|
|
137
|
-
withOrderBy(orderBy: OrderByNode[]): SelectQueryState {
|
|
138
|
-
return this.clone({
|
|
139
|
-
...this.ast,
|
|
140
|
-
orderBy: [...(this.ast.orderBy ?? []), ...orderBy]
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Adds DISTINCT columns to the query
|
|
146
|
-
* @param columns - Columns to make distinct
|
|
147
|
-
* @returns New SelectQueryState with DISTINCT clause
|
|
148
|
-
*/
|
|
149
|
-
withDistinct(columns: ColumnNode[]): SelectQueryState {
|
|
150
|
-
return this.clone({
|
|
151
|
-
...this.ast,
|
|
152
|
-
distinct: [...(this.ast.distinct ?? []), ...columns]
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Adds a LIMIT clause to the query
|
|
158
|
-
* @param limit - Maximum number of rows to return
|
|
159
|
-
* @returns New SelectQueryState with LIMIT clause
|
|
160
|
-
*/
|
|
161
|
-
withLimit(limit: number): SelectQueryState {
|
|
162
|
-
return this.clone({
|
|
163
|
-
...this.ast,
|
|
164
|
-
limit
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Adds an OFFSET clause to the query
|
|
170
|
-
* @param offset - Number of rows to skip
|
|
171
|
-
* @returns New SelectQueryState with OFFSET clause
|
|
172
|
-
*/
|
|
173
|
-
withOffset(offset: number): SelectQueryState {
|
|
174
|
-
return this.clone({
|
|
175
|
-
...this.ast,
|
|
176
|
-
offset
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Adds a WHERE clause to the query
|
|
105
|
+
* @param predicate - WHERE predicate expression
|
|
106
|
+
* @returns New SelectQueryState with WHERE clause
|
|
107
|
+
*/
|
|
108
|
+
withWhere(predicate: ExpressionNode): SelectQueryState {
|
|
109
|
+
return this.clone({
|
|
110
|
+
...this.ast,
|
|
111
|
+
where: predicate
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Adds a HAVING clause to the query
|
|
117
|
+
* @param predicate - HAVING predicate expression
|
|
118
|
+
* @returns New SelectQueryState with HAVING clause
|
|
119
|
+
*/
|
|
120
|
+
withHaving(predicate: ExpressionNode): SelectQueryState {
|
|
121
|
+
return this.clone({
|
|
122
|
+
...this.ast,
|
|
123
|
+
having: predicate
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Adds GROUP BY columns to the query
|
|
129
|
+
* @param columns - Terms to group by
|
|
130
|
+
* @returns New SelectQueryState with GROUP BY clause
|
|
131
|
+
*/
|
|
132
|
+
withGroupBy(columns: OrderingTerm[]): SelectQueryState {
|
|
133
|
+
return this.clone({
|
|
134
|
+
...this.ast,
|
|
135
|
+
groupBy: [...(this.ast.groupBy ?? []), ...columns]
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Adds ORDER BY clauses to the query
|
|
141
|
+
* @param orderBy - ORDER BY nodes
|
|
142
|
+
* @returns New SelectQueryState with ORDER BY clause
|
|
143
|
+
*/
|
|
144
|
+
withOrderBy(orderBy: OrderByNode[]): SelectQueryState {
|
|
145
|
+
return this.clone({
|
|
146
|
+
...this.ast,
|
|
147
|
+
orderBy: [...(this.ast.orderBy ?? []), ...orderBy]
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Adds DISTINCT columns to the query
|
|
153
|
+
* @param columns - Columns to make distinct
|
|
154
|
+
* @returns New SelectQueryState with DISTINCT clause
|
|
155
|
+
*/
|
|
156
|
+
withDistinct(columns: ColumnNode[]): SelectQueryState {
|
|
157
|
+
return this.clone({
|
|
158
|
+
...this.ast,
|
|
159
|
+
distinct: [...(this.ast.distinct ?? []), ...columns]
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Adds a LIMIT clause to the query
|
|
165
|
+
* @param limit - Maximum number of rows to return
|
|
166
|
+
* @returns New SelectQueryState with LIMIT clause
|
|
167
|
+
*/
|
|
168
|
+
withLimit(limit: number): SelectQueryState {
|
|
169
|
+
return this.clone({
|
|
170
|
+
...this.ast,
|
|
171
|
+
limit
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Adds an OFFSET clause to the query
|
|
177
|
+
* @param offset - Number of rows to skip
|
|
178
|
+
* @returns New SelectQueryState with OFFSET clause
|
|
179
|
+
*/
|
|
180
|
+
withOffset(offset: number): SelectQueryState {
|
|
181
|
+
return this.clone({
|
|
182
|
+
...this.ast,
|
|
183
|
+
offset
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
181
188
|
* Adds a Common Table Expression (CTE) to the query
|
|
182
189
|
* @param cte - CTE node to add
|
|
183
190
|
* @returns New SelectQueryState with CTE
|
|
@@ -2,7 +2,7 @@ import { TableDef } from '../schema/table.js';
|
|
|
2
2
|
|
|
3
3
|
import { ColumnDef } from '../schema/column.js';
|
|
4
4
|
|
|
5
|
-
import { SelectQueryNode, SetOperationKind } from '../core/ast/query.js';
|
|
5
|
+
import { OrderingTerm, SelectQueryNode, SetOperationKind } from '../core/ast/query.js';
|
|
6
6
|
|
|
7
7
|
import { HydrationPlan } from '../core/hydration/types.js';
|
|
8
8
|
|
|
@@ -727,21 +727,13 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
727
727
|
|
|
728
728
|
|
|
729
729
|
/**
|
|
730
|
-
|
|
731
730
|
* Adds a GROUP BY clause to the query
|
|
732
|
-
|
|
733
|
-
* @param col - Column definition or column node to group by
|
|
734
|
-
|
|
731
|
+
* @param term - Column definition or ordering term to group by
|
|
735
732
|
* @returns New query builder instance with the GROUP BY clause
|
|
736
|
-
|
|
737
733
|
*/
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
const nextContext = this.applyAst(this.context, service => service.withGroupBy(col));
|
|
742
|
-
|
|
734
|
+
groupBy(term: ColumnDef | OrderingTerm): SelectQueryBuilder<T, TTable> {
|
|
735
|
+
const nextContext = this.applyAst(this.context, service => service.withGroupBy(term));
|
|
743
736
|
return this.clone(nextContext);
|
|
744
|
-
|
|
745
737
|
}
|
|
746
738
|
|
|
747
739
|
|
|
@@ -767,23 +759,23 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
767
759
|
|
|
768
760
|
|
|
769
761
|
/**
|
|
770
|
-
|
|
771
762
|
* Adds an ORDER BY clause to the query
|
|
772
|
-
|
|
773
|
-
* @param
|
|
774
|
-
|
|
775
|
-
* @param direction - Order direction (defaults to ASC)
|
|
776
|
-
|
|
763
|
+
* @param term - Column definition or ordering term to order by
|
|
764
|
+
* @param directionOrOptions - Order direction or options (defaults to ASC)
|
|
777
765
|
* @returns New query builder instance with the ORDER BY clause
|
|
778
|
-
|
|
779
766
|
*/
|
|
767
|
+
orderBy(
|
|
768
|
+
term: ColumnDef | OrderingTerm,
|
|
769
|
+
directionOrOptions: OrderDirection | { direction?: OrderDirection; nulls?: 'FIRST' | 'LAST'; collation?: string } = ORDER_DIRECTIONS.ASC
|
|
770
|
+
): SelectQueryBuilder<T, TTable> {
|
|
771
|
+
const options = typeof directionOrOptions === 'string' ? { direction: directionOrOptions } : directionOrOptions;
|
|
772
|
+
const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
|
|
780
773
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
774
|
+
const nextContext = this.applyAst(this.context, service =>
|
|
775
|
+
service.withOrderBy(term, dir, options.nulls, options.collation)
|
|
776
|
+
);
|
|
784
777
|
|
|
785
778
|
return this.clone(nextContext);
|
|
786
|
-
|
|
787
779
|
}
|
|
788
780
|
|
|
789
781
|
|