@mikro-orm/sql 7.0.0-rc.3 → 7.0.1-dev.0

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.
Files changed (59) hide show
  1. package/AbstractSqlConnection.d.ts +5 -4
  2. package/AbstractSqlConnection.js +18 -5
  3. package/AbstractSqlDriver.d.ts +1 -1
  4. package/AbstractSqlDriver.js +39 -10
  5. package/AbstractSqlPlatform.d.ts +34 -0
  6. package/AbstractSqlPlatform.js +47 -3
  7. package/PivotCollectionPersister.d.ts +2 -11
  8. package/PivotCollectionPersister.js +59 -59
  9. package/README.md +5 -4
  10. package/SqlEntityManager.d.ts +1 -1
  11. package/dialects/index.d.ts +1 -0
  12. package/dialects/index.js +1 -0
  13. package/dialects/mysql/BaseMySqlPlatform.d.ts +6 -0
  14. package/dialects/mysql/BaseMySqlPlatform.js +17 -0
  15. package/dialects/mysql/MySqlSchemaHelper.d.ts +1 -1
  16. package/dialects/mysql/MySqlSchemaHelper.js +6 -6
  17. package/dialects/oracledb/OracleDialect.d.ts +78 -0
  18. package/dialects/oracledb/OracleDialect.js +166 -0
  19. package/dialects/oracledb/OracleNativeQueryBuilder.d.ts +19 -0
  20. package/dialects/oracledb/OracleNativeQueryBuilder.js +249 -0
  21. package/dialects/oracledb/index.d.ts +2 -0
  22. package/dialects/oracledb/index.js +2 -0
  23. package/dialects/postgresql/BasePostgreSqlPlatform.d.ts +6 -0
  24. package/dialects/postgresql/BasePostgreSqlPlatform.js +12 -8
  25. package/dialects/postgresql/PostgreSqlSchemaHelper.js +13 -13
  26. package/dialects/sqlite/SqlitePlatform.d.ts +1 -0
  27. package/dialects/sqlite/SqlitePlatform.js +3 -0
  28. package/dialects/sqlite/SqliteSchemaHelper.js +12 -8
  29. package/index.d.ts +1 -1
  30. package/index.js +0 -1
  31. package/package.json +3 -3
  32. package/plugin/index.d.ts +1 -14
  33. package/plugin/index.js +13 -13
  34. package/plugin/transformer.d.ts +6 -22
  35. package/plugin/transformer.js +81 -73
  36. package/query/ArrayCriteriaNode.d.ts +1 -1
  37. package/query/CriteriaNodeFactory.js +15 -3
  38. package/query/NativeQueryBuilder.d.ts +3 -3
  39. package/query/NativeQueryBuilder.js +4 -2
  40. package/query/ObjectCriteriaNode.js +4 -4
  41. package/query/QueryBuilder.d.ts +58 -62
  42. package/query/QueryBuilder.js +377 -370
  43. package/query/QueryBuilderHelper.d.ts +14 -11
  44. package/query/QueryBuilderHelper.js +324 -137
  45. package/query/ScalarCriteriaNode.js +3 -1
  46. package/query/enums.d.ts +2 -0
  47. package/query/enums.js +2 -0
  48. package/schema/DatabaseSchema.d.ts +7 -5
  49. package/schema/DatabaseSchema.js +50 -33
  50. package/schema/DatabaseTable.d.ts +8 -6
  51. package/schema/DatabaseTable.js +84 -60
  52. package/schema/SchemaComparator.d.ts +1 -3
  53. package/schema/SchemaComparator.js +22 -20
  54. package/schema/SchemaHelper.d.ts +2 -13
  55. package/schema/SchemaHelper.js +2 -1
  56. package/schema/SqlSchemaGenerator.d.ts +4 -14
  57. package/schema/SqlSchemaGenerator.js +15 -7
  58. package/typings.d.ts +4 -1
  59. package/tsconfig.build.tsbuildinfo +0 -1
@@ -1,3 +1,4 @@
1
+ var _a;
1
2
  import { EntityMetadata, helper, inspect, isRaw, LoadStrategy, LockMode, PopulateHint, QueryFlag, QueryHelper, raw, RawQueryFragment, Reference, ReferenceKind, serialize, Utils, ValidationError, } from '@mikro-orm/core';
2
3
  import { JoinType, QueryType } from './enums.js';
3
4
  import { QueryBuilderHelper } from './QueryBuilderHelper.js';
@@ -31,61 +32,54 @@ export class QueryBuilder {
31
32
  connectionType;
32
33
  em;
33
34
  loggerContext;
35
+ #state = _a.createDefaultState();
36
+ #helper;
37
+ #query;
38
+ /** @internal */
39
+ static createDefaultState() {
40
+ return {
41
+ aliasCounter: 0,
42
+ explicitAlias: false,
43
+ populateHintFinalized: false,
44
+ joins: {},
45
+ cond: {},
46
+ orderBy: [],
47
+ groupBy: [],
48
+ having: {},
49
+ comments: [],
50
+ hintComments: [],
51
+ subQueries: {},
52
+ aliases: {},
53
+ tptAlias: {},
54
+ ctes: [],
55
+ tptJoinsApplied: false,
56
+ autoJoinedPaths: [],
57
+ populate: [],
58
+ populateMap: {},
59
+ flags: new Set([QueryFlag.CONVERT_CUSTOM_TYPES]),
60
+ finalized: false,
61
+ joinedProps: new Map(),
62
+ };
63
+ }
34
64
  get mainAlias() {
35
65
  this.ensureFromClause();
36
- return this._mainAlias;
66
+ return this.#state.mainAlias;
37
67
  }
38
68
  get alias() {
39
69
  return this.mainAlias.aliasName;
40
70
  }
41
71
  get helper() {
42
72
  this.ensureFromClause();
43
- return this._helper;
73
+ return this.#helper;
44
74
  }
45
75
  get type() {
46
- return this._type ?? QueryType.SELECT;
76
+ return this.#state.type ?? QueryType.SELECT;
47
77
  }
48
78
  /** @internal */
49
- _populate = [];
50
- /** @internal */
51
- _populateMap = {};
52
- aliasCounter = 0;
53
- flags = new Set([QueryFlag.CONVERT_CUSTOM_TYPES]);
54
- finalized = false;
55
- populateHintFinalized = false;
56
- _joins = {};
57
- _explicitAlias = false;
58
- _schema;
59
- _cond = {};
60
- _data;
61
- _orderBy = [];
62
- _groupBy = [];
63
- _having = {};
64
- _returning;
65
- _onConflict;
66
- _limit;
67
- _offset;
68
- _distinctOn;
69
- _joinedProps = new Map();
70
- _cache;
71
- _indexHint;
72
- _collation;
73
- _comments = [];
74
- _hintComments = [];
75
- flushMode;
76
- lockMode;
77
- lockTables;
78
- subQueries = {};
79
- _mainAlias;
80
- _aliases = {};
81
- _tptAlias = {}; // maps entity className to alias for TPT parent tables
82
- _helper;
83
- _query;
84
- _unionQuery;
85
- _ctes = [];
79
+ get state() {
80
+ return this.#state;
81
+ }
86
82
  platform;
87
- tptJoinsApplied = false;
88
- autoJoinedPaths = [];
89
83
  /**
90
84
  * @internal
91
85
  */
@@ -98,15 +92,15 @@ export class QueryBuilder {
98
92
  this.loggerContext = loggerContext;
99
93
  this.platform = this.driver.getPlatform();
100
94
  if (alias) {
101
- this.aliasCounter++;
102
- this._explicitAlias = true;
95
+ this.#state.aliasCounter++;
96
+ this.#state.explicitAlias = true;
103
97
  }
104
98
  // @ts-expect-error union type does not match the overloaded method signature
105
99
  this.from(entityName, alias);
106
100
  }
107
101
  select(fields, distinct = false) {
108
102
  this.ensureNotFinalized();
109
- this._fields = Utils.asArray(fields).flatMap(f => {
103
+ this.#state.fields = Utils.asArray(fields).flatMap(f => {
110
104
  if (typeof f !== 'string') {
111
105
  // Normalize sql.ref('prop') and sql.ref('prop').as('alias') to string form
112
106
  if (isRaw(f) && f.sql === '??' && f.params.length === 1) {
@@ -117,14 +111,14 @@ export class QueryBuilder {
117
111
  }
118
112
  return f;
119
113
  }
120
- const asMatch = f.match(FIELD_ALIAS_RE);
114
+ const asMatch = FIELD_ALIAS_RE.exec(f);
121
115
  if (asMatch) {
122
116
  return `${this.resolveNestedPath(asMatch[1].trim())} as ${asMatch[2]}`;
123
117
  }
124
118
  return this.resolveNestedPath(f);
125
119
  });
126
120
  if (distinct) {
127
- this.flags.add(QueryFlag.DISTINCT);
121
+ this.#state.flags.add(QueryFlag.DISTINCT);
128
122
  }
129
123
  return this.init(QueryType.SELECT);
130
124
  }
@@ -133,10 +127,10 @@ export class QueryBuilder {
133
127
  */
134
128
  addSelect(fields) {
135
129
  this.ensureNotFinalized();
136
- if (this._type && this._type !== QueryType.SELECT) {
130
+ if (this.#state.type && this.#state.type !== QueryType.SELECT) {
137
131
  return this;
138
132
  }
139
- return this.select([...Utils.asArray(this._fields), ...Utils.asArray(fields)]);
133
+ return this.select([...Utils.asArray(this.#state.fields), ...Utils.asArray(fields)]);
140
134
  }
141
135
  distinct() {
142
136
  this.ensureNotFinalized();
@@ -144,7 +138,7 @@ export class QueryBuilder {
144
138
  }
145
139
  distinctOn(fields) {
146
140
  this.ensureNotFinalized();
147
- this._distinctOn = Utils.asArray(fields);
141
+ this.#state.distinctOn = Utils.asArray(fields);
148
142
  return this;
149
143
  }
150
144
  /**
@@ -219,16 +213,16 @@ export class QueryBuilder {
219
213
  */
220
214
  count(field, distinct = false) {
221
215
  if (field) {
222
- this._fields = Utils.asArray(field);
216
+ this.#state.fields = Utils.asArray(field);
223
217
  }
224
218
  else if (distinct || this.hasToManyJoins()) {
225
- this._fields = this.mainAlias.meta.primaryKeys;
219
+ this.#state.fields = this.mainAlias.meta.primaryKeys;
226
220
  }
227
221
  else {
228
- this._fields = [raw('*')];
222
+ this.#state.fields = [raw('*')];
229
223
  }
230
224
  if (distinct) {
231
- this.flags.add(QueryFlag.DISTINCT);
225
+ this.#state.flags.add(QueryFlag.DISTINCT);
232
226
  }
233
227
  return this.init(QueryType.COUNT);
234
228
  }
@@ -262,30 +256,30 @@ export class QueryBuilder {
262
256
  * ```
263
257
  */
264
258
  joinAndSelect(field, alias, cond = {}, type = JoinType.innerJoin, path, fields, schema) {
265
- if (!this._type) {
259
+ if (!this.#state.type) {
266
260
  this.select('*');
267
261
  }
268
262
  let subquery;
269
263
  if (Array.isArray(field)) {
270
- const rawFragment = field[1] instanceof QueryBuilder ? field[1].toRaw() : field[1];
264
+ const rawFragment = field[1] instanceof _a ? field[1].toRaw() : field[1];
271
265
  subquery = this.platform.formatQuery(rawFragment.sql, rawFragment.params);
272
266
  field = field[0];
273
267
  }
274
268
  const { prop, key } = this.joinReference(field, alias, cond, type, path, schema, subquery);
275
269
  const [fromAlias] = this.helper.splitField(field);
276
270
  if (subquery) {
277
- this._joins[key].subquery = subquery;
271
+ this.#state.joins[key].subquery = subquery;
278
272
  }
279
- const populate = this._joinedProps.get(fromAlias);
273
+ const populate = this.#state.joinedProps.get(fromAlias);
280
274
  const item = { field: prop.name, strategy: LoadStrategy.JOINED, children: [] };
281
275
  if (populate) {
282
276
  populate.children.push(item);
283
277
  }
284
278
  else {
285
279
  // root entity
286
- this._populate.push(item);
280
+ this.#state.populate.push(item);
287
281
  }
288
- this._joinedProps.set(alias, item);
282
+ this.#state.joinedProps.set(alias, item);
289
283
  this.addSelect(this.getFieldsForJoinedLoad(prop, alias, fields));
290
284
  return this;
291
285
  }
@@ -306,12 +300,12 @@ export class QueryBuilder {
306
300
  getFieldsForJoinedLoad(prop, alias, explicitFields) {
307
301
  const fields = [];
308
302
  const populate = [];
309
- const joinKey = Object.keys(this._joins).find(join => join.endsWith(`#${alias}`));
303
+ const joinKey = Object.keys(this.#state.joins).find(join => join.endsWith(`#${alias}`));
310
304
  const targetMeta = prop.targetMeta;
311
- const schema = this._schema ?? (targetMeta.schema !== '*' ? targetMeta.schema : undefined);
305
+ const schema = this.#state.schema ?? (targetMeta.schema !== '*' ? targetMeta.schema : undefined);
312
306
  if (joinKey) {
313
- const path = this._joins[joinKey].path.split('.').slice(1);
314
- let children = this._populate;
307
+ const path = this.#state.joins[joinKey].path.split('.').slice(1);
308
+ let children = this.#state.populate;
315
309
  for (let i = 0; i < path.length; i++) {
316
310
  const child = children.filter(hint => {
317
311
  const [propName] = hint.field.split(':', 2);
@@ -361,13 +355,13 @@ export class QueryBuilder {
361
355
  * @internal
362
356
  */
363
357
  scheduleFilterCheck(path) {
364
- this.autoJoinedPaths.push(path);
358
+ this.#state.autoJoinedPaths.push(path);
365
359
  }
366
360
  /**
367
361
  * @internal
368
362
  */
369
363
  async applyJoinedFilters(em, filterOptions) {
370
- for (const path of this.autoJoinedPaths) {
364
+ for (const path of this.#state.autoJoinedPaths) {
371
365
  const join = this.getJoinForPath(path);
372
366
  if (join.type === JoinType.pivotJoin) {
373
367
  continue;
@@ -403,10 +397,10 @@ export class QueryBuilder {
403
397
  withSubQuery(subQuery, alias) {
404
398
  this.ensureNotFinalized();
405
399
  if (isRaw(subQuery)) {
406
- this.subQueries[alias] = this.platform.formatQuery(subQuery.sql, subQuery.params);
400
+ this.#state.subQueries[alias] = this.platform.formatQuery(subQuery.sql, subQuery.params);
407
401
  }
408
402
  else {
409
- this.subQueries[alias] = subQuery.toString();
403
+ this.#state.subQueries[alias] = subQuery.toString();
410
404
  }
411
405
  return this;
412
406
  }
@@ -430,13 +424,13 @@ export class QueryBuilder {
430
424
  platform: this.platform,
431
425
  aliasMap: this.getAliasMap(),
432
426
  aliased: [QueryType.SELECT, QueryType.COUNT].includes(this.type),
433
- convertCustomTypes: this.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES),
427
+ convertCustomTypes: this.#state.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES),
434
428
  });
435
429
  }
436
430
  const op = operator || params;
437
- const topLevel = !op || !(Utils.hasObjectKeys(this._cond) || RawQueryFragment.hasObjectFragments(this._cond));
431
+ const topLevel = !op || !(Utils.hasObjectKeys(this.#state.cond) || RawQueryFragment.hasObjectFragments(this.#state.cond));
438
432
  const criteriaNode = CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processedCond);
439
- const ignoreBranching = this.__populateWhere === 'infer';
433
+ const ignoreBranching = this.#state.resolvedPopulateWhere === 'infer';
440
434
  if ([QueryType.UPDATE, QueryType.DELETE].includes(this.type) &&
441
435
  criteriaNode.willAutoJoin(this, undefined, { ignoreBranching })) {
442
436
  // use sub-query to support joining
@@ -444,18 +438,18 @@ export class QueryBuilder {
444
438
  this.select(this.mainAlias.meta.primaryKeys, true);
445
439
  }
446
440
  if (topLevel) {
447
- this._cond = criteriaNode.process(this, { ignoreBranching });
441
+ this.#state.cond = criteriaNode.process(this, { ignoreBranching });
448
442
  }
449
- else if (Array.isArray(this._cond[op])) {
450
- this._cond[op].push(criteriaNode.process(this, { ignoreBranching }));
443
+ else if (Array.isArray(this.#state.cond[op])) {
444
+ this.#state.cond[op].push(criteriaNode.process(this, { ignoreBranching }));
451
445
  }
452
446
  else {
453
- const cond1 = [this._cond, criteriaNode.process(this, { ignoreBranching })];
454
- this._cond = { [op]: cond1 };
447
+ const cond1 = [this.#state.cond, criteriaNode.process(this, { ignoreBranching })];
448
+ this.#state.cond = { [op]: cond1 };
455
449
  }
456
- if (this._onConflict) {
457
- this._onConflict[this._onConflict.length - 1].where = this.helper.processOnConflictCondition(this._cond, this._schema);
458
- this._cond = {};
450
+ if (this.#state.onConflict) {
451
+ this.#state.onConflict[this.#state.onConflict.length - 1].where = this.helper.processOnConflictCondition(this.#state.cond, this.#state.schema);
452
+ this.#state.cond = {};
459
453
  }
460
454
  return this;
461
455
  }
@@ -474,7 +468,7 @@ export class QueryBuilder {
474
468
  processOrderBy(orderBy, reset = true) {
475
469
  this.ensureNotFinalized();
476
470
  if (reset) {
477
- this._orderBy = [];
471
+ this.#state.orderBy = [];
478
472
  }
479
473
  const selectAliases = this.getSelectAliases();
480
474
  Utils.asArray(orderBy).forEach(orig => {
@@ -499,7 +493,7 @@ export class QueryBuilder {
499
493
  convertCustomTypes: false,
500
494
  type: 'orderBy',
501
495
  });
502
- this._orderBy.push(CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processed).process(this, {
496
+ this.#state.orderBy.push(CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, processed).process(this, {
503
497
  matchPopulateJoins: true,
504
498
  type: 'orderBy',
505
499
  }));
@@ -509,9 +503,9 @@ export class QueryBuilder {
509
503
  /** Collect custom aliases from select fields (stored as 'resolved as alias' strings by select()). */
510
504
  getSelectAliases() {
511
505
  const aliases = new Set();
512
- for (const field of this._fields ?? []) {
506
+ for (const field of this.#state.fields ?? []) {
513
507
  if (typeof field === 'string') {
514
- const m = field.match(FIELD_ALIAS_RE);
508
+ const m = FIELD_ALIAS_RE.exec(field);
515
509
  if (m) {
516
510
  aliases.add(m[2]);
517
511
  }
@@ -521,7 +515,7 @@ export class QueryBuilder {
521
515
  }
522
516
  groupBy(fields) {
523
517
  this.ensureNotFinalized();
524
- this._groupBy = Utils.asArray(fields).flatMap(f => {
518
+ this.#state.groupBy = Utils.asArray(fields).flatMap(f => {
525
519
  if (typeof f !== 'string') {
526
520
  // Normalize sql.ref('prop') to string for proper formula resolution
527
521
  if (isRaw(f) && f.sql === '??' && f.params.length === 1) {
@@ -549,12 +543,12 @@ export class QueryBuilder {
549
543
  cond = { [raw(`(${cond})`, params)]: [] };
550
544
  }
551
545
  const processed = CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, cond, undefined, undefined, false).process(this, { type: 'having' });
552
- if (!this._having || !operator) {
553
- this._having = processed;
546
+ if (!this.#state.having || !operator) {
547
+ this.#state.having = processed;
554
548
  }
555
549
  else {
556
- const cond1 = [this._having, processed];
557
- this._having = { [operator]: cond1 };
550
+ const cond1 = [this.#state.having, processed];
551
+ this.#state.having = { [operator]: cond1 };
558
552
  }
559
553
  return this;
560
554
  }
@@ -567,8 +561,8 @@ export class QueryBuilder {
567
561
  onConflict(fields = []) {
568
562
  const meta = this.mainAlias.meta;
569
563
  this.ensureNotFinalized();
570
- this._onConflict ??= [];
571
- this._onConflict.push({
564
+ this.#state.onConflict ??= [];
565
+ this.#state.onConflict.push({
572
566
  fields: isRaw(fields)
573
567
  ? fields
574
568
  : Utils.asArray(fields).flatMap(f => {
@@ -580,24 +574,24 @@ export class QueryBuilder {
580
574
  return this;
581
575
  }
582
576
  ignore() {
583
- if (!this._onConflict) {
577
+ if (!this.#state.onConflict) {
584
578
  throw new Error('You need to call `qb.onConflict()` first to use `qb.ignore()`');
585
579
  }
586
- this._onConflict[this._onConflict.length - 1].ignore = true;
580
+ this.#state.onConflict[this.#state.onConflict.length - 1].ignore = true;
587
581
  return this;
588
582
  }
589
583
  merge(data) {
590
- if (!this._onConflict) {
584
+ if (!this.#state.onConflict) {
591
585
  throw new Error('You need to call `qb.onConflict()` first to use `qb.merge()`');
592
586
  }
593
587
  if (Array.isArray(data) && data.length === 0) {
594
588
  return this.ignore();
595
589
  }
596
- this._onConflict[this._onConflict.length - 1].merge = data;
590
+ this.#state.onConflict[this.#state.onConflict.length - 1].merge = data;
597
591
  return this;
598
592
  }
599
593
  returning(fields) {
600
- this._returning = Utils.asArray(fields);
594
+ this.#state.returning = Utils.asArray(fields);
601
595
  return this;
602
596
  }
603
597
  /**
@@ -605,9 +599,9 @@ export class QueryBuilder {
605
599
  */
606
600
  populate(populate, populateWhere, populateFilter) {
607
601
  this.ensureNotFinalized();
608
- this._populate = populate;
609
- this._populateWhere = populateWhere;
610
- this._populateFilter = populateFilter;
602
+ this.#state.populate = populate;
603
+ this.#state.populateWhere = populateWhere;
604
+ this.#state.populateFilter = populateFilter;
611
605
  return this;
612
606
  }
613
607
  /**
@@ -621,7 +615,7 @@ export class QueryBuilder {
621
615
  */
622
616
  limit(limit, offset = 0) {
623
617
  this.ensureNotFinalized();
624
- this._limit = limit;
618
+ this.#state.limit = limit;
625
619
  if (offset) {
626
620
  this.offset(offset);
627
621
  }
@@ -637,12 +631,12 @@ export class QueryBuilder {
637
631
  */
638
632
  offset(offset) {
639
633
  this.ensureNotFinalized();
640
- this._offset = offset;
634
+ this.#state.offset = offset;
641
635
  return this;
642
636
  }
643
637
  withSchema(schema) {
644
638
  this.ensureNotFinalized();
645
- this._schema = schema;
639
+ this.#state.schema = schema;
646
640
  return this;
647
641
  }
648
642
  setLockMode(mode, tables) {
@@ -650,31 +644,31 @@ export class QueryBuilder {
650
644
  if (mode != null && ![LockMode.OPTIMISTIC, LockMode.NONE].includes(mode) && !this.context) {
651
645
  throw ValidationError.transactionRequired();
652
646
  }
653
- this.lockMode = mode;
654
- this.lockTables = tables;
647
+ this.#state.lockMode = mode;
648
+ this.#state.lockTables = tables;
655
649
  return this;
656
650
  }
657
651
  setFlushMode(flushMode) {
658
652
  this.ensureNotFinalized();
659
- this.flushMode = flushMode;
653
+ this.#state.flushMode = flushMode;
660
654
  return this;
661
655
  }
662
656
  setFlag(flag) {
663
657
  this.ensureNotFinalized();
664
- this.flags.add(flag);
658
+ this.#state.flags.add(flag);
665
659
  return this;
666
660
  }
667
661
  unsetFlag(flag) {
668
662
  this.ensureNotFinalized();
669
- this.flags.delete(flag);
663
+ this.#state.flags.delete(flag);
670
664
  return this;
671
665
  }
672
666
  hasFlag(flag) {
673
- return this.flags.has(flag);
667
+ return this.#state.flags.has(flag);
674
668
  }
675
669
  cache(config = true) {
676
670
  this.ensureNotFinalized();
677
- this._cache = config;
671
+ this.#state.cache = config;
678
672
  return this;
679
673
  }
680
674
  /**
@@ -682,7 +676,7 @@ export class QueryBuilder {
682
676
  */
683
677
  indexHint(sql) {
684
678
  this.ensureNotFinalized();
685
- this._indexHint = sql;
679
+ this.#state.indexHint = sql;
686
680
  return this;
687
681
  }
688
682
  /**
@@ -690,7 +684,7 @@ export class QueryBuilder {
690
684
  */
691
685
  collation(collation) {
692
686
  this.ensureNotFinalized();
693
- this._collation = collation;
687
+ this.#state.collation = collation;
694
688
  return this;
695
689
  }
696
690
  /**
@@ -698,7 +692,7 @@ export class QueryBuilder {
698
692
  */
699
693
  comment(comment) {
700
694
  this.ensureNotFinalized();
701
- this._comments.push(...Utils.asArray(comment));
695
+ this.#state.comments.push(...Utils.asArray(comment));
702
696
  return this;
703
697
  }
704
698
  /**
@@ -708,43 +702,43 @@ export class QueryBuilder {
708
702
  */
709
703
  hintComment(comment) {
710
704
  this.ensureNotFinalized();
711
- this._hintComments.push(...Utils.asArray(comment));
705
+ this.#state.hintComments.push(...Utils.asArray(comment));
712
706
  return this;
713
707
  }
714
708
  from(target, aliasName) {
715
709
  this.ensureNotFinalized();
716
- if (target instanceof QueryBuilder) {
710
+ if (target instanceof _a) {
717
711
  this.fromSubQuery(target, aliasName);
718
712
  }
719
713
  else if (typeof target === 'string' && !this.metadata.find(target)) {
720
714
  this.fromRawTable(target, aliasName);
721
715
  }
722
716
  else {
723
- if (aliasName && this._mainAlias && Utils.className(target) !== this._mainAlias.aliasName) {
724
- throw new Error(`Cannot override the alias to '${aliasName}' since a query already contains references to '${this._mainAlias.aliasName}'`);
717
+ if (aliasName && this.#state.mainAlias && Utils.className(target) !== this.#state.mainAlias.aliasName) {
718
+ throw new Error(`Cannot override the alias to '${aliasName}' since a query already contains references to '${this.#state.mainAlias.aliasName}'`);
725
719
  }
726
720
  this.fromEntityName(target, aliasName);
727
721
  }
728
722
  return this;
729
723
  }
730
724
  getNativeQuery(processVirtualEntity = true) {
731
- if (this._unionQuery) {
732
- if (!this._query?.qb) {
733
- this._query = {};
725
+ if (this.#state.unionQuery) {
726
+ if (!this.#query?.qb) {
727
+ this.#query = {};
734
728
  const nqb = this.platform.createNativeQueryBuilder();
735
729
  nqb.select('*');
736
- nqb.from(raw(`(${this._unionQuery.sql})`, this._unionQuery.params));
737
- this._query.qb = nqb;
730
+ nqb.from(raw(`(${this.#state.unionQuery.sql})`, this.#state.unionQuery.params));
731
+ this.#query.qb = nqb;
738
732
  }
739
- return this._query.qb;
733
+ return this.#query.qb;
740
734
  }
741
- if (this._query?.qb) {
742
- return this._query.qb;
735
+ if (this.#query?.qb) {
736
+ return this.#query.qb;
743
737
  }
744
- this._query = {};
738
+ this.#query = {};
745
739
  this.finalize();
746
740
  const qb = this.getQueryBase(processVirtualEntity);
747
- for (const cte of this._ctes) {
741
+ for (const cte of this.#state.ctes) {
748
742
  const query = cte.query;
749
743
  const opts = { columns: cte.columns, materialized: cte.materialized };
750
744
  if (cte.recursive) {
@@ -756,27 +750,62 @@ export class QueryBuilder {
756
750
  }
757
751
  const schema = this.getSchema(this.mainAlias);
758
752
  const isNotEmptyObject = (obj) => Utils.hasObjectKeys(obj) || RawQueryFragment.hasObjectFragments(obj);
759
- Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this._cond, qb), this._cond && !this._onConflict);
760
- Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this._groupBy, 'groupBy', schema)), isNotEmptyObject(this._groupBy));
761
- Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this._having, qb, undefined, 'having'), isNotEmptyObject(this._having));
753
+ Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this.#state.cond, qb), this.#state.cond && !this.#state.onConflict);
754
+ Utils.runIfNotEmpty(() => qb.groupBy(this.prepareFields(this.#state.groupBy, 'groupBy', schema)), isNotEmptyObject(this.#state.groupBy));
755
+ Utils.runIfNotEmpty(() => this.helper.appendQueryCondition(this.type, this.#state.having, qb, undefined, 'having'), isNotEmptyObject(this.#state.having));
762
756
  Utils.runIfNotEmpty(() => {
763
- const queryOrder = this.helper.getQueryOrder(this.type, this._orderBy, this._populateMap, this._collation);
757
+ const queryOrder = this.helper.getQueryOrder(this.type, this.#state.orderBy, this.#state.populateMap, this.#state.collation);
764
758
  if (queryOrder.length > 0) {
765
759
  const sql = Utils.unique(queryOrder).join(', ');
766
760
  qb.orderBy(sql);
767
761
  return;
768
762
  }
769
- }, isNotEmptyObject(this._orderBy));
770
- Utils.runIfNotEmpty(() => qb.limit(this._limit), this._limit != null);
771
- Utils.runIfNotEmpty(() => qb.offset(this._offset), this._offset);
772
- Utils.runIfNotEmpty(() => qb.comment(this._comments), this._comments);
773
- Utils.runIfNotEmpty(() => qb.hintComment(this._hintComments), this._hintComments);
774
- Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(QueryType.UPSERT, this._onConflict, qb), this._onConflict);
775
- if (this.lockMode) {
776
- this.helper.getLockSQL(qb, this.lockMode, this.lockTables, this._joins);
777
- }
778
- this.helper.finalize(this.type, qb, this.mainAlias.meta, this._data, this._returning);
779
- return (this._query.qb = qb);
763
+ }, isNotEmptyObject(this.#state.orderBy));
764
+ Utils.runIfNotEmpty(() => qb.limit(this.#state.limit), this.#state.limit != null);
765
+ Utils.runIfNotEmpty(() => qb.offset(this.#state.offset), this.#state.offset);
766
+ Utils.runIfNotEmpty(() => qb.comment(this.#state.comments), this.#state.comments);
767
+ Utils.runIfNotEmpty(() => qb.hintComment(this.#state.hintComments), this.#state.hintComments);
768
+ Utils.runIfNotEmpty(() => this.helper.appendOnConflictClause(QueryType.UPSERT, this.#state.onConflict, qb), this.#state.onConflict);
769
+ if (this.#state.lockMode) {
770
+ this.helper.getLockSQL(qb, this.#state.lockMode, this.#state.lockTables, this.#state.joins);
771
+ }
772
+ this.processReturningStatement(qb, this.mainAlias.meta, this.#state.data, this.#state.returning);
773
+ return (this.#query.qb = qb);
774
+ }
775
+ processReturningStatement(qb, meta, data, returning) {
776
+ const usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
777
+ if (!meta || !data || !usesReturningStatement) {
778
+ return;
779
+ }
780
+ // always respect explicit returning hint
781
+ if (returning && returning.length > 0) {
782
+ qb.returning(returning.map(field => this.helper.mapper(field, this.type)));
783
+ return;
784
+ }
785
+ if (this.type === QueryType.INSERT) {
786
+ const returningProps = meta.hydrateProps
787
+ .filter(prop => prop.returning || (prop.persist !== false && ((prop.primary && prop.autoincrement) || prop.defaultRaw)))
788
+ .filter(prop => !(prop.name in data));
789
+ if (returningProps.length > 0) {
790
+ qb.returning(Utils.flatten(returningProps.map(prop => prop.fieldNames)));
791
+ }
792
+ return;
793
+ }
794
+ if (this.type === QueryType.UPDATE) {
795
+ const returningProps = meta.hydrateProps.filter(prop => prop.fieldNames && isRaw(data[prop.fieldNames[0]]));
796
+ if (returningProps.length > 0) {
797
+ qb.returning(returningProps.flatMap((prop) => {
798
+ if (prop.hasConvertToJSValueSQL) {
799
+ const aliased = this.platform.quoteIdentifier(prop.fieldNames[0]);
800
+ const sql = prop.customType.convertToJSValueSQL(aliased, this.platform) +
801
+ ' as ' +
802
+ this.platform.quoteIdentifier(prop.fieldNames[0]);
803
+ return [raw(sql)];
804
+ }
805
+ return prop.fieldNames;
806
+ }));
807
+ }
808
+ }
780
809
  }
781
810
  /**
782
811
  * Returns the query with parameters as wildcards.
@@ -792,16 +821,16 @@ export class QueryBuilder {
792
821
  return raw(sql, params);
793
822
  }
794
823
  toQuery() {
795
- if (this._unionQuery) {
796
- return this._unionQuery;
824
+ if (this.#state.unionQuery) {
825
+ return this.#state.unionQuery;
797
826
  }
798
- if (this._query?.sql) {
799
- return { sql: this._query.sql, params: this._query.params };
827
+ if (this.#query?.sql) {
828
+ return { sql: this.#query.sql, params: this.#query.params };
800
829
  }
801
830
  const query = this.getNativeQuery().compile();
802
- this._query.sql = query.sql;
803
- this._query.params = query.params;
804
- return { sql: this._query.sql, params: this._query.params };
831
+ this.#query.sql = query.sql;
832
+ this.#query.params = query.params;
833
+ return { sql: this.#query.sql, params: this.#query.params };
805
834
  }
806
835
  /**
807
836
  * Returns the list of all parameters for this query.
@@ -833,7 +862,7 @@ export class QueryBuilder {
833
862
  * @internal
834
863
  */
835
864
  getJoinForPath(path, options) {
836
- const joins = Object.values(this._joins);
865
+ const joins = Object.values(this.#state.joins);
837
866
  if (joins.length === 0) {
838
867
  return undefined;
839
868
  }
@@ -865,7 +894,7 @@ export class QueryBuilder {
865
894
  */
866
895
  getNextAlias(entityName = 'e') {
867
896
  entityName = Utils.className(entityName);
868
- return this.driver.config.getNamingStrategy().aliasName(entityName, this.aliasCounter++);
897
+ return this.driver.config.getNamingStrategy().aliasName(entityName, this.#state.aliasCounter++);
869
898
  }
870
899
  /**
871
900
  * Registers a join for a specific polymorphic target type.
@@ -878,15 +907,15 @@ export class QueryBuilder {
878
907
  const referencedColumnNames = targetMeta.getPrimaryProps().flatMap(pk => pk.fieldNames);
879
908
  const targetProp = { ...prop, targetMeta, referencedColumnNames };
880
909
  const aliasedName = `${ownerAlias}.${prop.name}[${targetMeta.className}]#${alias}`;
881
- this._joins[aliasedName] = this.helper.joinManyToOneReference(targetProp, ownerAlias, alias, type, {}, schema);
882
- this._joins[aliasedName].path = path;
910
+ this.#state.joins[aliasedName] = this.helper.joinManyToOneReference(targetProp, ownerAlias, alias, type, {}, schema);
911
+ this.#state.joins[aliasedName].path = path;
883
912
  this.createAlias(targetMeta.class, alias);
884
913
  }
885
914
  /**
886
915
  * @internal
887
916
  */
888
917
  getAliasMap() {
889
- return Object.fromEntries(Object.entries(this._aliases).map(([key, value]) => [key, value.entityName]));
918
+ return Object.fromEntries(Object.entries(this.#state.aliases).map(([key, value]) => [key, value.entityName]));
890
919
  }
891
920
  /**
892
921
  * Executes this QB and returns the raw results, mapped to the property names (unless disabled via last parameter).
@@ -901,11 +930,11 @@ export class QueryBuilder {
901
930
  if (!this.connectionType && (isRunType || this.context)) {
902
931
  this.connectionType = 'write';
903
932
  }
904
- if (!this.finalized && method === 'get' && this.type === QueryType.SELECT) {
933
+ if (!this.#state.finalized && method === 'get' && this.type === QueryType.SELECT) {
905
934
  this.limit(1);
906
935
  }
907
936
  const query = this.toQuery();
908
- const cached = await this.em?.tryCache(this.mainAlias.entityName, this._cache, [
937
+ const cached = await this.em?.tryCache(this.mainAlias.entityName, this.#state.cache, [
909
938
  'qb.execute',
910
939
  query.sql,
911
940
  query.params,
@@ -918,17 +947,17 @@ export class QueryBuilder {
918
947
  const res = await this.getConnection().execute(query.sql, query.params, method, this.context, loggerContext);
919
948
  const meta = this.mainAlias.meta;
920
949
  if (!options.mapResults || !meta) {
921
- await this.em?.storeCache(this._cache, cached, res);
950
+ await this.em?.storeCache(this.#state.cache, cached, res);
922
951
  return res;
923
952
  }
924
953
  if (method === 'run') {
925
954
  return res;
926
955
  }
927
- const joinedProps = this.driver.joinedProps(meta, this._populate);
956
+ const joinedProps = this.driver.joinedProps(meta, this.#state.populate);
928
957
  let mapped;
929
958
  if (Array.isArray(res)) {
930
959
  const map = {};
931
- mapped = res.map(r => this.driver.mapResult(r, meta, this._populate, this, map));
960
+ mapped = res.map(r => this.driver.mapResult(r, meta, this.#state.populate, this, map));
932
961
  if (options.mergeResults && joinedProps.length > 0) {
933
962
  mapped = this.driver.mergeJoinedResult(mapped, this.mainAlias.meta, joinedProps);
934
963
  }
@@ -937,10 +966,10 @@ export class QueryBuilder {
937
966
  mapped = [this.driver.mapResult(res, meta, joinedProps, this)];
938
967
  }
939
968
  if (method === 'get') {
940
- await this.em?.storeCache(this._cache, cached, mapped[0]);
969
+ await this.em?.storeCache(this.#state.cache, cached, mapped[0]);
941
970
  return mapped[0];
942
971
  }
943
- await this.em?.storeCache(this._cache, cached, mapped);
972
+ await this.em?.storeCache(this.#state.cache, cached, mapped);
944
973
  return mapped;
945
974
  }
946
975
  getConnection() {
@@ -976,13 +1005,13 @@ export class QueryBuilder {
976
1005
  yield* res;
977
1006
  return;
978
1007
  }
979
- const joinedProps = this.driver.joinedProps(meta, this._populate);
1008
+ const joinedProps = this.driver.joinedProps(meta, this.#state.populate);
980
1009
  const stack = [];
981
1010
  const hash = (data) => {
982
1011
  return Utils.getPrimaryKeyHash(meta.primaryKeys.map(pk => data[pk]));
983
1012
  };
984
1013
  for await (const row of res) {
985
- const mapped = this.driver.mapResult(row, meta, this._populate, this);
1014
+ const mapped = this.driver.mapResult(row, meta, this.#state.populate, this);
986
1015
  if (!options.mergeResults || joinedProps.length === 0) {
987
1016
  yield this.mapResult(mapped, options.mapResults);
988
1017
  continue;
@@ -1011,7 +1040,7 @@ export class QueryBuilder {
1011
1040
  * Executes the query, returning array of results mapped to entity instances.
1012
1041
  */
1013
1042
  async getResultList(limit) {
1014
- await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.flushMode });
1043
+ await this.em.tryFlush(this.mainAlias.entityName, { flushMode: this.#state.flushMode });
1015
1044
  const res = await this.execute('all', true);
1016
1045
  return this.mapResults(res, limit);
1017
1046
  }
@@ -1033,15 +1062,15 @@ export class QueryBuilder {
1033
1062
  if (!map) {
1034
1063
  return row;
1035
1064
  }
1036
- const entity = this.em.map(this.mainAlias.entityName, row, { schema: this._schema });
1037
- this.propagatePopulateHint(entity, this._populate);
1065
+ const entity = this.em.map(this.mainAlias.entityName, row, { schema: this.#state.schema });
1066
+ this.propagatePopulateHint(entity, this.#state.populate);
1038
1067
  return entity;
1039
1068
  }
1040
1069
  mapResults(res, limit) {
1041
1070
  const entities = [];
1042
1071
  for (const row of res) {
1043
1072
  const entity = this.mapResult(row);
1044
- this.propagatePopulateHint(entity, this._populate);
1073
+ this.propagatePopulateHint(entity, this.#state.populate);
1045
1074
  entities.push(entity);
1046
1075
  if (limit != null && --limit === 0) {
1047
1076
  break;
@@ -1053,7 +1082,7 @@ export class QueryBuilder {
1053
1082
  * Executes the query, returning the first result or null
1054
1083
  */
1055
1084
  async getSingleResult() {
1056
- if (!this.finalized) {
1085
+ if (!this.#state.finalized) {
1057
1086
  this.limit(1);
1058
1087
  }
1059
1088
  const [res] = await this.getResultList(1);
@@ -1065,7 +1094,7 @@ export class QueryBuilder {
1065
1094
  res = await this.execute('get', false);
1066
1095
  }
1067
1096
  else {
1068
- const qb = (this._type === undefined ? this : this.clone());
1097
+ const qb = (this.#state.type === undefined ? this : this.clone());
1069
1098
  qb.processPopulateHint(); // needs to happen sooner so `qb.hasToManyJoins()` reports correctly
1070
1099
  qb.count(field, distinct ?? qb.hasToManyJoins())
1071
1100
  .limit(undefined)
@@ -1138,12 +1167,12 @@ export class QueryBuilder {
1138
1167
  const parts = [];
1139
1168
  const params = [];
1140
1169
  for (const qb of all) {
1141
- const compiled = qb instanceof QueryBuilder ? qb.toQuery() : qb.compile();
1170
+ const compiled = qb instanceof _a ? qb.toQuery() : qb.compile();
1142
1171
  parts.push(`(${compiled.sql})`);
1143
1172
  params.push(...compiled.params);
1144
1173
  }
1145
1174
  const result = this.clone(true);
1146
- result._unionQuery = { sql: parts.join(` ${separator} `), params };
1175
+ result.#state.unionQuery = { sql: parts.join(` ${separator} `), params };
1147
1176
  return result;
1148
1177
  }
1149
1178
  with(name, query, options) {
@@ -1154,12 +1183,12 @@ export class QueryBuilder {
1154
1183
  }
1155
1184
  addCte(name, query, options, recursive) {
1156
1185
  this.ensureNotFinalized();
1157
- if (this._ctes.some(cte => cte.name === name)) {
1186
+ if (this.#state.ctes.some(cte => cte.name === name)) {
1158
1187
  throw new Error(`CTE with name '${name}' already exists`);
1159
1188
  }
1160
1189
  // Eagerly compile QueryBuilder to RawQueryFragment — later mutations to the sub-query won't be reflected
1161
- const compiled = query instanceof QueryBuilder ? query.toRaw() : query;
1162
- this._ctes.push({
1190
+ const compiled = query instanceof _a ? query.toRaw() : query;
1191
+ this.#state.ctes.push({
1163
1192
  name,
1164
1193
  query: compiled,
1165
1194
  recursive,
@@ -1169,53 +1198,26 @@ export class QueryBuilder {
1169
1198
  return this;
1170
1199
  }
1171
1200
  clone(reset, preserve) {
1172
- const qb = new QueryBuilder(this.mainAlias.entityName, this.metadata, this.driver, this.context, this.mainAlias.aliasName, this.connectionType, this.em);
1173
- reset = reset || [];
1174
- // clone array/object properties
1175
- const properties = [
1176
- 'flags',
1177
- '_populate',
1178
- '_populateWhere',
1179
- '_populateFilter',
1180
- '__populateWhere',
1181
- '_populateMap',
1182
- '_joins',
1183
- '_joinedProps',
1184
- '_cond',
1185
- '_data',
1186
- '_orderBy',
1187
- '_schema',
1188
- '_indexHint',
1189
- '_collation',
1190
- '_cache',
1191
- 'subQueries',
1192
- 'lockMode',
1193
- 'lockTables',
1194
- '_groupBy',
1195
- '_having',
1196
- '_returning',
1197
- '_comments',
1198
- '_hintComments',
1199
- 'aliasCounter',
1200
- '_unionQuery',
1201
- ];
1202
- for (const prop of Object.keys(this)) {
1203
- if (!preserve?.includes(prop) &&
1204
- (reset === true || reset.includes(prop) || ['_helper', '_query'].includes(prop))) {
1205
- continue;
1201
+ const qb = new _a(this.#state.mainAlias.entityName, this.metadata, this.driver, this.context, this.#state.mainAlias.aliasName, this.connectionType, this.em);
1202
+ if (reset !== true) {
1203
+ qb.#state = Utils.copy(this.#state);
1204
+ // CTEs contain NativeQueryBuilder instances that should not be deep-cloned
1205
+ qb.#state.ctes = this.#state.ctes.map(cte => ({ ...cte }));
1206
+ if (Array.isArray(reset)) {
1207
+ const fresh = _a.createDefaultState();
1208
+ for (const key of reset) {
1209
+ qb.#state[key] = fresh[key];
1210
+ }
1206
1211
  }
1207
- qb[prop] = properties.includes(prop) ? Utils.copy(this[prop]) : this[prop];
1208
- }
1209
- /* v8 ignore next */
1210
- if (this._fields && reset !== true && !reset.includes('_fields')) {
1211
- qb._fields = [...this._fields];
1212
1212
  }
1213
- if (this._ctes.length && reset !== true && !reset.includes('_ctes')) {
1214
- qb._ctes = this._ctes.map(cte => ({ ...cte }));
1213
+ else if (preserve) {
1214
+ for (const key of preserve) {
1215
+ qb.#state[key] = Utils.copy(this.#state[key]);
1216
+ }
1215
1217
  }
1216
- qb._aliases = { ...this._aliases };
1217
- qb._helper.aliasMap = qb._aliases;
1218
- qb.finalized = false;
1218
+ qb.#state.finalized = false;
1219
+ qb.#query = undefined;
1220
+ qb.#helper = qb.createQueryBuilderHelper();
1219
1221
  return qb;
1220
1222
  }
1221
1223
  /**
@@ -1235,11 +1237,11 @@ export class QueryBuilder {
1235
1237
  if (typeof meta.expression === 'string') {
1236
1238
  return `(${meta.expression}) as ${this.platform.quoteIdentifier(this.alias)}`;
1237
1239
  }
1238
- const res = meta.expression(this.em, this._cond, {});
1240
+ const res = meta.expression(this.em, this.#state.cond, {});
1239
1241
  if (typeof res === 'string') {
1240
1242
  return `(${res}) as ${this.platform.quoteIdentifier(this.alias)}`;
1241
1243
  }
1242
- if (res instanceof QueryBuilder) {
1244
+ if (res instanceof _a) {
1243
1245
  return `(${res.getFormattedQuery()}) as ${this.platform.quoteIdentifier(this.alias)}`;
1244
1246
  }
1245
1247
  if (isRaw(res)) {
@@ -1258,11 +1260,11 @@ export class QueryBuilder {
1258
1260
  addPropertyJoin(prop, ownerAlias, alias, type, path, schema) {
1259
1261
  schema ??= prop.targetMeta?.schema === '*' ? '*' : this.driver.getSchemaName(prop.targetMeta);
1260
1262
  const key = `[tpt]${ownerAlias}#${alias}`;
1261
- this._joins[key] =
1263
+ this.#state.joins[key] =
1262
1264
  prop.kind === ReferenceKind.MANY_TO_ONE
1263
1265
  ? this.helper.joinManyToOneReference(prop, ownerAlias, alias, type, {}, schema)
1264
1266
  : this.helper.joinOneToReference(prop, ownerAlias, alias, type, {}, schema);
1265
- this._joins[key].path = path;
1267
+ this.#state.joins[key].path = path;
1266
1268
  return key;
1267
1269
  }
1268
1270
  joinReference(field, alias, cond, type, path, schema, subquery) {
@@ -1272,7 +1274,7 @@ export class QueryBuilder {
1272
1274
  name: '__subquery__',
1273
1275
  kind: ReferenceKind.MANY_TO_ONE,
1274
1276
  };
1275
- if (field instanceof QueryBuilder) {
1277
+ if (field instanceof _a) {
1276
1278
  prop.type = Utils.className(field.mainAlias.entityName);
1277
1279
  prop.targetMeta = field.mainAlias.meta;
1278
1280
  field = field.getNativeQuery();
@@ -1281,7 +1283,7 @@ export class QueryBuilder {
1281
1283
  field = this.platform.formatQuery(field.sql, field.params);
1282
1284
  }
1283
1285
  const key = `${this.alias}.${prop.name}#${alias}`;
1284
- this._joins[key] = {
1286
+ this.#state.joins[key] = {
1285
1287
  prop,
1286
1288
  alias,
1287
1289
  type,
@@ -1297,10 +1299,10 @@ export class QueryBuilder {
1297
1299
  }
1298
1300
  const [fromAlias, fromField] = this.helper.splitField(field);
1299
1301
  const q = (str) => `'${str}'`;
1300
- if (!this._aliases[fromAlias]) {
1301
- throw new Error(`Trying to join ${q(fromField)} with alias ${q(fromAlias)}, but ${q(fromAlias)} is not a known alias. Available aliases are: ${Object.keys(this._aliases).map(q).join(', ')}.`);
1302
+ if (!this.#state.aliases[fromAlias]) {
1303
+ throw new Error(`Trying to join ${q(fromField)} with alias ${q(fromAlias)}, but ${q(fromAlias)} is not a known alias. Available aliases are: ${Object.keys(this.#state.aliases).map(q).join(', ')}.`);
1302
1304
  }
1303
- const entityName = this._aliases[fromAlias].entityName;
1305
+ const entityName = this.#state.aliases[fromAlias].entityName;
1304
1306
  const meta = this.metadata.get(entityName);
1305
1307
  const prop = meta.properties[fromField];
1306
1308
  if (!prop) {
@@ -1323,10 +1325,10 @@ export class QueryBuilder {
1323
1325
  const criteriaNode = CriteriaNodeFactory.createNode(this.metadata, prop.targetMeta.class, cond);
1324
1326
  cond = criteriaNode.process(this, { ignoreBranching: true, alias });
1325
1327
  let aliasedName = `${fromAlias}.${prop.name}#${alias}`;
1326
- path ??= `${Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? Utils.className(entityName)}.${prop.name}`;
1328
+ path ??= `${Object.values(this.#state.joins).find(j => j.alias === fromAlias)?.path ?? Utils.className(entityName)}.${prop.name}`;
1327
1329
  if (prop.kind === ReferenceKind.ONE_TO_MANY) {
1328
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
1329
- this._joins[aliasedName].path ??= path;
1330
+ this.#state.joins[aliasedName] = this.helper.joinOneToReference(prop, fromAlias, alias, type, cond, schema);
1331
+ this.#state.joins[aliasedName].path ??= path;
1330
1332
  }
1331
1333
  else if (prop.kind === ReferenceKind.MANY_TO_MANY) {
1332
1334
  let pivotAlias = alias;
@@ -1336,19 +1338,19 @@ export class QueryBuilder {
1336
1338
  aliasedName = `${fromAlias}.${prop.name}#${pivotAlias}`;
1337
1339
  }
1338
1340
  const joins = this.helper.joinManyToManyReference(prop, fromAlias, alias, pivotAlias, type, cond, path, schema);
1339
- Object.assign(this._joins, joins);
1341
+ Object.assign(this.#state.joins, joins);
1340
1342
  this.createAlias(prop.pivotEntity, pivotAlias);
1341
- this._joins[aliasedName].path ??= path;
1343
+ this.#state.joins[aliasedName].path ??= path;
1342
1344
  aliasedName = Object.keys(joins)[1];
1343
1345
  }
1344
1346
  else if (prop.kind === ReferenceKind.ONE_TO_ONE) {
1345
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, ownerAlias, alias, type, cond, schema);
1346
- this._joins[aliasedName].path ??= path;
1347
+ this.#state.joins[aliasedName] = this.helper.joinOneToReference(prop, ownerAlias, alias, type, cond, schema);
1348
+ this.#state.joins[aliasedName].path ??= path;
1347
1349
  }
1348
1350
  else {
1349
1351
  // MANY_TO_ONE
1350
- this._joins[aliasedName] = this.helper.joinManyToOneReference(prop, ownerAlias, alias, type, cond, schema);
1351
- this._joins[aliasedName].path ??= path;
1352
+ this.#state.joins[aliasedName] = this.helper.joinManyToOneReference(prop, ownerAlias, alias, type, cond, schema);
1353
+ this.#state.joins[aliasedName].path ??= path;
1352
1354
  }
1353
1355
  return { prop, key: aliasedName };
1354
1356
  }
@@ -1366,14 +1368,14 @@ export class QueryBuilder {
1366
1368
  // Strip 'as alias' suffix if present — the alias is passed to mapper at the end
1367
1369
  let field = originalField;
1368
1370
  let customAlias;
1369
- const asMatch = originalField.match(FIELD_ALIAS_RE);
1371
+ const asMatch = FIELD_ALIAS_RE.exec(originalField);
1370
1372
  if (asMatch) {
1371
1373
  field = asMatch[1].trim();
1372
1374
  customAlias = asMatch[2];
1373
1375
  }
1374
- const join = Object.keys(this._joins).find(k => field === k.substring(0, k.indexOf('#')));
1376
+ const join = Object.keys(this.#state.joins).find(k => field === k.substring(0, k.indexOf('#')));
1375
1377
  if (join && type === 'where') {
1376
- ret.push(...this.helper.mapJoinColumns(this.type, this._joins[join]));
1378
+ ret.push(...this.helper.mapJoinColumns(this.type, this.#state.joins[join]));
1377
1379
  return;
1378
1380
  }
1379
1381
  const [a, f] = this.helper.splitField(field);
@@ -1387,7 +1389,7 @@ export class QueryBuilder {
1387
1389
  }
1388
1390
  if (prop?.embedded || (prop?.kind === ReferenceKind.EMBEDDED && prop.object)) {
1389
1391
  const name = prop.embeddedPath?.join('.') ?? prop.fieldNames[0];
1390
- const aliased = this._aliases[a] ? `${a}.${name}` : name;
1392
+ const aliased = this.#state.aliases[a] ? `${a}.${name}` : name;
1391
1393
  ret.push(getFieldName(aliased, customAlias));
1392
1394
  return;
1393
1395
  }
@@ -1420,16 +1422,16 @@ export class QueryBuilder {
1420
1422
  ret.push(getFieldName(field, customAlias));
1421
1423
  });
1422
1424
  const requiresSQLConversion = this.mainAlias.meta.props.filter(p => p.hasConvertToJSValueSQL && p.persist !== false);
1423
- if (this.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES) &&
1425
+ if (this.#state.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES) &&
1424
1426
  (fields.includes('*') || fields.includes(`${this.mainAlias.aliasName}.*`)) &&
1425
1427
  requiresSQLConversion.length > 0) {
1426
1428
  for (const p of requiresSQLConversion) {
1427
1429
  ret.push(this.helper.mapper(p.name, this.type));
1428
1430
  }
1429
1431
  }
1430
- for (const f of Object.keys(this._populateMap)) {
1431
- if (type === 'where' && this._joins[f]) {
1432
- ret.push(...this.helper.mapJoinColumns(this.type, this._joins[f]));
1432
+ for (const f of Object.keys(this.#state.populateMap)) {
1433
+ if (type === 'where' && this.#state.joins[f]) {
1434
+ ret.push(...this.helper.mapJoinColumns(this.type, this.#state.joins[f]));
1433
1435
  }
1434
1436
  }
1435
1437
  return Utils.unique(ret);
@@ -1445,16 +1447,16 @@ export class QueryBuilder {
1445
1447
  }
1446
1448
  const parts = field.split('.');
1447
1449
  // Simple alias.property case - let prepareFields handle it
1448
- if (parts.length === 2 && this._aliases[parts[0]]) {
1450
+ if (parts.length === 2 && this.#state.aliases[parts[0]]) {
1449
1451
  return field;
1450
1452
  }
1451
1453
  // Start with root alias
1452
1454
  let currentAlias = parts[0];
1453
- let currentMeta = this._aliases[currentAlias]
1454
- ? this.metadata.get(this._aliases[currentAlias].entityName)
1455
+ let currentMeta = this.#state.aliases[currentAlias]
1456
+ ? this.metadata.get(this.#state.aliases[currentAlias].entityName)
1455
1457
  : this.mainAlias.meta;
1456
1458
  // If first part is not an alias, it's a property of the main entity
1457
- if (!this._aliases[currentAlias]) {
1459
+ if (!this.#state.aliases[currentAlias]) {
1458
1460
  currentAlias = this.mainAlias.aliasName;
1459
1461
  parts.unshift(currentAlias);
1460
1462
  }
@@ -1492,14 +1494,14 @@ export class QueryBuilder {
1492
1494
  }
1493
1495
  // Find existing join or create new one
1494
1496
  const joinPath = parts.slice(0, i + 1).join('.');
1495
- const existingJoinKey = Object.keys(this._joins).find(k => {
1496
- const join = this._joins[k];
1497
+ const existingJoinKey = Object.keys(this.#state.joins).find(k => {
1498
+ const join = this.#state.joins[k];
1497
1499
  // Check by path or by key prefix (key format is `alias.field#joinAlias`)
1498
1500
  return join.path === joinPath || k.startsWith(`${currentAlias}.${propName}#`);
1499
1501
  });
1500
1502
  let joinAlias;
1501
1503
  if (existingJoinKey) {
1502
- joinAlias = this._joins[existingJoinKey].alias;
1504
+ joinAlias = this.#state.joins[existingJoinKey].alias;
1503
1505
  }
1504
1506
  else {
1505
1507
  joinAlias = this.getNextAlias(prop.targetMeta?.className ?? propName);
@@ -1516,18 +1518,18 @@ export class QueryBuilder {
1516
1518
  }
1517
1519
  init(type, data, cond) {
1518
1520
  this.ensureNotFinalized();
1519
- this._type = type;
1520
- if ([QueryType.UPDATE, QueryType.DELETE].includes(type) && Utils.hasObjectKeys(this._cond)) {
1521
+ this.#state.type = type;
1522
+ if ([QueryType.UPDATE, QueryType.DELETE].includes(type) && Utils.hasObjectKeys(this.#state.cond)) {
1521
1523
  throw new Error(`You are trying to call \`qb.where().${type.toLowerCase()}()\`. Calling \`qb.${type.toLowerCase()}()\` before \`qb.where()\` is required.`);
1522
1524
  }
1523
1525
  if (!this.helper.isTableNameAliasRequired(type)) {
1524
- delete this._fields;
1526
+ this.#state.fields = undefined;
1525
1527
  }
1526
1528
  if (data) {
1527
1529
  if (Utils.isEntity(data)) {
1528
1530
  data = this.em?.getComparator().prepareEntity(data) ?? serialize(data);
1529
1531
  }
1530
- this._data = this.helper.processData(data, this.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES), false);
1532
+ this.#state.data = this.helper.processData(data, this.#state.flags.has(QueryFlag.CONVERT_CUSTOM_TYPES), false);
1531
1533
  }
1532
1534
  if (cond) {
1533
1535
  this.where(cond);
@@ -1535,9 +1537,9 @@ export class QueryBuilder {
1535
1537
  return this;
1536
1538
  }
1537
1539
  getQueryBase(processVirtualEntity) {
1538
- const qb = this.platform.createNativeQueryBuilder().setFlags(this.flags);
1540
+ const qb = this.platform.createNativeQueryBuilder().setFlags(this.#state.flags);
1539
1541
  const { subQuery, aliasName, entityName, meta, rawTableName } = this.mainAlias;
1540
- const requiresAlias = this.finalized && (this._explicitAlias || this.helper.isTableNameAliasRequired(this.type));
1542
+ const requiresAlias = this.#state.finalized && (this.#state.explicitAlias || this.helper.isTableNameAliasRequired(this.type));
1541
1543
  const alias = requiresAlias ? aliasName : undefined;
1542
1544
  const schema = this.getSchema(this.mainAlias);
1543
1545
  const tableName = rawTableName
@@ -1547,41 +1549,42 @@ export class QueryBuilder {
1547
1549
  : subQuery
1548
1550
  ? raw(`(${subQuery.sql}) as ${this.platform.quoteIdentifier(aliasName)}`, subQuery.params)
1549
1551
  : this.helper.getTableName(entityName);
1550
- const joinSchema = this._schema ?? this.em?.schema ?? schema;
1552
+ const joinSchema = this.#state.schema ?? this.em?.schema ?? schema;
1553
+ const schemaOverride = this.#state.schema ?? this.em?.schema;
1551
1554
  if (meta.virtual && processVirtualEntity) {
1552
- qb.from(raw(this.fromVirtual(meta)), { indexHint: this._indexHint });
1555
+ qb.from(raw(this.fromVirtual(meta)), { indexHint: this.#state.indexHint });
1553
1556
  }
1554
1557
  else {
1555
1558
  qb.from(tableName, {
1556
1559
  schema: rawTableName ? undefined : schema,
1557
1560
  alias,
1558
- indexHint: this._indexHint,
1561
+ indexHint: this.#state.indexHint,
1559
1562
  });
1560
1563
  }
1561
1564
  switch (this.type) {
1562
1565
  case QueryType.SELECT:
1563
- qb.select(this.prepareFields(this._fields, 'where', schema));
1564
- if (this._distinctOn) {
1565
- qb.distinctOn(this.prepareFields(this._distinctOn, 'where', schema));
1566
+ qb.select(this.prepareFields(this.#state.fields, 'where', schema));
1567
+ if (this.#state.distinctOn) {
1568
+ qb.distinctOn(this.prepareFields(this.#state.distinctOn, 'where', schema));
1566
1569
  }
1567
- else if (this.flags.has(QueryFlag.DISTINCT)) {
1570
+ else if (this.#state.flags.has(QueryFlag.DISTINCT)) {
1568
1571
  qb.distinct();
1569
1572
  }
1570
- this.helper.processJoins(qb, this._joins, joinSchema);
1573
+ this.helper.processJoins(qb, this.#state.joins, joinSchema, schemaOverride);
1571
1574
  break;
1572
1575
  case QueryType.COUNT: {
1573
- const fields = this._fields.map(f => this.helper.mapper(f, this.type, undefined, undefined, schema));
1574
- qb.count(fields, this.flags.has(QueryFlag.DISTINCT));
1575
- this.helper.processJoins(qb, this._joins, joinSchema);
1576
+ const fields = this.#state.fields.map(f => this.helper.mapper(f, this.type, undefined, undefined, schema));
1577
+ qb.count(fields, this.#state.flags.has(QueryFlag.DISTINCT));
1578
+ this.helper.processJoins(qb, this.#state.joins, joinSchema, schemaOverride);
1576
1579
  break;
1577
1580
  }
1578
1581
  case QueryType.INSERT:
1579
- qb.insert(this._data);
1582
+ qb.insert(this.#state.data);
1580
1583
  break;
1581
1584
  case QueryType.UPDATE:
1582
- qb.update(this._data);
1583
- this.helper.processJoins(qb, this._joins, joinSchema);
1584
- this.helper.updateVersionProperty(qb, this._data);
1585
+ qb.update(this.#state.data);
1586
+ this.helper.processJoins(qb, this.#state.joins, joinSchema, schemaOverride);
1587
+ this.helper.updateVersionProperty(qb, this.#state.data);
1585
1588
  break;
1586
1589
  case QueryType.DELETE:
1587
1590
  qb.delete();
@@ -1632,17 +1635,17 @@ export class QueryBuilder {
1632
1635
  ![QueryType.SELECT, QueryType.COUNT].includes(this.type)) {
1633
1636
  return;
1634
1637
  }
1635
- if (this.tptJoinsApplied) {
1638
+ if (this.#state.tptJoinsApplied) {
1636
1639
  return;
1637
1640
  }
1638
- this.tptJoinsApplied = true;
1641
+ this.#state.tptJoinsApplied = true;
1639
1642
  let childMeta = meta;
1640
1643
  let childAlias = this.mainAlias.aliasName;
1641
1644
  while (childMeta.tptParent) {
1642
1645
  const parentMeta = childMeta.tptParent;
1643
1646
  const parentAlias = this.getNextAlias(parentMeta.className);
1644
1647
  this.createAlias(parentMeta.class, parentAlias);
1645
- this._tptAlias[parentMeta.className] = parentAlias;
1648
+ this.#state.tptAlias[parentMeta.className] = parentAlias;
1646
1649
  this.addPropertyJoin(childMeta.tptParentProp, childAlias, parentAlias, JoinType.innerJoin, `[tpt]${childMeta.className}`);
1647
1650
  childMeta = parentMeta;
1648
1651
  childAlias = parentAlias;
@@ -1658,17 +1661,17 @@ export class QueryBuilder {
1658
1661
  ![QueryType.SELECT, QueryType.COUNT].includes(this.type)) {
1659
1662
  return;
1660
1663
  }
1661
- if (!this._fields?.includes('*') && !this._fields?.includes(`${this.mainAlias.aliasName}.*`)) {
1664
+ if (!this.#state.fields?.includes('*') && !this.#state.fields?.includes(`${this.mainAlias.aliasName}.*`)) {
1662
1665
  return;
1663
1666
  }
1664
1667
  let parentMeta = meta.tptParent;
1665
1668
  while (parentMeta) {
1666
- const parentAlias = this._tptAlias[parentMeta.className];
1669
+ const parentAlias = this.#state.tptAlias[parentMeta.className];
1667
1670
  if (parentAlias) {
1668
1671
  const schema = parentMeta.schema === '*' ? '*' : this.driver.getSchemaName(parentMeta);
1669
1672
  parentMeta
1670
1673
  .ownProps.filter(prop => this.platform.shouldHaveColumn(prop, []))
1671
- .forEach(prop => this._fields.push(...this.driver.mapPropToFieldNames(this, prop, parentAlias, parentMeta, schema)));
1674
+ .forEach(prop => this.#state.fields.push(...this.driver.mapPropToFieldNames(this, prop, parentAlias, parentMeta, schema)));
1672
1675
  }
1673
1676
  parentMeta = parentMeta.tptParent;
1674
1677
  }
@@ -1683,32 +1686,32 @@ export class QueryBuilder {
1683
1686
  if (!descendants?.length || ![QueryType.SELECT, QueryType.COUNT].includes(this.type)) {
1684
1687
  return;
1685
1688
  }
1686
- if (!this._fields?.includes('*') && !this._fields?.includes(`${this.mainAlias.aliasName}.*`)) {
1689
+ if (!this.#state.fields?.includes('*') && !this.#state.fields?.includes(`${this.mainAlias.aliasName}.*`)) {
1687
1690
  return;
1688
1691
  }
1689
1692
  // LEFT JOIN each descendant table and add their fields
1690
1693
  for (const childMeta of descendants) {
1691
1694
  const childAlias = this.getNextAlias(childMeta.className);
1692
1695
  this.createAlias(childMeta.class, childAlias);
1693
- this._tptAlias[childMeta.className] = childAlias;
1696
+ this.#state.tptAlias[childMeta.className] = childAlias;
1694
1697
  this.addPropertyJoin(childMeta.tptInverseProp, this.mainAlias.aliasName, childAlias, JoinType.leftJoin, `[tpt]${meta.className}`);
1695
1698
  // Add child fields
1696
1699
  const schema = childMeta.schema === '*' ? '*' : this.driver.getSchemaName(childMeta);
1697
1700
  childMeta
1698
1701
  .ownProps.filter(prop => !prop.primary && this.platform.shouldHaveColumn(prop, []))
1699
- .forEach(prop => this._fields.push(...this.driver.mapPropToFieldNames(this, prop, childAlias, childMeta, schema)));
1702
+ .forEach(prop => this.#state.fields.push(...this.driver.mapPropToFieldNames(this, prop, childAlias, childMeta, schema)));
1700
1703
  }
1701
1704
  // Add computed discriminator (CASE WHEN to determine concrete type)
1702
1705
  // descendants is pre-sorted by depth (deepest first) during discovery
1703
1706
  if (meta.tptDiscriminatorColumn) {
1704
- this._fields.push(this.driver.buildTPTDiscriminatorExpression(meta, descendants, this._tptAlias, this.mainAlias.aliasName));
1707
+ this.#state.fields.push(this.driver.buildTPTDiscriminatorExpression(meta, descendants, this.#state.tptAlias, this.mainAlias.aliasName));
1705
1708
  }
1706
1709
  }
1707
1710
  finalize() {
1708
- if (this.finalized) {
1711
+ if (this.#state.finalized) {
1709
1712
  return;
1710
1713
  }
1711
- if (!this._type) {
1714
+ if (!this.#state.type) {
1712
1715
  this.select('*');
1713
1716
  }
1714
1717
  const meta = this.mainAlias.meta;
@@ -1718,99 +1721,102 @@ export class QueryBuilder {
1718
1721
  this.applyTPTPolymorphicJoins();
1719
1722
  this.processPopulateHint();
1720
1723
  this.processNestedJoins();
1721
- if (meta && (this._fields?.includes('*') || this._fields?.includes(`${this.mainAlias.aliasName}.*`))) {
1724
+ if (meta && (this.#state.fields?.includes('*') || this.#state.fields?.includes(`${this.mainAlias.aliasName}.*`))) {
1722
1725
  const schema = this.getSchema(this.mainAlias);
1723
1726
  // Create a column mapping with unquoted aliases - quoting should be handled by the user via `quote` helper
1724
1727
  // For TPT, use helper to resolve correct alias per property (inherited props use parent alias)
1725
1728
  const quotedMainAlias = this.platform.quoteIdentifier(this.mainAlias.aliasName).toString();
1726
1729
  const columns = meta.createColumnMappingObject(prop => this.helper.getTPTAliasForProperty(prop.name, this.mainAlias.aliasName), quotedMainAlias);
1727
1730
  meta.props
1728
- .filter(prop => prop.formula && (!prop.lazy || this.flags.has(QueryFlag.INCLUDE_LAZY_FORMULAS)))
1731
+ .filter(prop => prop.formula && (!prop.lazy || this.#state.flags.has(QueryFlag.INCLUDE_LAZY_FORMULAS)))
1729
1732
  .map(prop => {
1730
1733
  const aliased = this.platform.quoteIdentifier(prop.fieldNames[0]);
1731
1734
  const table = this.helper.createFormulaTable(quotedMainAlias, meta, schema);
1732
1735
  return `${this.driver.evaluateFormula(prop.formula, columns, table)} as ${aliased}`;
1733
1736
  })
1734
- .filter(field => !this._fields.some(f => {
1737
+ .filter(field => !this.#state.fields.some(f => {
1735
1738
  if (isRaw(f)) {
1736
1739
  return f.sql === field && f.params.length === 0;
1737
1740
  }
1738
1741
  return f === field;
1739
1742
  }))
1740
- .forEach(field => this._fields.push(raw(field)));
1743
+ .forEach(field => this.#state.fields.push(raw(field)));
1741
1744
  }
1742
- QueryHelper.processObjectParams(this._data);
1743
- QueryHelper.processObjectParams(this._cond);
1744
- QueryHelper.processObjectParams(this._having);
1745
+ QueryHelper.processObjectParams(this.#state.data);
1746
+ QueryHelper.processObjectParams(this.#state.cond);
1747
+ QueryHelper.processObjectParams(this.#state.having);
1745
1748
  // automatically enable paginate flag when we detect to-many joins, but only if there is no `group by` clause
1746
- if (!this.flags.has(QueryFlag.DISABLE_PAGINATE) && this._groupBy.length === 0 && this.hasToManyJoins()) {
1747
- this.flags.add(QueryFlag.PAGINATE);
1749
+ if (!this.#state.flags.has(QueryFlag.DISABLE_PAGINATE) &&
1750
+ this.#state.groupBy.length === 0 &&
1751
+ this.hasToManyJoins()) {
1752
+ this.#state.flags.add(QueryFlag.PAGINATE);
1748
1753
  }
1749
1754
  if (meta &&
1750
1755
  !meta.virtual &&
1751
- this.flags.has(QueryFlag.PAGINATE) &&
1752
- !this.flags.has(QueryFlag.DISABLE_PAGINATE) &&
1753
- (this._limit > 0 || this._offset > 0)) {
1756
+ this.#state.flags.has(QueryFlag.PAGINATE) &&
1757
+ !this.#state.flags.has(QueryFlag.DISABLE_PAGINATE) &&
1758
+ (this.#state.limit > 0 || this.#state.offset > 0)) {
1754
1759
  this.wrapPaginateSubQuery(meta);
1755
1760
  }
1756
- if (meta && (this.flags.has(QueryFlag.UPDATE_SUB_QUERY) || this.flags.has(QueryFlag.DELETE_SUB_QUERY))) {
1761
+ if (meta &&
1762
+ (this.#state.flags.has(QueryFlag.UPDATE_SUB_QUERY) || this.#state.flags.has(QueryFlag.DELETE_SUB_QUERY))) {
1757
1763
  this.wrapModifySubQuery(meta);
1758
1764
  }
1759
- this.finalized = true;
1765
+ this.#state.finalized = true;
1760
1766
  }
1761
1767
  /** @internal */
1762
1768
  processPopulateHint() {
1763
- if (this.populateHintFinalized) {
1769
+ if (this.#state.populateHintFinalized) {
1764
1770
  return;
1765
1771
  }
1766
1772
  const meta = this.mainAlias.meta;
1767
- if (meta && this.flags.has(QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
1768
- const relationsToPopulate = this._populate.map(({ field }) => field);
1773
+ if (meta && this.#state.flags.has(QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
1774
+ const relationsToPopulate = this.#state.populate.map(({ field }) => field);
1769
1775
  meta.relations
1770
1776
  .filter(prop => prop.kind === ReferenceKind.ONE_TO_ONE &&
1771
1777
  !prop.owner &&
1772
1778
  !relationsToPopulate.includes(prop.name) &&
1773
1779
  !relationsToPopulate.includes(`${prop.name}:ref`))
1774
1780
  .map(prop => ({ field: `${prop.name}:ref` }))
1775
- .forEach(item => this._populate.push(item));
1781
+ .forEach(item => this.#state.populate.push(item));
1776
1782
  }
1777
- this._populate.forEach(({ field }) => {
1783
+ this.#state.populate.forEach(({ field }) => {
1778
1784
  const [fromAlias, fromField] = this.helper.splitField(field);
1779
1785
  const aliasedField = `${fromAlias}.${fromField}`;
1780
- const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
1781
- if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
1782
- this._populateMap[join] = this._joins[join].alias;
1786
+ const join = Object.keys(this.#state.joins).find(k => `${aliasedField}#${this.#state.joins[k].alias}` === k);
1787
+ if (join && this.#state.joins[join] && this.helper.isOneToOneInverse(fromField)) {
1788
+ this.#state.populateMap[join] = this.#state.joins[join].alias;
1783
1789
  return;
1784
1790
  }
1785
1791
  if (meta && this.helper.isOneToOneInverse(fromField)) {
1786
1792
  const prop = meta.properties[fromField];
1787
1793
  const alias = this.getNextAlias(prop.pivotEntity ?? prop.targetMeta.class);
1788
1794
  const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
1789
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, this.mainAlias.aliasName, alias, JoinType.leftJoin);
1790
- this._joins[aliasedName].path =
1791
- `${Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? meta.className}.${prop.name}`;
1792
- this._populateMap[aliasedName] = this._joins[aliasedName].alias;
1795
+ this.#state.joins[aliasedName] = this.helper.joinOneToReference(prop, this.mainAlias.aliasName, alias, JoinType.leftJoin);
1796
+ this.#state.joins[aliasedName].path =
1797
+ `${Object.values(this.#state.joins).find(j => j.alias === fromAlias)?.path ?? meta.className}.${prop.name}`;
1798
+ this.#state.populateMap[aliasedName] = this.#state.joins[aliasedName].alias;
1793
1799
  this.createAlias(prop.targetMeta.class, alias);
1794
1800
  }
1795
1801
  });
1796
1802
  this.processPopulateWhere(false);
1797
1803
  this.processPopulateWhere(true);
1798
- this.populateHintFinalized = true;
1804
+ this.#state.populateHintFinalized = true;
1799
1805
  }
1800
1806
  processPopulateWhere(filter) {
1801
- const key = filter ? '_populateFilter' : '_populateWhere';
1802
- if (this[key] == null || this[key] === PopulateHint.ALL) {
1807
+ const value = filter ? this.#state.populateFilter : this.#state.populateWhere;
1808
+ if (value == null || value === PopulateHint.ALL) {
1803
1809
  return;
1804
1810
  }
1805
- let joins = Object.values(this._joins);
1811
+ let joins = Object.values(this.#state.joins);
1806
1812
  for (const join of joins) {
1807
1813
  join.cond_ ??= join.cond;
1808
1814
  join.cond = { ...join.cond };
1809
1815
  }
1810
- if (typeof this[key] === 'object') {
1811
- const cond = CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, this[key]).process(this, { matchPopulateJoins: true, ignoreBranching: true, preferNoBranch: true, filter });
1816
+ if (typeof value === 'object') {
1817
+ const cond = CriteriaNodeFactory.createNode(this.metadata, this.mainAlias.entityName, value).process(this, { matchPopulateJoins: true, ignoreBranching: true, preferNoBranch: true, filter });
1812
1818
  // there might be new joins created by processing the `populateWhere` object
1813
- joins = Object.values(this._joins);
1819
+ joins = Object.values(this.#state.joins);
1814
1820
  this.mergeOnConditions(joins, cond, filter);
1815
1821
  }
1816
1822
  }
@@ -1856,10 +1862,10 @@ export class QueryBuilder {
1856
1862
  * otherwise the inner join could discard rows of the root table.
1857
1863
  */
1858
1864
  processNestedJoins() {
1859
- if (this.flags.has(QueryFlag.DISABLE_NESTED_INNER_JOIN)) {
1865
+ if (this.#state.flags.has(QueryFlag.DISABLE_NESTED_INNER_JOIN)) {
1860
1866
  return;
1861
1867
  }
1862
- const joins = Object.values(this._joins);
1868
+ const joins = Object.values(this.#state.joins);
1863
1869
  const lookupParentGroup = (j) => {
1864
1870
  return j.nested ?? (j.parent ? lookupParentGroup(j.parent) : undefined);
1865
1871
  };
@@ -1882,30 +1888,30 @@ export class QueryBuilder {
1882
1888
  }
1883
1889
  }
1884
1890
  hasToManyJoins() {
1885
- return Object.values(this._joins).some(join => {
1891
+ return Object.values(this.#state.joins).some(join => {
1886
1892
  return [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
1887
1893
  });
1888
1894
  }
1889
1895
  wrapPaginateSubQuery(meta) {
1890
1896
  const schema = this.getSchema(this.mainAlias);
1891
1897
  const pks = this.prepareFields(meta.primaryKeys, 'sub-query', schema);
1892
- const subQuery = this.clone(['_orderBy', '_fields', 'lockMode', 'lockTableAliases'])
1898
+ const subQuery = this.clone(['orderBy', 'fields', 'lockMode', 'lockTables'])
1893
1899
  .select(pks)
1894
1900
  .groupBy(pks)
1895
- .limit(this._limit);
1901
+ .limit(this.#state.limit);
1896
1902
  // revert the on conditions added via populateWhere, we want to apply those only once
1897
- for (const join of Object.values(subQuery._joins)) {
1903
+ for (const join of Object.values(subQuery.#state.joins)) {
1898
1904
  if (join.cond_) {
1899
1905
  join.cond = join.cond_;
1900
1906
  }
1901
1907
  }
1902
- if (this._offset) {
1903
- subQuery.offset(this._offset);
1908
+ if (this.#state.offset) {
1909
+ subQuery.offset(this.#state.offset);
1904
1910
  }
1905
1911
  const addToSelect = [];
1906
- if (this._orderBy.length > 0) {
1912
+ if (this.#state.orderBy.length > 0) {
1907
1913
  const orderBy = [];
1908
- for (const orderMap of this._orderBy) {
1914
+ for (const orderMap of this.#state.orderBy) {
1909
1915
  for (const field of Utils.getObjectQueryKeys(orderMap)) {
1910
1916
  const direction = orderMap[field];
1911
1917
  if (RawQueryFragment.isKnownFragmentSymbol(field)) {
@@ -1926,11 +1932,11 @@ export class QueryBuilder {
1926
1932
  }
1927
1933
  subQuery.orderBy(orderBy);
1928
1934
  }
1929
- subQuery.finalized = true;
1935
+ subQuery.#state.finalized = true;
1930
1936
  const innerQuery = subQuery.as(this.mainAlias.aliasName).clear('select').select(pks);
1931
1937
  if (addToSelect.length > 0) {
1932
1938
  addToSelect.forEach(prop => {
1933
- const field = this._fields.find(field => {
1939
+ const field = this.#state.fields.find(field => {
1934
1940
  if (typeof field === 'object' && field && '__as' in field) {
1935
1941
  return field.__as === prop;
1936
1942
  }
@@ -1956,18 +1962,18 @@ export class QueryBuilder {
1956
1962
  // https://stackoverflow.com/questions/17892762/mysql-this-version-of-mysql-doesnt-yet-support-limit-in-all-any-some-subqu
1957
1963
  const subSubQuery = this.platform.createNativeQueryBuilder();
1958
1964
  subSubQuery.select(pks).from(innerQuery);
1959
- this._limit = undefined;
1960
- this._offset = undefined;
1965
+ this.#state.limit = undefined;
1966
+ this.#state.offset = undefined;
1961
1967
  // Save the original WHERE conditions before pruning joins
1962
- const originalCond = this._cond;
1968
+ const originalCond = this.#state.cond;
1963
1969
  const populatePaths = this.getPopulatePaths();
1964
- if (!this._fields.some(field => isRaw(field))) {
1970
+ if (!this.#state.fields.some(field => isRaw(field))) {
1965
1971
  this.pruneJoinsForPagination(meta, populatePaths);
1966
1972
  }
1967
1973
  // Transfer WHERE conditions to ORDER BY joins (GH #6160)
1968
1974
  this.transferConditionsForOrderByJoins(meta, originalCond, populatePaths);
1969
1975
  const { sql, params } = subSubQuery.compile();
1970
- this.select(this._fields).where({
1976
+ this.select(this.#state.fields).where({
1971
1977
  [Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: raw(sql, params) },
1972
1978
  });
1973
1979
  }
@@ -1986,7 +1992,7 @@ export class QueryBuilder {
1986
1992
  }
1987
1993
  }
1988
1994
  }
1989
- addPath(this._populate);
1995
+ addPath(this.#state.populate);
1990
1996
  return paths;
1991
1997
  }
1992
1998
  normalizeJoinPath(join, meta) {
@@ -1998,14 +2004,14 @@ export class QueryBuilder {
1998
2004
  * GH #6160
1999
2005
  */
2000
2006
  transferConditionsForOrderByJoins(meta, cond, populatePaths) {
2001
- if (!cond || this._orderBy.length === 0) {
2007
+ if (!cond || this.#state.orderBy.length === 0) {
2002
2008
  return;
2003
2009
  }
2004
- const orderByAliases = new Set(this._orderBy
2010
+ const orderByAliases = new Set(this.#state.orderBy
2005
2011
  .flatMap(hint => Object.keys(hint))
2006
2012
  .filter(k => !RawQueryFragment.isKnownFragmentSymbol(k))
2007
2013
  .map(k => k.split('.')[0]));
2008
- for (const join of Object.values(this._joins)) {
2014
+ for (const join of Object.values(this.#state.joins)) {
2009
2015
  const joinPath = this.normalizeJoinPath(join, meta);
2010
2016
  const isPopulateJoin = populatePaths.has(joinPath);
2011
2017
  // Only transfer conditions for joins used for ORDER BY but not for population
@@ -2018,8 +2024,8 @@ export class QueryBuilder {
2018
2024
  * Removes joins that are not used for population or ordering to improve performance.
2019
2025
  */
2020
2026
  pruneJoinsForPagination(meta, populatePaths) {
2021
- const orderByAliases = this._orderBy.flatMap(hint => Object.keys(hint)).map(k => k.split('.')[0]);
2022
- const joins = Object.entries(this._joins);
2027
+ const orderByAliases = this.#state.orderBy.flatMap(hint => Object.keys(hint)).map(k => k.split('.')[0]);
2028
+ const joins = Object.entries(this.#state.joins);
2023
2029
  const rootAlias = this.alias;
2024
2030
  function addParentAlias(alias) {
2025
2031
  const join = joins.find(j => j[1].alias === alias);
@@ -2034,7 +2040,7 @@ export class QueryBuilder {
2034
2040
  for (const [key, join] of joins) {
2035
2041
  const path = this.normalizeJoinPath(join, meta);
2036
2042
  if (!populatePaths.has(path) && !orderByAliases.includes(join.alias)) {
2037
- delete this._joins[key];
2043
+ delete this.#state.joins[key];
2038
2044
  }
2039
2045
  }
2040
2046
  }
@@ -2066,25 +2072,25 @@ export class QueryBuilder {
2066
2072
  }
2067
2073
  wrapModifySubQuery(meta) {
2068
2074
  const subQuery = this.clone();
2069
- subQuery.finalized = true;
2075
+ subQuery.#state.finalized = true;
2070
2076
  // wrap one more time to get around MySQL limitations
2071
2077
  // https://stackoverflow.com/questions/45494/mysql-error-1093-cant-specify-target-table-for-update-in-from-clause
2072
2078
  const subSubQuery = this.platform.createNativeQueryBuilder();
2073
- const method = this.flags.has(QueryFlag.UPDATE_SUB_QUERY) ? 'update' : 'delete';
2079
+ const method = this.#state.flags.has(QueryFlag.UPDATE_SUB_QUERY) ? 'update' : 'delete';
2074
2080
  const schema = this.getSchema(this.mainAlias);
2075
2081
  const pks = this.prepareFields(meta.primaryKeys, 'sub-query', schema);
2076
- this._cond = {}; // otherwise we would trigger validation error
2077
- this._joins = {}; // included in the subquery
2082
+ this.#state.cond = {}; // otherwise we would trigger validation error
2083
+ this.#state.joins = {}; // included in the subquery
2078
2084
  subSubQuery.select(pks).from(subQuery.as(this.mainAlias.aliasName));
2079
2085
  const { sql, params } = subSubQuery.compile();
2080
- this[method](this._data).where({
2086
+ this[method](this.#state.data).where({
2081
2087
  [Utils.getPrimaryKeyHash(meta.primaryKeys)]: { $in: raw(sql, params) },
2082
2088
  });
2083
2089
  }
2084
2090
  getSchema(alias) {
2085
2091
  const { meta } = alias;
2086
2092
  const metaSchema = meta.schema && meta.schema !== '*' ? meta.schema : undefined;
2087
- const schema = this._schema ?? metaSchema ?? this.em?.schema ?? this.em?.config.getSchema(true);
2093
+ const schema = this.#state.schema ?? metaSchema ?? this.em?.schema ?? this.em?.config.getSchema(true);
2088
2094
  if (schema === this.platform.getDefaultSchemaName()) {
2089
2095
  return undefined;
2090
2096
  }
@@ -2094,51 +2100,51 @@ export class QueryBuilder {
2094
2100
  createAlias(entityName, aliasName, subQuery) {
2095
2101
  const meta = this.metadata.find(entityName);
2096
2102
  const alias = { aliasName, entityName, meta, subQuery };
2097
- this._aliases[aliasName] = alias;
2103
+ this.#state.aliases[aliasName] = alias;
2098
2104
  return alias;
2099
2105
  }
2100
2106
  createMainAlias(entityName, aliasName, subQuery) {
2101
- this._mainAlias = this.createAlias(entityName, aliasName, subQuery);
2102
- this._helper = this.createQueryBuilderHelper();
2103
- return this._mainAlias;
2107
+ this.#state.mainAlias = this.createAlias(entityName, aliasName, subQuery);
2108
+ this.#helper = this.createQueryBuilderHelper();
2109
+ return this.#state.mainAlias;
2104
2110
  }
2105
2111
  fromSubQuery(target, aliasName) {
2106
2112
  const { entityName } = target.mainAlias;
2107
2113
  aliasName ??= this.getNextAlias(entityName);
2108
- const subQuery = target._unionQuery ? target.toRaw() : target.getNativeQuery();
2114
+ const subQuery = target.#state.unionQuery ? target.toRaw() : target.getNativeQuery();
2109
2115
  this.createMainAlias(entityName, aliasName, subQuery);
2110
2116
  }
2111
2117
  fromEntityName(entityName, aliasName) {
2112
- aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(entityName);
2118
+ aliasName ??= this.#state.mainAlias?.aliasName ?? this.getNextAlias(entityName);
2113
2119
  this.createMainAlias(entityName, aliasName);
2114
2120
  }
2115
2121
  fromRawTable(tableName, aliasName) {
2116
- aliasName ??= this._mainAlias?.aliasName ?? this.getNextAlias(tableName);
2122
+ aliasName ??= this.#state.mainAlias?.aliasName ?? this.getNextAlias(tableName);
2117
2123
  const meta = new EntityMetadata({
2118
2124
  className: tableName,
2119
2125
  collection: tableName,
2120
2126
  });
2121
2127
  meta.root = meta;
2122
- this._mainAlias = {
2128
+ this.#state.mainAlias = {
2123
2129
  aliasName,
2124
2130
  entityName: tableName,
2125
2131
  meta,
2126
2132
  rawTableName: tableName,
2127
2133
  };
2128
- this._aliases[aliasName] = this._mainAlias;
2129
- this._helper = this.createQueryBuilderHelper();
2134
+ this.#state.aliases[aliasName] = this.#state.mainAlias;
2135
+ this.#helper = this.createQueryBuilderHelper();
2130
2136
  }
2131
2137
  createQueryBuilderHelper() {
2132
- return new QueryBuilderHelper(this.mainAlias.entityName, this.mainAlias.aliasName, this._aliases, this.subQueries, this.driver, this._tptAlias);
2138
+ return new QueryBuilderHelper(this.mainAlias.entityName, this.mainAlias.aliasName, this.#state.aliases, this.#state.subQueries, this.driver, this.#state.tptAlias);
2133
2139
  }
2134
2140
  ensureFromClause() {
2135
2141
  /* v8 ignore next */
2136
- if (!this._mainAlias) {
2142
+ if (!this.#state.mainAlias) {
2137
2143
  throw new Error(`Cannot proceed to build a query because the main alias is not set.`);
2138
2144
  }
2139
2145
  }
2140
2146
  ensureNotFinalized() {
2141
- if (this.finalized) {
2147
+ if (this.#state.finalized) {
2142
2148
  throw new Error('This QueryBuilder instance is already finalized, clone it first if you want to modify it.');
2143
2149
  }
2144
2150
  }
@@ -2155,26 +2161,27 @@ export class QueryBuilder {
2155
2161
  .forEach(k => delete object[k]);
2156
2162
  hidden.forEach(k => delete object[k]);
2157
2163
  let prefix = this.type ? this.type.substring(0, 1) + this.type.toLowerCase().substring(1) : '';
2158
- if (this._data) {
2159
- object.data = this._data;
2164
+ if (this.#state.data) {
2165
+ object.data = this.#state.data;
2160
2166
  }
2161
- if (this._schema) {
2162
- object.schema = this._schema;
2167
+ if (this.#state.schema) {
2168
+ object.schema = this.#state.schema;
2163
2169
  }
2164
- if (!Utils.isEmpty(this._cond)) {
2165
- object.where = this._cond;
2170
+ if (!Utils.isEmpty(this.#state.cond)) {
2171
+ object.where = this.#state.cond;
2166
2172
  }
2167
- if (this._onConflict?.[0]) {
2173
+ if (this.#state.onConflict?.[0]) {
2168
2174
  prefix = 'Upsert';
2169
- object.onConflict = this._onConflict[0];
2175
+ object.onConflict = this.#state.onConflict[0];
2170
2176
  }
2171
- if (!Utils.isEmpty(this._orderBy)) {
2172
- object.orderBy = this._orderBy;
2177
+ if (!Utils.isEmpty(this.#state.orderBy)) {
2178
+ object.orderBy = this.#state.orderBy;
2173
2179
  }
2174
- const name = this._mainAlias
2175
- ? `${prefix}QueryBuilder<${Utils.className(this._mainAlias?.entityName)}>`
2180
+ const name = this.#state.mainAlias
2181
+ ? `${prefix}QueryBuilder<${Utils.className(this.#state.mainAlias?.entityName)}>`
2176
2182
  : 'QueryBuilder';
2177
2183
  const ret = inspect(object, { depth });
2178
2184
  return ret === '[Object]' ? `[${name}]` : name + ' ' + ret;
2179
2185
  }
2180
2186
  }
2187
+ _a = QueryBuilder;