Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating migrations when having entities with CreateDateColumn/UpdateDateColumn and default values as CURRENT_TIMESTAMP leads to a lot of redundant queries in resulting migrations #6412

Closed
noneedinmagic opened this issue Jul 16, 2020 · 1 comment · Fixed by #7517

Comments

@noneedinmagic
Copy link

noneedinmagic commented Jul 16, 2020

Issue type:

[ ] question
[x] bug report
[ ] feature request
[ ] documentation issue

Database system/driver:

[ ] cordova
[ ] mongodb
[ ] mssql
[x] mysql / mariadb
[ ] oracle
[ ] postgres
[ ] cockroachdb
[ ] sqlite
[ ] sqljs
[ ] react-native
[ ] expo

TypeORM version:

[x] latest
[ ] @next
[ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

Hello! I have and issue in different projects for the last couple of month. Every time when I try to generate migrations it creates a lot of redundant queries to change created_at and updated_at fields even if there are no changes.

Example of the entity (slightly redacted to avoid confusion with my own reusable code, it definitely had the same issue in such form):

@Entity()
export class ProductBrand extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @Column()
  public name: string;

  CreateDateColumn({
      name: 'created_at',
      type: 'datetime',
      precision: null,
      default: () => 'CURRENT_TIMESTAMP',
      transformer: DatetimeTransformer,
  })
  public createdAt: Moment;

  UpdateDateColumn({
      name: 'updated_at',
      type: 'datetime',
      precision: null,
      default: () => 'CURRENT_TIMESTAMP',
      onUpdate: 'CURRENT_TIMESTAMP',
      transformer: DatetimeTransformer,
  })
  public updatedAt: Moment;

  @OneToMany(() => Product, (product) => product.brand)
  @Type(() => Product)
  public products?: Product[];

  @OneToMany(() => ProductBrandAlias, (alias) => alias.brand)
  @Type(() => ProductBrandAlias)
  public aliases?: ProductBrandAlias[];
}

The scripts:

    "migrate": "npx ts-node ./node_modules/typeorm/cli.js migration:run",
    "migrate:down": "npx ts-node -r module-alias/register ./node_modules/typeorm/cli.js migration:revert",
    "migrate:create": "npx ts-node -r module-alias/register ./node_modules/typeorm/cli.js migration:create",
    "migrate:gen": "npx ts-node -r module-alias/register ./node_modules/typeorm/cli.js migration:generate",

Running command:
npm run build && npm run migrate:gen -- -n Test

Resulting migration:

import {MigrationInterface, QueryRunner} from "typeorm";

export class Test1594918763683 implements MigrationInterface {
    name = 'Test1594918763683'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `product_code` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_code` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_brand` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_brand` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_price` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_price` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `product_price` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_price` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_brand` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_brand` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_code` CHANGE `updated_at` `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP");
        await queryRunner.query("ALTER TABLE `product_code` CHANGE `created_at` `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP");
    }

}

As you can see, these commands are totally equal and just cluttering my migrations. And this is a code from the project only with 4 such entities! In another project I have 13 entities with those columns, so there I need to remove ~52 string from each generated migration which is really annoying :(

@chihabeeddine
Copy link

I'm having this problem, does anyone have a solution for this ?

AlexMesser added a commit that referenced this issue Mar 30, 2021
AlexMesser added a commit that referenced this issue Apr 1, 2021
…ies during synchronization (#7517)

* fix #3991

* fix #3991

* improved test for #2737;
fixed remaining issues in #2737;

* fix #6412

* added test for #4281 and #4658

* fixed `NOW()` function usage in MySQL/MariaDB;
fixed precision in datetime functions for MySQL/MariaDB;
improved #3991 test for MySQL/MariaDB;

* added test for #2333

* added test for #7381

* added "remove" operation check in #4658 test

* fixed precision in datetime functions for PostgreSQl;
improved #3991 test for PostgreSQl;

* improved #3991 test for CockroachDB;

* improved #3991 test for Sqlite;

* improved #3991 test for Oracle and SQLServer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants