fix: resolve issue CREATE/DROP Index concurrently (#10634)

Closes: #10626
This commit is contained in:
Alessio Napolitano 2024-01-26 06:38:30 +01:00 committed by GitHub
parent b67ae360f6
commit 8aa8690f94
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 81 additions and 5 deletions

View File

@ -140,6 +140,7 @@ export class Thing {
## Concurrent creation
In order to avoid having to obtain an access exclusive lock when creating and dropping indexes in postgres, you may create them using the CONCURRENTLY modifier.
If you want use the concurrent option, you need set `migrationsTransactionMode: none` between data source options.
Typeorm supports generating SQL with this option if when the concurrent option is specified on the index.

View File

@ -4297,9 +4297,9 @@ export class PostgresQueryRunner
.map((columnName) => `"${columnName}"`)
.join(", ")
return new Query(
`CREATE ${index.isUnique ? "UNIQUE " : ""}${
index.isConcurrent ? "CONCURRENTLY " : ""
}INDEX "${index.name}" ON ${this.escapePath(table)} ${
`CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX${
index.isConcurrent ? " CONCURRENTLY" : ""
} "${index.name}" ON ${this.escapePath(table)} ${
index.isSpatial ? "USING GiST " : ""
}(${columns}) ${index.where ? "WHERE " + index.where : ""}`,
)
@ -4338,12 +4338,12 @@ export class PostgresQueryRunner
return schema
? new Query(
`DROP INDEX ${
concurrent ? "CONCURRENTLY" : ""
concurrent ? "CONCURRENTLY " : ""
}"${schema}"."${indexName}"`,
)
: new Query(
`DROP INDEX ${
concurrent ? "CONCURRENTLY" : ""
concurrent ? "CONCURRENTLY " : ""
}"${indexName}"`,
)
}

View File

@ -0,0 +1,13 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "../../../../src"
@Entity({
name: "user",
})
export class User {
@PrimaryGeneratedColumn()
id: number
@Index("concurrentTest", { concurrent: true })
@Column({ nullable: true })
name: string
}

View File

@ -0,0 +1,62 @@
import "reflect-metadata"
import {
createTestingConnections,
closeTestingConnections,
} from "../../utils/test-utils"
import { DataSource } from "../../../src/index.js"
import { expect } from "chai"
describe("github issues > #10626 Postgres CREATE INDEX CONCURRENTLY bug", () => {
let dataSources: DataSource[]
before(
async () =>
(dataSources = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: false,
dropSchema: true,
enabledDrivers: ["postgres"],
logging: true,
})),
)
after(() => closeTestingConnections(dataSources))
it("has to create INDEX CONCURRENTLY", () =>
Promise.all(
dataSources.map(async (dataSource) => {
await dataSource.setOptions({
...dataSource.options,
migrationsTransactionMode: "none",
})
await dataSource.synchronize()
const concurrentTestIndexes = await dataSource.query(
`SELECT * FROM pg_indexes WHERE indexname = 'concurrentTest'`,
)
expect(concurrentTestIndexes).has.length(1)
}),
))
it("has to drop INDEX CONCURRENTLY", () =>
Promise.all(
dataSources.map(async (dataSource) => {
await dataSource.setOptions({
...dataSource.options,
migrationsTransactionMode: "none",
})
await dataSource.synchronize()
const queryRunner = dataSource.createQueryRunner()
let table = await queryRunner.getTable("user")
if (table) {
await queryRunner.dropIndex(table, table?.indices[0])
}
const queries = queryRunner.getMemorySql().upQueries
expect(queries[0].query).to.be.eql(
'DROP INDEX "public"."concurrentTest"',
)
await queryRunner.release()
}),
))
})