@mikro-orm/sql 7.0.0-dev.299 → 7.0.0-dev.301

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.
@@ -80,10 +80,13 @@ export class DatabaseTable {
80
80
  this.columns[field] = {
81
81
  name: prop.fieldNames[idx],
82
82
  type: prop.columnTypes[idx],
83
- generated: prop.generated instanceof RawQueryFragment ? this.platform.formatQuery(prop.generated.sql, prop.generated.params) : prop.generated,
83
+ generated: prop.generated instanceof RawQueryFragment
84
+ ? this.platform.formatQuery(prop.generated.sql, prop.generated.params)
85
+ : prop.generated,
84
86
  mappedType,
85
87
  unsigned: prop.unsigned && this.platform.isNumericColumn(mappedType),
86
- autoincrement: prop.autoincrement ?? (primary && prop.kind === ReferenceKind.SCALAR && this.platform.isNumericColumn(mappedType)),
88
+ autoincrement: prop.autoincrement ??
89
+ (primary && prop.kind === ReferenceKind.SCALAR && this.platform.isNumericColumn(mappedType)),
87
90
  primary,
88
91
  nullable: this.columns[field]?.nullable ?? !!prop.nullable,
89
92
  nativeEnumName: prop.nativeEnumName,
@@ -105,7 +108,9 @@ export class DatabaseTable {
105
108
  });
106
109
  if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && !prop.polymorphic) {
107
110
  const constraintName = this.getIndexName(prop.foreignKeyName ?? true, prop.fieldNames, 'foreign');
108
- let schema = prop.targetMeta.root.schema === '*' ? this.schema : (prop.targetMeta.root.schema ?? config.get('schema', this.platform.getDefaultSchemaName()));
111
+ let schema = prop.targetMeta.root.schema === '*'
112
+ ? this.schema
113
+ : (prop.targetMeta.root.schema ?? config.get('schema', this.platform.getDefaultSchemaName()));
109
114
  if (prop.referencedTableName.includes('.')) {
110
115
  schema = undefined;
111
116
  }
@@ -154,19 +159,20 @@ export class DatabaseTable {
154
159
  return this.platform.getIndexName(this.name, columnNames, type);
155
160
  }
156
161
  getEntityDeclaration(namingStrategy, schemaHelper, scalarPropertiesForRelations) {
157
- const { fksOnColumnProps, fksOnStandaloneProps, columnFks, fkIndexes, nullableForeignKeys, skippedColumnNames, } = this.foreignKeysToProps(namingStrategy, scalarPropertiesForRelations);
162
+ const { fksOnColumnProps, fksOnStandaloneProps, columnFks, fkIndexes, nullableForeignKeys, skippedColumnNames } = this.foreignKeysToProps(namingStrategy, scalarPropertiesForRelations);
158
163
  const name = namingStrategy.getEntityName(this.name, this.schema);
159
164
  const schema = new EntitySchema({ name, collection: this.name, schema: this.schema, comment: this.comment });
160
165
  const compositeFkIndexes = {};
161
166
  const compositeFkUniques = {};
162
- const potentiallyUnmappedIndexes = this.indexes.filter(index => !index.primary // Skip primary index. Whether it's in use by scalar column or FK, it's already mapped.
163
- && (( // Non-trivial non-composite indexes will be declared at the entity's metadata, though later outputted in the property
164
- index.columnNames.length > 1 // All composite indexes are to be mapped to entity decorators or FK props.
165
- || skippedColumnNames.includes(index.columnNames[0]) // Non-composite indexes for skipped columns are to be mapped as entity decorators.
166
- || index.deferMode || index.expression || !(index.columnNames[0] in columnFks)) // Trivial non-composite indexes for scalar props are to be mapped to the column.
167
- )
167
+ const potentiallyUnmappedIndexes = this.indexes.filter(index => !index.primary && // Skip primary index. Whether it's in use by scalar column or FK, it's already mapped.
168
+ // Non-trivial non-composite indexes will be declared at the entity's metadata, though later outputted in the property
169
+ (index.columnNames.length > 1 || // All composite indexes are to be mapped to entity decorators or FK props.
170
+ skippedColumnNames.includes(index.columnNames[0]) || // Non-composite indexes for skipped columns are to be mapped as entity decorators.
171
+ index.deferMode ||
172
+ index.expression ||
173
+ !(index.columnNames[0] in columnFks)) && // Trivial non-composite indexes for scalar props are to be mapped to the column.
168
174
  // ignore indexes that don't have all column names (this can happen in sqlite where there is no way to infer this for expressions)
169
- && !(index.columnNames.some(col => !col) && !index.expression));
175
+ !(index.columnNames.some(col => !col) && !index.expression));
170
176
  // Helper to map column name to property name
171
177
  const columnToPropertyName = (colName) => this.getPropertyName(namingStrategy, colName);
172
178
  for (const index of potentiallyUnmappedIndexes) {
@@ -198,8 +204,13 @@ export class DatabaseTable {
198
204
  }
199
205
  }
200
206
  // An index is trivial if it has no special options that require entity-level declaration
201
- const hasAdvancedOptions = index.columns?.length || index.include?.length || index.fillFactor ||
202
- index.type || index.invisible || index.disabled || index.clustered;
207
+ const hasAdvancedOptions = index.columns?.length ||
208
+ index.include?.length ||
209
+ index.fillFactor ||
210
+ index.type ||
211
+ index.invisible ||
212
+ index.disabled ||
213
+ index.clustered;
203
214
  const isTrivial = !index.deferMode && !index.expression && !hasAdvancedOptions;
204
215
  if (isTrivial) {
205
216
  // Index is for FK. Map to the FK prop and move on.
@@ -213,7 +224,8 @@ export class DatabaseTable {
213
224
  }
214
225
  }
215
226
  }
216
- const properties = ret.properties ?? this.getIndexProperties(index, columnFks, fksOnColumnProps, fksOnStandaloneProps, namingStrategy);
227
+ const properties = ret.properties ??
228
+ this.getIndexProperties(index, columnFks, fksOnColumnProps, fksOnStandaloneProps, namingStrategy);
217
229
  // If there is a column that cannot be unambiguously mapped to a prop, render an expression.
218
230
  if (typeof properties === 'undefined') {
219
231
  ret.expression ??= schemaHelper.getCreateIndexSQL(this.name, index);
@@ -237,7 +249,7 @@ export class DatabaseTable {
237
249
  }
238
250
  schema.addIndex(ret);
239
251
  }
240
- const addedStandaloneFkPropsBasedOnColumn = new Set;
252
+ const addedStandaloneFkPropsBasedOnColumn = new Set();
241
253
  const nonSkippedColumns = this.getColumns().filter(column => !skippedColumnNames.includes(column.name));
242
254
  for (const column of nonSkippedColumns) {
243
255
  const columnName = column.name;
@@ -259,10 +271,10 @@ export class DatabaseTable {
259
271
  schema.addProperty(prop.name, prop.type, prop);
260
272
  }
261
273
  const meta = schema.init().meta;
262
- const oneToOneCandidateProperties = meta.relations
263
- .filter(prop => prop.primary && prop.kind === ReferenceKind.MANY_TO_ONE);
264
- if (oneToOneCandidateProperties.length === 1
265
- && oneToOneCandidateProperties[0].fieldNames.length === (new Set(meta.getPrimaryProps().flatMap(prop => prop.fieldNames))).size) {
274
+ const oneToOneCandidateProperties = meta.relations.filter(prop => prop.primary && prop.kind === ReferenceKind.MANY_TO_ONE);
275
+ if (oneToOneCandidateProperties.length === 1 &&
276
+ oneToOneCandidateProperties[0].fieldNames.length ===
277
+ new Set(meta.getPrimaryProps().flatMap(prop => prop.fieldNames)).size) {
266
278
  oneToOneCandidateProperties[0].kind = ReferenceKind.ONE_TO_ONE;
267
279
  }
268
280
  return meta;
@@ -277,7 +289,8 @@ export class DatabaseTable {
277
289
  const standaloneFksBasedOnColumnNames = new Map();
278
290
  for (const currentFk of fks) {
279
291
  const fkIndex = this.findFkIndex(currentFk);
280
- if (currentFk.columnNames.length === 1 && !fks.some(fk => fk !== currentFk && fk.columnNames.length === 1 && currentFk.columnNames[0] === fk.columnNames[0])) {
292
+ if (currentFk.columnNames.length === 1 &&
293
+ !fks.some(fk => fk !== currentFk && fk.columnNames.length === 1 && currentFk.columnNames[0] === fk.columnNames[0])) {
281
294
  // Non-composite FK is the only possible one for a column. Render the column with it.
282
295
  const columnName = currentFk.columnNames[0];
283
296
  columnFks[columnName] ??= [];
@@ -316,7 +329,10 @@ export class DatabaseTable {
316
329
  if (nullableColumnsInFk.length > 0) {
317
330
  nullableForeignKeys.add(currentFk);
318
331
  }
319
- if (specificColumnNames.length === 1 && ((nullableColumnsInFk.length === currentFk.columnNames.length || nullableColumnsInFk.length === 0) || (nullableColumnsInFk.length === 1 && nullableColumnsInFk[0] === specificColumnNames[0]))) {
332
+ if (specificColumnNames.length === 1 &&
333
+ (nullableColumnsInFk.length === currentFk.columnNames.length ||
334
+ nullableColumnsInFk.length === 0 ||
335
+ (nullableColumnsInFk.length === 1 && nullableColumnsInFk[0] === specificColumnNames[0]))) {
320
336
  // Composite FK has exactly one column which is not used in any other FK.
321
337
  // The FK also doesn't have a mix of nullable and non-nullable columns,
322
338
  // or its only nullable column is this very one.
@@ -391,14 +407,16 @@ export class DatabaseTable {
391
407
  // But also does not skip if the column is not nullable, and yet all involved FKs are nullable,
392
408
  // or if one or more FKs involved has multiple nullable columns.
393
409
  smart: (column) => {
394
- return columnsInFks.includes(column.name)
395
- && !fksOnColumnProps.has(column.name)
396
- && (column.nullable
410
+ return (columnsInFks.includes(column.name) &&
411
+ !fksOnColumnProps.has(column.name) &&
412
+ (column.nullable
397
413
  ? columnFks[column.name].some(fk => !fk.columnNames.some(fkColumnName => fkColumnName !== column.name && this.getColumn(fkColumnName)?.nullable))
398
- : columnFks[column.name].some(fk => !nullableForeignKeys.has(fk)));
414
+ : columnFks[column.name].some(fk => !nullableForeignKeys.has(fk))));
399
415
  },
400
416
  };
401
- const skippedColumnNames = this.getColumns().filter(skippingHandlers[scalarPropertiesForRelations]).map(column => column.name);
417
+ const skippedColumnNames = this.getColumns()
418
+ .filter(skippingHandlers[scalarPropertiesForRelations])
419
+ .map(column => column.name);
402
420
  // Check standalone FKs named after columns for potential conflicts among themselves.
403
421
  // This typically happens when two standalone FKs named after a column resolve to the same prop name
404
422
  // because the respective columns include the referenced table in the name.
@@ -439,7 +457,8 @@ export class DatabaseTable {
439
457
  findFkIndex(currentFk) {
440
458
  const fkColumnsLength = currentFk.columnNames.length;
441
459
  const possibleIndexes = this.indexes.filter(index => {
442
- return index.columnNames.length === fkColumnsLength && !currentFk.columnNames.some((columnName, i) => index.columnNames[i] !== columnName);
460
+ return (index.columnNames.length === fkColumnsLength &&
461
+ !currentFk.columnNames.some((columnName, i) => index.columnNames[i] !== columnName));
443
462
  });
444
463
  possibleIndexes.sort((a, b) => {
445
464
  if (a.primary !== b.primary) {
@@ -502,7 +521,8 @@ export class DatabaseTable {
502
521
  return Array.from(propBaseNames).map(baseName => this.getPropertyName(namingStrategy, baseName, fksOnColumnProps.get(baseName)));
503
522
  }
504
523
  getSafeBaseNameForFkProp(namingStrategy, currentFk, fks, columnName) {
505
- if (columnName && this.getPropertyName(namingStrategy, columnName, currentFk) !== this.getPropertyName(namingStrategy, columnName)) {
524
+ if (columnName &&
525
+ this.getPropertyName(namingStrategy, columnName, currentFk) !== this.getPropertyName(namingStrategy, columnName)) {
506
526
  // The eligible scalar column name is different from the name of the FK prop of the same column.
507
527
  // Both can be safely rendered.
508
528
  // Use the column name as a base for the FK prop.
@@ -538,7 +558,9 @@ export class DatabaseTable {
538
558
  */
539
559
  getShortestName(skipDefaultSchema = true) {
540
560
  const defaultSchema = this.platform.getDefaultSchemaName();
541
- if (!this.schema || this.name.startsWith(defaultSchema + '.') || (this.schema === defaultSchema && skipDefaultSchema)) {
561
+ if (!this.schema ||
562
+ this.name.startsWith(defaultSchema + '.') ||
563
+ (this.schema === defaultSchema && skipDefaultSchema)) {
542
564
  return this.name;
543
565
  }
544
566
  return `${this.schema}.${this.name}`;
@@ -569,7 +591,7 @@ export class DatabaseTable {
569
591
  }
570
592
  getForeignKeyDeclaration(fk, namingStrategy, schemaHelper, fkIndex, nullable, propNameBase, fksOnColumnProps) {
571
593
  const prop = this.getPropertyName(namingStrategy, propNameBase, fk);
572
- const kind = (fkIndex?.unique && !fkIndex.primary) ? this.getReferenceKind(fk, fkIndex) : this.getReferenceKind(fk);
594
+ const kind = fkIndex?.unique && !fkIndex.primary ? this.getReferenceKind(fk, fkIndex) : this.getReferenceKind(fk);
573
595
  const runtimeType = this.getPropertyTypeForForeignKey(namingStrategy, fk);
574
596
  const fkOptions = {};
575
597
  fkOptions.fieldNames = fk.columnNames;
@@ -584,8 +606,8 @@ export class DatabaseTable {
584
606
  const column = this.getColumn(fk.columnNames[0]);
585
607
  const defaultRaw = this.getPropertyDefaultValue(schemaHelper, column, column.type, true);
586
608
  const defaultTs = this.getPropertyDefaultValue(schemaHelper, column, column.type);
587
- columnOptions.default = (defaultRaw !== defaultTs || defaultRaw === '') ? defaultTs : undefined;
588
- columnOptions.defaultRaw = (column.nullable && defaultRaw === 'null') ? undefined : defaultRaw;
609
+ columnOptions.default = defaultRaw !== defaultTs || defaultRaw === '' ? defaultTs : undefined;
610
+ columnOptions.defaultRaw = column.nullable && defaultRaw === 'null' ? undefined : defaultRaw;
589
611
  columnOptions.optional = typeof column.generated !== 'undefined' || defaultRaw !== 'null';
590
612
  columnOptions.generated = column.generated;
591
613
  columnOptions.nullable = column.nullable;
@@ -607,25 +629,29 @@ export class DatabaseTable {
607
629
  nullable,
608
630
  primary: fkIndex?.primary || !fk.columnNames.some(columnName => !this.getPrimaryKey()?.columnNames.includes(columnName)),
609
631
  index: !fkIndex?.unique ? fkIndex?.keyName : undefined,
610
- unique: (fkIndex?.unique && !fkIndex.primary) ? fkIndex.keyName : undefined,
632
+ unique: fkIndex?.unique && !fkIndex.primary ? fkIndex.keyName : undefined,
611
633
  ...fkOptions,
612
634
  };
613
635
  }
614
636
  getPropertyDeclaration(column, namingStrategy, schemaHelper, compositeFkIndexes, compositeFkUniques, columnFks, fk) {
615
637
  const prop = this.getPropertyName(namingStrategy, column.name, fk);
616
638
  const persist = !(column.name in columnFks && typeof fk === 'undefined');
617
- const index = compositeFkIndexes[prop] || this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && !idx.unique && !idx.primary);
618
- const unique = compositeFkUniques[prop] || this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && idx.unique && !idx.primary);
639
+ const index = compositeFkIndexes[prop] ||
640
+ this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && !idx.unique && !idx.primary);
641
+ const unique = compositeFkUniques[prop] ||
642
+ this.indexes.find(idx => idx.columnNames[0] === column.name && !idx.composite && idx.unique && !idx.primary);
619
643
  const kind = this.getReferenceKind(fk, unique);
620
644
  const runtimeType = this.getPropertyTypeForColumn(namingStrategy, column, fk);
621
- const type = fk ? runtimeType : (Utils.keys(t).find(k => {
622
- const typeInCoreMap = this.platform.getMappedType(k);
623
- return (typeInCoreMap !== Type.getType(UnknownType) || k === 'unknown') && typeInCoreMap === column.mappedType;
624
- }) ?? runtimeType);
625
- const ignoreSchemaChanges = (type === 'unknown' && column.length) ? (column.extra ? ['type', 'extra'] : ['type']) : undefined;
645
+ const type = fk
646
+ ? runtimeType
647
+ : (Utils.keys(t).find(k => {
648
+ const typeInCoreMap = this.platform.getMappedType(k);
649
+ return ((typeInCoreMap !== Type.getType(UnknownType) || k === 'unknown') && typeInCoreMap === column.mappedType);
650
+ }) ?? runtimeType);
651
+ const ignoreSchemaChanges = type === 'unknown' && column.length ? (column.extra ? ['type', 'extra'] : ['type']) : undefined;
626
652
  const defaultRaw = this.getPropertyDefaultValue(schemaHelper, column, runtimeType, true);
627
653
  const defaultParsed = this.getPropertyDefaultValue(schemaHelper, column, runtimeType);
628
- const defaultTs = (defaultRaw !== defaultParsed || defaultParsed === '') ? defaultParsed : undefined;
654
+ const defaultTs = defaultRaw !== defaultParsed || defaultParsed === '' ? defaultParsed : undefined;
629
655
  const fkOptions = {};
630
656
  if (fk) {
631
657
  fkOptions.fieldNames = fk.columnNames;
@@ -646,7 +672,7 @@ export class DatabaseTable {
646
672
  optional: defaultRaw !== 'null' || defaultTs != null || typeof column.generated !== 'undefined',
647
673
  columnType: column.type,
648
674
  default: defaultTs,
649
- defaultRaw: (column.nullable && defaultRaw === 'null') ? undefined : defaultRaw,
675
+ defaultRaw: column.nullable && defaultRaw === 'null' ? undefined : defaultRaw,
650
676
  nullable: column.nullable,
651
677
  primary: column.primary && persist,
652
678
  autoincrement: column.autoincrement,
@@ -720,7 +746,7 @@ export class DatabaseTable {
720
746
  const defaultValue = column.default ?? 'null';
721
747
  const val = schemaHelper.normalizeDefaultValue(defaultValue, column.length);
722
748
  if (val === 'null') {
723
- return raw ? 'null' : (column.nullable ? null : undefined);
749
+ return raw ? 'null' : column.nullable ? null : undefined;
724
750
  }
725
751
  if (propType === 'boolean' && !raw) {
726
752
  return !['0', 'false', 'f', 'n', 'no', 'off'].includes('' + column.default);
@@ -752,7 +778,9 @@ export class DatabaseTable {
752
778
  }
753
779
  addIndex(meta, index, type) {
754
780
  // If columns are specified but properties are not, derive properties from column names
755
- if (index.columns?.length && !index.expression && (!index.properties || Utils.asArray(index.properties).length === 0)) {
781
+ if (index.columns?.length &&
782
+ !index.expression &&
783
+ (!index.properties || Utils.asArray(index.properties).length === 0)) {
756
784
  index = { ...index, properties: index.columns.map(c => c.name) };
757
785
  }
758
786
  const properties = Utils.unique(Utils.flatten(Utils.asArray(index.properties).map(prop => {
@@ -787,13 +815,15 @@ export class DatabaseTable {
787
815
  }
788
816
  const name = this.getIndexName(index.name, properties, type);
789
817
  // Process include columns (map property names to field names)
790
- const includeColumns = index.include ? Utils.unique(Utils.flatten(Utils.asArray(index.include).map(prop => {
791
- if (meta.properties[prop]) {
792
- return meta.properties[prop].fieldNames;
793
- }
794
- /* v8 ignore next */
795
- return [prop];
796
- }))) : undefined;
818
+ const includeColumns = index.include
819
+ ? Utils.unique(Utils.flatten(Utils.asArray(index.include).map(prop => {
820
+ if (meta.properties[prop]) {
821
+ return meta.properties[prop].fieldNames;
822
+ }
823
+ /* v8 ignore next */
824
+ return [prop];
825
+ })))
826
+ : undefined;
797
827
  // Process columns with advanced options (map property names to field names)
798
828
  const columns = index.columns?.map(col => {
799
829
  const fieldName = meta.properties[col.name]?.fieldNames[0] ?? col.name;
@@ -59,7 +59,9 @@ export class SchemaComparator {
59
59
  if (toSchema.hasNativeEnum(key)) {
60
60
  continue;
61
61
  }
62
- if (key.startsWith(`${fromSchema.name}.`) && (fromSchema.name !== toSchema.name || toSchema.getNativeEnum(key.substring(fromSchema.name.length + 1))?.schema === '*')) {
62
+ if (key.startsWith(`${fromSchema.name}.`) &&
63
+ (fromSchema.name !== toSchema.name ||
64
+ toSchema.getNativeEnum(key.substring(fromSchema.name.length + 1))?.schema === '*')) {
63
65
  continue;
64
66
  }
65
67
  diff.removedNativeEnums.push(nativeEnum);
@@ -164,7 +166,10 @@ export class SchemaComparator {
164
166
  };
165
167
  if (this.diffComment(fromTable.comment, toTable.comment)) {
166
168
  tableDifferences.changedComment = toTable.comment;
167
- this.log(`table comment changed for ${tableDifferences.name}`, { fromTableComment: fromTable.comment, toTableComment: toTable.comment });
169
+ this.log(`table comment changed for ${tableDifferences.name}`, {
170
+ fromTableComment: fromTable.comment,
171
+ toTableComment: toTable.comment,
172
+ });
168
173
  changes++;
169
174
  }
170
175
  const fromTableColumns = fromTable.getColumns();
@@ -222,7 +227,7 @@ export class SchemaComparator {
222
227
  // See if there are any removed indexes in "to" table
223
228
  for (const index of fromTableIndexes) {
224
229
  // See if index is removed in "to" table.
225
- if ((index.primary && !toTable.hasPrimaryKey()) || !index.primary && !toTable.hasIndex(index.keyName)) {
230
+ if ((index.primary && !toTable.hasPrimaryKey()) || (!index.primary && !toTable.hasIndex(index.keyName))) {
226
231
  tableDifferences.removedIndexes[index.keyName] = index;
227
232
  this.log(`index ${index.keyName} removed from table ${tableDifferences.name}`);
228
233
  changes++;
@@ -234,7 +239,10 @@ export class SchemaComparator {
234
239
  continue;
235
240
  }
236
241
  tableDifferences.changedIndexes[index.keyName] = toTableIndex;
237
- this.log(`index ${index.keyName} changed in table ${tableDifferences.name}`, { fromTableIndex: index, toTableIndex });
242
+ this.log(`index ${index.keyName} changed in table ${tableDifferences.name}`, {
243
+ fromTableIndex: index,
244
+ toTableIndex,
245
+ });
238
246
  changes++;
239
247
  }
240
248
  this.detectIndexRenamings(tableDifferences);
@@ -264,10 +272,15 @@ export class SchemaComparator {
264
272
  if (!this.diffExpression(check.expression, toTableCheck.expression)) {
265
273
  continue;
266
274
  }
267
- if (fromColumn?.enumItems && toColumn?.enumItems && !this.diffEnumItems(fromColumn.enumItems, toColumn.enumItems)) {
275
+ if (fromColumn?.enumItems &&
276
+ toColumn?.enumItems &&
277
+ !this.diffEnumItems(fromColumn.enumItems, toColumn.enumItems)) {
268
278
  continue;
269
279
  }
270
- this.log(`check constraint ${check.name} changed in table ${tableDifferences.name}`, { fromTableCheck: check, toTableCheck });
280
+ this.log(`check constraint ${check.name} changed in table ${tableDifferences.name}`, {
281
+ fromTableCheck: check,
282
+ toTableCheck,
283
+ });
271
284
  tableDifferences.changedChecks[check.name] = toTableCheck;
272
285
  changes++;
273
286
  }
@@ -280,7 +293,10 @@ export class SchemaComparator {
280
293
  delete toForeignKeys[toConstraint.constraintName];
281
294
  }
282
295
  else if (fromConstraint.constraintName.toLowerCase() === toConstraint.constraintName.toLowerCase()) {
283
- this.log(`FK constraint ${fromConstraint.constraintName} changed in table ${tableDifferences.name}`, { fromConstraint, toConstraint });
296
+ this.log(`FK constraint ${fromConstraint.constraintName} changed in table ${tableDifferences.name}`, {
297
+ fromConstraint,
298
+ toConstraint,
299
+ });
284
300
  tableDifferences.changedForeignKeys[toConstraint.constraintName] = toConstraint;
285
301
  changes++;
286
302
  delete fromForeignKeys[fromConstraint.constraintName];
@@ -295,7 +311,9 @@ export class SchemaComparator {
295
311
  }
296
312
  for (const toConstraint of Object.values(toForeignKeys)) {
297
313
  tableDifferences.addedForeignKeys[toConstraint.constraintName] = toConstraint;
298
- this.log(`FK constraint ${toConstraint.constraintName} added to table ${tableDifferences.name}`, { constraint: toConstraint });
314
+ this.log(`FK constraint ${toConstraint.constraintName} added to table ${tableDifferences.name}`, {
315
+ constraint: toConstraint,
316
+ });
299
317
  changes++;
300
318
  }
301
319
  return changes ? tableDifferences : false;
@@ -341,7 +359,10 @@ export class SchemaComparator {
341
359
  tableDifferences.renamedColumns[removedColumnName] = addedColumn;
342
360
  delete tableDifferences.addedColumns[addedColumnName];
343
361
  delete tableDifferences.removedColumns[removedColumnName];
344
- this.log(`renamed column detected in table ${tableDifferences.name}`, { old: removedColumnName, new: addedColumnName });
362
+ this.log(`renamed column detected in table ${tableDifferences.name}`, {
363
+ old: removedColumnName,
364
+ new: addedColumnName,
365
+ });
345
366
  }
346
367
  }
347
368
  /**
@@ -375,7 +396,10 @@ export class SchemaComparator {
375
396
  tableDifferences.renamedIndexes[removedIndexName] = addedIndex;
376
397
  delete tableDifferences.addedIndexes[addedIndexName];
377
398
  delete tableDifferences.removedIndexes[removedIndexName];
378
- this.log(`renamed index detected in table ${tableDifferences.name}`, { old: removedIndexName, new: addedIndexName });
399
+ this.log(`renamed index detected in table ${tableDifferences.name}`, {
400
+ old: removedIndexName,
401
+ new: addedIndexName,
402
+ });
379
403
  }
380
404
  }
381
405
  diffForeignKey(key1, key2, tableDifferences) {
@@ -402,10 +426,7 @@ export class SchemaComparator {
402
426
  }
403
427
  const defaultRule = ['restrict', 'no action'];
404
428
  const rule = (key, method) => {
405
- return (key[method] ?? defaultRule[0])
406
- .toLowerCase()
407
- .replace(defaultRule[1], defaultRule[0])
408
- .replace(/"/g, '');
429
+ return (key[method] ?? defaultRule[0]).toLowerCase().replace(defaultRule[1], defaultRule[0]).replace(/"/g, '');
409
430
  };
410
431
  const compare = (method) => rule(key1, method) === rule(key2, method);
411
432
  return !compare('updateRule') || !compare('deleteRule');
@@ -418,7 +439,8 @@ export class SchemaComparator {
418
439
  const fromProp = this.mapColumnToProperty({ ...fromColumn, autoincrement: false });
419
440
  const toProp = this.mapColumnToProperty({ ...toColumn, autoincrement: false });
420
441
  const fromColumnType = this.platform.normalizeColumnType(fromColumn.mappedType.getColumnType(fromProp, this.platform).toLowerCase(), fromProp);
421
- const fromNativeEnum = fromTable.nativeEnums[fromColumnType] ?? Object.values(fromTable.nativeEnums).find(e => e.name === fromColumnType && e.schema !== '*');
442
+ const fromNativeEnum = fromTable.nativeEnums[fromColumnType] ??
443
+ Object.values(fromTable.nativeEnums).find(e => e.name === fromColumnType && e.schema !== '*');
422
444
  let toColumnType = this.platform.normalizeColumnType(toColumn.mappedType.getColumnType(toProp, this.platform).toLowerCase(), toProp);
423
445
  const log = (msg, params) => {
424
446
  if (logging) {
@@ -430,8 +452,11 @@ export class SchemaComparator {
430
452
  if (fromColumnType !== toColumnType &&
431
453
  (!fromNativeEnum || `${fromNativeEnum.schema}.${fromNativeEnum.name}` !== toColumnType) &&
432
454
  !(fromColumn.ignoreSchemaChanges?.includes('type') || toColumn.ignoreSchemaChanges?.includes('type')) &&
433
- !fromColumn.generated && !toColumn.generated) {
434
- if (!toColumnType.includes('.') && fromTable.schema && fromTable.schema !== this.platform.getDefaultSchemaName()) {
455
+ !fromColumn.generated &&
456
+ !toColumn.generated) {
457
+ if (!toColumnType.includes('.') &&
458
+ fromTable.schema &&
459
+ fromTable.schema !== this.platform.getDefaultSchemaName()) {
435
460
  toColumnType = `${fromTable.schema}.${toColumnType}`;
436
461
  }
437
462
  if (fromColumnType !== toColumnType) {
@@ -455,8 +480,8 @@ export class SchemaComparator {
455
480
  log(`'unsigned' changed for column ${fromTable.name}.${fromColumn.name}`, { fromColumn, toColumn });
456
481
  changedProperties.add('unsigned');
457
482
  }
458
- if (!(fromColumn.ignoreSchemaChanges?.includes('default') ||
459
- toColumn.ignoreSchemaChanges?.includes('default')) && !this.hasSameDefaultValue(fromColumn, toColumn)) {
483
+ if (!(fromColumn.ignoreSchemaChanges?.includes('default') || toColumn.ignoreSchemaChanges?.includes('default')) &&
484
+ !this.hasSameDefaultValue(fromColumn, toColumn)) {
460
485
  log(`'default' changed for column ${fromTable.name}.${fromColumn.name}`, { fromColumn, toColumn });
461
486
  changedProperties.add('default');
462
487
  }
@@ -471,8 +496,7 @@ export class SchemaComparator {
471
496
  changedProperties.add('enumItems');
472
497
  }
473
498
  if ((fromColumn.extra || '').toLowerCase() !== (toColumn.extra || '').toLowerCase() &&
474
- !(fromColumn.ignoreSchemaChanges?.includes('extra') ||
475
- toColumn.ignoreSchemaChanges?.includes('extra'))) {
499
+ !(fromColumn.ignoreSchemaChanges?.includes('extra') || toColumn.ignoreSchemaChanges?.includes('extra'))) {
476
500
  log(`'extra' changed for column ${fromTable.name}.${fromColumn.name}`, { fromColumn, toColumn });
477
501
  changedProperties.add('extra');
478
502
  }
@@ -579,7 +603,7 @@ export class SchemaComparator {
579
603
  if (sort1 !== sort2) {
580
604
  return false;
581
605
  }
582
- const defaultNulls = (s) => s === 'DESC' ? 'FIRST' : 'LAST';
606
+ const defaultNulls = (s) => (s === 'DESC' ? 'FIRST' : 'LAST');
583
607
  const nulls1 = c1.nulls?.toUpperCase() ?? defaultNulls(sort1);
584
608
  const nulls2 = c2.nulls?.toUpperCase() ?? defaultNulls(sort2);
585
609
  if (nulls1 !== nulls2) {
@@ -610,9 +634,9 @@ export class SchemaComparator {
610
634
  // expressions like check constraints might be normalized by the driver,
611
635
  // e.g. quotes might be added (https://github.com/mikro-orm/mikro-orm/issues/3827)
612
636
  const simplify = (str) => {
613
- return str
637
+ return (str
614
638
  ?.replace(/_\w+'(.*?)'/g, '$1')
615
- .replace(/in\s*\((.*?)\)/ig, '= any (array[$1])')
639
+ .replace(/in\s*\((.*?)\)/gi, '= any (array[$1])')
616
640
  // MySQL normalizes count(*) to count(0)
617
641
  .replace(/\bcount\s*\(\s*0\s*\)/gi, 'count(*)')
618
642
  // Remove quotes first so we can process identifiers
@@ -628,7 +652,7 @@ export class SchemaComparator {
628
652
  .replace(/\bas\b/gi, '')
629
653
  // Remove remaining special chars, parentheses, type casts, asterisks, and normalize whitespace
630
654
  .replace(/[()\n[\]*]|::\w+| +/g, '')
631
- .replace(/anyarray\[(.*)]/ig, '$1')
655
+ .replace(/anyarray\[(.*)]/gi, '$1')
632
656
  .toLowerCase()
633
657
  // PostgreSQL adds default aliases to aggregate functions (e.g., count(*) AS count)
634
658
  // After removing AS and whitespace, this results in duplicate adjacent words
@@ -636,7 +660,7 @@ export class SchemaComparator {
636
660
  // Use lookahead to match repeated patterns of 3+ chars (avoid false positives on short sequences)
637
661
  .replace(/(\w{3,})\1/g, '$1')
638
662
  // Remove trailing semicolon (PostgreSQL adds it to view definitions)
639
- .replace(/;$/, '');
663
+ .replace(/;$/, ''));
640
664
  };
641
665
  return simplify(expr1) !== simplify(expr2);
642
666
  }
@@ -645,13 +669,13 @@ export class SchemaComparator {
645
669
  if (!defaultValue) {
646
670
  return null;
647
671
  }
648
- const val = defaultValue
649
- .replace(/^(_\w+\\)?'(.*?)\\?'$/, '$2')
650
- .replace(/^\(?'(.*?)'\)?$/, '$1');
672
+ const val = defaultValue.replace(/^(_\w+\\)?'(.*?)\\?'$/, '$2').replace(/^\(?'(.*?)'\)?$/, '$1');
651
673
  return parseJsonSafe(val);
652
674
  }
653
675
  hasSameDefaultValue(from, to) {
654
- if (from.default == null || from.default.toString().toLowerCase() === 'null' || from.default.toString().startsWith('nextval(')) {
676
+ if (from.default == null ||
677
+ from.default.toString().toLowerCase() === 'null' ||
678
+ from.default.toString().startsWith('nextval(')) {
655
679
  return to.default == null || to.default.toLowerCase() === 'null';
656
680
  }
657
681
  if (to.mappedType instanceof BooleanType) {
@@ -78,7 +78,7 @@ export class SchemaHelper {
78
78
  tableName = this.quote(tableName);
79
79
  oldColumnName = this.quote(oldColumnName);
80
80
  const columnName = this.quote(to.name);
81
- const schemaReference = (schemaName !== undefined && schemaName !== 'public') ? ('"' + schemaName + '".') : '';
81
+ const schemaReference = schemaName !== undefined && schemaName !== 'public' ? '"' + schemaName + '".' : '';
82
82
  const tableReference = schemaReference + tableName;
83
83
  return `alter table ${tableReference} rename column ${oldColumnName} to ${columnName}`;
84
84
  }
@@ -124,7 +124,8 @@ export class SchemaHelper {
124
124
  */
125
125
  getIndexColumns(index) {
126
126
  if (index.columns?.length) {
127
- return index.columns.map(col => {
127
+ return index.columns
128
+ .map(col => {
128
129
  let colDef = this.quote(col.name);
129
130
  // Collation comes after column name (SQLite syntax: column COLLATE name)
130
131
  if (col.collation) {
@@ -139,7 +140,8 @@ export class SchemaHelper {
139
140
  colDef += ` nulls ${col.nulls}`;
140
141
  }
141
142
  return colDef;
142
- }).join(', ');
143
+ })
144
+ .join(', ');
143
145
  }
144
146
  return index.columnNames.map(c => this.quote(c)).join(', ');
145
147
  }
@@ -256,9 +258,11 @@ export class SchemaHelper {
256
258
  return ret;
257
259
  }
258
260
  getAddColumnsSQL(table, columns) {
259
- const adds = columns.map(column => {
261
+ const adds = columns
262
+ .map(column => {
260
263
  return `add ${this.createTableColumn(column, table)}`;
261
- }).join(', ');
264
+ })
265
+ .join(', ');
262
266
  return [`alter table ${table.getQuotedName()} ${adds}`];
263
267
  }
264
268
  getDropColumnsSQL(tableName, columns, schemaName) {
@@ -310,12 +314,26 @@ export class SchemaHelper {
310
314
  Utils.runIfNotEmpty(() => col.push('not null'), !column.nullable && !column.generated);
311
315
  Utils.runIfNotEmpty(() => col.push('auto_increment'), column.autoincrement);
312
316
  Utils.runIfNotEmpty(() => col.push('unique'), column.autoincrement && !column.primary);
313
- if (column.autoincrement && !column.generated && !compositePK && (!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
317
+ if (column.autoincrement &&
318
+ !column.generated &&
319
+ !compositePK &&
320
+ (!changedProperties || changedProperties.has('autoincrement') || changedProperties.has('type'))) {
314
321
  Utils.runIfNotEmpty(() => col.push('primary key'), primaryKey && column.primary);
315
322
  }
316
323
  if (useDefault) {
317
324
  // https://dev.mysql.com/doc/refman/9.0/en/data-type-defaults.html
318
- const needsExpression = ['blob', 'text', 'json', 'point', 'linestring', 'polygon', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection'].some(type => column.type.toLowerCase().startsWith(type));
325
+ const needsExpression = [
326
+ 'blob',
327
+ 'text',
328
+ 'json',
329
+ 'point',
330
+ 'linestring',
331
+ 'polygon',
332
+ 'multipoint',
333
+ 'multilinestring',
334
+ 'multipolygon',
335
+ 'geometrycollection',
336
+ ].some(type => column.type.toLowerCase().startsWith(type));
319
337
  const defaultSql = needsExpression && !column.default.startsWith('(') ? `(${column.default})` : column.default;
320
338
  col.push(`default ${defaultSql}`);
321
339
  }
@@ -371,7 +389,9 @@ export class SchemaHelper {
371
389
  columnNames: [fk.column_name],
372
390
  constraintName: fk.constraint_name,
373
391
  localTableName: schemaName ? `${schemaName}.${tableName}` : tableName,
374
- referencedTableName: fk.referenced_schema_name ? `${fk.referenced_schema_name}.${fk.referenced_table_name}` : fk.referenced_table_name,
392
+ referencedTableName: fk.referenced_schema_name
393
+ ? `${fk.referenced_schema_name}.${fk.referenced_table_name}`
394
+ : fk.referenced_table_name,
375
395
  referencedColumnNames: [fk.referenced_column_name],
376
396
  updateRule: fk.update_rule.toLowerCase(),
377
397
  deleteRule: fk.delete_rule.toLowerCase(),
@@ -128,7 +128,8 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
128
128
  }
129
129
  const schema = options?.schema ?? this.config.get('schema', this.platform.getDefaultSchemaName());
130
130
  for (const meta of this.getOrderedMetadata(schema).reverse()) {
131
- await this.driver.createQueryBuilder(meta.class, this.em?.getTransactionContext(), 'write', false)
131
+ await this.driver
132
+ .createQueryBuilder(meta.class, this.em?.getTransactionContext(), 'write', false)
132
133
  .withSchema(schema)
133
134
  .truncate()
134
135
  .execute();
@@ -224,8 +225,11 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
224
225
  options.dropTables ??= true;
225
226
  const toSchema = this.getTargetSchema(options.schema);
226
227
  const schemas = toSchema.getNamespaces();
227
- const fromSchema = options.fromSchema ?? (await DatabaseSchema.create(this.connection, this.platform, this.config, options.schema, schemas, undefined, this.options.skipTables, this.options.skipViews));
228
- const wildcardSchemaTables = [...this.metadata.getAll().values()].filter(meta => meta.schema === '*').map(meta => meta.tableName);
228
+ const fromSchema = options.fromSchema ??
229
+ (await DatabaseSchema.create(this.connection, this.platform, this.config, options.schema, schemas, undefined, this.options.skipTables, this.options.skipViews));
230
+ const wildcardSchemaTables = [...this.metadata.getAll().values()]
231
+ .filter(meta => meta.schema === '*')
232
+ .map(meta => meta.tableName);
229
233
  fromSchema.prune(options.schema, wildcardSchemaTables);
230
234
  toSchema.prune(options.schema, wildcardSchemaTables);
231
235
  return { fromSchema, toSchema };
@@ -408,7 +412,11 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
408
412
  return;
409
413
  }
410
414
  const statements = groups.flatMap(group => {
411
- return group.join('\n').split(';\n').map(s => s.trim()).filter(s => s);
415
+ return group
416
+ .join('\n')
417
+ .split(';\n')
418
+ .map(s => s.trim())
419
+ .filter(s => s);
412
420
  });
413
421
  await Utils.runSerial(statements, stmt => this.driver.execute(stmt));
414
422
  }
@@ -476,9 +484,7 @@ export class SqlSchemaGenerator extends AbstractSchemaGenerator {
476
484
  }
477
485
  // Check if the definition references the other view's name
478
486
  // Use word boundary matching to avoid false positives
479
- const patterns = [
480
- new RegExp(`\\b${this.escapeRegExp(otherView.name.toLowerCase())}\\b`),
481
- ];
487
+ const patterns = [new RegExp(`\\b${this.escapeRegExp(otherView.name.toLowerCase())}\\b`)];
482
488
  if (otherView.schema) {
483
489
  patterns.push(new RegExp(`\\b${this.escapeRegExp(`${otherView.schema}.${otherView.name}`.toLowerCase())}\\b`));
484
490
  }