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 a915ebd92b88..d84f06147fa3 100644 --- a/packages/core/src/typings.ts +++ b/packages/core/src/typings.ts @@ -741,6 +741,8 @@ export interface GenerateOptions { scalarTypeInDecorator?: boolean; scalarPropertiesForRelations?: 'always' | 'never' | 'smart'; fileName?: (className: string) => string; + onlyPurePivotTables?: boolean; + readOnlyPivotTables?: boolean; } export interface IEntityGenerator { diff --git a/packages/core/src/utils/Configuration.ts b/packages/core/src/utils/Configuration.ts index da1b0ef17728..e50fb12b1052 100644 --- a/packages/core/src/utils/Configuration.ts +++ b/packages/core/src/utils/Configuration.ts @@ -118,6 +118,8 @@ export class Configuration className, + onlyPurePivotTables: false, + readOnlyPivotTables: false, }, metadataCache: { pretty: false, @@ -594,6 +596,8 @@ export interface MikroORMOptions string; + onlyPurePivotTables?: boolean; + readOnlyPivotTables?: boolean; }; metadataCache: { enabled?: boolean; diff --git a/packages/entity-generator/src/EntityGenerator.ts b/packages/entity-generator/src/EntityGenerator.ts index e95dd6efed99..09946da6d134 100644 --- a/packages/entity-generator/src/EntityGenerator.ts +++ b/packages/entity-generator/src/EntityGenerator.ts @@ -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,99 @@ 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; + } - if (!owner) { + 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 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)), + ); - if (this.referencedEntities.has(meta)) { - ownerProp.pivotEntity = meta.className; + // 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]; } - owner.addProperty(ownerProp); + + 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); + } + } + + 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 +229,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);