mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
fix: add collation update detection in PostgresDriver (#11441)
* fix(postgres): collation not updated in DB when changed in entity Closes: #8647 * test: issue #8647 * test: add enableDrivers, combine seperated cases * test: update test name * test: remove unnecessary characters in test case * style: fix formatting * style: fix comments typo
This commit is contained in:
parent
413f0a68c8
commit
24c3e38c51
@ -1249,7 +1249,8 @@ export class PostgresDriver implements Driver {
|
||||
tableColumn.srid !== columnMetadata.srid ||
|
||||
tableColumn.generatedType !== columnMetadata.generatedType ||
|
||||
(tableColumn.asExpression || "").trim() !==
|
||||
(columnMetadata.asExpression || "").trim()
|
||||
(columnMetadata.asExpression || "").trim() ||
|
||||
tableColumn.collation !== columnMetadata.collation
|
||||
|
||||
// DEBUG SECTION
|
||||
// if (isColumnChanged) {
|
||||
|
||||
@ -2183,6 +2183,31 @@ export class PostgresQueryRunner
|
||||
)
|
||||
}
|
||||
|
||||
// update column collation
|
||||
if (newColumn.collation !== oldColumn.collation) {
|
||||
upQueries.push(
|
||||
new Query(
|
||||
`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${
|
||||
newColumn.name
|
||||
}" TYPE ${newColumn.type} COLLATE "${
|
||||
newColumn.collation
|
||||
}"`,
|
||||
),
|
||||
)
|
||||
|
||||
const oldCollation = oldColumn.collation
|
||||
? `"${oldColumn.collation}"`
|
||||
: `pg_catalog."default"` // if there's no old collation, use default
|
||||
|
||||
downQueries.push(
|
||||
new Query(
|
||||
`ALTER TABLE ${this.escapePath(table)} ALTER COLUMN "${
|
||||
newColumn.name
|
||||
}" TYPE ${newColumn.type} COLLATE ${oldCollation}`,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (newColumn.generatedType !== oldColumn.generatedType) {
|
||||
// Convert generated column data to normal column
|
||||
if (
|
||||
|
||||
13
test/github-issues/8647/entity/item.entity.ts
Normal file
13
test/github-issues/8647/entity/item.entity.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Entity, PrimaryGeneratedColumn, Column } from "../../../../src/index"
|
||||
|
||||
export const OLD_COLLATION = "POSIX"
|
||||
export const NEW_COLLATION = "C"
|
||||
|
||||
@Entity()
|
||||
export class Item {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column({ type: "varchar", length: 100, collation: OLD_COLLATION })
|
||||
name: string
|
||||
}
|
||||
85
test/github-issues/8647/issue-8647.ts
Normal file
85
test/github-issues/8647/issue-8647.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import "reflect-metadata"
|
||||
import {
|
||||
createTestingConnections,
|
||||
closeTestingConnections,
|
||||
reloadTestingDatabases,
|
||||
} from "../../utils/test-utils"
|
||||
import { DataSource } from "../../../src/data-source/DataSource"
|
||||
import { expect } from "chai"
|
||||
import { Item, NEW_COLLATION } from "./entity/item.entity"
|
||||
|
||||
describe("github issues > #8647 Collation changes are not synced to RDBMS", () => {
|
||||
let connections: DataSource[]
|
||||
|
||||
before(
|
||||
async () =>
|
||||
(connections = await createTestingConnections({
|
||||
enabledDrivers: ["postgres"],
|
||||
driverSpecific: {
|
||||
applicationName: "collation-detection-test",
|
||||
},
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchema: true,
|
||||
})),
|
||||
)
|
||||
beforeEach(() => reloadTestingDatabases(connections))
|
||||
after(() => closeTestingConnections(connections))
|
||||
|
||||
const COLUMN_NAME = "name"
|
||||
|
||||
it("ALTER ... COLLATE query should be created", async () => {
|
||||
await Promise.all(
|
||||
connections.map(async (connection) => {
|
||||
// change metadata
|
||||
const meta = connection.getMetadata(Item)
|
||||
const col = meta.columns.find(
|
||||
(c) => c.propertyName === COLUMN_NAME,
|
||||
)!
|
||||
const OLD_COLLATION = col.collation
|
||||
col.collation = NEW_COLLATION
|
||||
|
||||
// capture generated up queries
|
||||
const sqlInMemory = await connection.driver
|
||||
.createSchemaBuilder()
|
||||
.log()
|
||||
const tableName = meta.tableName
|
||||
const expectedUp = `ALTER TABLE "${tableName}" ALTER COLUMN "${COLUMN_NAME}" TYPE character varying COLLATE "${NEW_COLLATION}"`
|
||||
const expectedDown = `ALTER TABLE "${tableName}" ALTER COLUMN "${COLUMN_NAME}" TYPE character varying COLLATE "${OLD_COLLATION}"`
|
||||
|
||||
// assert that the expected queries are in the generated SQL
|
||||
const upJoined = sqlInMemory.upQueries
|
||||
.map((q) => q.query.replace(/\s+/g, " ").trim())
|
||||
.join(" ")
|
||||
expect(upJoined).to.include(expectedUp)
|
||||
const downJoined = sqlInMemory.downQueries
|
||||
.map((q) => q.query.replace(/\s+/g, " ").trim())
|
||||
.join(" ")
|
||||
expect(downJoined).to.include(expectedDown)
|
||||
|
||||
// assert that collation changes are applied to the database
|
||||
const queryRunner = connection.createQueryRunner()
|
||||
|
||||
try {
|
||||
let table = await queryRunner.getTable(meta.tableName)
|
||||
const originColumn = table!.columns.find(
|
||||
(c) => c.name === COLUMN_NAME,
|
||||
)!
|
||||
// old collation should be appeared
|
||||
expect(originColumn.collation).to.equal(OLD_COLLATION)
|
||||
|
||||
await connection.synchronize()
|
||||
|
||||
table = await queryRunner.getTable(meta.tableName)
|
||||
const appliedColumn = table!.columns.find(
|
||||
(c) => c.name === COLUMN_NAME,
|
||||
)!
|
||||
// new collation should be appeared
|
||||
expect(appliedColumn.collation).to.equal(NEW_COLLATION)
|
||||
} finally {
|
||||
await queryRunner.release()
|
||||
}
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user