From c783c61f391bea18f1cee30379b887b880f25a98 Mon Sep 17 00:00:00 2001 From: Vasil Rangelov Date: Tue, 28 Nov 2023 12:30:54 +0200 Subject: [PATCH] feat(entity-generator): detect more ManyToMany relations Auto increment columns in pivot entities are now detected. They are also now properly emitted. Corrected FK index selection to prefer indexes that match the columns exactly, and never associate the index with more columns to the property itself (instead using it at the entity level). This in turn ensures correctly identifying more ManyToOne relations, which in turn ensures correctly identifying more ManyToMany opportunities. In addition, by default, pivot tables are allowed to contain additional props, including relations, but only if those props would not hinder the ORM's ability to freely insert and remove records from the collection. In other words, those additional props need to be optional, and have defaults that are either null or non-unique. This can be adjusted with the two new settings onlyPurePivotTables and readOnlyPivotTables. Also optimized some of the tests a bit, to never drop the schema, and create it and its tables only if it doesn't exist already. The tests trust that if the schema exists, it will be in the expected state. The DB containers can be re-created if those schemas are changed. --- docs/docs/entity-generator.md | 2 + packages/core/src/metadata/EntitySchema.ts | 2 +- packages/core/src/typings.ts | 3 +- packages/core/src/utils/Configuration.ts | 6 +- .../entity-generator/src/EntityGenerator.ts | 118 +- packages/entity-generator/src/SourceFile.ts | 16 + packages/knex/src/schema/DatabaseTable.ts | 11 +- .../AmbiguousFks.mysql.test.ts | 19 +- .../EntityGenerator.mysql.test.ts | 1 + .../FkIndexSelection.mysql.test.ts | 19 +- .../FkSharedWithColumn.mysql.test.ts | 19 +- .../ManyToManyRelations.mysql.test.ts | 233 + .../NonCompositeAmbiguousFks.mysql.test.ts | 19 +- .../NullableFks.mysql.test.ts | 19 +- .../entity-generator/OverlapFks.mysql.test.ts | 20 +- .../RefToPivotTable.mysql.test.ts | 21 +- .../TypesForScalarDecorators.mysql.test.ts | 29 +- .../AmbiguousFks.mysql.test.ts.snap | 36 +- .../FkIndexSelection.mysql.test.ts.snap | 214 +- .../ManyToManyRelations.mysql.test.ts.snap | 3834 +++++++++++++++++ ...onCompositeAmbiguousFks.mysql.test.ts.snap | 48 +- .../OverlapFks.mysql.test.ts.snap | 88 +- .../index-expressions.mysql.test.ts.snap | 2 +- .../index-expressions.postgres.test.ts.snap | 2 +- .../index-expressions.mysql.test.ts | 12 +- .../index-expressions.postgres.test.ts | 11 +- .../index-expressions.sqlite.test.ts | 1 - 27 files changed, 4498 insertions(+), 307 deletions(-) create mode 100644 tests/features/entity-generator/ManyToManyRelations.mysql.test.ts create mode 100644 tests/features/entity-generator/__snapshots__/ManyToManyRelations.mysql.test.ts.snap diff --git a/docs/docs/entity-generator.md b/docs/docs/entity-generator.md index 2c9d089bebf5..780b6f72faee 100644 --- a/docs/docs/entity-generator.md +++ b/docs/docs/entity-generator.md @@ -82,6 +82,8 @@ Available options: | `esmImport: boolean` | By default, import statements for entities without extensions are used. If set to `true`, uses ESM style import for imported entities, i.e. adds a `.js` suffix as extension. | | `scalarTypeInDecorator: boolean` | If `true`, include the `type` option in scalar property decorators. This information is discovered at runtime, but the process of discovery can be skipped by including this option in the decorator. If using `EntitySchema`, this type information is always included. | | `scalarPropertiesForRelations: 'never' \| 'always' \| 'smart'` | | +| `onlyPurePivotTables: boolean` | By default, M:N relations are allowed to use pivot tables containing additional columns. If set to `true`, M:N relations will not be generated for such pivot tables. | +| `readOnlyPivotTables: boolean` | By default, M:N relations are only generated if the collection would be writable, i.e. any additional columns need to be optional and have non-unique default values. If set to `true`, also generate M:N relations even if the collection would be read only (meaning the only way to write to it is by using the pivot entity directly). Such collections will include the `persist: false` option. This setting is effectively meaningless if `onlyPurePivotTables` is set to `true`. | Example configuration: diff --git a/packages/core/src/metadata/EntitySchema.ts b/packages/core/src/metadata/EntitySchema.ts index 528ac17961e1..e3a303fd395d 100644 --- a/packages/core/src/metadata/EntitySchema.ts +++ b/packages/core/src/metadata/EntitySchema.ts @@ -358,7 +358,7 @@ export class EntitySchema { this._meta.simplePK = !this._meta.compositePK && pks[0].kind === ReferenceKind.SCALAR && !pks[0].customType; } - if (pks.length === 1 && pks[0].type === 'number') { + if (pks.length === 1 && ['number', 'bigint'].includes(pks[0].type)) { pks[0].autoincrement ??= true; } diff --git a/packages/core/src/typings.ts b/packages/core/src/typings.ts index 4831dc80bae1..2447c097bdd6 100644 --- a/packages/core/src/typings.ts +++ b/packages/core/src/typings.ts @@ -741,7 +741,8 @@ export interface GenerateOptions { scalarTypeInDecorator?: boolean; scalarPropertiesForRelations?: 'always' | 'never' | 'smart'; fileName?: (className: string) => string; -} + onlyPurePivotTables?: boolean; + readOnlyPivotTables?: boolean;} export interface IEntityGenerator { generate(options?: GenerateOptions): Promise; diff --git a/packages/core/src/utils/Configuration.ts b/packages/core/src/utils/Configuration.ts index 33342cf01a01..99b5666ca004 100644 --- a/packages/core/src/utils/Configuration.ts +++ b/packages/core/src/utils/Configuration.ts @@ -118,7 +118,8 @@ export class Configuration { scalarTypeInDecorator: false, scalarPropertiesForRelations: 'never', fileName: (className: string) => className, - }, + onlyPurePivotTables: false, + readOnlyPivotTables: false }, metadataCache: { pretty: false, adapter: FileCacheAdapter, @@ -592,7 +593,8 @@ export interface MikroORMOptions ex scalarTypeInDecorator?: boolean; scalarPropertiesForRelations?: 'always' | 'never' | 'smart'; fileName?: (className: string) => string; - }; + onlyPurePivotTables?: boolean; + readOnlyPivotTables?: boolean; }; metadataCache: { enabled?: boolean; combined?: boolean | string; diff --git a/packages/entity-generator/src/EntityGenerator.ts b/packages/entity-generator/src/EntityGenerator.ts index 4155b8ab5b97..4a305d6286e4 100644 --- a/packages/entity-generator/src/EntityGenerator.ts +++ b/packages/entity-generator/src/EntityGenerator.ts @@ -1,4 +1,3 @@ -import { ensureDir, writeFile } from 'fs-extra'; import { type EntityMetadata, type EntityProperty, @@ -17,8 +16,9 @@ import { type EntityManager, type SchemaHelper, } from '@mikro-orm/knex'; -import { SourceFile } from './SourceFile'; +import { ensureDir, writeFile } from 'fs-extra'; import { EntitySchemaSourceFile } from './EntitySchemaSourceFile'; +import { SourceFile } from './SourceFile'; export class EntityGenerator { @@ -97,7 +97,7 @@ export class EntityGenerator { metadata = metadata.filter(table => !options.skipTables || !options.skipTables.includes(table.tableName)); - this.detectManyToManyRelations(metadata); + this.detectManyToManyRelations(metadata, options.onlyPurePivotTables!, options.readOnlyPivotTables!); if (options.bidirectionalRelations) { this.generateBidirectionalRelations(metadata); @@ -110,7 +110,7 @@ export class EntityGenerator { return metadata; } - private detectManyToManyRelations(metadata: EntityMetadata[]): void { + private detectManyToManyRelations(metadata: EntityMetadata[], onlyPurePivotTables: boolean, readOnlyPivotTables: boolean): void { for (const meta of metadata) { const isReferenced = metadata.some(m => { return m.tableName !== meta.tableName && m.relations.some(r => { @@ -122,39 +122,100 @@ export class EntityGenerator { this.referencedEntities.add(meta); } + + // Entities with non-composite PKs are never pivot tables. Skip. + if (!meta.compositePK) { + continue; + } + + // Entities where there are not exactly 2 PK relations that are both ManyToOne are never pivot tables. Skip. + const pkRelations = meta.relations.filter(rel => rel.primary); if ( - meta.compositePK && // needs to have composite PK - meta.relations.length === 2 && // there are exactly two relation properties - !meta.relations.some(rel => !rel.primary || rel.kind !== ReferenceKind.MANY_TO_ONE) && // all relations are m:1 and PKs - ( - // all properties are relations... - meta.relations.length === meta.props.length - // ... or at least all fields involved are only the fields of the relations - || (new Set(meta.props.flatMap(prop => prop.fieldNames)).size === (new Set(meta.relations.flatMap(rel => rel.fieldNames)).size)) - ) + pkRelations.length !== 2 || + pkRelations.some(rel => rel.kind !== ReferenceKind.MANY_TO_ONE) ) { - meta.pivotTable = true; - const owner = metadata.find(m => m.className === meta.relations[0].type); + continue; + } + + const pkRelationFields = new Set(pkRelations.flatMap(rel => rel.fieldNames)); + const nonPkFields = Array.from(new Set(meta.props.flatMap(prop => prop.fieldNames))).filter(fieldName => !pkRelationFields.has(fieldName)); + + let fixedOrderColumn: string | undefined; + let isReadOnly = false; - if (!owner) { + // If there are any fields other than the ones in the two PK relations, table may or may not be a pivot one. + // Check further and skip on disqualification. + if (nonPkFields.length > 0) { + // Additional columns have been disabled with the setting. + // Skip table even it otherwise would have qualified as a pivot table. + if (onlyPurePivotTables) { continue; } - const name = this.namingStrategy.columnNameToProperty(meta.tableName.replace(new RegExp('^' + owner.tableName + '_'), '')); - const ownerProp = { - name, - kind: ReferenceKind.MANY_TO_MANY, - pivotTable: meta.tableName, - type: meta.relations[1].type, - joinColumns: meta.relations[0].fieldNames, - inverseJoinColumns: meta.relations[1].fieldNames, - } as EntityProperty; + const pkRelationNames = pkRelations.map(rel => rel.name); + let otherProps = meta.props + .filter(prop => !pkRelationNames.includes(prop.name) && + prop.persist !== false && // Skip checking non-persist props + prop.fieldNames.some(fieldName => nonPkFields.includes(fieldName)), + ); + + // Deal with the auto increment column first. That is the column used for fixed ordering, if present. + const autoIncrementProp = meta.props.find(prop => prop.autoincrement && prop.fieldNames.length === 1); + if (autoIncrementProp) { + otherProps = otherProps.filter(prop => prop !== autoIncrementProp); + fixedOrderColumn = autoIncrementProp.fieldNames[0]; + } - if (this.referencedEntities.has(meta)) { - ownerProp.pivotEntity = meta.className; + isReadOnly = otherProps.some(prop => { + // If the prop is non-nullable and unique, it will trivially end up causing issues. + // Mark as read only. + if (!prop.nullable && prop.unique) { + return true; + } + + // Any other props need to also be optional. + // Whether they have a default or are generated, + // we've already checked that not explicitly setting the property means the default is either NULL, + // or a non-unique non-null value, making it safe to write to pivot entity. + return !prop.optional; + }); + + if (isReadOnly && !readOnlyPivotTables) { + continue; + } + + // If this now proven pivot entity has persistent props other than the fixed order column, + // output it, by considering it as a referenced one. + if (otherProps.length > 0) { + this.referencedEntities.add(meta); } - owner.addProperty(ownerProp); } + + meta.pivotTable = true; + const owner = metadata.find(m => m.className === meta.relations[0].type)!; + + const name = this.namingStrategy.columnNameToProperty(meta.tableName.replace(new RegExp('^' + owner.tableName + '_'), '')); + const ownerProp = { + name, + kind: ReferenceKind.MANY_TO_MANY, + pivotTable: meta.tableName, + type: meta.relations[1].type, + joinColumns: meta.relations[0].fieldNames, + inverseJoinColumns: meta.relations[1].fieldNames, + } as EntityProperty; + + if (this.referencedEntities.has(meta)) { + ownerProp.pivotEntity = meta.className; + } + if (fixedOrderColumn) { + ownerProp.fixedOrder = true; + ownerProp.fixedOrderColumn = fixedOrderColumn; + } + if (isReadOnly) { + ownerProp.persist = false; + } + + owner.addProperty(ownerProp); } } @@ -169,6 +230,7 @@ export class EntityGenerator { referencedTableName: meta.tableName, referencedColumnNames: Utils.flatten(targetMeta.getPrimaryProps().map(pk => pk.fieldNames)), mappedBy: prop.name, + persist: prop.persist, } as EntityProperty; if (prop.kind === ReferenceKind.MANY_TO_ONE) { diff --git a/packages/entity-generator/src/SourceFile.ts b/packages/entity-generator/src/SourceFile.ts index d56e7539f234..27eca13ba786 100644 --- a/packages/entity-generator/src/SourceFile.ts +++ b/packages/entity-generator/src/SourceFile.ts @@ -334,6 +334,15 @@ export class SourceFile { assign('precision'); assign('scale'); } + if (prop.autoincrement) { + if (!prop.primary || !['number', 'bigint'].includes(t) || this.meta.getPrimaryProps().length !== 1) { + options.autoincrement = true; + } + } else { + if (prop.primary && ['number', 'bigint'].includes(t) && this.meta.getPrimaryProps().length === 1) { + options.autoincrement = false; + } + } } protected getManyToManyDecoratorOptions(options: Dictionary, prop: EntityProperty) { @@ -365,6 +374,13 @@ export class SourceFile { } else { options.inverseJoinColumns = `[${prop.inverseJoinColumns.map(this.quote).join(', ')}]`; } + + if (prop.fixedOrder) { + options.fixedOrder = true; + if (prop.fixedOrderColumn && prop.fixedOrderColumn !== this.namingStrategy.referenceColumnName()) { + options.fixedOrderColumn = this.quote(prop.fixedOrderColumn); + } + } } protected getOneToManyDecoratorOptions(options: Dictionary, prop: EntityProperty) { diff --git a/packages/knex/src/schema/DatabaseTable.ts b/packages/knex/src/schema/DatabaseTable.ts index 9fc2a41525e8..c5e30623c665 100644 --- a/packages/knex/src/schema/DatabaseTable.ts +++ b/packages/knex/src/schema/DatabaseTable.ts @@ -226,7 +226,7 @@ export class DatabaseTable { // Index is for FK. Map to the FK prop and move on. const fkForIndex = fkIndexes.get(index); - if (fkForIndex) { + if (fkForIndex && !fkForIndex.fk.columnNames.some(col => !index.columnNames.includes(col))) { ret.properties = [this.getPropertyName(namingStrategy, fkForIndex.baseName, fkForIndex.fk)]; const map = index.unique ? compositeFkUniques : compositeFkIndexes; map[ret.properties[0]] = { keyName: index.keyName }; @@ -438,6 +438,10 @@ export class DatabaseTable { return index.columnNames.length >= fkColumnsLength && !currentFk.columnNames.some((columnName, i) => index.columnNames[i] !== columnName); }); possibleIndexes.sort((a, b) => { + if (a.columnNames.length !== b.columnNames.length) { + return a.columnNames.length < b.columnNames.length ? -1 : 1; + } + if (a.primary !== b.primary) { return a.primary ? -1 : 1; } @@ -446,10 +450,6 @@ export class DatabaseTable { return a.unique ? -1 : 1; } - if (a.columnNames.length !== b.columnNames.length) { - return a.columnNames.length < b.columnNames.length ? -1 : 1; - } - return a.keyName.localeCompare(b.keyName); }); @@ -661,6 +661,7 @@ export class DatabaseTable { defaultRaw: this.getPropertyDefaultValue(schemaHelper, column, type, true), nullable: column.nullable, primary: column.primary && persist, + autoincrement: column.autoincrement, fieldName: column.name, length: column.length, precision: column.precision, diff --git a/tests/features/entity-generator/AmbiguousFks.mysql.test.ts b/tests/features/entity-generator/AmbiguousFks.mysql.test.ts index ad3b1c0bec09..f58ce71233eb 100644 --- a/tests/features/entity-generator/AmbiguousFks.mysql.test.ts +++ b/tests/features/entity-generator/AmbiguousFks.mysql.test.ts @@ -169,8 +169,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -188,18 +191,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); - describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/EntityGenerator.mysql.test.ts b/tests/features/entity-generator/EntityGenerator.mysql.test.ts index 70f84fede762..3e0a90df06e5 100644 --- a/tests/features/entity-generator/EntityGenerator.mysql.test.ts +++ b/tests/features/entity-generator/EntityGenerator.mysql.test.ts @@ -9,6 +9,7 @@ describe('EntityGenerator', () => { const orm = await initORMMySql('mysql', {}, true); const dump = await orm.entityGenerator.generate({ save: true, path: './temp/entities' }); expect(dump).toMatchSnapshot('mysql-entity-dump'); + await expect(pathExists('./temp/entities/Author2.ts')).resolves.toBe(true); await remove('./temp/entities'); diff --git a/tests/features/entity-generator/FkIndexSelection.mysql.test.ts b/tests/features/entity-generator/FkIndexSelection.mysql.test.ts index 6ee5ff823ca9..de3085bcb88a 100644 --- a/tests/features/entity-generator/FkIndexSelection.mysql.test.ts +++ b/tests/features/entity-generator/FkIndexSelection.mysql.test.ts @@ -49,8 +49,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -68,18 +71,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); - describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/FkSharedWithColumn.mysql.test.ts b/tests/features/entity-generator/FkSharedWithColumn.mysql.test.ts index 4041678d3fd3..21e92b29bdba 100644 --- a/tests/features/entity-generator/FkSharedWithColumn.mysql.test.ts +++ b/tests/features/entity-generator/FkSharedWithColumn.mysql.test.ts @@ -53,8 +53,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -72,18 +75,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); - describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/ManyToManyRelations.mysql.test.ts b/tests/features/entity-generator/ManyToManyRelations.mysql.test.ts new file mode 100644 index 000000000000..441a12b56095 --- /dev/null +++ b/tests/features/entity-generator/ManyToManyRelations.mysql.test.ts @@ -0,0 +1,233 @@ +import { MikroORM } from '@mikro-orm/mysql'; +import { EntityGenerator } from '@mikro-orm/entity-generator'; + +let orm: MikroORM; + +const schemaName = 'many_to_many_variants'; +const schema = ` +CREATE TABLE IF NOT EXISTS \`users\` ( + \`user_id\` INT UNSIGNED NOT NULL AUTO_INCREMENT, + \`name\` VARCHAR(255) NOT NULL, + PRIMARY KEY (\`user_id\`), + UNIQUE INDEX \`name_UNIQUE\` (\`name\` ASC) VISIBLE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`flags\` ( + \`flag_id\` INT UNSIGNED NOT NULL, + \`name\` VARCHAR(255) NOT NULL, + PRIMARY KEY (\`flag_id\`), + UNIQUE INDEX \`name_UNIQUE\` (\`name\` ASC) VISIBLE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_flags\` ( + \`user_id\` INT UNSIGNED NOT NULL, + \`flag_id\` INT UNSIGNED NOT NULL, + PRIMARY KEY (\`user_id\`, \`flag_id\`), + INDEX \`fk_user_flags_flags1_idx\` (\`flag_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_flags_users\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT \`fk_user_flags_flags1\` + FOREIGN KEY (\`flag_id\`) + REFERENCES \`flags\` (\`flag_id\`) + ON DELETE RESTRICT + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`emails\` ( + \`email_id\` INT UNSIGNED NOT NULL AUTO_INCREMENT, + \`address\` VARCHAR(255) NOT NULL, + PRIMARY KEY (\`email_id\`), + UNIQUE INDEX \`address_UNIQUE\` (\`address\` ASC) VISIBLE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_emails\` ( + \`user_id\` INT UNSIGNED NOT NULL, + \`email_id\` INT UNSIGNED NOT NULL, + \`is_verified\` TINYINT(1) NOT NULL DEFAULT 0, + PRIMARY KEY (\`user_id\`, \`email_id\`), + INDEX \`fk_user_emails_emails1_idx\` (\`email_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_emails_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT \`fk_user_emails_emails1\` + FOREIGN KEY (\`email_id\`) + REFERENCES \`emails\` (\`email_id\`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_email_avatars\` ( + \`user_id\` INT UNSIGNED NOT NULL, + \`email_id\` INT UNSIGNED NOT NULL, + \`avatar_url\` VARCHAR(255) NOT NULL, + PRIMARY KEY (\`user_id\`, \`email_id\`), + INDEX \`fk_user_email_avatars_emails1_idx\` (\`email_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_email_avatars_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT \`fk_user_email_avatars_emails1\` + FOREIGN KEY (\`email_id\`) + REFERENCES \`emails\` (\`email_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`orders\` ( + \`order_id\` INT UNSIGNED NOT NULL AUTO_INCREMENT, + \`name\` VARCHAR(255) NOT NULL, + PRIMARY KEY (\`order_id\`)) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_orders\` ( + \`user_id\` INT UNSIGNED NOT NULL, + \`order_id\` INT UNSIGNED NOT NULL, + \`priority\` INT UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (\`user_id\`, \`order_id\`), + UNIQUE INDEX \`priority_UNIQUE\` (\`priority\` ASC) VISIBLE, + INDEX \`fk_user_orders_orders1_idx\` (\`order_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_orders_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE NO ACTION + ON UPDATE RESTRICT, + CONSTRAINT \`fk_user_orders_orders1\` + FOREIGN KEY (\`order_id\`) + REFERENCES \`orders\` (\`order_id\`) + ON DELETE CASCADE + ON UPDATE CASCADE) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`completed_orders\` ( + \`id\` INT UNSIGNED NOT NULL AUTO_INCREMENT, + \`user_id\` INT UNSIGNED NOT NULL, + \`order_id\` INT UNSIGNED NOT NULL, + PRIMARY KEY (\`id\`), + INDEX \`fk_completed_orders_users1_idx\` (\`user_id\` ASC) VISIBLE, + INDEX \`fk_completed_orders_orders1_idx\` (\`order_id\` ASC) VISIBLE, + UNIQUE INDEX \`user_id__order_id_unique\` (\`user_id\` ASC, \`order_id\` ASC) VISIBLE, + CONSTRAINT \`fk_completed_orders_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT \`fk_completed_orders_orders1\` + FOREIGN KEY (\`order_id\`) + REFERENCES \`orders\` (\`order_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_email_orders\` ( + \`user_id\` INT UNSIGNED NOT NULL, + \`email_id\` INT UNSIGNED NOT NULL, + \`order_id\` INT UNSIGNED NOT NULL, + PRIMARY KEY (\`user_id\`, \`email_id\`), + INDEX \`fk_user_email_orders_emails1_idx\` (\`email_id\` ASC) VISIBLE, + INDEX \`fk_user_email_orders_orders1_idx\` (\`order_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_email_orders_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT \`fk_user_email_orders_emails1\` + FOREIGN KEY (\`email_id\`) + REFERENCES \`emails\` (\`email_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT \`fk_user_email_orders_orders1\` + FOREIGN KEY (\`order_id\`) + REFERENCES \`orders\` (\`order_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION) +ENGINE = InnoDB; + +CREATE TABLE IF NOT EXISTS \`user_email_flags\` +( + \`user_id\` INT UNSIGNED NOT NULL, + \`email_id\` INT UNSIGNED NOT NULL, + \`flag_id\` INT UNSIGNED NOT NULL DEFAULT 1, + PRIMARY KEY (\`user_id\`, \`email_id\`), + INDEX \`fk_user_email_flags_emails1_idx\` (\`email_id\` ASC) VISIBLE, + INDEX \`fk_user_email_flags_flags1_idx\` (\`flag_id\` ASC) VISIBLE, + UNIQUE INDEX \`flag_id_UNIQUE\` (\`flag_id\` ASC) VISIBLE, + CONSTRAINT \`fk_user_email_flags_users1\` + FOREIGN KEY (\`user_id\`) + REFERENCES \`users\` (\`user_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT \`fk_user_email_flags_emails1\` + FOREIGN KEY (\`email_id\`) + REFERENCES \`emails\` (\`email_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION, + CONSTRAINT \`fk_user_email_flags_flags1\` + FOREIGN KEY (\`flag_id\`) + REFERENCES \`flags\` (\`flag_id\`) + ON DELETE NO ACTION + ON UPDATE NO ACTION +) + ENGINE = InnoDB; + `; + +beforeAll(async () => { + orm = await MikroORM.init({ + dbName: schemaName, + port: 3308, + discovery: { warnWhenNoEntities: false }, + extensions: [EntityGenerator], + multipleStatements: true, + }); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } + await orm.close(true); +}); + +beforeEach(async () => { + orm = await MikroORM.init({ + dbName: schemaName, + port: 3308, + discovery: { warnWhenNoEntities: false }, + extensions: [EntityGenerator], + multipleStatements: true, + }); +}); + +afterEach(async () => { + await orm.close(true); +}); + +describe(schemaName, () => { + describe.each([true, false])('bidirectionalRelations=%s', bidirectionalRelations => { + beforeEach(() => { + orm.config.get('entityGenerator').bidirectionalRelations = bidirectionalRelations; + }); + describe.each([true, false])('onlyPurePivotTables=%s', onlyPurePivotTables => { + beforeEach(() => { + orm.config.get('entityGenerator').onlyPurePivotTables = onlyPurePivotTables; + }); + + describe.each([true, false])('readOnlyPivotTables=%s', readOnlyPivotTables => { + beforeEach(() => { + orm.config.get('entityGenerator').readOnlyPivotTables = readOnlyPivotTables; + }); + + test.each([true, false])('entitySchema=%s', async entitySchema => { + orm.config.get('entityGenerator').entitySchema = entitySchema; + + const dump = await orm.entityGenerator.generate(); + expect(dump).toMatchSnapshot('dump'); + }); + }); + }); + }); +}); diff --git a/tests/features/entity-generator/NonCompositeAmbiguousFks.mysql.test.ts b/tests/features/entity-generator/NonCompositeAmbiguousFks.mysql.test.ts index 8f39233aa213..aee646cf62ae 100644 --- a/tests/features/entity-generator/NonCompositeAmbiguousFks.mysql.test.ts +++ b/tests/features/entity-generator/NonCompositeAmbiguousFks.mysql.test.ts @@ -77,8 +77,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -96,18 +99,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); - describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/NullableFks.mysql.test.ts b/tests/features/entity-generator/NullableFks.mysql.test.ts index da6ce2f7d0cb..b398f4556a59 100644 --- a/tests/features/entity-generator/NullableFks.mysql.test.ts +++ b/tests/features/entity-generator/NullableFks.mysql.test.ts @@ -96,8 +96,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -115,18 +118,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); - describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/OverlapFks.mysql.test.ts b/tests/features/entity-generator/OverlapFks.mysql.test.ts index 76c65740a14c..a9ced2a0a37b 100644 --- a/tests/features/entity-generator/OverlapFks.mysql.test.ts +++ b/tests/features/entity-generator/OverlapFks.mysql.test.ts @@ -48,6 +48,8 @@ CREATE TABLE IF NOT EXISTS \`product_country_map\` ( \`product_id\` INT UNSIGNED NOT NULL, \`is_currently_allowed\` TINYINT(1) NOT NULL DEFAULT 0, PRIMARY KEY (\`country\`, \`product_id\`), + INDEX \`full_idx\` (\`country\` ASC, \`product_id\` ASC, \`is_currently_allowed\` ASC) VISIBLE, + INDEX \`primary_reindex_idx\` (\`country\` ASC, \`product_id\` ASC) VISIBLE, CONSTRAINT \`fk_product_country_map_products1\` FOREIGN KEY (\`product_id\`) REFERENCES \`products\` (\`product_id\`) @@ -92,8 +94,11 @@ beforeAll(async () => { extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(schema); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(schema); + } await orm.close(true); }); @@ -111,17 +116,6 @@ afterEach(async () => { await orm.close(true); }); -afterAll(async () => { - orm = await MikroORM.init({ - dbName: schemaName, - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.dropDatabase(); - await orm.close(true); -}); describe(schemaName, () => { describe.each(['never', 'always', 'smart'])('scalarPropertiesForRelations=%s', i => { const scalarPropertiesForRelations = i as NonNullable; diff --git a/tests/features/entity-generator/RefToPivotTable.mysql.test.ts b/tests/features/entity-generator/RefToPivotTable.mysql.test.ts index e1a9a4b23678..5f102887d809 100644 --- a/tests/features/entity-generator/RefToPivotTable.mysql.test.ts +++ b/tests/features/entity-generator/RefToPivotTable.mysql.test.ts @@ -2,24 +2,20 @@ import { MikroORM } from '@mikro-orm/mysql'; import { EntityGenerator } from '@mikro-orm/entity-generator'; let orm: MikroORM; -beforeAll(async () => { + +test('RefToPivotTable', async () => { + const schemaName = 'pivot_ref_examples'; orm = await MikroORM.init({ - dbName: 'pivot_ref_examples', + dbName: schemaName, port: 3308, discovery: { warnWhenNoEntities: false }, extensions: [EntityGenerator], multipleStatements: true, }); - await orm.schema.ensureDatabase(); -}); - -afterAll(async () => { - await orm.schema.dropDatabase(); - await orm.close(true); -}); - -test('RefToPivotTable', async () => { - await orm.schema.execute(` + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(` CREATE TABLE IF NOT EXISTS \`sender\` ( \`sender_id\` SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT, \`name\` VARCHAR(255) NOT NULL, @@ -71,6 +67,7 @@ CREATE TABLE IF NOT EXISTS \`email_messages_log\` ( ON UPDATE CASCADE) ENGINE = InnoDB; `); + } const dump = await orm.entityGenerator.generate(); expect(dump).toMatchSnapshot('mysql-entity-dump'); }); diff --git a/tests/features/entity-generator/TypesForScalarDecorators.mysql.test.ts b/tests/features/entity-generator/TypesForScalarDecorators.mysql.test.ts index 5673bc3816d6..d3ce78dd0416 100644 --- a/tests/features/entity-generator/TypesForScalarDecorators.mysql.test.ts +++ b/tests/features/entity-generator/TypesForScalarDecorators.mysql.test.ts @@ -2,25 +2,21 @@ import { EntityGenerator } from '@mikro-orm/entity-generator'; import { MikroORM } from '@mikro-orm/mysql'; let orm: MikroORM; -beforeAll(async () => { - orm = await MikroORM.init({ - dbName: 'types_for_scalar_decorators', - port: 3308, - discovery: { warnWhenNoEntities: false }, - extensions: [EntityGenerator], - multipleStatements: true, - }); - await orm.schema.ensureDatabase(); -}); - -afterAll(async () => { - await orm.schema.dropDatabase(); - await orm.close(true); -}); describe('TypesForScalarDecorators', () => { test('generate entities from schema [mysql]', async () => { - await orm.schema.execute(` + const schemaName = 'types_for_scalar_decorators'; + orm = await MikroORM.init({ + dbName: schemaName, + port: 3308, + discovery: { warnWhenNoEntities: false }, + extensions: [EntityGenerator], + multipleStatements: true, + }); + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(` CREATE TABLE IF NOT EXISTS \`users\` ( \`user_id\` INT UNSIGNED NOT NULL AUTO_INCREMENT, @@ -31,6 +27,7 @@ CREATE TABLE IF NOT EXISTS \`users\` PRIMARY KEY (\`user_id\`) ) `); + } orm.config.get('entityGenerator').scalarTypeInDecorator = true; const dump = await orm.entityGenerator.generate(); expect(dump).toMatchSnapshot('dump'); diff --git a/tests/features/entity-generator/__snapshots__/AmbiguousFks.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/AmbiguousFks.mysql.test.ts.snap index 24196a33069d..707a3f4a5e91 100644 --- a/tests/features/entity-generator/__snapshots__/AmbiguousFks.mysql.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/AmbiguousFks.mysql.test.ts.snap @@ -54,7 +54,7 @@ export class ProductColors { product!: Products; @Index({ name: 'fk_product_colors_products1_idx' }) - @Property({ persist: false }) + @Property({ autoincrement: true, persist: false }) productId!: number; } @@ -320,7 +320,12 @@ export const ProductColorsSchema = new EntitySchema({ fieldName: 'product_id', index: 'fk_product_colors_products1_idx', }, - productId: { type: 'number', persist: false, index: 'fk_product_colors_products1_idx' }, + productId: { + type: 'number', + autoincrement: true, + persist: false, + index: 'fk_product_colors_products1_idx', + }, }, }); ", @@ -638,7 +643,7 @@ export class ProductColors { product!: Ref; @Index({ name: 'fk_product_colors_products1_idx' }) - @Property({ persist: false }) + @Property({ autoincrement: true, persist: false }) productId!: number; } @@ -913,7 +918,12 @@ export const ProductColorsSchema = new EntitySchema({ fieldName: 'product_id', index: 'fk_product_colors_products1_idx', }, - productId: { type: 'number', persist: false, index: 'fk_product_colors_products1_idx' }, + productId: { + type: 'number', + autoincrement: true, + persist: false, + index: 'fk_product_colors_products1_idx', + }, }, }); ", @@ -1292,7 +1302,7 @@ export class ProductColors { product!: Products; @Index({ name: 'fk_product_colors_products1_idx' }) - @Property({ persist: false }) + @Property({ autoincrement: true, persist: false }) productId!: number; @OneToMany({ entity: () => Sales, mappedBy: 'color' }) @@ -1612,7 +1622,12 @@ export const ProductColorsSchema = new EntitySchema({ fieldName: 'product_id', index: 'fk_product_colors_products1_idx', }, - productId: { type: 'number', persist: false, index: 'fk_product_colors_products1_idx' }, + productId: { + type: 'number', + autoincrement: true, + persist: false, + index: 'fk_product_colors_products1_idx', + }, colorInverse: { kind: '1:m', entity: () => Sales, mappedBy: 'color' }, }, }); @@ -1976,7 +1991,7 @@ export class ProductColors { product!: Ref; @Index({ name: 'fk_product_colors_products1_idx' }) - @Property({ persist: false }) + @Property({ autoincrement: true, persist: false }) productId!: number; @OneToMany({ entity: () => Sales, mappedBy: 'color' }) @@ -2305,7 +2320,12 @@ export const ProductColorsSchema = new EntitySchema({ fieldName: 'product_id', index: 'fk_product_colors_products1_idx', }, - productId: { type: 'number', persist: false, index: 'fk_product_colors_products1_idx' }, + productId: { + type: 'number', + autoincrement: true, + persist: false, + index: 'fk_product_colors_products1_idx', + }, colorInverse: { kind: '1:m', entity: () => Sales, mappedBy: 'color' }, }, }); diff --git a/tests/features/entity-generator/__snapshots__/FkIndexSelection.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/FkIndexSelection.mysql.test.ts.snap index 99138ba51543..4ec90b283b6e 100644 --- a/tests/features/entity-generator/__snapshots__/FkIndexSelection.mysql.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/FkIndexSelection.mysql.test.ts.snap @@ -32,11 +32,12 @@ export class FashionableColors { } ", - "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }) +@Unique({ name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -47,7 +48,6 @@ export class Users { @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; - @Index({ name: 'fk_users_cars_idx' }) @Property({ length: 255, nullable: true, persist: false }) favoriteCarBrand?: string; @@ -116,6 +116,9 @@ export const UsersSchema = new EntitySchema({ indexes: [ { name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }, ], + uniques: [ + { name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }, + ], properties: { userId: { primary: true, type: 'number' }, favorite: { @@ -128,13 +131,7 @@ export const UsersSchema = new EntitySchema({ nullable: true, index: 'fk_users_fashionable_colors1_idx', }, - favoriteCarBrand: { - type: 'string', - length: 255, - nullable: true, - persist: false, - index: 'fk_users_cars_idx', - }, + favoriteCarBrand: { type: 'string', length: 255, nullable: true, persist: false }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteColor: { type: 'string', length: 255, nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -176,11 +173,12 @@ export class FashionableColors { } ", - "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }) +@Unique({ name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -191,7 +189,6 @@ export class Users { @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; - @Index({ name: 'fk_users_cars_idx' }) @Property({ length: 255, nullable: true, persist: false }) favoriteCarBrand?: string; @@ -261,6 +258,9 @@ export const UsersSchema = new EntitySchema({ indexes: [ { name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }, ], + uniques: [ + { name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }, + ], properties: { userId: { primary: true, type: 'number' }, favorite: { @@ -274,13 +274,7 @@ export const UsersSchema = new EntitySchema({ nullable: true, index: 'fk_users_fashionable_colors1_idx', }, - favoriteCarBrand: { - type: 'string', - length: 255, - nullable: true, - persist: false, - index: 'fk_users_cars_idx', - }, + favoriteCarBrand: { type: 'string', length: 255, nullable: true, persist: false }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteColor: { type: 'string', length: 255, nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -326,11 +320,12 @@ export class FashionableColors { } ", - "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }) +@Unique({ name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -341,7 +336,6 @@ export class Users { @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; - @Index({ name: 'fk_users_cars_idx' }) @Property({ length: 255, nullable: true, persist: false }) favoriteCarBrand?: string; @@ -413,6 +407,9 @@ export const UsersSchema = new EntitySchema({ indexes: [ { name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }, ], + uniques: [ + { name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }, + ], properties: { userId: { primary: true, type: 'number' }, favorite: { @@ -425,13 +422,7 @@ export const UsersSchema = new EntitySchema({ nullable: true, index: 'fk_users_fashionable_colors1_idx', }, - favoriteCarBrand: { - type: 'string', - length: 255, - nullable: true, - persist: false, - index: 'fk_users_cars_idx', - }, + favoriteCarBrand: { type: 'string', length: 255, nullable: true, persist: false }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteColor: { type: 'string', length: 255, nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -477,11 +468,12 @@ export class FashionableColors { } ", - "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }) +@Unique({ name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -492,7 +484,6 @@ export class Users { @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; - @Index({ name: 'fk_users_cars_idx' }) @Property({ length: 255, nullable: true, persist: false }) favoriteCarBrand?: string; @@ -565,6 +556,9 @@ export const UsersSchema = new EntitySchema({ indexes: [ { name: 'favorites_idx', properties: ['favoriteColor', 'favoriteBook'] }, ], + uniques: [ + { name: 'when_set_unique', properties: ['favoriteCarBrand', 'favoriteColor'] }, + ], properties: { userId: { primary: true, type: 'number' }, favorite: { @@ -578,13 +572,7 @@ export const UsersSchema = new EntitySchema({ nullable: true, index: 'fk_users_fashionable_colors1_idx', }, - favoriteCarBrand: { - type: 'string', - length: 255, - nullable: true, - persist: false, - index: 'fk_users_cars_idx', - }, + favoriteCarBrand: { type: 'string', length: 255, nullable: true, persist: false }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteColor: { type: 'string', length: 255, nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -626,12 +614,12 @@ export class FashionableColors { } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -639,7 +627,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; @Property({ length: 255, nullable: true }) @@ -697,12 +685,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, fieldNames: [ 'favorite_car_year', @@ -710,7 +700,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteBook: { type: 'string', length: 255, nullable: true }, }, @@ -751,12 +740,12 @@ export class FashionableColors { } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -764,7 +753,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; @Property({ length: 255, nullable: true }) @@ -823,12 +812,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, ref: true, fieldNames: [ @@ -837,7 +828,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteBook: { type: 'string', length: 255, nullable: true }, }, @@ -863,7 +853,7 @@ export class Cars { } ", - "import { Entity, OneToOne, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; @Entity() @@ -877,17 +867,17 @@ export class FashionableColors { @PrimaryKey({ length: 255 }) color!: string; - @OneToOne({ entity: () => Users, mappedBy: 'favorite' }) - favoriteInverse?: Users; + @OneToMany({ entity: () => Users, mappedBy: 'favorite' }) + favoriteInverse = new Collection(this); } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -895,7 +885,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; @Property({ length: 255, nullable: true }) @@ -924,13 +914,14 @@ export const CarsSchema = new EntitySchema({ }, }); ", - "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; export class FashionableColors { [PrimaryKeyProp]?: ['year', 'color']; year!: unknown; color!: string; - favoriteInverse?: Users; + favoriteInverse = new Collection(this); } export const FashionableColorsSchema = new EntitySchema({ @@ -938,7 +929,7 @@ export const FashionableColorsSchema = new EntitySchema({ properties: { year: { primary: true, type: 'unknown', columnType: 'year' }, color: { primary: true, type: 'string', length: 255 }, - favoriteInverse: { kind: '1:1', entity: () => Users, mappedBy: 'favorite' }, + favoriteInverse: { kind: '1:m', entity: () => Users, mappedBy: 'favorite' }, }, }); ", @@ -955,12 +946,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, fieldNames: [ 'favorite_car_year', @@ -968,7 +961,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteBook: { type: 'string', length: 255, nullable: true }, }, @@ -994,7 +986,7 @@ export class Cars { } ", - "import { Entity, OneToOne, PrimaryKey, PrimaryKeyProp, Ref } from '@mikro-orm/core'; + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; @Entity() @@ -1008,17 +1000,17 @@ export class FashionableColors { @PrimaryKey({ length: 255 }) color!: string; - @OneToOne({ entity: () => Users, ref: true, mappedBy: 'favorite' }) - favoriteInverse?: Ref; + @OneToMany({ entity: () => Users, mappedBy: 'favorite' }) + favoriteInverse = new Collection(this); } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -1026,7 +1018,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; @Property({ length: 255, nullable: true }) @@ -1055,14 +1047,14 @@ export const CarsSchema = new EntitySchema({ }, }); ", - "import { EntitySchema, PrimaryKeyProp, Ref } from '@mikro-orm/core'; + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; export class FashionableColors { [PrimaryKeyProp]?: ['year', 'color']; year!: unknown; color!: string; - favoriteInverse?: Ref; + favoriteInverse = new Collection(this); } export const FashionableColorsSchema = new EntitySchema({ @@ -1070,7 +1062,7 @@ export const FashionableColorsSchema = new EntitySchema({ properties: { year: { primary: true, type: 'unknown', columnType: 'year' }, color: { primary: true, type: 'string', length: 255 }, - favoriteInverse: { kind: '1:1', entity: () => Users, ref: true, mappedBy: 'favorite' }, + favoriteInverse: { kind: '1:m', entity: () => Users, mappedBy: 'favorite' }, }, }); ", @@ -1088,12 +1080,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, ref: true, fieldNames: [ @@ -1102,7 +1096,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteBook: { type: 'string', length: 255, nullable: true }, }, @@ -1143,12 +1136,12 @@ export class FashionableColors { } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -1156,7 +1149,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; @Property({ columnType: 'year', nullable: true, persist: false }) @@ -1218,12 +1211,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, fieldNames: [ 'favorite_car_year', @@ -1231,7 +1226,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -1273,12 +1267,12 @@ export class FashionableColors { } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -1286,7 +1280,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; @Property({ columnType: 'year', nullable: true, persist: false }) @@ -1349,12 +1343,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, ref: true, fieldNames: [ @@ -1363,7 +1359,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -1390,7 +1385,7 @@ export class Cars { } ", - "import { Entity, OneToOne, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; @Entity() @@ -1404,17 +1399,17 @@ export class FashionableColors { @PrimaryKey({ length: 255 }) color!: string; - @OneToOne({ entity: () => Users, mappedBy: 'favorite' }) - favoriteInverse?: Users; + @OneToMany({ entity: () => Users, mappedBy: 'favorite' }) + favoriteInverse = new Collection(this); } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -1422,7 +1417,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: FashionableColors; @Property({ columnType: 'year', nullable: true, persist: false }) @@ -1454,13 +1449,14 @@ export const CarsSchema = new EntitySchema({ }, }); ", - "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; export class FashionableColors { [PrimaryKeyProp]?: ['year', 'color']; year!: unknown; color!: string; - favoriteInverse?: Users; + favoriteInverse = new Collection(this); } export const FashionableColorsSchema = new EntitySchema({ @@ -1468,7 +1464,7 @@ export const FashionableColorsSchema = new EntitySchema({ properties: { year: { primary: true, type: 'unknown', columnType: 'year' }, color: { primary: true, type: 'string', length: 255 }, - favoriteInverse: { kind: '1:1', entity: () => Users, mappedBy: 'favorite' }, + favoriteInverse: { kind: '1:m', entity: () => Users, mappedBy: 'favorite' }, }, }); ", @@ -1486,12 +1482,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, fieldNames: [ 'favorite_car_year', @@ -1499,7 +1497,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, @@ -1526,7 +1523,7 @@ export class Cars { } ", - "import { Entity, OneToOne, PrimaryKey, PrimaryKeyProp, Ref } from '@mikro-orm/core'; + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; @Entity() @@ -1540,17 +1537,17 @@ export class FashionableColors { @PrimaryKey({ length: 255 }) color!: string; - @OneToOne({ entity: () => Users, ref: true, mappedBy: 'favorite' }) - favoriteInverse?: Ref; + @OneToMany({ entity: () => Users, mappedBy: 'favorite' }) + favoriteInverse = new Collection(this); } ", - "import { Entity, Index, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, PrimaryKey, PrimaryKeyProp, Property, Ref, Unique } from '@mikro-orm/core'; import { FashionableColors } from './FashionableColors'; @Entity() @Index({ name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }) -@Index({ name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }) +@Unique({ name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }) export class Users { [PrimaryKeyProp]?: 'userId'; @@ -1558,7 +1555,7 @@ export class Users { @PrimaryKey() userId!: number; - @OneToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx', unique: 'when_set_unique' }) + @ManyToOne({ entity: () => FashionableColors, ref: true, fieldNames: ['favorite_car_year', 'favorite_color'], nullable: true, index: 'fk_users_fashionable_colors1_idx' }) favorite?: Ref; @Property({ columnType: 'year', nullable: true, persist: false }) @@ -1590,14 +1587,14 @@ export const CarsSchema = new EntitySchema({ }, }); ", - "import { EntitySchema, PrimaryKeyProp, Ref } from '@mikro-orm/core'; + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; import { Users } from './Users'; export class FashionableColors { [PrimaryKeyProp]?: ['year', 'color']; year!: unknown; color!: string; - favoriteInverse?: Ref; + favoriteInverse = new Collection(this); } export const FashionableColorsSchema = new EntitySchema({ @@ -1605,7 +1602,7 @@ export const FashionableColorsSchema = new EntitySchema({ properties: { year: { primary: true, type: 'unknown', columnType: 'year' }, color: { primary: true, type: 'string', length: 255 }, - favoriteInverse: { kind: '1:1', entity: () => Users, ref: true, mappedBy: 'favorite' }, + favoriteInverse: { kind: '1:m', entity: () => Users, mappedBy: 'favorite' }, }, }); ", @@ -1624,12 +1621,14 @@ export const UsersSchema = new EntitySchema({ class: Users, indexes: [ { name: 'favorites_idx', expression: 'create index \`favorites_idx\` on \`users\` (\`favorite_car_year\`, \`favorite_color\`, \`favorite_book\`)' }, - { name: 'fk_users_cars_idx', expression: 'create index \`fk_users_cars_idx\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`)' }, + ], + uniques: [ + { name: 'when_set_unique', expression: 'create unique index \`when_set_unique\` on \`users\` (\`favorite_car_brand\`, \`favorite_car_year\`, \`favorite_color\`)' }, ], properties: { userId: { primary: true, type: 'number' }, favorite: { - kind: '1:1', + kind: 'm:1', entity: () => FashionableColors, ref: true, fieldNames: [ @@ -1638,7 +1637,6 @@ export const UsersSchema = new EntitySchema({ ], nullable: true, index: 'fk_users_fashionable_colors1_idx', - unique: 'when_set_unique', }, favoriteCarYear: { type: 'unknown', columnType: 'year', nullable: true, persist: false }, favoriteBook: { type: 'string', length: 255, nullable: true }, diff --git a/tests/features/entity-generator/__snapshots__/ManyToManyRelations.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/ManyToManyRelations.mysql.test.ts.snap new file mode 100644 index 000000000000..34cfbff7a547 --- /dev/null +++ b/tests/features/entity-generator/__snapshots__/ManyToManyRelations.mysql.test.ts.snap @@ -0,0 +1,3834 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=false readOnlyPivotTables=false entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Collection, Entity, ManyToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @ManyToMany({ entity: () => Orders, pivotTable: 'user_orders', joinColumn: 'user_id', inverseJoinColumn: 'order_id', fixedOrder: true, fixedOrderColumn: 'priority' }) + userOrders = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=false readOnlyPivotTables=false entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); + userOrders = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userOrders: { + kind: 'm:n', + entity: () => Orders, + pivotTable: 'user_orders', + joinColumn: 'user_id', + inverseJoinColumn: 'order_id', + fixedOrder: true, + fixedOrderColumn: 'priority', + }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=false readOnlyPivotTables=true entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Collection, Entity, ManyToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; +import { UserEmailAvatars } from './UserEmailAvatars'; +import { UserEmailFlags } from './UserEmailFlags'; +import { UserEmailOrders } from './UserEmailOrders'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_avatars', pivotEntity: () => UserEmailAvatars, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailAvatars = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_flags', pivotEntity: () => UserEmailFlags, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailFlags = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_orders', pivotEntity: () => UserEmailOrders, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailOrders = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_emails', pivotEntity: () => UserEmails, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmails = new Collection(this); + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @ManyToMany({ entity: () => Orders, pivotTable: 'user_orders', joinColumn: 'user_id', inverseJoinColumn: 'order_id', fixedOrder: true, fixedOrderColumn: 'priority' }) + userOrders = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=false readOnlyPivotTables=true entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userEmailAvatars = new Collection(this); + userEmailFlags = new Collection(this); + userEmailOrders = new Collection(this); + userEmails = new Collection(this); + userFlags = new Collection(this); + userOrders = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userEmailAvatars: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_avatars', + pivotEntity: () => UserEmailAvatars, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmailFlags: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_flags', + pivotEntity: () => UserEmailFlags, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmailOrders: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_orders', + pivotEntity: () => UserEmailOrders, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmails: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_emails', + pivotEntity: () => UserEmails, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userOrders: { + kind: 'm:n', + entity: () => Orders, + pivotTable: 'user_orders', + joinColumn: 'user_id', + inverseJoinColumn: 'order_id', + fixedOrder: true, + fixedOrderColumn: 'priority', + }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=true readOnlyPivotTables=false entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserOrders { + + [PrimaryKeyProp]?: ['user', 'order']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_orders_orders1_idx' }) + order!: Orders; + + @Unique({ name: 'priority_UNIQUE' }) + @Property({ autoincrement: true }) + priority!: number; + +} +", + "import { Collection, Entity, ManyToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=true readOnlyPivotTables=false entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserOrders { + [PrimaryKeyProp]?: ['user', 'order']; + user!: Users; + order!: Orders; + priority!: number; +} + +export const UserOrdersSchema = new EntitySchema({ + class: UserOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + order: { + primary: true, + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_orders_orders1_idx', + }, + priority: { type: 'number', autoincrement: true, unique: 'priority_UNIQUE' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=true readOnlyPivotTables=true entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserOrders { + + [PrimaryKeyProp]?: ['user', 'order']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_orders_orders1_idx' }) + order!: Orders; + + @Unique({ name: 'priority_UNIQUE' }) + @Property({ autoincrement: true }) + priority!: number; + +} +", + "import { Collection, Entity, ManyToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=false onlyPurePivotTables=true readOnlyPivotTables=true entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserOrders { + [PrimaryKeyProp]?: ['user', 'order']; + user!: Users; + order!: Orders; + priority!: number; +} + +export const UserOrdersSchema = new EntitySchema({ + class: UserOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + order: { + primary: true, + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_orders_orders1_idx', + }, + priority: { type: 'number', autoincrement: true, unique: 'priority_UNIQUE' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=false readOnlyPivotTables=false entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + + @OneToMany({ entity: () => UserEmails, mappedBy: 'email' }) + emailInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmailFlags } from './UserEmailFlags'; +import { Users } from './Users'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @OneToOne({ entity: () => UserEmailFlags, mappedBy: 'flag' }) + flagInverse?: UserEmailFlags; + + @ManyToMany({ entity: () => Users, mappedBy: 'userFlags' }) + userFlagsInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { UserEmailOrders } from './UserEmailOrders'; +import { Users } from './Users'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + + @OneToMany({ entity: () => UserEmailOrders, mappedBy: 'order' }) + orderInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userOrders' }) + userOrdersInverse = new Collection(this); + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @ManyToMany({ entity: () => Orders, pivotTable: 'user_orders', joinColumn: 'user_id', inverseJoinColumn: 'order_id', fixedOrder: true, fixedOrderColumn: 'priority' }) + userOrders = new Collection(this); + + @OneToMany({ entity: () => UserEmails, mappedBy: 'user' }) + userInverse = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=false readOnlyPivotTables=false entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; + emailInverse = new Collection(this); +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + emailInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'email' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; + flagInverse?: UserEmailFlags; + userFlagsInverse = new Collection(this); +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + flagInverse: { kind: '1:1', entity: () => UserEmailFlags, mappedBy: 'flag' }, + userFlagsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userFlags' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmailOrders } from './UserEmailOrders'; +import { Users } from './Users'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; + orderInverse = new Collection(this); + userOrdersInverse = new Collection(this); +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + orderInverse: { kind: '1:m', entity: () => UserEmailOrders, mappedBy: 'order' }, + userOrdersInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userOrders' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; +import { UserEmails } from './UserEmails'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); + userOrders = new Collection(this); + userInverse = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userOrders: { + kind: 'm:n', + entity: () => Orders, + pivotTable: 'user_orders', + joinColumn: 'user_id', + inverseJoinColumn: 'order_id', + fixedOrder: true, + fixedOrderColumn: 'priority', + }, + userInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'user' }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=false readOnlyPivotTables=true entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; +import { Users } from './Users'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + + @OneToMany({ entity: () => UserEmails, mappedBy: 'email' }) + emailInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userEmailAvatars', persist: false }) + userEmailAvatarsInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userEmailFlags', persist: false }) + userEmailFlagsInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userEmailOrders', persist: false }) + userEmailOrdersInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userEmails', persist: false }) + userEmailsInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmailFlags } from './UserEmailFlags'; +import { Users } from './Users'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @OneToOne({ entity: () => UserEmailFlags, mappedBy: 'flag' }) + flagInverse?: UserEmailFlags; + + @ManyToMany({ entity: () => Users, mappedBy: 'userFlags' }) + userFlagsInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { UserEmailOrders } from './UserEmailOrders'; +import { Users } from './Users'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + + @OneToMany({ entity: () => UserEmailOrders, mappedBy: 'order' }) + orderInverse = new Collection(this); + + @ManyToMany({ entity: () => Users, mappedBy: 'userOrders' }) + userOrdersInverse = new Collection(this); + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; +import { UserEmailAvatars } from './UserEmailAvatars'; +import { UserEmailFlags } from './UserEmailFlags'; +import { UserEmailOrders } from './UserEmailOrders'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_avatars', pivotEntity: () => UserEmailAvatars, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailAvatars = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_flags', pivotEntity: () => UserEmailFlags, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailFlags = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_email_orders', pivotEntity: () => UserEmailOrders, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmailOrders = new Collection(this); + + @ManyToMany({ entity: () => Emails, pivotTable: 'user_emails', pivotEntity: () => UserEmails, joinColumn: 'user_id', inverseJoinColumn: 'email_id', persist: false }) + userEmails = new Collection(this); + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @ManyToMany({ entity: () => Orders, pivotTable: 'user_orders', joinColumn: 'user_id', inverseJoinColumn: 'order_id', fixedOrder: true, fixedOrderColumn: 'priority' }) + userOrders = new Collection(this); + + @OneToMany({ entity: () => UserEmails, mappedBy: 'user' }) + userInverse = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=false readOnlyPivotTables=true entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; +import { Users } from './Users'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; + emailInverse = new Collection(this); + userEmailAvatarsInverse = new Collection(this); + userEmailFlagsInverse = new Collection(this); + userEmailOrdersInverse = new Collection(this); + userEmailsInverse = new Collection(this); +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + emailInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'email' }, + userEmailAvatarsInverse: { + kind: 'm:n', + entity: () => Users, + mappedBy: 'userEmailAvatars', + persist: false, + }, + userEmailFlagsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userEmailFlags', persist: false }, + userEmailOrdersInverse: { + kind: 'm:n', + entity: () => Users, + mappedBy: 'userEmailOrders', + persist: false, + }, + userEmailsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userEmails', persist: false }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; + flagInverse?: UserEmailFlags; + userFlagsInverse = new Collection(this); +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + flagInverse: { kind: '1:1', entity: () => UserEmailFlags, mappedBy: 'flag' }, + userFlagsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userFlags' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmailOrders } from './UserEmailOrders'; +import { Users } from './Users'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; + orderInverse = new Collection(this); + userOrdersInverse = new Collection(this); +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + orderInverse: { kind: '1:m', entity: () => UserEmailOrders, mappedBy: 'order' }, + userOrdersInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userOrders' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Orders } from './Orders'; +import { UserEmails } from './UserEmails'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userEmailAvatars = new Collection(this); + userEmailFlags = new Collection(this); + userEmailOrders = new Collection(this); + userEmails = new Collection(this); + userFlags = new Collection(this); + userOrders = new Collection(this); + userInverse = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userEmailAvatars: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_avatars', + pivotEntity: () => UserEmailAvatars, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmailFlags: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_flags', + pivotEntity: () => UserEmailFlags, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmailOrders: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_email_orders', + pivotEntity: () => UserEmailOrders, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userEmails: { + kind: 'm:n', + entity: () => Emails, + pivotTable: 'user_emails', + pivotEntity: () => UserEmails, + joinColumn: 'user_id', + inverseJoinColumn: 'email_id', + persist: false, + }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userOrders: { + kind: 'm:n', + entity: () => Orders, + pivotTable: 'user_orders', + joinColumn: 'user_id', + inverseJoinColumn: 'order_id', + fixedOrder: true, + fixedOrderColumn: 'priority', + }, + userInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'user' }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=true readOnlyPivotTables=false entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + + @OneToMany({ entity: () => UserEmails, mappedBy: 'email' }) + emailInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmailFlags } from './UserEmailFlags'; +import { Users } from './Users'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @OneToOne({ entity: () => UserEmailFlags, mappedBy: 'flag' }) + flagInverse?: UserEmailFlags; + + @ManyToMany({ entity: () => Users, mappedBy: 'userFlags' }) + userFlagsInverse = new Collection(this); + +} +", + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { UserOrders } from './UserOrders'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + + @OneToMany({ entity: () => UserOrders, mappedBy: 'order' }) + orderInverse = new Collection(this); + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserOrders { + + [PrimaryKeyProp]?: ['user', 'order']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_orders_orders1_idx' }) + order!: Orders; + + @Unique({ name: 'priority_UNIQUE' }) + @Property({ autoincrement: true }) + priority!: number; + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { UserOrders } from './UserOrders'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @OneToMany({ entity: () => UserOrders, mappedBy: 'user' }) + userInverse = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=true readOnlyPivotTables=false entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; + emailInverse = new Collection(this); +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + emailInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'email' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; + flagInverse?: UserEmailFlags; + userFlagsInverse = new Collection(this); +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + flagInverse: { kind: '1:1', entity: () => UserEmailFlags, mappedBy: 'flag' }, + userFlagsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userFlags' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserOrders } from './UserOrders'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; + orderInverse = new Collection(this); +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + orderInverse: { kind: '1:m', entity: () => UserOrders, mappedBy: 'order' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserOrders { + [PrimaryKeyProp]?: ['user', 'order']; + user!: Users; + order!: Orders; + priority!: number; +} + +export const UserOrdersSchema = new EntitySchema({ + class: UserOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + order: { + primary: true, + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_orders_orders1_idx', + }, + priority: { type: 'number', autoincrement: true, unique: 'priority_UNIQUE' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { UserOrders } from './UserOrders'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); + userInverse = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userInverse: { kind: '1:m', entity: () => UserOrders, mappedBy: 'user' }, + }, +}); +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=true readOnlyPivotTables=true entitySchema=false: dump 1`] = ` +[ + "import { Entity, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +@Unique({ name: 'user_id__order_id_unique', properties: ['user', 'order'] }) +export class CompletedOrders { + + @PrimaryKey() + id!: number; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', index: 'fk_completed_orders_users1_idx' }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_completed_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +@Entity() +export class Emails { + + [PrimaryKeyProp]?: 'emailId'; + + @PrimaryKey() + emailId!: number; + + @Unique({ name: 'address_UNIQUE' }) + @Property({ length: 255 }) + address!: string; + + @OneToMany({ entity: () => UserEmails, mappedBy: 'email' }) + emailInverse = new Collection(this); + +} +", + "import { Collection, Entity, ManyToMany, OneToOne, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { UserEmailFlags } from './UserEmailFlags'; +import { Users } from './Users'; + +@Entity() +export class Flags { + + [PrimaryKeyProp]?: 'flagId'; + + @PrimaryKey({ autoincrement: false }) + flagId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @OneToOne({ entity: () => UserEmailFlags, mappedBy: 'flag' }) + flagInverse?: UserEmailFlags; + + @ManyToMany({ entity: () => Users, mappedBy: 'userFlags' }) + userFlagsInverse = new Collection(this); + +} +", + "import { Collection, Entity, OneToMany, PrimaryKey, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { UserOrders } from './UserOrders'; + +@Entity() +export class Orders { + + [PrimaryKeyProp]?: 'orderId'; + + @PrimaryKey() + orderId!: number; + + @Property({ length: 255 }) + name!: string; + + @OneToMany({ entity: () => UserOrders, mappedBy: 'order' }) + orderInverse = new Collection(this); + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmailAvatars { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_avatars_emails1_idx' }) + email!: Emails; + + @Property({ length: 255 }) + avatarUrl!: string; + +} +", + "import { Entity, ManyToOne, OneToOne, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Flags } from './Flags'; +import { Users } from './Users'; + +@Entity() +export class UserEmailFlags { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'flag'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_flags_emails1_idx' }) + email!: Emails; + + @OneToOne({ entity: () => Flags, fieldName: 'flag_id', defaultRaw: \`1\`, index: 'fk_user_email_flags_flags1_idx', unique: 'flag_id_UNIQUE' }) + flag!: Flags; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserEmailOrders { + + [PrimaryKeyProp]?: ['user', 'email']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', primary: true, index: 'fk_user_email_orders_emails1_idx' }) + email!: Emails; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', index: 'fk_user_email_orders_orders1_idx' }) + order!: Orders; + +} +", + "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; +import { Emails } from './Emails'; +import { Users } from './Users'; + +@Entity() +export class UserEmails { + + [PrimaryKeyProp]?: ['user', 'email']; + + [OptionalProps]?: 'isVerified'; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Emails, fieldName: 'email_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_emails_emails1_idx' }) + email!: Emails; + + @Property({ default: false }) + isVerified: boolean = false; + +} +", + "import { Entity, ManyToOne, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Orders } from './Orders'; +import { Users } from './Users'; + +@Entity() +export class UserOrders { + + [PrimaryKeyProp]?: ['user', 'order']; + + @ManyToOne({ entity: () => Users, fieldName: 'user_id', primary: true }) + user!: Users; + + @ManyToOne({ entity: () => Orders, fieldName: 'order_id', updateRule: 'cascade', deleteRule: 'cascade', primary: true, index: 'fk_user_orders_orders1_idx' }) + order!: Orders; + + @Unique({ name: 'priority_UNIQUE' }) + @Property({ autoincrement: true }) + priority!: number; + +} +", + "import { Collection, Entity, ManyToMany, OneToMany, PrimaryKey, PrimaryKeyProp, Property, Unique } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { UserOrders } from './UserOrders'; + +@Entity() +export class Users { + + [PrimaryKeyProp]?: 'userId'; + + @PrimaryKey() + userId!: number; + + @Unique({ name: 'name_UNIQUE' }) + @Property({ length: 255 }) + name!: string; + + @ManyToMany({ entity: () => Flags, pivotTable: 'user_flags', joinColumn: 'user_id', inverseJoinColumn: 'flag_id' }) + userFlags = new Collection(this); + + @OneToMany({ entity: () => UserOrders, mappedBy: 'user' }) + userInverse = new Collection(this); + +} +", +] +`; + +exports[`many_to_many_variants bidirectionalRelations=true onlyPurePivotTables=true readOnlyPivotTables=true entitySchema=true: dump 1`] = ` +[ + "import { EntitySchema } from '@mikro-orm/core'; + +export class CompletedOrders { + id!: number; + user!: Users; + order!: Orders; +} + +export const CompletedOrdersSchema = new EntitySchema({ + class: CompletedOrders, + uniques: [ + { name: 'user_id__order_id_unique', properties: ['user', 'order'] }, + ], + properties: { + id: { primary: true, type: 'number' }, + user: { + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + index: 'fk_completed_orders_users1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_completed_orders_orders1_idx', + }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserEmails } from './UserEmails'; + +export class Emails { + [PrimaryKeyProp]?: 'emailId'; + emailId!: number; + address!: string; + emailInverse = new Collection(this); +} + +export const EmailsSchema = new EntitySchema({ + class: Emails, + properties: { + emailId: { primary: true, type: 'number' }, + address: { type: 'string', length: 255, unique: 'address_UNIQUE' }, + emailInverse: { kind: '1:m', entity: () => UserEmails, mappedBy: 'email' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Users } from './Users'; + +export class Flags { + [PrimaryKeyProp]?: 'flagId'; + flagId!: number; + name!: string; + flagInverse?: UserEmailFlags; + userFlagsInverse = new Collection(this); +} + +export const FlagsSchema = new EntitySchema({ + class: Flags, + properties: { + flagId: { primary: true, type: 'number', autoincrement: false }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + flagInverse: { kind: '1:1', entity: () => UserEmailFlags, mappedBy: 'flag' }, + userFlagsInverse: { kind: 'm:n', entity: () => Users, mappedBy: 'userFlags' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { UserOrders } from './UserOrders'; + +export class Orders { + [PrimaryKeyProp]?: 'orderId'; + orderId!: number; + name!: string; + orderInverse = new Collection(this); +} + +export const OrdersSchema = new EntitySchema({ + class: Orders, + properties: { + orderId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255 }, + orderInverse: { kind: '1:m', entity: () => UserOrders, mappedBy: 'order' }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailAvatars { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + avatarUrl!: string; +} + +export const UserEmailAvatarsSchema = new EntitySchema({ + class: UserEmailAvatars, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_avatars_emails1_idx', + }, + avatarUrl: { type: 'string', length: 255 }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailFlags { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'flag'; + user!: Users; + email!: Emails; + flag!: Flags; +} + +export const UserEmailFlagsSchema = new EntitySchema({ + class: UserEmailFlags, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_flags_emails1_idx', + }, + flag: { + kind: '1:1', + entity: () => Flags, + fieldName: 'flag_id', + defaultRaw: \`1\`, + index: 'fk_user_email_flags_flags1_idx', + unique: 'flag_id_UNIQUE', + }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmailOrders { + [PrimaryKeyProp]?: ['user', 'email']; + user!: Users; + email!: Emails; + order!: Orders; +} + +export const UserEmailOrdersSchema = new EntitySchema({ + class: UserEmailOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + index: 'fk_user_email_orders_emails1_idx', + }, + order: { + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + index: 'fk_user_email_orders_orders1_idx', + }, + }, +}); +", + "import { EntitySchema, OptionalProps, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserEmails { + [PrimaryKeyProp]?: ['user', 'email']; + [OptionalProps]?: 'isVerified'; + user!: Users; + email!: Emails; + isVerified: boolean = false; +} + +export const UserEmailsSchema = new EntitySchema({ + class: UserEmails, + properties: { + user: { + primary: true, + kind: 'm:1', + entity: () => Users, + fieldName: 'user_id', + updateRule: 'cascade', + deleteRule: 'cascade', + }, + email: { + primary: true, + kind: 'm:1', + entity: () => Emails, + fieldName: 'email_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_emails_emails1_idx', + }, + isVerified: { type: 'boolean', default: false }, + }, +}); +", + "import { EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; + +export class UserOrders { + [PrimaryKeyProp]?: ['user', 'order']; + user!: Users; + order!: Orders; + priority!: number; +} + +export const UserOrdersSchema = new EntitySchema({ + class: UserOrders, + properties: { + user: { primary: true, kind: 'm:1', entity: () => Users, fieldName: 'user_id' }, + order: { + primary: true, + kind: 'm:1', + entity: () => Orders, + fieldName: 'order_id', + updateRule: 'cascade', + deleteRule: 'cascade', + index: 'fk_user_orders_orders1_idx', + }, + priority: { type: 'number', autoincrement: true, unique: 'priority_UNIQUE' }, + }, +}); +", + "import { Collection, EntitySchema, PrimaryKeyProp } from '@mikro-orm/core'; +import { Flags } from './Flags'; +import { UserOrders } from './UserOrders'; + +export class Users { + [PrimaryKeyProp]?: 'userId'; + userId!: number; + name!: string; + userFlags = new Collection(this); + userInverse = new Collection(this); +} + +export const UsersSchema = new EntitySchema({ + class: Users, + properties: { + userId: { primary: true, type: 'number' }, + name: { type: 'string', length: 255, unique: 'name_UNIQUE' }, + userFlags: { + kind: 'm:n', + entity: () => Flags, + pivotTable: 'user_flags', + joinColumn: 'user_id', + inverseJoinColumn: 'flag_id', + }, + userInverse: { kind: '1:m', entity: () => UserOrders, mappedBy: 'user' }, + }, +}); +", +] +`; diff --git a/tests/features/entity-generator/__snapshots__/NonCompositeAmbiguousFks.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/NonCompositeAmbiguousFks.mysql.test.ts.snap index c114fa4550ea..3204819cca30 100644 --- a/tests/features/entity-generator/__snapshots__/NonCompositeAmbiguousFks.mysql.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/NonCompositeAmbiguousFks.mysql.test.ts.snap @@ -63,7 +63,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -170,7 +170,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -290,7 +290,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -411,7 +411,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -554,7 +554,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -688,7 +688,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', entity: () => ManufacturedProducts, mappedBy: 'product' }, }, @@ -825,7 +825,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -974,7 +974,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', @@ -1101,7 +1101,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -1197,7 +1197,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -1302,7 +1302,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -1412,7 +1412,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -1540,7 +1540,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -1663,7 +1663,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', entity: () => ManufacturedProducts, mappedBy: 'product' }, }, @@ -1785,7 +1785,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -1923,7 +1923,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', @@ -2041,7 +2041,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -2137,7 +2137,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -2242,7 +2242,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -2352,7 +2352,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, }, }); @@ -2480,7 +2480,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -2603,7 +2603,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', entity: () => ManufacturedProducts, mappedBy: 'product' }, }, @@ -2725,7 +2725,7 @@ export class Products { [PrimaryKeyProp]?: 'productId'; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) productId!: number; @Property({ length: 255 }) @@ -2863,7 +2863,7 @@ export class Products { export const ProductsSchema = new EntitySchema({ class: Products, properties: { - productId: { primary: true, type: 'number' }, + productId: { primary: true, type: 'number', autoincrement: false }, name: { type: 'string', length: 255 }, productInverse: { kind: '1:1', diff --git a/tests/features/entity-generator/__snapshots__/OverlapFks.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/OverlapFks.mysql.test.ts.snap index 6089b4743913..762488635119 100644 --- a/tests/features/entity-generator/__snapshots__/OverlapFks.mysql.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/OverlapFks.mysql.test.ts.snap @@ -19,6 +19,8 @@ import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['countries', 'productId'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['product', 'countries']; @@ -183,6 +185,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['countries', 'productId'] }, + ], properties: { country: { type: 'unknown', columnType: 'char(2)', persist: false }, product: { @@ -342,6 +348,8 @@ import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['countries', 'productId'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['product', 'countries']; @@ -508,6 +516,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['countries', 'productId'] }, + ], properties: { country: { type: 'unknown', columnType: 'char(2)', persist: false }, product: { @@ -687,6 +699,8 @@ import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['countries', 'productId'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['product', 'countries']; @@ -871,6 +885,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['countries', 'productId'] }, + ], properties: { country: { type: 'unknown', columnType: 'char(2)', persist: false }, product: { @@ -1045,6 +1063,8 @@ import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['countries', 'productId'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['product', 'countries']; @@ -1231,6 +1251,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['countries', 'productId', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['countries', 'productId'] }, + ], properties: { country: { type: 'unknown', columnType: 'char(2)', persist: false }, product: { @@ -1410,11 +1434,13 @@ export class Countries { } ", - "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -1554,6 +1580,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, kind: 'm:1', entity: () => Countries, fieldName: 'country' }, product: { @@ -1699,11 +1729,13 @@ export class Countries { } ", - "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -1845,6 +1877,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, @@ -2009,12 +2045,14 @@ export class Countries { } ", - "import { Collection, Entity, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Collection, Entity, Index, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -2174,6 +2212,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, kind: 'm:1', entity: () => Countries, fieldName: 'country' }, product: { @@ -2333,12 +2375,14 @@ export class Countries { } ", - "import { Collection, Entity, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Collection, Entity, Index, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -2500,6 +2544,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, @@ -2670,11 +2718,13 @@ export class Countries { } ", - "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -2814,6 +2864,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, kind: 'm:1', entity: () => Countries, fieldName: 'country' }, product: { @@ -2959,11 +3013,13 @@ export class Countries { } ", - "import { Entity, ManyToOne, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Entity, Index, ManyToOne, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -3105,6 +3161,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, @@ -3269,12 +3329,14 @@ export class Countries { } ", - "import { Collection, Entity, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; + "import { Collection, Entity, Index, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -3434,6 +3496,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, kind: 'm:1', entity: () => Countries, fieldName: 'country' }, product: { @@ -3593,12 +3659,14 @@ export class Countries { } ", - "import { Collection, Entity, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; + "import { Collection, Entity, Index, ManyToOne, OneToMany, OptionalProps, PrimaryKeyProp, Property, Ref } from '@mikro-orm/core'; import { Countries } from './Countries'; import { Products } from './Products'; import { Sales } from './Sales'; @Entity() +@Index({ name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }) +@Index({ name: 'primary_reindex_idx', properties: ['country', 'product'] }) export class ProductCountryMap { [PrimaryKeyProp]?: ['country', 'product']; @@ -3760,6 +3828,10 @@ export class ProductCountryMap { export const ProductCountryMapSchema = new EntitySchema({ class: ProductCountryMap, + indexes: [ + { name: 'full_idx', properties: ['country', 'product', 'isCurrentlyAllowed'] }, + { name: 'primary_reindex_idx', properties: ['country', 'product'] }, + ], properties: { country: { primary: true, diff --git a/tests/features/entity-generator/__snapshots__/index-expressions.mysql.test.ts.snap b/tests/features/entity-generator/__snapshots__/index-expressions.mysql.test.ts.snap index 4cbdb2d82000..7ef6fea4029d 100644 --- a/tests/features/entity-generator/__snapshots__/index-expressions.mysql.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/index-expressions.mysql.test.ts.snap @@ -14,7 +14,7 @@ export class DcimDevice { @Property({ length: 0, nullable: true }) created?: Date; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) id!: bigint; @Property({ length: 255, nullable: true }) diff --git a/tests/features/entity-generator/__snapshots__/index-expressions.postgres.test.ts.snap b/tests/features/entity-generator/__snapshots__/index-expressions.postgres.test.ts.snap index 279dbde88499..0c4106ead719 100644 --- a/tests/features/entity-generator/__snapshots__/index-expressions.postgres.test.ts.snap +++ b/tests/features/entity-generator/__snapshots__/index-expressions.postgres.test.ts.snap @@ -14,7 +14,7 @@ export class DcimDevice { @Property({ length: 6, nullable: true }) created?: Date; - @PrimaryKey() + @PrimaryKey({ autoincrement: false }) id!: bigint; @Property({ nullable: true }) diff --git a/tests/features/entity-generator/index-expressions.mysql.test.ts b/tests/features/entity-generator/index-expressions.mysql.test.ts index b7fd171d76a2..1da2317f83b7 100644 --- a/tests/features/entity-generator/index-expressions.mysql.test.ts +++ b/tests/features/entity-generator/index-expressions.mysql.test.ts @@ -2,8 +2,9 @@ import { MikroORM } from '@mikro-orm/mysql'; import { EntityGenerator } from '@mikro-orm/entity-generator'; test('4911', async () => { + const schemaName = '4911'; const orm = await MikroORM.init({ - dbName: '4911', + dbName: schemaName, port: 3308, discovery: { warnWhenNoEntities: false, @@ -11,9 +12,10 @@ test('4911', async () => { multipleStatements: true, extensions: [EntityGenerator], }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(`drop table if exists dcim_device`); - await orm.schema.execute(` + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(` CREATE TABLE \`dcim_device\` ( \`created\` timestamp, \`id\` int8 NOT NULL, @@ -60,6 +62,8 @@ CREATE INDEX dcim_device_cluster_id_cf852f78 ON \`dcim_device\` (cluster_id); CREATE UNIQUE INDEX dcim_device_asset_tag_key ON \`dcim_device\` (asset_tag); CREATE INDEX dcim_device_asset_tag_8dac1079_like ON \`dcim_device\` (asset_tag); `); + } + const dump = await orm.entityGenerator.generate(); expect(dump).toMatchSnapshot(); await orm.close(true); diff --git a/tests/features/entity-generator/index-expressions.postgres.test.ts b/tests/features/entity-generator/index-expressions.postgres.test.ts index c33fd47a7282..0d732e0b5a4c 100644 --- a/tests/features/entity-generator/index-expressions.postgres.test.ts +++ b/tests/features/entity-generator/index-expressions.postgres.test.ts @@ -2,16 +2,18 @@ import { MikroORM } from '@mikro-orm/postgresql'; import { EntityGenerator } from '@mikro-orm/entity-generator'; test('4911', async () => { + const schemaName = '4911'; const orm = await MikroORM.init({ - dbName: '4911', + dbName: schemaName, discovery: { warnWhenNoEntities: false, }, extensions: [EntityGenerator], }); - await orm.schema.ensureDatabase(); - await orm.schema.execute(`drop table if exists dcim_device`); - await orm.schema.execute(` + const driver = orm.config.getDriver(); + if (!await driver.getPlatform().getSchemaHelper()?.databaseExists(driver.getConnection(), schemaName)) { + await orm.schema.createSchema({ schema: schemaName }); + await orm.schema.execute(` CREATE TABLE "public"."dcim_device" ( "created" timestamptz, "id" int8 NOT NULL, @@ -58,6 +60,7 @@ CREATE INDEX dcim_device_cluster_id_cf852f78 ON "public"."dcim_device" USING BTR CREATE UNIQUE INDEX dcim_device_asset_tag_key ON "public"."dcim_device" USING BTREE (asset_tag); CREATE INDEX dcim_device_asset_tag_8dac1079_like ON "public"."dcim_device" USING BTREE (asset_tag varchar_pattern_ops); `); + } const dump = await orm.entityGenerator.generate(); expect(dump).toMatchSnapshot(); await orm.close(true); diff --git a/tests/features/entity-generator/index-expressions.sqlite.test.ts b/tests/features/entity-generator/index-expressions.sqlite.test.ts index 17fdfbbedd1e..217040cda2a0 100644 --- a/tests/features/entity-generator/index-expressions.sqlite.test.ts +++ b/tests/features/entity-generator/index-expressions.sqlite.test.ts @@ -10,7 +10,6 @@ test('4911', async () => { extensions: [EntityGenerator], }); await orm.schema.ensureDatabase(); - await orm.schema.execute(`drop table if exists dcim_device`); await orm.schema.execute(` CREATE TABLE "dcim_device" ("created" timestamptz, "id" int8 NOT NULL, "name" varchar, "_name" varchar, "asset_tag" varchar, "position" numeric, "face" varchar NOT NULL, "vc_position" int2 CHECK (vc_position >= 0), "vc_priority" int2 CHECK (vc_priority >= 0), "cluster_id" int8, "role_id" int8 NOT NULL, "device_type_id" int8 NOT NULL, "location_id" int8, "platform_id" int8, "primary_ip4_id" int8, "primary_ip6_id" int8, "rack_id" int8, "site_id" int8 NOT NULL, "tenant_id" int8, "virtual_chassis_id" int8, "airflow" varchar NOT NULL, "config_template_id" int8, "oob_ip_id" int8, PRIMARY KEY ("id")); CREATE INDEX dcim_device_virtual_chassis_id_aed51693 ON "dcim_device" (virtual_chassis_id);