@mikro-orm/knex 6.4.2-dev.0 → 6.4.2-dev.10

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.
@@ -248,7 +248,8 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
248
248
  relationPojo[prop.name] = root[alias];
249
249
  }
250
250
  });
251
- const targetProps = ref
251
+ const mapToPk = !!(ref || prop.mapToPk);
252
+ const targetProps = mapToPk
252
253
  ? meta2.getPrimaryProps()
253
254
  : meta2.props.filter(prop => this.platform.shouldHaveColumn(prop, hint.children || []));
254
255
  const tz = this.platform.getTimezone();
@@ -290,7 +291,7 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
290
291
  for (const prop of targetProps) {
291
292
  prop.fieldNames.map(name => delete root[`${relationAlias}__${name}`]);
292
293
  }
293
- if (ref) {
294
+ if (mapToPk) {
294
295
  const tmp = Object.values(relationPojo);
295
296
  /* istanbul ignore next */
296
297
  relationPojo = (meta2.compositePK ? tmp : tmp[0]);
@@ -870,6 +871,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
870
871
  if (hint.filter && hint.strategy === core_1.LoadStrategy.JOINED) {
871
872
  return true;
872
873
  }
874
+ // skip redundant joins for 1:1 owner population hints when using `mapToPk`
875
+ if (prop.kind === core_1.ReferenceKind.ONE_TO_ONE && prop.mapToPk && prop.owner) {
876
+ return false;
877
+ }
873
878
  if ((options?.strategy || hint.strategy || prop.strategy || this.config.get('loadStrategy')) !== core_1.LoadStrategy.JOINED) {
874
879
  // force joined strategy for explicit 1:1 owner populate hint as it would require a join anyway
875
880
  return prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner;
@@ -972,10 +977,10 @@ class AbstractSqlDriver extends core_1.DatabaseDriver {
972
977
  }
973
978
  });
974
979
  const childExclude = exclude ? core_1.Utils.extractChildElements(exclude, prop.name) : exclude;
975
- if (!ref) {
980
+ if (!ref && !prop.mapToPk) {
976
981
  fields.push(...this.getFieldsForJoinedLoad(qb, meta2, childExplicitFields.length === 0 ? undefined : childExplicitFields, childExclude, hint.children, options, tableAlias, path, count));
977
982
  }
978
- else if (hint.filter) {
983
+ else if (hint.filter || prop.mapToPk) {
979
984
  fields.push(...prop.referencedColumnNames.map(col => qb.helper.mapper(`${tableAlias}.${col}`, qb.type, undefined, `${tableAlias}__${col}`)));
980
985
  }
981
986
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikro-orm/knex",
3
- "version": "6.4.2-dev.0",
3
+ "version": "6.4.2-dev.10",
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
  "main": "index.js",
6
6
  "module": "index.mjs",
@@ -66,7 +66,7 @@
66
66
  "@mikro-orm/core": "^6.4.1"
67
67
  },
68
68
  "peerDependencies": {
69
- "@mikro-orm/core": "6.4.2-dev.0",
69
+ "@mikro-orm/core": "6.4.2-dev.10",
70
70
  "better-sqlite3": "*",
71
71
  "libsql": "*",
72
72
  "mariadb": "*"
@@ -80,6 +80,7 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
80
80
  protected aliasCounter: number;
81
81
  protected flags: Set<QueryFlag>;
82
82
  protected finalized: boolean;
83
+ protected populateHintFinalized: boolean;
83
84
  protected _joins: Dictionary<JoinOptions>;
84
85
  protected _explicitAlias: boolean;
85
86
  protected _schema?: string;
@@ -285,6 +286,8 @@ export declare class QueryBuilder<Entity extends object = AnyEntity, RootAlias e
285
286
  private getQueryBase;
286
287
  private applyDiscriminatorCondition;
287
288
  private finalize;
289
+ /** @internal */
290
+ processPopulateHint(): void;
288
291
  private processPopulateWhere;
289
292
  private mergeOnConditions;
290
293
  private hasToManyJoins;
@@ -62,6 +62,7 @@ class QueryBuilder {
62
62
  aliasCounter = 0;
63
63
  flags = new Set([core_1.QueryFlag.CONVERT_CUSTOM_TYPES]);
64
64
  finalized = false;
65
+ populateHintFinalized = false;
65
66
  _joins = {};
66
67
  _explicitAlias = false;
67
68
  _schema;
@@ -150,7 +151,7 @@ class QueryBuilder {
150
151
  if (field) {
151
152
  this._fields = core_1.Utils.asArray(field);
152
153
  }
153
- else if (this.hasToManyJoins()) {
154
+ else if (distinct || this.hasToManyJoins()) {
154
155
  this._fields = this.mainAlias.metadata.primaryKeys;
155
156
  }
156
157
  else {
@@ -699,7 +700,7 @@ class QueryBuilder {
699
700
  const res = await this.execute('all', true);
700
701
  const entities = [];
701
702
  function propagatePopulateHint(entity, hint) {
702
- (0, core_1.helper)(entity).__serializationContext.populate ??= hint;
703
+ (0, core_1.helper)(entity).__serializationContext.populate = hint.concat((0, core_1.helper)(entity).__serializationContext.populate ?? []);
703
704
  hint.forEach(hint => {
704
705
  const [propName] = hint.field.split(':', 2);
705
706
  const value = core_1.Reference.unwrapReference(entity[propName]);
@@ -742,6 +743,7 @@ class QueryBuilder {
742
743
  }
743
744
  else {
744
745
  const qb = this.type === undefined ? this : this.clone();
746
+ qb.processPopulateHint(); // needs to happen sooner so `qb.hasToManyJoins()` reports correctly
745
747
  qb.count(field, distinct ?? qb.hasToManyJoins()).limit(undefined).offset(undefined).orderBy([]);
746
748
  res = await qb.execute('get', false);
747
749
  }
@@ -1121,30 +1123,7 @@ class QueryBuilder {
1121
1123
  }
1122
1124
  const meta = this.mainAlias.metadata;
1123
1125
  this.applyDiscriminatorCondition();
1124
- if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
1125
- const relationsToPopulate = this._populate.map(({ field }) => field);
1126
- meta.relations
1127
- .filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name) && !relationsToPopulate.includes(`${prop.name}:ref`))
1128
- .map(prop => ({ field: `${prop.name}:ref` }))
1129
- .forEach(item => this._populate.push(item));
1130
- }
1131
- this._populate.forEach(({ field }) => {
1132
- const [fromAlias, fromField] = this.helper.splitField(field);
1133
- const aliasedField = `${fromAlias}.${fromField}`;
1134
- const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
1135
- if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
1136
- this._populateMap[join] = this._joins[join].alias;
1137
- return;
1138
- }
1139
- if (meta && this.helper.isOneToOneInverse(fromField)) {
1140
- const prop = meta.properties[fromField];
1141
- const alias = this.getNextAlias(prop.pivotEntity ?? prop.type);
1142
- const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
1143
- this._joins[aliasedName] = this.helper.joinOneToReference(prop, this.mainAlias.aliasName, alias, enums_1.JoinType.leftJoin);
1144
- this._joins[aliasedName].path = `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? meta.className)}.${prop.name}`;
1145
- this._populateMap[aliasedName] = this._joins[aliasedName].alias;
1146
- }
1147
- });
1126
+ this.processPopulateHint();
1148
1127
  if (meta && (this._fields?.includes('*') || this._fields?.includes(`${this.mainAlias.aliasName}.*`))) {
1149
1128
  meta.props
1150
1129
  .filter(prop => prop.formula && (!prop.lazy || this.flags.has(core_1.QueryFlag.INCLUDE_LAZY_FORMULAS)))
@@ -1161,8 +1140,6 @@ class QueryBuilder {
1161
1140
  }))
1162
1141
  .forEach(field => this._fields.push((0, core_1.raw)(field)));
1163
1142
  }
1164
- this.processPopulateWhere(false);
1165
- this.processPopulateWhere(true);
1166
1143
  core_1.QueryHelper.processObjectParams(this._data);
1167
1144
  core_1.QueryHelper.processObjectParams(this._cond);
1168
1145
  core_1.QueryHelper.processObjectParams(this._having);
@@ -1178,6 +1155,40 @@ class QueryBuilder {
1178
1155
  }
1179
1156
  this.finalized = true;
1180
1157
  }
1158
+ /** @internal */
1159
+ processPopulateHint() {
1160
+ if (this.populateHintFinalized) {
1161
+ return;
1162
+ }
1163
+ const meta = this.mainAlias.metadata;
1164
+ if (meta && this.flags.has(core_1.QueryFlag.AUTO_JOIN_ONE_TO_ONE_OWNER)) {
1165
+ const relationsToPopulate = this._populate.map(({ field }) => field);
1166
+ meta.relations
1167
+ .filter(prop => prop.kind === core_1.ReferenceKind.ONE_TO_ONE && !prop.owner && !relationsToPopulate.includes(prop.name) && !relationsToPopulate.includes(`${prop.name}:ref`))
1168
+ .map(prop => ({ field: `${prop.name}:ref` }))
1169
+ .forEach(item => this._populate.push(item));
1170
+ }
1171
+ this._populate.forEach(({ field }) => {
1172
+ const [fromAlias, fromField] = this.helper.splitField(field);
1173
+ const aliasedField = `${fromAlias}.${fromField}`;
1174
+ const join = Object.keys(this._joins).find(k => `${aliasedField}#${this._joins[k].alias}` === k);
1175
+ if (join && this._joins[join] && this.helper.isOneToOneInverse(fromField)) {
1176
+ this._populateMap[join] = this._joins[join].alias;
1177
+ return;
1178
+ }
1179
+ if (meta && this.helper.isOneToOneInverse(fromField)) {
1180
+ const prop = meta.properties[fromField];
1181
+ const alias = this.getNextAlias(prop.pivotEntity ?? prop.type);
1182
+ const aliasedName = `${fromAlias}.${prop.name}#${alias}`;
1183
+ this._joins[aliasedName] = this.helper.joinOneToReference(prop, this.mainAlias.aliasName, alias, enums_1.JoinType.leftJoin);
1184
+ this._joins[aliasedName].path = `${(Object.values(this._joins).find(j => j.alias === fromAlias)?.path ?? meta.className)}.${prop.name}`;
1185
+ this._populateMap[aliasedName] = this._joins[aliasedName].alias;
1186
+ }
1187
+ });
1188
+ this.processPopulateWhere(false);
1189
+ this.processPopulateWhere(true);
1190
+ this.populateHintFinalized = true;
1191
+ }
1181
1192
  processPopulateWhere(filter) {
1182
1193
  const key = filter ? '_populateFilter' : '_populateWhere';
1183
1194
  if (this[key] == null || this[key] === core_1.PopulateHint.ALL) {
@@ -1233,7 +1244,9 @@ class QueryBuilder {
1233
1244
  }
1234
1245
  }
1235
1246
  hasToManyJoins() {
1247
+ // console.log(this._joins);
1236
1248
  return Object.values(this._joins).some(join => {
1249
+ // console.log(join.prop.name, join.prop.kind, [ReferenceKind.ONE_TO_MANY, ReferenceKind.MANY_TO_MANY].includes(join.prop.kind));
1237
1250
  return [core_1.ReferenceKind.ONE_TO_MANY, core_1.ReferenceKind.MANY_TO_MANY].includes(join.prop.kind);
1238
1251
  });
1239
1252
  }
@@ -75,4 +75,6 @@ export declare abstract class SchemaHelper {
75
75
  ignoreSchema?: string[];
76
76
  managementDbName?: string;
77
77
  };
78
+ private processComment;
79
+ protected handleMultilineComment(comment: string): string;
78
80
  }
@@ -147,7 +147,7 @@ class SchemaHelper {
147
147
  core_1.Utils.runIfNotEmpty(() => col.nullable(), column.nullable && guard('nullable'));
148
148
  core_1.Utils.runIfNotEmpty(() => col.notNullable(), !column.nullable && !column.generated);
149
149
  core_1.Utils.runIfNotEmpty(() => col.unsigned(), column.unsigned);
150
- core_1.Utils.runIfNotEmpty(() => col.comment(column.comment), column.comment);
150
+ core_1.Utils.runIfNotEmpty(() => col.comment(this.processComment(column.comment)), column.comment);
151
151
  this.configureColumnDefault(column, col, knex, changedProperties);
152
152
  return col;
153
153
  }
@@ -425,5 +425,11 @@ class SchemaHelper {
425
425
  get options() {
426
426
  return this.platform.getConfig().get('schemaGenerator');
427
427
  }
428
+ processComment(comment) {
429
+ return this.platform.getSchemaHelper().handleMultilineComment(comment);
430
+ }
431
+ handleMultilineComment(comment) {
432
+ return comment.replaceAll('\n', '\\n');
433
+ }
428
434
  }
429
435
  exports.SchemaHelper = SchemaHelper;