将 "enumName" ColumnOption 用于 Postgres 枚举类型时重复迁移

Duplicate migrations when using "enumName" ColumnOption for a Postgres enum type

我有一个名为 TaskNotification 的实体,其中有一个名为 type 的枚举字段。我使用 enumName 选项在数据库中给它一个特定的名称 TaskNotificationType

import { Entity, Column } from 'typeorm';

export enum TaskNotificationType {
  ASSIGNED
}

@Entity('taskNotifications')
export class TaskNotification {
  @Column({
    type: 'enum',
    enum: TaskNotificationType,
    enumName: 'TaskNotificationType',
    default: TaskNotificationType.ASSIGNED,
  })
  type: TaskNotificationType;

  /* Some more code */
}

当我为此实体 class 创建新的迁移时,我得到以下迁移。这是正确的,也是预期的。

import {MigrationInterface, QueryRunner} from "typeorm";

export class addNotifications1620795716886 implements MigrationInterface {
    name = 'addNotifications1620795716886'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TYPE "TaskNotificationType" AS ENUM('0')`);
        await queryRunner.query(`CREATE TABLE "taskNotifications" ("id" character varying(21) NOT NULL, "senderID" character varying(21) NOT NULL, "taskID" character varying(21) NOT NULL, "type" "TaskNotificationType" NOT NULL DEFAULT '0', CONSTRAINT "PK_bf03149248aee7c64532028321e" PRIMARY KEY ("id"))`);
        await queryRunner.query(`CREATE TABLE "notificationStatuses" ("id" character varying(21) NOT NULL, "receiverID" character varying(21) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "sentAt" TIMESTAMP WITH TIME ZONE, "readAt" TIMESTAMP WITH TIME ZONE, "taskNotificationID" character varying(21) NOT NULL, CONSTRAINT "PK_735fedb2f492dc91b0adf8233b0" PRIMARY KEY ("id"))`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" ADD CONSTRAINT "FK_9b92958e250c1f46393e0e88066" FOREIGN KEY ("taskID") REFERENCES "tasks"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
        await queryRunner.query(`ALTER TABLE "notificationStatuses" ADD CONSTRAINT "FK_14dbeaea4a320e7375cb22e7e7a" FOREIGN KEY ("taskNotificationID") REFERENCES "taskNotifications"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "notificationStatuses" DROP CONSTRAINT "FK_14dbeaea4a320e7375cb22e7e7a"`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" DROP CONSTRAINT "FK_9b92958e250c1f46393e0e88066"`);
        await queryRunner.query(`DROP TABLE "notificationStatuses"`);
        await queryRunner.query(`DROP TABLE "taskNotifications"`);
        await queryRunner.query(`DROP TYPE "TaskNotificationType"`);
    }

}

当我重建应用程序和 运行 迁移时,数据库会根据需要进行更新。所以到目前为止没有问题。

但是,如果我尝试在不更改任何实体的情况下创建另一个迁移,我将获得如下所示的另一个迁移。请注意 updown 方法之间枚举的名称差异。 (这里发生了什么?)

import {MigrationInterface, QueryRunner} from "typeorm";

export class addNotificationsDuplicate1620795984398 implements MigrationInterface {
    name = 'addNotificationsDuplicate1620795984398'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "taskNotifications" DROP COLUMN "type"`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" ADD "type" "TaskNotificationType" NOT NULL DEFAULT '0'`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "taskNotifications" DROP COLUMN "type"`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" ADD "type" "tasknotificationtype" NOT NULL DEFAULT '0'`);
    }

}

如果我没有在列选项中使用 enumName,typeorm 会分配一个默认名称 taskNotifications_type_enum

这是为此的迁移:

      
import {MigrationInterface, QueryRunner} from "typeorm";
    
export class addNotifications1620796454176 implements MigrationInterface {
    name = 'addNotifications1620796454176'
    
    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TYPE "taskNotifications_type_enum" AS ENUM('0')`);
        await queryRunner.query(`CREATE TABLE "taskNotifications" ("id" character varying(21) NOT NULL, "senderID" character varying(21) NOT NULL, "taskID" character varying(21) NOT NULL, "type" "taskNotifications_type_enum" NOT NULL DEFAULT '0', CONSTRAINT "PK_bf03149248aee7c64532028321e" PRIMARY KEY ("id"))`);
        await queryRunner.query(`CREATE TABLE "notificationStatuses" ("id" character varying(21) NOT NULL, "receiverID" character varying(21) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "sentAt" TIMESTAMP WITH TIME ZONE, "readAt" TIMESTAMP WITH TIME ZONE, "taskNotificationID" character varying(21) NOT NULL, CONSTRAINT "PK_735fedb2f492dc91b0adf8233b0" PRIMARY KEY ("id"))`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" ADD CONSTRAINT "FK_9b92958e250c1f46393e0e88066" FOREIGN KEY ("taskID") REFERENCES "tasks"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
        await queryRunner.query(`ALTER TABLE "notificationStatuses" ADD CONSTRAINT "FK_14dbeaea4a320e7375cb22e7e7a" FOREIGN KEY ("taskNotificationID") REFERENCES "taskNotifications"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
        }
    
    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "notificationStatuses" DROP CONSTRAINT "FK_14dbeaea4a320e7375cb22e7e7a"`);
        await queryRunner.query(`ALTER TABLE "taskNotifications" DROP CONSTRAINT "FK_9b92958e250c1f46393e0e88066"`);
        await queryRunner.query(`DROP TABLE "notificationStatuses"`);
        await queryRunner.query(`DROP TABLE "taskNotifications"`);
        await queryRunner.query(`DROP TYPE "taskNotifications_type_enum"`);
        }
    
}

然后如果我尝试在不更改实体的情况下生成迁移,它不会生成新的迁移。 (这是正确且预期的行为)

但是,如果我在之后添加 enumName,它不会为名称更改生成新的迁移。当我们尝试 运行 迁移而不更改任何实体时,它会抛出我们看到的常见错误。 (又被抓了)

╰>>> npm run typeorm:novadelite migration:generate -- -n addNotificationsDuplicate

> novade-lite-backend@0.1.4 typeorm:novadelite /Users/eranga/Documents/Projects/Novade/NovadeLiteBackend
> ts-node ./node_modules/.bin/typeorm --config src/modules/Database/OrmConfigs/novadeLiteOrmConfig "migration:generate" "-n" "addNotificationsDuplicate"

No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command

这里有什么问题,我如何使用 typeorm 为我的枚举类型指定一个特定的名称?

非常感谢任何帮助!


(在极少数情况下这会成为 typeorm 中的一个问题,我已经创建了一个 issue in Github

这确实是 Typeorm 中的一个问题,已由 AlexMesser in this PR 修复。

在撰写本文时,Typeorm 的版本是 0.2.32,此修复将在下一个版本中发布!