question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

migration:generate does not automatically drop tables

See original GitHub issue

Issue Description

When I create an entity, generate a migration, and run said migration, it creates a table for the entity in the mysql database as expected. When I delete the entity, and attempt to generate a new migration on top of the old one, the typeorm does not find any changes.

Expected Behavior

I expected typeorm to recognize that the entity did not exist and so the table could be dropped. Typeorm should have made a new migration to drop the table whose entity was deleted.

Actual Behavior

I made the following entity:

import {
  Entity,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class Foo {
  @PrimaryGeneratedColumn()
  id: number;
}

I ran typeorm migration:generate -- -n addFoo which created the following migration:

import {MigrationInterface, QueryRunner} from "typeorm";

export class addFoo1624984985251 implements MigrationInterface {
    name = 'addFoo1624984985251'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("CREATE TABLE `foo` (`id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`)) ENGINE=InnoDB");
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("DROP TABLE `foo`");
    }

}

I ran typeorm migration:run which ran the migration and updated the database as expected.

I deleted the file in which foo was defined.

I ran typeorm migration:generate -- -n removeFoo add got the following output:

> api@0.0.1 typeorm /usr/src/app
> node --require ts-node/register ./node_modules/typeorm/cli.js "migration:generate" "-n" "removeFoo"

No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! api@0.0.1 typeorm: `node --require ts-node/register ./node_modules/typeorm/cli.js "migration:generate" "-n" "removeFoo"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the api@0.0.1 typeorm script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-06-29T16_41_52_271Z-debug.log

Steps to Reproduce

The entity and migrations above are the files in their entirety, so the entity can be used to reproduce.

  1. Create an entity
  2. Generate a migration
  3. Run migrations
  4. Delete entity
  5. Generate a migration

My Environment

| Dependency | Version | | Operating System | macOS Big Sur v11.4 | | Node.js version | v16.2.0 | | Typescript version | v4.2.4 | | TypeORM version | v0.2.32 |

Additional Context

I first found this issue when joining tables in many-to-many relationships were not being dropped automatically. This open issue also has this bug https://github.com/typeorm/typeorm/issues/5463 This issue occurs both for regular tables for declared entities and for joining tables. Typeorm has no problem automatically changing everything else such as foreign keys, column names, etc.

Relevant Database Driver(s)

  • mysql

Are you willing to resolve this issue by submitting a Pull Request?

  • No, I don’t have the time and I wouldn’t even know how to start.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:16
  • Comments:10

github_iconTop GitHub Comments

6reactions
wojtekKrolcommented, Jun 23, 2022

Same

0reactions
Mayviscommented, Nov 17, 2022

If you have dev database, and can’t find previous migration that up and down the table.

First, I will directly drop table in dev database by using GUI or sql, then run npm run migration:generate -n='RemoveArtistScheduleTable' to create new migration. It will generate below queryRunner migration code.

import {MigrationInterface, QueryRunner} from "typeorm";

export class RemoveArtistScheduleTable1668646897289 implements MigrationInterface {
    name = 'RemoveArtistScheduleTable1668646897289'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TABLE "artists_schedules" ("artist_schedule_id" SERIAL NOT NULL, "name_zh" character varying(128) NOT NULL, "name_en" character varying(128) NOT NULL, "start_date" TIMESTAMP NOT NULL, "end_date" TIMESTAMP NOT NULL, "note" character varying(128), CONSTRAINT "PK_afe7d234982880815818a709f42" PRIMARY KEY ("artist_schedule_id"))`);
        await queryRunner.query(`CREATE TABLE "artists_schedules_j" ("artist_id" uuid NOT NULL, "artist_schedule_id" integer NOT NULL, CONSTRAINT "PK_49265248f108d71b1ce9ecd2f21" PRIMARY KEY ("artist_id", "artist_schedule_id"))`);
        await queryRunner.query(`CREATE INDEX "IDX_63c4b28c4b8133e39341a9603f" ON "artists_schedules_j" ("artist_id") `);
        await queryRunner.query(`CREATE INDEX "IDX_aa80b7ae66291fccde2e4b3182" ON "artists_schedules_j" ("artist_schedule_id") `);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_63c4b28c4b8133e39341a9603f4" FOREIGN KEY ("artist_id") REFERENCES "artists"("artist_id") ON DELETE SET NULL ON UPDATE CASCADE`);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_aa80b7ae66291fccde2e4b31823" FOREIGN KEY ("artist_schedule_id") REFERENCES "artists_schedules"("artist_schedule_id") ON DELETE CASCADE ON UPDATE CASCADE`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" DROP CONSTRAINT "FK_aa80b7ae66291fccde2e4b31823"`);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" DROP CONSTRAINT "FK_63c4b28c4b8133e39341a9603f4"`);
        await queryRunner.query(`DROP TABLE "artists_schedules_j"`);
        await queryRunner.query(`DROP TABLE "artists_schedules"`);
    }
}

Second, manually run the sql to create table again. In this case, execute below sql to re-create table.

CREATE TABLE "artists_schedules" ("artist_schedule_id" SERIAL NOT NULL, "name_zh" character varying(128) NOT NULL, "name_en" character varying(128) NOT NULL, "start_date" TIMESTAMP NOT NULL, "end_date" TIMESTAMP NOT NULL, "note" character varying(128), CONSTRAINT "PK_afe7d234982880815818a709f42" PRIMARY KEY ("artist_schedule_id"))
CREATE TABLE "artists_schedules_j" ("artist_id" uuid NOT NULL, "artist_schedule_id" integer NOT NULL, CONSTRAINT "PK_49265248f108d71b1ce9ecd2f21" PRIMARY KEY ("artist_id", "artist_schedule_id"))
CREATE INDEX "IDX_63c4b28c4b8133e39341a9603f" ON "artists_schedules_j" ("artist_id")
CREATE INDEX "IDX_aa80b7ae66291fccde2e4b3182" ON "artists_schedules_j" ("artist_schedule_id")
ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_63c4b28c4b8133e39341a9603f4" FOREIGN KEY ("artist_id") REFERENCES "artists"("artist_id") ON DELETE SET NULL ON UPDATE CASCADE
ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_aa80b7ae66291fccde2e4b31823" FOREIGN KEY ("artist_schedule_id") REFERENCES "artists_schedules"("artist_schedule_id") ON DELETE CASCADE ON UPDATE CASCADE

Finally, switch queryRunner method. Then delete your entity, associated code and run npm run migration:run on your dev and prod database.

import {MigrationInterface, QueryRunner} from "typeorm";

export class RemoveArtistScheduleTable1668646897289 implements MigrationInterface {
    name = 'RemoveArtistScheduleTable1668646897289'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" DROP CONSTRAINT "FK_aa80b7ae66291fccde2e4b31823"`);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" DROP CONSTRAINT "FK_63c4b28c4b8133e39341a9603f4"`);
        await queryRunner.query(`DROP TABLE "artists_schedules_j"`);
        await queryRunner.query(`DROP TABLE "artists_schedules"`);
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query(`CREATE TABLE "artists_schedules" ("artist_schedule_id" SERIAL NOT NULL, "name_zh" character varying(128) NOT NULL, "name_en" character varying(128) NOT NULL, "start_date" TIMESTAMP NOT NULL, "end_date" TIMESTAMP NOT NULL, "note" character varying(128), CONSTRAINT "PK_afe7d234982880815818a709f42" PRIMARY KEY ("artist_schedule_id"))`);
        await queryRunner.query(`CREATE TABLE "artists_schedules_j" ("artist_id" uuid NOT NULL, "artist_schedule_id" integer NOT NULL, CONSTRAINT "PK_49265248f108d71b1ce9ecd2f21" PRIMARY KEY ("artist_id", "artist_schedule_id"))`);
        await queryRunner.query(`CREATE INDEX "IDX_63c4b28c4b8133e39341a9603f" ON "artists_schedules_j" ("artist_id") `);
        await queryRunner.query(`CREATE INDEX "IDX_aa80b7ae66291fccde2e4b3182" ON "artists_schedules_j" ("artist_schedule_id") `);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_63c4b28c4b8133e39341a9603f4" FOREIGN KEY ("artist_id") REFERENCES "artists"("artist_id") ON DELETE SET NULL ON UPDATE CASCADE`);
        await queryRunner.query(`ALTER TABLE "artists_schedules_j" ADD CONSTRAINT "FK_aa80b7ae66291fccde2e4b31823" FOREIGN KEY ("artist_schedule_id") REFERENCES "artists_schedules"("artist_schedule_id") ON DELETE CASCADE ON UPDATE CASCADE`);
    }
}

I know this is a little bit complicated, but I always do this way. Hope this can help.

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeORM migration:generate working great except for DROP
The workaround is to manually add the "DROP TABLE" statement to the generated migration file. You may copy it from the down method...
Read more >
Migration generate drops/creates all constraints #1686 - GitHub
On an existing database in PostgreSQL 9.6.2 migration generation wants to drop all unique constraints and create them again. I ran this ...
Read more >
Migrations - typeorm - GitBook
TypeORM is able to automatically generate migration files with schema changes ... isCascade - If true , automatically drop objects (tables, functions, etc.) ......
Read more >
Database: Migrations - The PHP Framework For Web Artisans
The migrate:fresh command will drop all database tables regardless of their prefix. This command should be used with caution when developing on a...
Read more >
Active Record Migrations - Rails Edge Guides
Before this migration is run, there will be no table. After, the table ... Similarly, you can generate a migration to remove a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found