@mikro-orm/sql 7.2.0-dev.0 → 7.2.0-dev.1

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.
@@ -168,7 +168,7 @@ export declare abstract class AbstractSqlDriver<Connection extends AbstractSqlCo
168
168
  protected extractManyToMany<T>(meta: EntityMetadata<T>, data: EntityDictionary<T>): EntityData<T>;
169
169
  protected processManyToMany<T extends object>(meta: EntityMetadata<T>, pks: Primary<T>[], collections: EntityData<T>, clear: boolean, options?: DriverMethodOptions): Promise<void>;
170
170
  lockPessimistic<T extends object>(entity: T, options: LockOptions): Promise<void>;
171
- protected buildPopulateWhere<T extends object>(meta: EntityMetadata<T>, joinedProps: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'populateWhere'>): ObjectQuery<T>;
171
+ protected buildPopulateWhere<T extends object>(meta: EntityMetadata<T>, joinedProps: PopulateOptions<T>[], options: Pick<FindOptions<any>, 'populateWhere' | 'strategy'>): ObjectQuery<T>;
172
172
  /**
173
173
  * Builds a UNION ALL (or UNION) subquery from `unionWhere` branches and merges it
174
174
  * into the main WHERE as `pk IN (branch_1 UNION ALL branch_2 ...)`.
@@ -2124,7 +2124,9 @@ export class AbstractSqlDriver extends DatabaseDriver {
2124
2124
  if (hint.children) {
2125
2125
  const targetMeta = prop.targetMeta;
2126
2126
  if (targetMeta) {
2127
- const inner = this.buildPopulateWhere(targetMeta, hint.children, {});
2127
+ // only joined children contribute to the ON conditions, the rest is handled by the entity loader
2128
+ const children = this.joinedProps(targetMeta, hint.children, options);
2129
+ const inner = this.buildPopulateWhere(targetMeta, children, { strategy: options.strategy });
2128
2130
  if (!Utils.isEmpty(inner) || RawQueryFragment.hasObjectFragments(inner)) {
2129
2131
  where[prop.name] ??= {};
2130
2132
  Object.assign(where[prop.name], inner);
@@ -6,6 +6,7 @@ import { NativeQueryBuilder } from './query/NativeQueryBuilder.js';
6
6
  /** Base class for SQL database platforms, providing SQL generation and quoting utilities. */
7
7
  export declare abstract class AbstractSqlPlatform extends Platform {
8
8
  #private;
9
+ private static readonly ORDER_BY_DIRECTIONS;
9
10
  protected readonly schemaHelper?: SchemaHelper;
10
11
  usesPivotTable(): boolean;
11
12
  indexForeignKeys(): boolean;
@@ -46,6 +47,12 @@ export declare abstract class AbstractSqlPlatform extends Platform {
46
47
  * @internal
47
48
  */
48
49
  getOrderByExpression(column: string, direction: string, collation?: string): string[];
50
+ /**
51
+ * `toLowerCase()` folds every `QueryOrder` enum member (and the normalized `QueryOrderNumeric`
52
+ * values) onto the six allow-listed directions, so only unknown values are rejected.
53
+ * @internal
54
+ */
55
+ validateOrderByDirection(direction: string): string;
49
56
  /**
50
57
  * Quotes a collation name for use in COLLATE clauses.
51
58
  * @internal
@@ -5,6 +5,14 @@ import { NativeQueryBuilder } from './query/NativeQueryBuilder.js';
5
5
  /** Base class for SQL database platforms, providing SQL generation and quoting utilities. */
6
6
  export class AbstractSqlPlatform extends Platform {
7
7
  static #JSON_PROPERTY_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
8
+ static ORDER_BY_DIRECTIONS = new Set([
9
+ 'asc',
10
+ 'desc',
11
+ 'asc nulls first',
12
+ 'asc nulls last',
13
+ 'desc nulls first',
14
+ 'desc nulls last',
15
+ ]);
8
16
  schemaHelper;
9
17
  usesPivotTable() {
10
18
  return true;
@@ -115,10 +123,23 @@ export class AbstractSqlPlatform extends Platform {
115
123
  * @internal
116
124
  */
117
125
  getOrderByExpression(column, direction, collation) {
126
+ const dir = this.validateOrderByDirection(direction);
118
127
  if (collation) {
119
- return [`${column} collate ${this.quoteCollation(collation)} ${direction.toLowerCase()}`];
128
+ return [`${column} collate ${this.quoteCollation(collation)} ${dir}`];
120
129
  }
121
- return [`${column} ${direction.toLowerCase()}`];
130
+ return [`${column} ${dir}`];
131
+ }
132
+ /**
133
+ * `toLowerCase()` folds every `QueryOrder` enum member (and the normalized `QueryOrderNumeric`
134
+ * values) onto the six allow-listed directions, so only unknown values are rejected.
135
+ * @internal
136
+ */
137
+ validateOrderByDirection(direction) {
138
+ const dir = ('' + direction).toLowerCase().trim();
139
+ if (!AbstractSqlPlatform.ORDER_BY_DIRECTIONS.has(dir)) {
140
+ throw new Error(`Invalid order direction: '${direction}'`);
141
+ }
142
+ return dir;
122
143
  }
123
144
  /**
124
145
  * Quotes a collation name for use in COLLATE clauses.
@@ -114,7 +114,7 @@ export class BaseMySqlPlatform extends AbstractSqlPlatform {
114
114
  }
115
115
  getOrderByExpression(column, direction, collation) {
116
116
  const ret = [];
117
- const dir = direction.toLowerCase();
117
+ const dir = this.validateOrderByDirection(direction);
118
118
  const col = collation ? `${column} collate ${this.quoteCollation(collation)}` : column;
119
119
  if (dir in this.ORDER_BY_NULLS_TRANSLATE) {
120
120
  ret.push(`${col} ${this.ORDER_BY_NULLS_TRANSLATE[dir]}`);
@@ -54,10 +54,10 @@ export class MySqlSchemaHelper extends SchemaHelper {
54
54
  return sql;
55
55
  }
56
56
  getListTablesSQL() {
57
- return `select table_name as table_name, nullif(table_schema, schema()) as schema_name, table_comment as table_comment, table_collation as table_collation from information_schema.tables where table_type = 'BASE TABLE' and table_schema = schema()`;
57
+ return `select table_name as table_name, nullif(table_schema, schema()) as schema_name, table_comment as table_comment, table_collation as table_collation from information_schema.tables where table_type = 'BASE TABLE' and table_schema = schema() order by table_name`;
58
58
  }
59
59
  getListViewsSQL() {
60
- return `select table_name as view_name, nullif(table_schema, schema()) as schema_name, view_definition from information_schema.views where table_schema = schema()`;
60
+ return `select table_name as view_name, nullif(table_schema, schema()) as schema_name, view_definition from information_schema.views where table_schema = schema() order by table_name`;
61
61
  }
62
62
  async loadViews(schema, connection, schemaName, ctx) {
63
63
  const views = await connection.execute(this.getListViewsSQL(), [], 'all', ctx);
@@ -372,6 +372,7 @@ export class MySqlSchemaHelper extends SchemaHelper {
372
372
  from information_schema.routines r
373
373
  where r.routine_schema = database()
374
374
  and r.routine_type in ('PROCEDURE', 'FUNCTION')
375
+ order by r.routine_name
375
376
  `;
376
377
  const [rows, params] = await Promise.all([
377
378
  connection.execute(sql),
@@ -579,6 +579,7 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
579
579
  )
580
580
  -- exclude trigger-helper functions; they're managed alongside their owning trigger.
581
581
  and p.prorettype <> 'trigger'::regtype
582
+ order by n.nspname, p.proname
582
583
  `;
583
584
  const rows = await connection.execute(sql);
584
585
  return rows.map(row => {
@@ -775,7 +776,8 @@ export class PostgreSqlSchemaHelper extends SchemaHelper {
775
776
  left join pg_enum e on t.oid = e.enumtypid
776
777
  join pg_catalog.pg_namespace n on n.oid = t.typnamespace
777
778
  where t.typtype = 'e' and n.nspname in (${Array(uniqueSchemas.length).fill('?').join(', ')})
778
- group by t.typname, n.nspname`, uniqueSchemas, 'all', ctx);
779
+ group by t.typname, n.nspname
780
+ order by n.nspname, t.typname`, uniqueSchemas, 'all', ctx);
779
781
  return res.reduce((o, row) => {
780
782
  let name = row.enum_name;
781
783
  if (row.schema_name && row.schema_name !== this.platform.getDefaultSchemaName()) {
@@ -52,7 +52,7 @@ export class SqliteSchemaHelper extends SchemaHelper {
52
52
  for (const dbName of targetSchemas) {
53
53
  const prefix = this.getSchemaPrefix(dbName);
54
54
  const tables = await connection.execute(`select name from ${prefix}sqlite_master where type = 'table' ` +
55
- `and name != 'sqlite_sequence' and name != 'geometry_columns' and name != 'spatial_ref_sys'`, [], 'all', ctx);
55
+ `and name != 'sqlite_sequence' and name != 'geometry_columns' and name != 'spatial_ref_sys' order by name`, [], 'all', ctx);
56
56
  for (const t of tables) {
57
57
  allTables.push({ table_name: t.name, schema_name: dbName });
58
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/sql",
3
- "version": "7.2.0-dev.0",
3
+ "version": "7.2.0-dev.1",
4
4
  "description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
5
5
  "keywords": [
6
6
  "data-mapper",
@@ -47,13 +47,13 @@
47
47
  "copy": "node ../../scripts/copy.mjs"
48
48
  },
49
49
  "dependencies": {
50
- "kysely": "0.29.3"
50
+ "kysely": "0.29.4"
51
51
  },
52
52
  "devDependencies": {
53
- "@mikro-orm/core": "^7.1.6"
53
+ "@mikro-orm/core": "^7.1.7"
54
54
  },
55
55
  "peerDependencies": {
56
- "@mikro-orm/core": "7.2.0-dev.0"
56
+ "@mikro-orm/core": "7.2.0-dev.1"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">= 22.17.0"
@@ -52,6 +52,12 @@ type IsNever<T, True = true, False = false> = [T] extends [never] ? True : False
52
52
  type GetAlias<T extends string> = T extends `${infer A}.${string}` ? A : never;
53
53
  type GetPropName<T extends string> = T extends `${string}.${infer P}` ? P : T;
54
54
  type AppendToHint<Parent extends string, Child extends string> = `${Parent}.${Child}`;
55
+ /**
56
+ * Extracts the entity type from a query builder via its main alias. Matching against
57
+ * `QueryBuilder<infer T>` is unreliable once another generic, such as selected fields,
58
+ * differs from its default.
59
+ */
60
+ type QueryBuilderEntity<Q extends QueryBuilder<any>> = Q['mainAlias'] extends Alias<infer T extends object> ? T : object;
55
61
  /**
56
62
  * Context tuple format: [Path, Alias, Type, Select]
57
63
  * - Path: The relation path from root entity (e.g., 'books', 'books.author')
@@ -85,7 +91,7 @@ type ContextRelationKeys<Context> = Context[keyof Context] extends infer Join ?
85
91
  export type QBField<Entity, RootAlias extends string, Context> = EntityRelations<Entity> | `${RootAlias}.${EntityRelations<Entity>}` | ([Context] extends [never] ? never : ContextRelationKeys<Context>);
86
92
  type ContextFieldKeys<Context> = Context[keyof Context] extends infer Join ? Join extends any ? Join extends [string, infer Alias, infer Type, any] ? `${Alias & string}.${keyof Type & string}` : never : never : never;
87
93
  type WithAlias<T extends string> = T | `${T} as ${string}`;
88
- export type Field<Entity, RootAlias extends string = never, Context = never> = WithAlias<EntityKey<Entity>> | (IsNever<RootAlias> extends true ? never : WithAlias<`${RootAlias}.${EntityKey<Entity>}`> | `${RootAlias}.*`) | ([Context] extends [never] ? never : WithAlias<ContextFieldKeys<Context>> | `${AliasNames<Context>}.*`) | '*' | QueryBuilder<any> | NativeQueryBuilder | RawQueryFragment<any> | (RawQueryFragment & symbol);
94
+ export type Field<Entity, RootAlias extends string = never, Context = never> = WithAlias<EntityKey<Entity>> | (IsNever<RootAlias> extends true ? never : WithAlias<`${RootAlias}.${EntityKey<Entity>}`> | `${RootAlias}.*`) | ([Context] extends [never] ? never : WithAlias<ContextFieldKeys<Context>> | `${AliasNames<Context>}.*`) | '*' | AnyQueryBuilder | NativeQueryBuilder | RawQueryFragment<any> | (RawQueryFragment & symbol);
89
95
  type RootAliasOrderKeys<RootAlias extends string, Entity> = {
90
96
  [K in `${RootAlias}.${EntityKey<Entity>}`]?: QueryOrderKeysFlat;
91
97
  };
@@ -432,29 +438,29 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
432
438
  * .where({ 'a.name': 'John' });
433
439
  * ```
434
440
  */
435
- join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
441
+ join<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, Fields, CTEs>;
436
442
  /**
437
443
  * Adds a JOIN clause to the query for a subquery.
438
444
  */
439
- join<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
445
+ join<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, type?: JoinType, path?: string, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, Fields, CTEs>;
440
446
  /**
441
447
  * Adds an INNER JOIN clause to the query for an entity relation.
442
448
  */
443
- innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
449
+ innerJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, Fields, CTEs>;
444
450
  /**
445
451
  * Adds an INNER JOIN clause to the query for a subquery.
446
452
  */
447
- innerJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
448
- innerJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
453
+ innerJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, Fields, CTEs>;
454
+ innerJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, Fields, CTEs>;
449
455
  /**
450
456
  * Adds a LEFT JOIN clause to the query for an entity relation.
451
457
  */
452
- leftJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, '*', CTEs>;
458
+ leftJoin<Field extends QBField<Entity, RootAlias, Context>, Alias extends string>(field: Field, alias: Alias, cond?: JoinCondition<JoinedEntityType<Entity, Context, Field & string>, Alias>, schema?: string): SelectQueryBuilder<Entity, RootAlias, ModifyHint<RootAlias, Context, Hint, Field> & {}, ModifyContext<Entity, Context, Field, Alias>, RawAliases, Fields, CTEs>;
453
459
  /**
454
460
  * Adds a LEFT JOIN clause to the query for a subquery.
455
461
  */
456
- leftJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
457
- leftJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, '*', CTEs>;
462
+ leftJoin<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, Fields, CTEs>;
463
+ leftJoinLateral<Alias extends string>(field: RawQueryFragment | QueryBuilder<any>, alias: Alias, cond?: RawJoinCondition, schema?: string): SelectQueryBuilder<Entity, RootAlias, Hint, ModifyContext<Entity, Context, string, Alias>, RawAliases, Fields, CTEs>;
458
464
  /**
459
465
  * Adds a JOIN clause and automatically selects the joined entity's fields.
460
466
  * This is useful for eager loading related entities.
@@ -723,7 +729,9 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
723
729
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
724
730
  * Allows setting a main string alias of the selection data.
725
731
  */
726
- from<Entity extends object>(target: QueryBuilder<Entity>, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
732
+ from<Entity extends object>(target: Subquery & {
733
+ readonly mainAlias: Alias<Entity>;
734
+ }, aliasName?: string): SelectQueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
727
735
  /**
728
736
  * Specifies FROM which entity's table select/update/delete will be executed, removing all previously set FROM-s.
729
737
  * Allows setting a main string alias of the selection data.
@@ -733,7 +741,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
733
741
  * Specifies a CTE name as the FROM source, with full type safety.
734
742
  * The entity type is inferred from the CTE definition passed to `.with()`.
735
743
  */
736
- from<Name extends string & keyof CTEs, Alias extends string = Name>(target: Name, aliasName?: Alias): SelectQueryBuilder<CTEs[Name], Alias, never, never, never, '*', CTEs>;
744
+ from<Name extends string & keyof CTEs, Alias extends string = Name>(target: Name, aliasName?: Alias): SelectQueryBuilder<CTEs[Name], Alias, never, never, never, Fields, CTEs>;
737
745
  getNativeQuery(processVirtualEntity?: boolean): NativeQueryBuilder;
738
746
  protected processReturningStatement(qb: NativeQueryBuilder, meta?: EntityMetadata, data?: Dictionary, returning?: Field<any>[]): void;
739
747
  /**
@@ -849,7 +857,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
849
857
  * const results = await em.find(Employee, { id: { $in: subquery } });
850
858
  * ```
851
859
  */
852
- unionAll(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
860
+ unionAll(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
853
861
  /**
854
862
  * Combines the current query with one or more other queries using `UNION` (with deduplication).
855
863
  * All queries must select the same columns. Returns a `QueryBuilder` that
@@ -864,7 +872,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
864
872
  * const results = await em.find(Employee, { id: { $in: subquery } });
865
873
  * ```
866
874
  */
867
- union(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity>;
875
+ union(...others: (QueryBuilder<any> | NativeQueryBuilder)[]): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs>;
868
876
  private buildUnionQuery;
869
877
  /**
870
878
  * Adds a Common Table Expression (CTE) to the query.
@@ -879,7 +887,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
879
887
  * .from('recent_books', 'rb'); // entity type inferred as Book
880
888
  * ```
881
889
  */
882
- with<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, Q extends QueryBuilder<infer T> ? T : object>>;
890
+ with<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, QueryBuilderEntity<Q>>>;
883
891
  /**
884
892
  * Adds a Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
885
893
  * The CTE name is tracked but without entity type inference — use `from()` to query from it.
@@ -900,7 +908,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
900
908
  * .from('category_tree', 'ct'); // entity type inferred as Category
901
909
  * ```
902
910
  */
903
- withRecursive<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, Q extends QueryBuilder<infer T> ? T : object>>;
911
+ withRecursive<Name extends string, Q extends QueryBuilder<any>>(name: Name, query: Q, options?: CteOptions): QueryBuilder<Entity, RootAlias, Hint, Context, RawAliases, Fields, CTEs & Record<Name, QueryBuilderEntity<Q>>>;
904
912
  /**
905
913
  * Adds a recursive Common Table Expression (CTE) to the query using a `NativeQueryBuilder` or raw SQL fragment.
906
914
  * The CTE name is tracked but without entity type inference — use `from()` to query from it.
@@ -782,7 +782,9 @@ export class QueryBuilder {
782
782
  this.fromRawTable(target, aliasName);
783
783
  }
784
784
  else {
785
- if (aliasName && this.#state.mainAlias && Utils.className(target) !== this.#state.mainAlias.aliasName) {
785
+ if (aliasName &&
786
+ this.#state.mainAlias &&
787
+ Utils.className(target) !== this.#state.mainAlias.aliasName) {
786
788
  throw new Error(`Cannot override the alias to '${aliasName}' since a query already contains references to '${this.#state.mainAlias.aliasName}'`);
787
789
  }
788
790
  this.fromEntityName(target, aliasName);