mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: allow json as alias for longtext mariadb (#10018)
This commit is contained in:
parent
54f4f8986a
commit
2a2bb4bdc1
@ -732,12 +732,17 @@ export class MysqlDriver implements Driver {
|
||||
return "tinyint"
|
||||
} else if (column.type === "uuid" && !this.uuidColumnTypeSuported) {
|
||||
return "varchar"
|
||||
} else if (column.type === "json" && this.options.type === "mariadb") {
|
||||
} else if (
|
||||
column.type === "json" &&
|
||||
this.options.type === "mariadb" &&
|
||||
!VersionUtils.isGreaterOrEqual(this.version ?? "0.0.0", "10.4.3")
|
||||
) {
|
||||
/*
|
||||
* MariaDB implements this as a LONGTEXT rather, as the JSON data type contradicts the SQL standard,
|
||||
* and MariaDB's benchmarks indicate that performance is at least equivalent.
|
||||
*
|
||||
* @see https://mariadb.com/kb/en/json-data-type/
|
||||
* if Version is 10.4.3 or greater, JSON is an alias for longtext and an automatic check_json(column) constraint is added
|
||||
*/
|
||||
return "longtext"
|
||||
} else if (
|
||||
@ -999,7 +1004,7 @@ export class MysqlDriver implements Driver {
|
||||
|
||||
const isColumnChanged =
|
||||
tableColumn.name !== columnMetadata.databaseName ||
|
||||
tableColumn.type !== this.normalizeType(columnMetadata) ||
|
||||
this.isColumnDataTypeChanged(tableColumn, columnMetadata) ||
|
||||
tableColumn.length !== this.getColumnLength(columnMetadata) ||
|
||||
tableColumn.width !== columnMetadata.width ||
|
||||
(columnMetadata.precision !== undefined &&
|
||||
@ -1358,4 +1363,22 @@ export class MysqlDriver implements Driver {
|
||||
|
||||
return comment
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper to check if column data types have changed
|
||||
* This can be used to manage checking any types the
|
||||
* database may alias
|
||||
*/
|
||||
private isColumnDataTypeChanged(
|
||||
tableColumn: TableColumn,
|
||||
columnMetadata: ColumnMetadata,
|
||||
) {
|
||||
// this is an exception for mariadb versions where json is an alias for longtext
|
||||
if (
|
||||
this.normalizeType(columnMetadata) === "json" &&
|
||||
tableColumn.type.toLowerCase() === "longtext"
|
||||
)
|
||||
return false
|
||||
return tableColumn.type !== this.normalizeType(columnMetadata)
|
||||
}
|
||||
}
|
||||
|
||||
10
test/github-issues/9903/entity/User.ts
Normal file
10
test/github-issues/9903/entity/User.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from "../../../../src"
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn("increment")
|
||||
id?: number
|
||||
|
||||
@Column({ type: "json" })
|
||||
jsonData: string
|
||||
}
|
||||
83
test/github-issues/9903/issue-9903.ts
Normal file
83
test/github-issues/9903/issue-9903.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import "../../utils/test-setup"
|
||||
import {
|
||||
createTestingConnections,
|
||||
closeTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../utils/test-utils"
|
||||
import { DataSource } from "../../../src/index"
|
||||
import { expect } from "chai"
|
||||
import { User } from "./entity/User"
|
||||
|
||||
describe("github issues > #9903 json data type", () => {
|
||||
let connections: DataSource[]
|
||||
|
||||
afterEach(() => closeTestingConnections(connections))
|
||||
|
||||
describe("json supported type for mariadb", () => {
|
||||
const expectedJsonString = JSON.stringify({
|
||||
firstName: "Quality",
|
||||
lastName: "Tester",
|
||||
})
|
||||
const newUser: User = {
|
||||
jsonData: expectedJsonString,
|
||||
}
|
||||
|
||||
const badJsonUser: User = {
|
||||
jsonData: `'''faux---'''`,
|
||||
}
|
||||
|
||||
before(
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
enabledDrivers: ["mariadb"],
|
||||
})),
|
||||
)
|
||||
beforeEach(() => reloadTestingDatabases(connections))
|
||||
|
||||
it("should create table with json constraint", () =>
|
||||
Promise.all(
|
||||
connections.map(async (connection) => {
|
||||
const userRepository = connection.getRepository(User)
|
||||
|
||||
await userRepository.save(newUser)
|
||||
|
||||
const savedUser = await userRepository.findOneOrFail({
|
||||
where: { id: newUser.id },
|
||||
})
|
||||
|
||||
expect(savedUser).to.not.be.null
|
||||
expect(savedUser.jsonData).to.equal(expectedJsonString)
|
||||
|
||||
// trying to save bad json
|
||||
// here when executing the save the value is passed to JSON.stringify(),
|
||||
// this will ensure its json valid in mariadb so this won't break the constraint
|
||||
try {
|
||||
await userRepository.save(badJsonUser)
|
||||
} catch (err) {
|
||||
expect.fail(
|
||||
null,
|
||||
null,
|
||||
"Should have not thrown an error",
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
await userRepository.query(
|
||||
"INSERT INTO user values (?, ?)",
|
||||
[3, badJsonUser.jsonData],
|
||||
)
|
||||
expect.fail(null, null, "Should have thrown an error")
|
||||
} catch (err) {
|
||||
expect(err).not.to.be.undefined
|
||||
expect(err.sqlMessage).not.to.be.undefined
|
||||
expect(err.sqlMessage).to.equal(
|
||||
"CONSTRAINT `user.jsonData` failed for `test`.`user`",
|
||||
)
|
||||
}
|
||||
}),
|
||||
))
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user