Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fix: migration:generate issue with onUpdate using mariadb 10.4 (#6714)
* Update MysqlQueryRunner.ts

In Mariadb the extra information of a DDL is in upper case and in javascript String.indexOf() function is case sensitive, because of that when you generate a new migrations  in mariadb it always create a line to update  "onUpdate" lines.

 example:
```sql
CREATE TABLE `test` (
  `test_id` int(11) NOT NULL AUTO_INCREMENT,
  `test_update` timestamp() NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`test_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
```

When you try to generate a new migration always create the next migration file:

```ts
import { MigrationInterface, QueryRunner } from 'typeorm';

export class test261600082802966 implements MigrationInterface {
  name = 'test261600082802966';

  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      'ALTER TABLE `test` CHANGE `test_update` `test_update` timestamp() NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()'
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.query(
      'ALTER TABLE `test` CHANGE `test_update` `test_update` timestamp() NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE current_timestamp()'
    );
  }
}
```
Entity file test.ts
```ts
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@entity()
export class test extends BaseEntity {
  @PrimaryGeneratedColumn({})
  test_id: number;

  @column({
    type: 'timestamp',
    default: () => 'CURRENT_TIMESTAMP()',
    onUpdate: 'CURRENT_TIMESTAMP()',
    nullable: false,
  })
  test_update: Date;
}
```

* Update MysqlQueryRunner.ts

* add test to issue 6714

* Update MysqlQueryRunner.ts

* Update issue-6714.ts

Co-authored-by: jesusegado <j.fernandez@lionline.de>
  • Loading branch information
jesussegado and jesusegado committed Sep 17, 2020
1 parent 8820d4a commit 6e28322
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/driver/mysql/MysqlQueryRunner.ts
Expand Up @@ -1321,7 +1321,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
}

if (dbColumn["EXTRA"].indexOf("on update") !== -1) {
tableColumn.onUpdate = dbColumn["EXTRA"].substring(dbColumn["EXTRA"].indexOf("on update") + 10);
// New versions of MariaDB return expressions in lowercase. We need to set it in
// uppercase so the comparison in MysqlDriver#compareExtraValues does not fail.
tableColumn.onUpdate = dbColumn["EXTRA"].substring(dbColumn["EXTRA"].indexOf("on update") + 10).toUpperCase();
}

if (dbColumn["GENERATION_EXPRESSION"]) {
Expand Down
17 changes: 17 additions & 0 deletions test/github-issues/6714/entity/session.ts
@@ -0,0 +1,17 @@
import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src";

@Entity({ name: "Session" })
export class Session {

@PrimaryGeneratedColumn()
id?: number;

@Column({
type: "timestamp",
precision: 3,
default: () => "CURRENT_TIMESTAMP(3)",
onUpdate: "CURRENT_TIMESTAMP(3)",
})
ts: Date;

}
15 changes: 15 additions & 0 deletions test/github-issues/6714/entity/sessionchanged.ts
@@ -0,0 +1,15 @@
import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src";

@Entity({ name: "Session" })
export class Session {
@PrimaryGeneratedColumn()
id?: number;

@Column({
type: "timestamp",
precision: 4,
default: () => "CURRENT_TIMESTAMP(4)",
onUpdate: "CURRENT_TIMESTAMP(4)",
})
ts: Date;
}
59 changes: 59 additions & 0 deletions test/github-issues/6714/issue-6714.ts
@@ -0,0 +1,59 @@
import "reflect-metadata";
import {
createTestingConnections,
closeTestingConnections,
reloadTestingDatabases,
} from "../../utils/test-utils";
import { Connection } from "../../../src/connection/Connection";
import { expect } from "chai";
import { Session as baseEntity } from "./entity/session";
import { Session as changedEntity } from "./entity/sessionchanged";

describe("github issues > #6714 Migration:generate issue with onUpdate using mariadb 10.4", () => {
it("dont change anything", async () => {
let connections: Connection[];
connections = await createTestingConnections({
entities: [baseEntity],
schemaCreate: false,
dropSchema: true,
enabledDrivers: ["mariadb"],
});
await reloadTestingDatabases(connections);
await Promise.all(
connections.map(async (connection) => {
const schemaBuilder = connection.driver.createSchemaBuilder();
const syncQueries = await schemaBuilder.log();
expect(syncQueries.downQueries).to.be.eql([]);
expect(syncQueries.upQueries).to.be.eql([]);
})
);
await closeTestingConnections(connections);
});
it("recognizing on update changes", async () => {
// this connection create database with a Session entity
const baseConnections = await createTestingConnections({
entities: [baseEntity],
schemaCreate: true, // create the database
dropSchema: true,
enabledDrivers: ["mariadb"],
});
// this connection change Session entity on update value
const connections = await createTestingConnections({
entities: [changedEntity],
schemaCreate: false, // don't change the entity
dropSchema: false,
enabledDrivers: ["mariadb"],
name: "test",
});
await Promise.all(
connections.map(async (connection) => {
const schemaBuilder = connection.driver.createSchemaBuilder();
const syncQueries = await schemaBuilder.log();
expect(syncQueries.downQueries.length).not.to.be.eql(0);
expect(syncQueries.upQueries.length).not.to.be.eql(0);
})
);
await closeTestingConnections(baseConnections);
await closeTestingConnections(connections);
});
});

0 comments on commit 6e28322

Please sign in to comment.