oguimbal / pg-mem

An in memory postgres DB instance for your unit tests
MIT License
1.95k stars 94 forks source link

Using TypeORM JoinTable pointing to an entity table will cause duplicated table registration #330

Open leogcba opened 1 year ago

leogcba commented 1 year ago

Describe the bug

This is hard to describe. Basically, when you use @JoinTable pointing to the same table used by the @Entity decorator, pg-mem treats each table as a different entity and tries to register the table twice. As the entity defines an enum type, the enum types is registered twice trowing the error.

The issue is in the _registerType(type){} function.

Failed SQL statement: CREATE TYPE "public"."device_activity_type" AS ENUM('Login', 'Logout');

To Reproduce

Create these entities:

export enum DeviceActivityType {
    Login = 'Login',
    Logout = 'Logout',
}

@Entity('device_activity') // THIS IS THE JOIN TABLE USED IN THE ENTITY BELOW
export class DeviceActivity extends BaseEntity {
    @PrimaryColumn({ type: 'uuid' })
    public deviceId: string;

    @PrimaryColumn({ type: 'uuid' })
    public customerId: string;

    @PrimaryColumn({ type: 'uuid' })
    public packageId: string;

    @PrimaryColumn({
        enum: DeviceActivityType,
        enumName: 'device_activity_type',
        type: 'enum',
    })
    public activityType: DeviceActivityType; // THIS MUST BE AN ENUM TO REPRODUCE THE ISSUE

    @Column({ type: 'text' })
    public name: string;

    @Column({ nullable: true, type: 'text' })
    public description?: string;
}

@Entity('devices')
export class Device extends BaseEntity {
    @PrimaryColumn({ type: 'uuid' })
    public id: string;

    @PrimaryColumn({ type: 'uuid' })
    public customerId: string;

    @Column()
    public hostname: string;

    @ManyToMany(() => Package)
    @JoinTable({
        inverseJoinColumns: [{ name: 'packageId' }, { name: 'customerId' }],
        joinColumns: [
            { name: 'deviceId', referencedColumnName: 'id' },
            { name: 'customerId', referencedColumnName: 'customerId' },
        ],
        name: 'device_activity', // THIS MUST POINT TO THE TABLE ABOVE
    })
    public packages?: Package[];
}
@Entity('packages')
export class Package extends BaseEntity {
    @PrimaryColumn({ type: 'uuid' })
    public id: string;

    @Column()
    public name: string;

    @Column()
    public enabled: boolean;

    @Column({ type: 'uuid' })
    public customerId: string;

    @ManyToMany(() => Device)
    public devices: Device[];
}

Register the DB:

this.db.adapters.createTypeormDataSource({
    entities: [
        'src/**/device.entity.ts',
        'src/**/package.entity.ts',
        'src/**/deviceActivity.entity.ts',
    ],
    synchronize: true,
    type: 'postgres',
})

pg-mem version

2.6.12