mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: check for version of MariaDB before extracting COLUMN_DEFAULT (#4783)
Added VersionUtils module to make it easier to compare coerce and compare versions of MariaDB database. See https://mariadb.com/kb/en/library/information-schema-columns-table/ Relevant excerpt for `COLUMN_DEFAULT`: > Default value for the column. From MariaDB 10.2.7, literals are quoted > to distinguish them from expressions. NULL means that the column has no > default. In MariaDB 10.2.6 and earlier, no quotes were used for any type > of default and NULL can either mean that there is no default, or that > the default column value is NULL.
This commit is contained in:
parent
d967180efc
commit
c30b4859d4
@ -27,7 +27,7 @@ services:
|
||||
|
||||
# mariadb
|
||||
mariadb:
|
||||
image: "mariadb:10.1.37"
|
||||
image: "mariadb:10.4.8"
|
||||
container_name: "typeorm-mariadb"
|
||||
ports:
|
||||
- "3307:3306"
|
||||
|
||||
@ -21,6 +21,7 @@ import {ColumnType, PromiseUtils} from "../../index";
|
||||
import {TableCheck} from "../../schema-builder/table/TableCheck";
|
||||
import {IsolationLevel} from "../types/IsolationLevel";
|
||||
import {TableExclusion} from "../../schema-builder/table/TableExclusion";
|
||||
import { VersionUtils } from "../../util/VersionUtils";
|
||||
|
||||
/**
|
||||
* Runs queries on a single mysql database connection.
|
||||
@ -1243,6 +1244,7 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
|
||||
return [];
|
||||
|
||||
const isMariaDb = this.driver.options.type === "mariadb";
|
||||
const dbVersion = await this.getVersion();
|
||||
|
||||
// create tables for loaded tables
|
||||
return Promise.all(dbTables.map(async dbTable => {
|
||||
@ -1290,8 +1292,16 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
|
||||
|| (isMariaDb && dbColumn["COLUMN_DEFAULT"] === "NULL")) {
|
||||
tableColumn.default = undefined;
|
||||
|
||||
} else if (/^CURRENT_TIMESTAMP(\([0-9]*\))?$/i.test(dbColumn["COLUMN_DEFAULT"])) {
|
||||
// New versions of MariaDB return expressions in lowercase. We need to set it in
|
||||
// uppercase so the comparison in MysqlDriver#compareDefaultValues does not fail.
|
||||
tableColumn.default = dbColumn["COLUMN_DEFAULT"].toUpperCase();
|
||||
} else if (isMariaDb && VersionUtils.isGreaterOrEqual(dbVersion, "10.2.7")) {
|
||||
// MariaDB started adding quotes to literals in COLUMN_DEFAULT since version 10.2.7
|
||||
// See https://mariadb.com/kb/en/library/information-schema-columns-table/
|
||||
tableColumn.default = dbColumn["COLUMN_DEFAULT"];
|
||||
} else {
|
||||
tableColumn.default = dbColumn["COLUMN_DEFAULT"] === "CURRENT_TIMESTAMP" ? dbColumn["COLUMN_DEFAULT"] : `'${dbColumn["COLUMN_DEFAULT"]}'`;
|
||||
tableColumn.default = `'${dbColumn["COLUMN_DEFAULT"]}'`;
|
||||
}
|
||||
|
||||
if (dbColumn["EXTRA"].indexOf("on update") !== -1) {
|
||||
@ -1659,4 +1669,9 @@ export class MysqlQueryRunner extends BaseQueryRunner implements QueryRunner {
|
||||
return c;
|
||||
}
|
||||
|
||||
protected async getVersion(): Promise<string> {
|
||||
const result = await this.query(`SELECT VERSION() AS \`version\``);
|
||||
return result[0]["version"];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
20
src/util/VersionUtils.ts
Normal file
20
src/util/VersionUtils.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export type Version = [number, number, number];
|
||||
|
||||
export class VersionUtils {
|
||||
static isGreaterOrEqual(version: string, targetVersion: string): boolean {
|
||||
const v1 = parseVersion(version);
|
||||
const v2 = parseVersion(targetVersion);
|
||||
|
||||
return v1[0] > v2[0] ||
|
||||
v1[0] === v2[0] && v1[1] > v2[1] ||
|
||||
v1[0] === v2[0] && v1[1] === v2[1] && v1[2] >= v2[2];
|
||||
}
|
||||
}
|
||||
|
||||
function parseVersion(version: string = ""): Version {
|
||||
const v: Version = [0, 0, 0];
|
||||
|
||||
version.split(".").forEach((value, i) => v[i] = parseInt(value, 10));
|
||||
|
||||
return v;
|
||||
}
|
||||
12
test/github-issues/4782/entity/Item.ts
Normal file
12
test/github-issues/4782/entity/Item.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { CreateDateColumn } from "../../../../src";
|
||||
import { PrimaryGeneratedColumn } from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import { Entity } from "../../../../src/decorator/entity/Entity";
|
||||
|
||||
@Entity()
|
||||
export class Item {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@CreateDateColumn()
|
||||
date: Date;
|
||||
}
|
||||
56
test/github-issues/4782/issue-4782.ts
Normal file
56
test/github-issues/4782/issue-4782.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import "reflect-metadata";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
import { VersionUtils } from "../../../src/util/VersionUtils";
|
||||
|
||||
describe("github issues > 4782 mariadb driver wants to recreate create/update date columns CURRENT_TIMESTAMP(6) === current_timestamp(6)", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
// logging: true,
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
enabledDrivers: ["mysql", "mariadb"]
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
it("should not want to execute migrations twice", () => Promise.all(connections.map(async connection => {
|
||||
const sql1 = await connection.driver.createSchemaBuilder().log();
|
||||
expect(sql1.upQueries).to.eql([]);
|
||||
})));
|
||||
|
||||
describe("VersionUtils", () => {
|
||||
describe("isGreaterOrEqual", () => {
|
||||
it("should return false when comparing invalid versions", () => {
|
||||
expect(VersionUtils.isGreaterOrEqual("", "")).to.equal(false);
|
||||
});
|
||||
|
||||
it("should return false when targetVersion is larger", () => {
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "1.2.4")).to.equal(false);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "1.4.3")).to.equal(false);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "2.2.3")).to.equal(false);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2", "1.3")).to.equal(false);
|
||||
expect(VersionUtils.isGreaterOrEqual("1", "2")).to.equal(false);
|
||||
expect(VersionUtils.isGreaterOrEqual(undefined as unknown as string, "0.0.1")).to.equal(false);
|
||||
});
|
||||
|
||||
it("should return true when targetVersion is smaller", () => {
|
||||
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "1.2.2")).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "1.1.3")).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2.3", "0.2.3")).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("1.2", "1.2")).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("1", "1")).to.equal(true);
|
||||
});
|
||||
|
||||
it("should work with mariadb-style versions", () => {
|
||||
const dbVersion = "10.4.8-MariaDB-1:10.4.8+maria~bionic";
|
||||
expect(VersionUtils.isGreaterOrEqual("10.4.9", dbVersion)).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("10.4.8", dbVersion)).to.equal(true);
|
||||
expect(VersionUtils.isGreaterOrEqual("10.4.7", dbVersion)).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user