metal-orm 1.0.33 → 1.0.34
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 +7 -5
- package/dist/index.cjs +295 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2585 -98
- package/dist/index.d.ts +2585 -98
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -6
- package/scripts/generate-entities.mjs +1 -1
- package/src/index.ts +1 -0
- package/src/orm/entity.ts +5 -5
- package/src/orm/execute.ts +4 -4
- package/src/orm/orm-session.ts +229 -229
- package/src/query-builder/select.ts +885 -886
- package/src/schema/types.ts +39 -39
- package/dist/decorators/index.cjs +0 -4968
- package/dist/decorators/index.cjs.map +0 -1
- package/dist/decorators/index.d.cts +0 -70
- package/dist/decorators/index.d.ts +0 -70
- package/dist/decorators/index.js +0 -4933
- package/dist/decorators/index.js.map +0 -1
- package/dist/select-BuMpVcVt.d.cts +0 -2424
- package/dist/select-BuMpVcVt.d.ts +0 -2424
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table.js';
|
|
2
|
-
|
|
3
|
-
import { ColumnDef } from '../schema/column.js';
|
|
4
|
-
|
|
5
|
-
import { SelectQueryNode, SetOperationKind } from '../core/ast/query.js';
|
|
6
|
-
|
|
7
|
-
import { HydrationPlan } from '../core/hydration/types.js';
|
|
8
|
-
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
|
|
3
|
+
import { ColumnDef } from '../schema/column.js';
|
|
4
|
+
|
|
5
|
+
import { SelectQueryNode, SetOperationKind } from '../core/ast/query.js';
|
|
6
|
+
|
|
7
|
+
import { HydrationPlan } from '../core/hydration/types.js';
|
|
8
|
+
|
|
9
9
|
import {
|
|
10
10
|
|
|
11
11
|
ColumnNode,
|
|
@@ -30,33 +30,33 @@ import {
|
|
|
30
30
|
|
|
31
31
|
} from '../core/ast/expression.js';
|
|
32
32
|
import { derivedTable } from '../core/ast/builders.js';
|
|
33
|
-
|
|
34
|
-
import { CompiledQuery, Dialect } from '../core/dialect/abstract.js';
|
|
35
|
-
|
|
36
|
-
import { DialectKey, resolveDialectInput } from '../core/dialect/dialect-factory.js';
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
type SelectDialectInput = Dialect | DialectKey;
|
|
41
|
-
|
|
42
|
-
import { SelectQueryState } from './select-query-state.js';
|
|
43
|
-
|
|
44
|
-
import { HydrationManager } from './hydration-manager.js';
|
|
45
|
-
|
|
46
|
-
import {
|
|
47
|
-
|
|
48
|
-
resolveSelectQueryBuilderDependencies,
|
|
49
|
-
|
|
50
|
-
SelectQueryBuilderContext,
|
|
51
|
-
|
|
52
|
-
SelectQueryBuilderDependencies,
|
|
53
|
-
|
|
54
|
-
SelectQueryBuilderEnvironment
|
|
55
|
-
|
|
56
|
-
} from './select-query-builder-deps.js';
|
|
57
|
-
|
|
58
|
-
import { QueryAstService } from './query-ast-service.js';
|
|
59
|
-
|
|
33
|
+
|
|
34
|
+
import { CompiledQuery, Dialect } from '../core/dialect/abstract.js';
|
|
35
|
+
|
|
36
|
+
import { DialectKey, resolveDialectInput } from '../core/dialect/dialect-factory.js';
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
type SelectDialectInput = Dialect | DialectKey;
|
|
41
|
+
|
|
42
|
+
import { SelectQueryState } from './select-query-state.js';
|
|
43
|
+
|
|
44
|
+
import { HydrationManager } from './hydration-manager.js';
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
|
|
48
|
+
resolveSelectQueryBuilderDependencies,
|
|
49
|
+
|
|
50
|
+
SelectQueryBuilderContext,
|
|
51
|
+
|
|
52
|
+
SelectQueryBuilderDependencies,
|
|
53
|
+
|
|
54
|
+
SelectQueryBuilderEnvironment
|
|
55
|
+
|
|
56
|
+
} from './select-query-builder-deps.js';
|
|
57
|
+
|
|
58
|
+
import { QueryAstService } from './query-ast-service.js';
|
|
59
|
+
|
|
60
60
|
import { ColumnSelector } from './column-selector.js';
|
|
61
61
|
|
|
62
62
|
import { RelationManager } from './relation-manager.js';
|
|
@@ -66,17 +66,17 @@ import { RelationIncludeOptions } from './relation-types.js';
|
|
|
66
66
|
import type { RelationDef } from '../schema/relation.js';
|
|
67
67
|
|
|
68
68
|
import { JOIN_KINDS, JoinKind, ORDER_DIRECTIONS, OrderDirection } from '../core/sql/sql.js';
|
|
69
|
-
|
|
70
|
-
import {
|
|
71
|
-
|
|
72
|
-
import { OrmSession } from '../orm/orm-session.ts';
|
|
73
|
-
|
|
74
|
-
import { ExecutionContext } from '../orm/execution-context.js';
|
|
75
|
-
|
|
76
|
-
import { HydrationContext } from '../orm/hydration-context.js';
|
|
77
|
-
|
|
78
|
-
import { executeHydrated, executeHydratedWithContexts } from '../orm/execute.js';
|
|
79
|
-
|
|
69
|
+
|
|
70
|
+
import { EntityInstance, RelationMap, RelationTargetTable } from '../schema/types.js';
|
|
71
|
+
|
|
72
|
+
import { OrmSession } from '../orm/orm-session.ts';
|
|
73
|
+
|
|
74
|
+
import { ExecutionContext } from '../orm/execution-context.js';
|
|
75
|
+
|
|
76
|
+
import { HydrationContext } from '../orm/hydration-context.js';
|
|
77
|
+
|
|
78
|
+
import { executeHydrated, executeHydratedWithContexts } from '../orm/execute.js';
|
|
79
|
+
|
|
80
80
|
import { createJoinNode } from '../core/ast/join-node.js';
|
|
81
81
|
|
|
82
82
|
|
|
@@ -100,83 +100,83 @@ type RelationCallback = <TChildTable extends TableDef>(
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
|
-
|
|
104
|
-
* Main query builder class for constructing SQL SELECT queries
|
|
105
|
-
|
|
106
|
-
* @typeParam T - Result type for projections (unused)
|
|
107
|
-
|
|
108
|
-
* @typeParam TTable - Table definition being queried
|
|
109
|
-
|
|
110
|
-
*/
|
|
111
|
-
|
|
112
|
-
export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
113
|
-
|
|
114
|
-
private readonly env: SelectQueryBuilderEnvironment;
|
|
115
|
-
|
|
116
|
-
private readonly context: SelectQueryBuilderContext;
|
|
117
|
-
|
|
118
|
-
private readonly columnSelector: ColumnSelector;
|
|
119
|
-
|
|
120
|
-
private readonly relationManager: RelationManager;
|
|
121
|
-
|
|
122
|
-
private readonly lazyRelations: Set<string>;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
|
|
128
|
-
* Creates a new SelectQueryBuilder instance
|
|
129
|
-
|
|
130
|
-
* @param table - Table definition to query
|
|
131
|
-
|
|
132
|
-
* @param state - Optional initial query state
|
|
133
|
-
|
|
134
|
-
* @param hydration - Optional hydration manager
|
|
135
|
-
|
|
136
|
-
* @param dependencies - Optional query builder dependencies
|
|
137
|
-
|
|
138
|
-
*/
|
|
139
|
-
|
|
140
|
-
constructor(
|
|
141
|
-
|
|
142
|
-
table: TTable,
|
|
143
|
-
|
|
144
|
-
state?: SelectQueryState,
|
|
145
|
-
|
|
146
|
-
hydration?: HydrationManager,
|
|
147
|
-
|
|
148
|
-
dependencies?: Partial<SelectQueryBuilderDependencies>,
|
|
149
|
-
|
|
150
|
-
lazyRelations?: Set<string>
|
|
151
|
-
|
|
152
|
-
) {
|
|
153
|
-
|
|
154
|
-
const deps = resolveSelectQueryBuilderDependencies(dependencies);
|
|
155
|
-
|
|
156
|
-
this.env = { table, deps };
|
|
157
|
-
|
|
158
|
-
const initialState = state ?? deps.createState(table);
|
|
159
|
-
|
|
160
|
-
const initialHydration = hydration ?? deps.createHydration(table);
|
|
161
|
-
|
|
162
|
-
this.context = {
|
|
163
|
-
|
|
164
|
-
state: initialState,
|
|
165
|
-
|
|
166
|
-
hydration: initialHydration
|
|
167
|
-
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
this.lazyRelations = new Set(lazyRelations ?? []);
|
|
171
|
-
|
|
172
|
-
this.columnSelector = new ColumnSelector(this.env);
|
|
173
|
-
|
|
174
|
-
this.relationManager = new RelationManager(this.env);
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
103
|
+
|
|
104
|
+
* Main query builder class for constructing SQL SELECT queries
|
|
105
|
+
|
|
106
|
+
* @typeParam T - Result type for projections (unused)
|
|
107
|
+
|
|
108
|
+
* @typeParam TTable - Table definition being queried
|
|
109
|
+
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
113
|
+
|
|
114
|
+
private readonly env: SelectQueryBuilderEnvironment;
|
|
115
|
+
|
|
116
|
+
private readonly context: SelectQueryBuilderContext;
|
|
117
|
+
|
|
118
|
+
private readonly columnSelector: ColumnSelector;
|
|
119
|
+
|
|
120
|
+
private readonly relationManager: RelationManager;
|
|
121
|
+
|
|
122
|
+
private readonly lazyRelations: Set<string>;
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
|
|
128
|
+
* Creates a new SelectQueryBuilder instance
|
|
129
|
+
|
|
130
|
+
* @param table - Table definition to query
|
|
131
|
+
|
|
132
|
+
* @param state - Optional initial query state
|
|
133
|
+
|
|
134
|
+
* @param hydration - Optional hydration manager
|
|
135
|
+
|
|
136
|
+
* @param dependencies - Optional query builder dependencies
|
|
137
|
+
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
constructor(
|
|
141
|
+
|
|
142
|
+
table: TTable,
|
|
143
|
+
|
|
144
|
+
state?: SelectQueryState,
|
|
145
|
+
|
|
146
|
+
hydration?: HydrationManager,
|
|
147
|
+
|
|
148
|
+
dependencies?: Partial<SelectQueryBuilderDependencies>,
|
|
149
|
+
|
|
150
|
+
lazyRelations?: Set<string>
|
|
151
|
+
|
|
152
|
+
) {
|
|
153
|
+
|
|
154
|
+
const deps = resolveSelectQueryBuilderDependencies(dependencies);
|
|
155
|
+
|
|
156
|
+
this.env = { table, deps };
|
|
157
|
+
|
|
158
|
+
const initialState = state ?? deps.createState(table);
|
|
159
|
+
|
|
160
|
+
const initialHydration = hydration ?? deps.createHydration(table);
|
|
161
|
+
|
|
162
|
+
this.context = {
|
|
163
|
+
|
|
164
|
+
state: initialState,
|
|
165
|
+
|
|
166
|
+
hydration: initialHydration
|
|
167
|
+
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
this.lazyRelations = new Set(lazyRelations ?? []);
|
|
171
|
+
|
|
172
|
+
this.columnSelector = new ColumnSelector(this.env);
|
|
173
|
+
|
|
174
|
+
this.relationManager = new RelationManager(this.env);
|
|
175
|
+
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
180
|
private clone(
|
|
181
181
|
|
|
182
182
|
context: SelectQueryBuilderContext = this.context,
|
|
@@ -202,9 +202,9 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
202
202
|
const nextContext = this.applyAst(this.context, service => service.withFrom(nextFrom));
|
|
203
203
|
return this.clone(nextContext);
|
|
204
204
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
208
|
private resolveQueryNode(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryNode {
|
|
209
209
|
|
|
210
210
|
return typeof (query as any).getAST === 'function'
|
|
@@ -223,81 +223,81 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
223
223
|
where: combinedWhere
|
|
224
224
|
};
|
|
225
225
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
private createChildBuilder<R, TChild extends TableDef>(table: TChild): SelectQueryBuilder<R, TChild> {
|
|
230
|
-
|
|
231
|
-
return new SelectQueryBuilder(table, undefined, undefined, this.env.deps);
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
private applyAst(
|
|
238
|
-
|
|
239
|
-
context: SelectQueryBuilderContext,
|
|
240
|
-
|
|
241
|
-
mutator: (service: QueryAstService) => SelectQueryState
|
|
242
|
-
|
|
243
|
-
): SelectQueryBuilderContext {
|
|
244
|
-
|
|
245
|
-
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
246
|
-
|
|
247
|
-
const nextState = mutator(astService);
|
|
248
|
-
|
|
249
|
-
return { state: nextState, hydration: context.hydration };
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
private applyJoin(
|
|
256
|
-
|
|
257
|
-
context: SelectQueryBuilderContext,
|
|
258
|
-
|
|
259
|
-
table: TableDef,
|
|
260
|
-
|
|
261
|
-
condition: BinaryExpressionNode,
|
|
262
|
-
|
|
263
|
-
kind: JoinKind
|
|
264
|
-
|
|
265
|
-
): SelectQueryBuilderContext {
|
|
266
|
-
|
|
267
|
-
const joinNode = createJoinNode(kind, table.name, condition);
|
|
268
|
-
|
|
269
|
-
return this.applyAst(context, service => service.withJoin(joinNode));
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
private applySetOperation(
|
|
276
|
-
|
|
277
|
-
operator: SetOperationKind,
|
|
278
|
-
|
|
279
|
-
query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode
|
|
280
|
-
|
|
281
|
-
): SelectQueryBuilderContext {
|
|
282
|
-
|
|
283
|
-
const subAst = this.resolveQueryNode(query);
|
|
284
|
-
|
|
285
|
-
return this.applyAst(this.context, service => service.withSetOperation(operator, subAst));
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
|
|
293
|
-
* Selects specific columns for the query
|
|
294
|
-
|
|
295
|
-
* @param columns - Record of column definitions, function nodes, case expressions, or window functions
|
|
296
|
-
|
|
297
|
-
* @returns New query builder instance with selected columns
|
|
298
|
-
|
|
299
|
-
*/
|
|
300
|
-
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
private createChildBuilder<R, TChild extends TableDef>(table: TChild): SelectQueryBuilder<R, TChild> {
|
|
230
|
+
|
|
231
|
+
return new SelectQueryBuilder(table, undefined, undefined, this.env.deps);
|
|
232
|
+
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
private applyAst(
|
|
238
|
+
|
|
239
|
+
context: SelectQueryBuilderContext,
|
|
240
|
+
|
|
241
|
+
mutator: (service: QueryAstService) => SelectQueryState
|
|
242
|
+
|
|
243
|
+
): SelectQueryBuilderContext {
|
|
244
|
+
|
|
245
|
+
const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
|
|
246
|
+
|
|
247
|
+
const nextState = mutator(astService);
|
|
248
|
+
|
|
249
|
+
return { state: nextState, hydration: context.hydration };
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
private applyJoin(
|
|
256
|
+
|
|
257
|
+
context: SelectQueryBuilderContext,
|
|
258
|
+
|
|
259
|
+
table: TableDef,
|
|
260
|
+
|
|
261
|
+
condition: BinaryExpressionNode,
|
|
262
|
+
|
|
263
|
+
kind: JoinKind
|
|
264
|
+
|
|
265
|
+
): SelectQueryBuilderContext {
|
|
266
|
+
|
|
267
|
+
const joinNode = createJoinNode(kind, table.name, condition);
|
|
268
|
+
|
|
269
|
+
return this.applyAst(context, service => service.withJoin(joinNode));
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
private applySetOperation(
|
|
276
|
+
|
|
277
|
+
operator: SetOperationKind,
|
|
278
|
+
|
|
279
|
+
query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode
|
|
280
|
+
|
|
281
|
+
): SelectQueryBuilderContext {
|
|
282
|
+
|
|
283
|
+
const subAst = this.resolveQueryNode(query);
|
|
284
|
+
|
|
285
|
+
return this.applyAst(this.context, service => service.withSetOperation(operator, subAst));
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
|
|
293
|
+
* Selects specific columns for the query
|
|
294
|
+
|
|
295
|
+
* @param columns - Record of column definitions, function nodes, case expressions, or window functions
|
|
296
|
+
|
|
297
|
+
* @returns New query builder instance with selected columns
|
|
298
|
+
|
|
299
|
+
*/
|
|
300
|
+
|
|
301
301
|
select(columns: Record<string, ColumnSelectionValue>): SelectQueryBuilder<T, TTable> {
|
|
302
302
|
|
|
303
303
|
return this.clone(this.columnSelector.select(this.context, columns));
|
|
@@ -323,66 +323,66 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
323
323
|
return this.select(selection);
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
|
|
330
|
-
* Selects raw column expressions
|
|
331
|
-
|
|
332
|
-
* @param cols - Column expressions as strings
|
|
333
|
-
|
|
334
|
-
* @returns New query builder instance with raw column selections
|
|
335
|
-
|
|
336
|
-
*/
|
|
337
|
-
|
|
338
|
-
selectRaw(...cols: string[]): SelectQueryBuilder<T, TTable> {
|
|
339
|
-
|
|
340
|
-
return this.clone(this.columnSelector.selectRaw(this.context, cols));
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
|
|
348
|
-
* Adds a Common Table Expression (CTE) to the query
|
|
349
|
-
|
|
350
|
-
* @param name - Name of the CTE
|
|
351
|
-
|
|
352
|
-
* @param query - Query builder or query node for the CTE
|
|
353
|
-
|
|
354
|
-
* @param columns - Optional column names for the CTE
|
|
355
|
-
|
|
356
|
-
* @returns New query builder instance with the CTE
|
|
357
|
-
|
|
358
|
-
*/
|
|
359
|
-
|
|
360
|
-
with(name: string, query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode, columns?: string[]): SelectQueryBuilder<T, TTable> {
|
|
361
|
-
|
|
362
|
-
const subAst = this.resolveQueryNode(query);
|
|
363
|
-
|
|
364
|
-
const nextContext = this.applyAst(this.context, service => service.withCte(name, subAst, columns, false));
|
|
365
|
-
|
|
366
|
-
return this.clone(nextContext);
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
|
|
374
|
-
* Adds a recursive Common Table Expression (CTE) to the query
|
|
375
|
-
|
|
376
|
-
* @param name - Name of the CTE
|
|
377
|
-
|
|
378
|
-
* @param query - Query builder or query node for the CTE
|
|
379
|
-
|
|
380
|
-
* @param columns - Optional column names for the CTE
|
|
381
|
-
|
|
382
|
-
* @returns New query builder instance with the recursive CTE
|
|
383
|
-
|
|
384
|
-
*/
|
|
385
|
-
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
|
|
330
|
+
* Selects raw column expressions
|
|
331
|
+
|
|
332
|
+
* @param cols - Column expressions as strings
|
|
333
|
+
|
|
334
|
+
* @returns New query builder instance with raw column selections
|
|
335
|
+
|
|
336
|
+
*/
|
|
337
|
+
|
|
338
|
+
selectRaw(...cols: string[]): SelectQueryBuilder<T, TTable> {
|
|
339
|
+
|
|
340
|
+
return this.clone(this.columnSelector.selectRaw(this.context, cols));
|
|
341
|
+
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
|
|
348
|
+
* Adds a Common Table Expression (CTE) to the query
|
|
349
|
+
|
|
350
|
+
* @param name - Name of the CTE
|
|
351
|
+
|
|
352
|
+
* @param query - Query builder or query node for the CTE
|
|
353
|
+
|
|
354
|
+
* @param columns - Optional column names for the CTE
|
|
355
|
+
|
|
356
|
+
* @returns New query builder instance with the CTE
|
|
357
|
+
|
|
358
|
+
*/
|
|
359
|
+
|
|
360
|
+
with(name: string, query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode, columns?: string[]): SelectQueryBuilder<T, TTable> {
|
|
361
|
+
|
|
362
|
+
const subAst = this.resolveQueryNode(query);
|
|
363
|
+
|
|
364
|
+
const nextContext = this.applyAst(this.context, service => service.withCte(name, subAst, columns, false));
|
|
365
|
+
|
|
366
|
+
return this.clone(nextContext);
|
|
367
|
+
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
|
|
374
|
+
* Adds a recursive Common Table Expression (CTE) to the query
|
|
375
|
+
|
|
376
|
+
* @param name - Name of the CTE
|
|
377
|
+
|
|
378
|
+
* @param query - Query builder or query node for the CTE
|
|
379
|
+
|
|
380
|
+
* @param columns - Optional column names for the CTE
|
|
381
|
+
|
|
382
|
+
* @returns New query builder instance with the recursive CTE
|
|
383
|
+
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
386
|
withRecursive(name: string, query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode, columns?: string[]): SelectQueryBuilder<T, TTable> {
|
|
387
387
|
|
|
388
388
|
const subAst = this.resolveQueryNode(query);
|
|
@@ -411,21 +411,21 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
411
411
|
const nextContext = this.applyAst(this.context, service => service.withFrom(fromNode));
|
|
412
412
|
return this.clone(nextContext);
|
|
413
413
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
|
|
419
|
-
* Selects a subquery as a column
|
|
420
|
-
|
|
421
|
-
* @param alias - Alias for the subquery column
|
|
422
|
-
|
|
423
|
-
* @param sub - Query builder or query node for the subquery
|
|
424
|
-
|
|
425
|
-
* @returns New query builder instance with the subquery selection
|
|
426
|
-
|
|
427
|
-
*/
|
|
428
|
-
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
|
|
419
|
+
* Selects a subquery as a column
|
|
420
|
+
|
|
421
|
+
* @param alias - Alias for the subquery column
|
|
422
|
+
|
|
423
|
+
* @param sub - Query builder or query node for the subquery
|
|
424
|
+
|
|
425
|
+
* @returns New query builder instance with the subquery selection
|
|
426
|
+
|
|
427
|
+
*/
|
|
428
|
+
|
|
429
429
|
selectSubquery(alias: string, sub: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
430
430
|
|
|
431
431
|
const query = this.resolveQueryNode(sub);
|
|
@@ -457,478 +457,478 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
457
457
|
return this.clone(nextContext);
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
|
|
464
|
-
* Adds an INNER JOIN to the query
|
|
465
|
-
|
|
466
|
-
* @param table - Table to join
|
|
467
|
-
|
|
468
|
-
* @param condition - Join condition expression
|
|
469
|
-
|
|
470
|
-
* @returns New query builder instance with the INNER JOIN
|
|
471
|
-
|
|
472
|
-
*/
|
|
473
|
-
|
|
474
|
-
innerJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
475
|
-
|
|
476
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
|
|
477
|
-
|
|
478
|
-
return this.clone(nextContext);
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
/**
|
|
485
|
-
|
|
486
|
-
* Adds a LEFT JOIN to the query
|
|
487
|
-
|
|
488
|
-
* @param table - Table to join
|
|
489
|
-
|
|
490
|
-
* @param condition - Join condition expression
|
|
491
|
-
|
|
492
|
-
* @returns New query builder instance with the LEFT JOIN
|
|
493
|
-
|
|
494
|
-
*/
|
|
495
|
-
|
|
496
|
-
leftJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
497
|
-
|
|
498
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
|
|
499
|
-
|
|
500
|
-
return this.clone(nextContext);
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
|
|
508
|
-
* Adds a RIGHT JOIN to the query
|
|
509
|
-
|
|
510
|
-
* @param table - Table to join
|
|
511
|
-
|
|
512
|
-
* @param condition - Join condition expression
|
|
513
|
-
|
|
514
|
-
* @returns New query builder instance with the RIGHT JOIN
|
|
515
|
-
|
|
516
|
-
*/
|
|
517
|
-
|
|
518
|
-
rightJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
519
|
-
|
|
520
|
-
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
|
|
521
|
-
|
|
522
|
-
return this.clone(nextContext);
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
|
|
530
|
-
* Matches records based on a relationship
|
|
531
|
-
|
|
532
|
-
* @param relationName - Name of the relationship to match
|
|
533
|
-
|
|
534
|
-
* @param predicate - Optional predicate expression
|
|
535
|
-
|
|
536
|
-
* @returns New query builder instance with the relationship match
|
|
537
|
-
|
|
538
|
-
*/
|
|
539
|
-
|
|
540
|
-
match(relationName: string, predicate?: ExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
541
|
-
|
|
542
|
-
const nextContext = this.relationManager.match(this.context, relationName, predicate);
|
|
543
|
-
|
|
544
|
-
return this.clone(nextContext);
|
|
545
|
-
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
|
|
552
|
-
* Joins a related table
|
|
553
|
-
|
|
554
|
-
* @param relationName - Name of the relationship to join
|
|
555
|
-
|
|
556
|
-
* @param joinKind - Type of join (defaults to INNER)
|
|
557
|
-
|
|
558
|
-
* @param extraCondition - Optional additional join condition
|
|
559
|
-
|
|
560
|
-
* @returns New query builder instance with the relationship join
|
|
561
|
-
|
|
562
|
-
*/
|
|
563
|
-
|
|
564
|
-
joinRelation(
|
|
565
|
-
|
|
566
|
-
relationName: string,
|
|
567
|
-
|
|
568
|
-
joinKind: JoinKind = JOIN_KINDS.INNER,
|
|
569
|
-
|
|
570
|
-
extraCondition?: ExpressionNode
|
|
571
|
-
|
|
572
|
-
): SelectQueryBuilder<T, TTable> {
|
|
573
|
-
|
|
574
|
-
const nextContext = this.relationManager.joinRelation(this.context, relationName, joinKind, extraCondition);
|
|
575
|
-
|
|
576
|
-
return this.clone(nextContext);
|
|
577
|
-
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
|
|
584
|
-
* Includes related data in the query results
|
|
585
|
-
|
|
586
|
-
* @param relationName - Name of the relationship to include
|
|
587
|
-
|
|
588
|
-
* @param options - Optional include options
|
|
589
|
-
|
|
590
|
-
* @returns New query builder instance with the relationship inclusion
|
|
591
|
-
|
|
592
|
-
*/
|
|
593
|
-
|
|
594
|
-
include(relationName: string, options?: RelationIncludeOptions): SelectQueryBuilder<T, TTable> {
|
|
595
|
-
|
|
596
|
-
const nextContext = this.relationManager.include(this.context, relationName, options);
|
|
597
|
-
|
|
598
|
-
return this.clone(nextContext);
|
|
599
|
-
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
includeLazy<K extends keyof RelationMap<TTable>>(relationName: K): SelectQueryBuilder<T, TTable> {
|
|
605
460
|
|
|
606
|
-
const nextLazy = new Set(this.lazyRelations);
|
|
607
461
|
|
|
608
|
-
|
|
462
|
+
/**
|
|
609
463
|
|
|
610
|
-
|
|
464
|
+
* Adds an INNER JOIN to the query
|
|
611
465
|
|
|
612
|
-
|
|
466
|
+
* @param table - Table to join
|
|
467
|
+
|
|
468
|
+
* @param condition - Join condition expression
|
|
469
|
+
|
|
470
|
+
* @returns New query builder instance with the INNER JOIN
|
|
613
471
|
|
|
614
|
-
/**
|
|
615
|
-
* Selects columns for a related table in a single hop.
|
|
616
472
|
*/
|
|
617
|
-
selectRelationColumns<
|
|
618
|
-
K extends keyof TTable['relations'] & string,
|
|
619
|
-
TRel extends RelationDef = TTable['relations'][K],
|
|
620
|
-
TTarget extends TableDef = RelationTargetTable<TRel>,
|
|
621
|
-
C extends keyof TTarget['columns'] & string = keyof TTarget['columns'] & string
|
|
622
|
-
>(relationName: K, ...cols: C[]): SelectQueryBuilder<T, TTable> {
|
|
623
|
-
const relation = this.env.table.relations[relationName] as RelationDef | undefined;
|
|
624
|
-
if (!relation) {
|
|
625
|
-
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
626
|
-
}
|
|
627
|
-
const target = relation.target;
|
|
628
473
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
}
|
|
635
|
-
}
|
|
474
|
+
innerJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
475
|
+
|
|
476
|
+
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.INNER);
|
|
477
|
+
|
|
478
|
+
return this.clone(nextContext);
|
|
636
479
|
|
|
637
|
-
return this.include(relationName as string, { columns: cols as string[] });
|
|
638
480
|
}
|
|
639
481
|
|
|
640
482
|
|
|
483
|
+
|
|
641
484
|
/**
|
|
642
|
-
|
|
485
|
+
|
|
486
|
+
* Adds a LEFT JOIN to the query
|
|
487
|
+
|
|
488
|
+
* @param table - Table to join
|
|
489
|
+
|
|
490
|
+
* @param condition - Join condition expression
|
|
491
|
+
|
|
492
|
+
* @returns New query builder instance with the LEFT JOIN
|
|
493
|
+
|
|
643
494
|
*/
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
495
|
+
|
|
496
|
+
leftJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
497
|
+
|
|
498
|
+
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.LEFT);
|
|
499
|
+
|
|
500
|
+
return this.clone(nextContext);
|
|
501
|
+
|
|
651
502
|
}
|
|
652
503
|
|
|
653
504
|
|
|
505
|
+
|
|
654
506
|
/**
|
|
655
|
-
|
|
507
|
+
|
|
508
|
+
* Adds a RIGHT JOIN to the query
|
|
509
|
+
|
|
510
|
+
* @param table - Table to join
|
|
511
|
+
|
|
512
|
+
* @param condition - Join condition expression
|
|
513
|
+
|
|
514
|
+
* @returns New query builder instance with the RIGHT JOIN
|
|
515
|
+
|
|
656
516
|
*/
|
|
657
|
-
selectColumnsDeep(config: DeepSelectConfig<TTable>): SelectQueryBuilder<T, TTable> {
|
|
658
|
-
let qb: SelectQueryBuilder<T, TTable> = this;
|
|
659
517
|
|
|
660
|
-
|
|
661
|
-
qb = qb.selectColumns(...config.root);
|
|
662
|
-
}
|
|
518
|
+
rightJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
663
519
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const cols = config[relName as keyof DeepSelectConfig<TTable>] as string[] | undefined;
|
|
668
|
-
if (!cols || !cols.length) continue;
|
|
669
|
-
qb = qb.selectRelationColumns(relName, ...(cols as string[]));
|
|
670
|
-
}
|
|
520
|
+
const nextContext = this.applyJoin(this.context, table, condition, JOIN_KINDS.RIGHT);
|
|
521
|
+
|
|
522
|
+
return this.clone(nextContext);
|
|
671
523
|
|
|
672
|
-
return qb;
|
|
673
524
|
}
|
|
674
525
|
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
*
|
|
734
|
-
|
|
735
|
-
* @
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
|
|
530
|
+
* Matches records based on a relationship
|
|
531
|
+
|
|
532
|
+
* @param relationName - Name of the relationship to match
|
|
533
|
+
|
|
534
|
+
* @param predicate - Optional predicate expression
|
|
535
|
+
|
|
536
|
+
* @returns New query builder instance with the relationship match
|
|
537
|
+
|
|
538
|
+
*/
|
|
539
|
+
|
|
540
|
+
match(relationName: string, predicate?: ExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
541
|
+
|
|
542
|
+
const nextContext = this.relationManager.match(this.context, relationName, predicate);
|
|
543
|
+
|
|
544
|
+
return this.clone(nextContext);
|
|
545
|
+
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
|
|
552
|
+
* Joins a related table
|
|
553
|
+
|
|
554
|
+
* @param relationName - Name of the relationship to join
|
|
555
|
+
|
|
556
|
+
* @param joinKind - Type of join (defaults to INNER)
|
|
557
|
+
|
|
558
|
+
* @param extraCondition - Optional additional join condition
|
|
559
|
+
|
|
560
|
+
* @returns New query builder instance with the relationship join
|
|
561
|
+
|
|
562
|
+
*/
|
|
563
|
+
|
|
564
|
+
joinRelation(
|
|
565
|
+
|
|
566
|
+
relationName: string,
|
|
567
|
+
|
|
568
|
+
joinKind: JoinKind = JOIN_KINDS.INNER,
|
|
569
|
+
|
|
570
|
+
extraCondition?: ExpressionNode
|
|
571
|
+
|
|
572
|
+
): SelectQueryBuilder<T, TTable> {
|
|
573
|
+
|
|
574
|
+
const nextContext = this.relationManager.joinRelation(this.context, relationName, joinKind, extraCondition);
|
|
575
|
+
|
|
576
|
+
return this.clone(nextContext);
|
|
577
|
+
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
|
|
584
|
+
* Includes related data in the query results
|
|
585
|
+
|
|
586
|
+
* @param relationName - Name of the relationship to include
|
|
587
|
+
|
|
588
|
+
* @param options - Optional include options
|
|
589
|
+
|
|
590
|
+
* @returns New query builder instance with the relationship inclusion
|
|
591
|
+
|
|
592
|
+
*/
|
|
593
|
+
|
|
594
|
+
include(relationName: string, options?: RelationIncludeOptions): SelectQueryBuilder<T, TTable> {
|
|
595
|
+
|
|
596
|
+
const nextContext = this.relationManager.include(this.context, relationName, options);
|
|
597
|
+
|
|
598
|
+
return this.clone(nextContext);
|
|
599
|
+
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
includeLazy<K extends keyof RelationMap<TTable>>(relationName: K): SelectQueryBuilder<T, TTable> {
|
|
605
|
+
|
|
606
|
+
const nextLazy = new Set(this.lazyRelations);
|
|
607
|
+
|
|
608
|
+
nextLazy.add(relationName as string);
|
|
609
|
+
|
|
610
|
+
return this.clone(this.context, nextLazy);
|
|
611
|
+
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Selects columns for a related table in a single hop.
|
|
616
|
+
*/
|
|
617
|
+
selectRelationColumns<
|
|
618
|
+
K extends keyof TTable['relations'] & string,
|
|
619
|
+
TRel extends RelationDef = TTable['relations'][K],
|
|
620
|
+
TTarget extends TableDef = RelationTargetTable<TRel>,
|
|
621
|
+
C extends keyof TTarget['columns'] & string = keyof TTarget['columns'] & string
|
|
622
|
+
>(relationName: K, ...cols: C[]): SelectQueryBuilder<T, TTable> {
|
|
623
|
+
const relation = this.env.table.relations[relationName] as RelationDef | undefined;
|
|
624
|
+
if (!relation) {
|
|
625
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
626
|
+
}
|
|
627
|
+
const target = relation.target;
|
|
628
|
+
|
|
629
|
+
for (const col of cols) {
|
|
630
|
+
if (!target.columns[col]) {
|
|
631
|
+
throw new Error(
|
|
632
|
+
`Column '${col}' not found on related table '${target.name}' for relation '${relationName}'`
|
|
633
|
+
);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return this.include(relationName as string, { columns: cols as string[] });
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Convenience alias for selecting specific columns from a relation.
|
|
643
|
+
*/
|
|
644
|
+
includePick<
|
|
645
|
+
K extends keyof TTable['relations'] & string,
|
|
646
|
+
TRel extends RelationDef = TTable['relations'][K],
|
|
647
|
+
TTarget extends TableDef = RelationTargetTable<TRel>,
|
|
648
|
+
C extends keyof TTarget['columns'] & string = keyof TTarget['columns'] & string
|
|
649
|
+
>(relationName: K, cols: C[]): SelectQueryBuilder<T, TTable> {
|
|
650
|
+
return this.selectRelationColumns(relationName, ...cols);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Selects columns for the root table and relations from a single config object.
|
|
656
|
+
*/
|
|
657
|
+
selectColumnsDeep(config: DeepSelectConfig<TTable>): SelectQueryBuilder<T, TTable> {
|
|
658
|
+
let qb: SelectQueryBuilder<T, TTable> = this;
|
|
659
|
+
|
|
660
|
+
if (config.root?.length) {
|
|
661
|
+
qb = qb.selectColumns(...config.root);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
for (const key of Object.keys(config) as (keyof typeof config)[]) {
|
|
665
|
+
if (key === 'root') continue;
|
|
666
|
+
const relName = key as keyof TTable['relations'] & string;
|
|
667
|
+
const cols = config[relName as keyof DeepSelectConfig<TTable>] as string[] | undefined;
|
|
668
|
+
if (!cols || !cols.length) continue;
|
|
669
|
+
qb = qb.selectRelationColumns(relName, ...(cols as string[]));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
return qb;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
getLazyRelations(): (keyof RelationMap<TTable>)[] {
|
|
678
|
+
|
|
679
|
+
return Array.from(this.lazyRelations) as (keyof RelationMap<TTable>)[];
|
|
680
|
+
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
getTable(): TTable {
|
|
686
|
+
|
|
687
|
+
return this.env.table as TTable;
|
|
688
|
+
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
async execute(ctx: OrmSession): Promise<EntityInstance<TTable>[]> {
|
|
694
|
+
|
|
695
|
+
return executeHydrated(ctx, this);
|
|
696
|
+
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
async executeWithContexts(execCtx: ExecutionContext, hydCtx: HydrationContext): Promise<EntityInstance<TTable>[]> {
|
|
702
|
+
|
|
703
|
+
return executeHydratedWithContexts(execCtx, hydCtx, this);
|
|
704
|
+
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
|
|
711
|
+
* Adds a WHERE condition to the query
|
|
712
|
+
|
|
713
|
+
* @param expr - Expression for the WHERE clause
|
|
714
|
+
|
|
715
|
+
* @returns New query builder instance with the WHERE condition
|
|
716
|
+
|
|
717
|
+
*/
|
|
718
|
+
|
|
719
|
+
where(expr: ExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
720
|
+
|
|
721
|
+
const nextContext = this.applyAst(this.context, service => service.withWhere(expr));
|
|
722
|
+
|
|
723
|
+
return this.clone(nextContext);
|
|
724
|
+
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
|
|
731
|
+
* Adds a GROUP BY clause to the query
|
|
732
|
+
|
|
733
|
+
* @param col - Column definition or column node to group by
|
|
734
|
+
|
|
735
|
+
* @returns New query builder instance with the GROUP BY clause
|
|
736
|
+
|
|
737
|
+
*/
|
|
738
|
+
|
|
739
|
+
groupBy(col: ColumnDef | ColumnNode): SelectQueryBuilder<T, TTable> {
|
|
740
|
+
|
|
741
|
+
const nextContext = this.applyAst(this.context, service => service.withGroupBy(col));
|
|
742
|
+
|
|
743
|
+
return this.clone(nextContext);
|
|
744
|
+
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
|
|
751
|
+
* Adds a HAVING condition to the query
|
|
752
|
+
|
|
753
|
+
* @param expr - Expression for the HAVING clause
|
|
754
|
+
|
|
755
|
+
* @returns New query builder instance with the HAVING condition
|
|
756
|
+
|
|
757
|
+
*/
|
|
758
|
+
|
|
759
|
+
having(expr: ExpressionNode): SelectQueryBuilder<T, TTable> {
|
|
760
|
+
|
|
761
|
+
const nextContext = this.applyAst(this.context, service => service.withHaving(expr));
|
|
762
|
+
|
|
763
|
+
return this.clone(nextContext);
|
|
764
|
+
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
|
|
771
|
+
* Adds an ORDER BY clause to the query
|
|
772
|
+
|
|
773
|
+
* @param col - Column definition or column node to order by
|
|
774
|
+
|
|
775
|
+
* @param direction - Order direction (defaults to ASC)
|
|
776
|
+
|
|
777
|
+
* @returns New query builder instance with the ORDER BY clause
|
|
778
|
+
|
|
779
|
+
*/
|
|
780
|
+
|
|
781
|
+
orderBy(col: ColumnDef | ColumnNode, direction: OrderDirection = ORDER_DIRECTIONS.ASC): SelectQueryBuilder<T, TTable> {
|
|
782
|
+
|
|
783
|
+
const nextContext = this.applyAst(this.context, service => service.withOrderBy(col, direction));
|
|
784
|
+
|
|
785
|
+
return this.clone(nextContext);
|
|
786
|
+
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
|
|
793
|
+
* Adds a DISTINCT clause to the query
|
|
794
|
+
|
|
795
|
+
* @param cols - Columns to make distinct
|
|
796
|
+
|
|
797
|
+
* @returns New query builder instance with the DISTINCT clause
|
|
798
|
+
|
|
799
|
+
*/
|
|
800
|
+
|
|
801
|
+
distinct(...cols: (ColumnDef | ColumnNode)[]): SelectQueryBuilder<T, TTable> {
|
|
802
|
+
|
|
803
|
+
return this.clone(this.columnSelector.distinct(this.context, cols));
|
|
804
|
+
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
|
|
811
|
+
* Adds a LIMIT clause to the query
|
|
812
|
+
|
|
813
|
+
* @param n - Maximum number of rows to return
|
|
814
|
+
|
|
815
|
+
* @returns New query builder instance with the LIMIT clause
|
|
816
|
+
|
|
817
|
+
*/
|
|
818
|
+
|
|
819
|
+
limit(n: number): SelectQueryBuilder<T, TTable> {
|
|
820
|
+
|
|
821
|
+
const nextContext = this.applyAst(this.context, service => service.withLimit(n));
|
|
822
|
+
|
|
823
|
+
return this.clone(nextContext);
|
|
824
|
+
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
|
|
831
|
+
* Adds an OFFSET clause to the query
|
|
832
|
+
|
|
833
|
+
* @param n - Number of rows to skip
|
|
834
|
+
|
|
835
|
+
* @returns New query builder instance with the OFFSET clause
|
|
836
|
+
|
|
837
|
+
*/
|
|
838
|
+
|
|
839
|
+
offset(n: number): SelectQueryBuilder<T, TTable> {
|
|
840
|
+
|
|
841
|
+
const nextContext = this.applyAst(this.context, service => service.withOffset(n));
|
|
842
|
+
|
|
843
|
+
return this.clone(nextContext);
|
|
844
|
+
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
|
|
851
|
+
* Combines this query with another using UNION
|
|
852
|
+
|
|
853
|
+
* @param query - Query to union with
|
|
854
|
+
|
|
855
|
+
* @returns New query builder instance with the set operation
|
|
856
|
+
|
|
857
|
+
*/
|
|
858
|
+
|
|
859
|
+
union(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
860
|
+
|
|
861
|
+
return this.clone(this.applySetOperation('UNION', query));
|
|
862
|
+
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
/**
|
|
868
|
+
|
|
869
|
+
* Combines this query with another using UNION ALL
|
|
870
|
+
|
|
871
|
+
* @param query - Query to union with
|
|
872
|
+
|
|
873
|
+
* @returns New query builder instance with the set operation
|
|
874
|
+
|
|
875
|
+
*/
|
|
876
|
+
|
|
877
|
+
unionAll(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
878
|
+
|
|
879
|
+
return this.clone(this.applySetOperation('UNION ALL', query));
|
|
880
|
+
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
|
|
887
|
+
* Combines this query with another using INTERSECT
|
|
888
|
+
|
|
889
|
+
* @param query - Query to intersect with
|
|
890
|
+
|
|
891
|
+
* @returns New query builder instance with the set operation
|
|
892
|
+
|
|
893
|
+
*/
|
|
894
|
+
|
|
895
|
+
intersect(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
896
|
+
|
|
897
|
+
return this.clone(this.applySetOperation('INTERSECT', query));
|
|
898
|
+
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
|
|
905
|
+
* Combines this query with another using EXCEPT
|
|
906
|
+
|
|
907
|
+
* @param query - Query to subtract
|
|
908
|
+
|
|
909
|
+
* @returns New query builder instance with the set operation
|
|
910
|
+
|
|
911
|
+
*/
|
|
912
|
+
|
|
913
|
+
except(query: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode): SelectQueryBuilder<T, TTable> {
|
|
914
|
+
|
|
915
|
+
return this.clone(this.applySetOperation('EXCEPT', query));
|
|
916
|
+
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
|
|
923
|
+
* Adds a WHERE EXISTS condition to the query
|
|
924
|
+
|
|
925
|
+
* @param subquery - Subquery to check for existence
|
|
926
|
+
|
|
927
|
+
* @returns New query builder instance with the WHERE EXISTS condition
|
|
928
|
+
|
|
929
|
+
*/
|
|
930
|
+
|
|
931
|
+
whereExists(
|
|
932
932
|
subquery: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode,
|
|
933
933
|
correlate?: ExpressionNode
|
|
934
934
|
): SelectQueryBuilder<T, TTable> {
|
|
@@ -936,19 +936,19 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
936
936
|
const correlated = this.applyCorrelation(subAst, correlate);
|
|
937
937
|
return this.where(exists(correlated));
|
|
938
938
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
/**
|
|
943
|
-
|
|
944
|
-
* Adds a WHERE NOT EXISTS condition to the query
|
|
945
|
-
|
|
946
|
-
* @param subquery - Subquery to check for non-existence
|
|
947
|
-
|
|
948
|
-
* @returns New query builder instance with the WHERE NOT EXISTS condition
|
|
949
|
-
|
|
950
|
-
*/
|
|
951
|
-
|
|
939
|
+
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
|
|
944
|
+
* Adds a WHERE NOT EXISTS condition to the query
|
|
945
|
+
|
|
946
|
+
* @param subquery - Subquery to check for non-existence
|
|
947
|
+
|
|
948
|
+
* @returns New query builder instance with the WHERE NOT EXISTS condition
|
|
949
|
+
|
|
950
|
+
*/
|
|
951
|
+
|
|
952
952
|
whereNotExists(
|
|
953
953
|
subquery: SelectQueryBuilder<any, TableDef<any>> | SelectQueryNode,
|
|
954
954
|
correlate?: ExpressionNode
|
|
@@ -957,21 +957,21 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
957
957
|
const correlated = this.applyCorrelation(subAst, correlate);
|
|
958
958
|
return this.where(notExists(correlated));
|
|
959
959
|
}
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
/**
|
|
964
|
-
|
|
965
|
-
* Adds a WHERE EXISTS condition based on a relationship
|
|
966
|
-
|
|
967
|
-
* @param relationName - Name of the relationship to check
|
|
968
|
-
|
|
969
|
-
* @param callback - Optional callback to modify the relationship query
|
|
970
|
-
|
|
971
|
-
* @returns New query builder instance with the relationship existence check
|
|
972
|
-
|
|
973
|
-
*/
|
|
974
|
-
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
/**
|
|
964
|
+
|
|
965
|
+
* Adds a WHERE EXISTS condition based on a relationship
|
|
966
|
+
|
|
967
|
+
* @param relationName - Name of the relationship to check
|
|
968
|
+
|
|
969
|
+
* @param callback - Optional callback to modify the relationship query
|
|
970
|
+
|
|
971
|
+
* @returns New query builder instance with the relationship existence check
|
|
972
|
+
|
|
973
|
+
*/
|
|
974
|
+
|
|
975
975
|
whereHas(
|
|
976
976
|
|
|
977
977
|
relationName: string,
|
|
@@ -986,12 +986,12 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
986
986
|
|
|
987
987
|
if (!relation) {
|
|
988
988
|
|
|
989
|
-
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
990
|
-
|
|
991
|
-
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
989
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
990
|
+
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
|
|
995
995
|
const callback = typeof callbackOrOptions === 'function' ? callbackOrOptions as RelationCallback : undefined;
|
|
996
996
|
const options = (typeof callbackOrOptions === 'function' ? maybeOptions : callbackOrOptions) as WhereHasOptions | undefined;
|
|
997
997
|
|
|
@@ -1002,9 +1002,9 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1002
1002
|
subQb = callback(subQb);
|
|
1003
1003
|
|
|
1004
1004
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
1008
|
const subAst = subQb.getAST();
|
|
1009
1009
|
|
|
1010
1010
|
const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
|
|
@@ -1012,21 +1012,21 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1012
1012
|
return this.where(exists(finalSubAst));
|
|
1013
1013
|
|
|
1014
1014
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
/**
|
|
1019
|
-
|
|
1020
|
-
* Adds a WHERE NOT EXISTS condition based on a relationship
|
|
1021
|
-
|
|
1022
|
-
* @param relationName - Name of the relationship to check
|
|
1023
|
-
|
|
1024
|
-
* @param callback - Optional callback to modify the relationship query
|
|
1025
|
-
|
|
1026
|
-
* @returns New query builder instance with the relationship non-existence check
|
|
1027
|
-
|
|
1028
|
-
*/
|
|
1029
|
-
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
|
|
1020
|
+
* Adds a WHERE NOT EXISTS condition based on a relationship
|
|
1021
|
+
|
|
1022
|
+
* @param relationName - Name of the relationship to check
|
|
1023
|
+
|
|
1024
|
+
* @param callback - Optional callback to modify the relationship query
|
|
1025
|
+
|
|
1026
|
+
* @returns New query builder instance with the relationship non-existence check
|
|
1027
|
+
|
|
1028
|
+
*/
|
|
1029
|
+
|
|
1030
1030
|
whereHasNot(
|
|
1031
1031
|
|
|
1032
1032
|
relationName: string,
|
|
@@ -1041,12 +1041,12 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1041
1041
|
|
|
1042
1042
|
if (!relation) {
|
|
1043
1043
|
|
|
1044
|
-
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1044
|
+
throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
|
|
1045
|
+
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
1050
|
const callback = typeof callbackOrOptions === 'function' ? callbackOrOptions as RelationCallback : undefined;
|
|
1051
1051
|
const options = (typeof callbackOrOptions === 'function' ? maybeOptions : callbackOrOptions) as WhereHasOptions | undefined;
|
|
1052
1052
|
|
|
@@ -1067,106 +1067,105 @@ export class SelectQueryBuilder<T = any, TTable extends TableDef = TableDef> {
|
|
|
1067
1067
|
return this.where(notExists(finalSubAst));
|
|
1068
1068
|
|
|
1069
1069
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
/**
|
|
1074
|
-
|
|
1075
|
-
* Compiles the query to SQL for a specific dialect
|
|
1076
|
-
|
|
1077
|
-
* @param dialect - Database dialect to compile for
|
|
1078
|
-
|
|
1079
|
-
* @returns Compiled query with SQL and parameters
|
|
1080
|
-
|
|
1081
|
-
*/
|
|
1082
|
-
|
|
1083
|
-
compile(dialect: SelectDialectInput): CompiledQuery {
|
|
1084
|
-
|
|
1085
|
-
const resolved = resolveDialectInput(dialect);
|
|
1086
|
-
|
|
1087
|
-
return resolved.compileSelect(this.context.state.ast);
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
/**
|
|
1094
|
-
|
|
1095
|
-
* Converts the query to SQL string for a specific dialect
|
|
1096
|
-
|
|
1097
|
-
* @param dialect - Database dialect to generate SQL for
|
|
1098
|
-
|
|
1099
|
-
* @returns SQL string representation of the query
|
|
1100
|
-
|
|
1101
|
-
*/
|
|
1102
|
-
|
|
1103
|
-
toSql(dialect: SelectDialectInput): string {
|
|
1104
|
-
|
|
1105
|
-
return this.compile(dialect).sql;
|
|
1106
|
-
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
/**
|
|
1112
|
-
|
|
1113
|
-
* Gets the hydration plan for the query
|
|
1114
|
-
|
|
1115
|
-
* @returns Hydration plan or undefined if none exists
|
|
1116
|
-
|
|
1117
|
-
*/
|
|
1118
|
-
|
|
1119
|
-
getHydrationPlan(): HydrationPlan | undefined {
|
|
1120
|
-
|
|
1121
|
-
return this.context.hydration.getPlan();
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
/**
|
|
1128
|
-
|
|
1129
|
-
* Gets the Abstract Syntax Tree (AST) representation of the query
|
|
1130
|
-
|
|
1131
|
-
* @returns Query AST with hydration applied
|
|
1132
|
-
|
|
1133
|
-
*/
|
|
1134
|
-
|
|
1135
|
-
getAST(): SelectQueryNode {
|
|
1136
|
-
|
|
1137
|
-
return this.context.hydration.applyToAst(this.context.state.ast);
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
/**
|
|
1146
|
-
|
|
1147
|
-
* Creates a column node for use in expressions
|
|
1148
|
-
|
|
1149
|
-
* @param table - Table name
|
|
1150
|
-
|
|
1151
|
-
* @param name - Column name
|
|
1152
|
-
|
|
1153
|
-
* @returns ColumnNode with the specified table and name
|
|
1154
|
-
|
|
1155
|
-
*/
|
|
1156
|
-
|
|
1157
|
-
export const createColumn = (table: string, name: string): ColumnNode => ({ type: 'Column', table, name });
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
/**
|
|
1162
|
-
|
|
1163
|
-
* Creates a literal value node for use in expressions
|
|
1164
|
-
|
|
1165
|
-
* @param val - Literal value (string or number)
|
|
1166
|
-
|
|
1167
|
-
* @returns LiteralNode with the specified value
|
|
1168
|
-
|
|
1169
|
-
*/
|
|
1170
|
-
|
|
1171
|
-
export const createLiteral = (val: string | number): LiteralNode => ({ type: 'Literal', value: val });
|
|
1172
|
-
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
|
|
1075
|
+
* Compiles the query to SQL for a specific dialect
|
|
1076
|
+
|
|
1077
|
+
* @param dialect - Database dialect to compile for
|
|
1078
|
+
|
|
1079
|
+
* @returns Compiled query with SQL and parameters
|
|
1080
|
+
|
|
1081
|
+
*/
|
|
1082
|
+
|
|
1083
|
+
compile(dialect: SelectDialectInput): CompiledQuery {
|
|
1084
|
+
|
|
1085
|
+
const resolved = resolveDialectInput(dialect);
|
|
1086
|
+
|
|
1087
|
+
return resolved.compileSelect(this.context.state.ast);
|
|
1088
|
+
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
/**
|
|
1094
|
+
|
|
1095
|
+
* Converts the query to SQL string for a specific dialect
|
|
1096
|
+
|
|
1097
|
+
* @param dialect - Database dialect to generate SQL for
|
|
1098
|
+
|
|
1099
|
+
* @returns SQL string representation of the query
|
|
1100
|
+
|
|
1101
|
+
*/
|
|
1102
|
+
|
|
1103
|
+
toSql(dialect: SelectDialectInput): string {
|
|
1104
|
+
|
|
1105
|
+
return this.compile(dialect).sql;
|
|
1106
|
+
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
|
|
1113
|
+
* Gets the hydration plan for the query
|
|
1114
|
+
|
|
1115
|
+
* @returns Hydration plan or undefined if none exists
|
|
1116
|
+
|
|
1117
|
+
*/
|
|
1118
|
+
|
|
1119
|
+
getHydrationPlan(): HydrationPlan | undefined {
|
|
1120
|
+
|
|
1121
|
+
return this.context.hydration.getPlan();
|
|
1122
|
+
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
/**
|
|
1128
|
+
|
|
1129
|
+
* Gets the Abstract Syntax Tree (AST) representation of the query
|
|
1130
|
+
|
|
1131
|
+
* @returns Query AST with hydration applied
|
|
1132
|
+
|
|
1133
|
+
*/
|
|
1134
|
+
|
|
1135
|
+
getAST(): SelectQueryNode {
|
|
1136
|
+
|
|
1137
|
+
return this.context.hydration.applyToAst(this.context.state.ast);
|
|
1138
|
+
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
|
|
1145
|
+
/**
|
|
1146
|
+
|
|
1147
|
+
* Creates a column node for use in expressions
|
|
1148
|
+
|
|
1149
|
+
* @param table - Table name
|
|
1150
|
+
|
|
1151
|
+
* @param name - Column name
|
|
1152
|
+
|
|
1153
|
+
* @returns ColumnNode with the specified table and name
|
|
1154
|
+
|
|
1155
|
+
*/
|
|
1156
|
+
|
|
1157
|
+
export const createColumn = (table: string, name: string): ColumnNode => ({ type: 'Column', table, name });
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
|
|
1163
|
+
* Creates a literal value node for use in expressions
|
|
1164
|
+
|
|
1165
|
+
* @param val - Literal value (string or number)
|
|
1166
|
+
|
|
1167
|
+
* @returns LiteralNode with the specified value
|
|
1168
|
+
|
|
1169
|
+
*/
|
|
1170
|
+
|
|
1171
|
+
export const createLiteral = (val: string | number): LiteralNode => ({ type: 'Literal', value: val });
|