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.
@@ -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 { Entity, 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
-
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
- nextLazy.add(relationName as string);
462
+ /**
609
463
 
610
- return this.clone(this.context, nextLazy);
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
- 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
- }
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
- * Convenience alias for selecting specific columns from a relation.
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
- 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);
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
- * Selects columns for the root table and relations from a single config object.
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
- if (config.root?.length) {
661
- qb = qb.selectColumns(...config.root);
662
- }
518
+ rightJoin(table: TableDef, condition: BinaryExpressionNode): SelectQueryBuilder<T, TTable> {
663
519
 
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
- }
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
- 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<Entity<TTable>[]> {
694
-
695
- return executeHydrated(ctx, this);
696
-
697
- }
698
-
699
-
700
-
701
- async executeWithContexts(execCtx: ExecutionContext, hydCtx: HydrationContext): Promise<Entity<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(
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 });