Jonathan
Jonathan

Reputation: 16359

With TypeORM migrations how to seed a column during a migration

Consider the following, where between two queryRunner.query commands, I want to do some logic to seed a new column.

  public async up(queryRunner: QueryRunner): Promise<any> {
    await queryRunner.query(`ALTER TABLE "users" ADD "selectedNotebookId" uuid`);

    const userRepo = await queryRunner.connection.getRepository(User);

    const allUsers = await userRepo.find({
      where: {},
      relations: ['notebooks']
    });

    const bar = new ProgressBar(':bar', { total: allUsers.length });

    const promises: Promise<void>[] = allUsers.map((user: User) => {
      user.selectedNotebook = user.notebooks[0];
      return userRepo.save(user).then(() => {
        bar.tick();
      });
    });

    await Promise.all(promises);

    await queryRunner.query(
      `ALTER TABLE "users" ADD CONSTRAINT "UQ_df4319c3d54b91856514f0dbcb3" UNIQUE ("selectedNotebookId")`
    );
    await queryRunner.query(
      `ALTER TABLE "users" ADD CONSTRAINT "FK_df4319c3d54b91856514f0dbcb3" FOREIGN KEY ("selectedNotebookId") REFERENCES "notebook"("id")`
    );
  }

The issue that I am happening is the that the first ALTER TABLE command is blocking the subsequently query.

My gut is the issue is that both statements are wrapped in the transaction that the migration framework provides

What is the best way to work around this.

Thanks!!

Upvotes: 3

Views: 5096

Answers (1)

Jonathan
Jonathan

Reputation: 16359

Figure it out:

  public async up(queryRunner: QueryRunner): Promise<any> {
    await queryRunner.query(`START TRANSACTION`);
    await queryRunner.query(`ALTER TABLE "users" ADD "selectedNotebookId" uuid`);
    await queryRunner.query(`COMMIT TRANSACTION`);

    const userRepo = await queryRunner.connection.getRepository(User);

    const allUsers = await userRepo.find({
      where: {},
      relations: ['notebooks']
    });

    const bar = new ProgressBar(':bar', { total: allUsers.length });

    const promises: Promise<void>[] = allUsers.map((user: User) => {
      user.selectedNotebook = user.notebooks[0];
      return userRepo.save(user).then(() => {
        bar.tick();
      });
    });

    await Promise.all(promises);

    await queryRunner.query(
      `ALTER TABLE "users" ADD CONSTRAINT "UQ_df4319c3d54b91856514f0dbcb3" UNIQUE ("selectedNotebookId")`
    );
    await queryRunner.query(
      `ALTER TABLE "users" ADD CONSTRAINT "FK_df4319c3d54b91856514f0dbcb3" FOREIGN KEY ("selectedNotebookId") REFERENCES "notebook"("id")`
    );
  }

notice the await queryRunner.query(START TRANSACTION); that wraps the ALTER TABLE command

that creates a subtransaction for us. NOTE -- this might only work for postgreSQL

Upvotes: 3

Related Questions