feat: add concurrent indexes for postgres (#10442)

This commit is contained in:
Samuel Lukes 2023-12-29 11:52:49 +01:00 committed by GitHub
parent 75ec8f2032
commit f4e6eaf155
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 5 deletions

View File

@ -137,6 +137,18 @@ 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.
Typeorm supports generating SQL with this option if when the concurrent option is specified on the index.
```typescript
@Index(["firstName", "middleName", "lastName"], { concurrent: true })
```
For more information see the [postgres documentation](https://www.postgresql.org/docs/current/sql-createindex.html).
## Disabling synchronization
TypeORM does not support some index options and definitions (e.g. `lower`, `pg_trgm`) because of lot of different database specifics and multiple

View File

@ -139,6 +139,7 @@ export function Index(
parser: options ? options.parser : undefined,
sparse: options && options.sparse ? true : false,
background: options && options.background ? true : false,
concurrent: options && options.concurrent ? true : false,
expireAfterSeconds: options
? options.expireAfterSeconds
: undefined,

View File

@ -52,6 +52,12 @@ export interface IndexOptions {
*/
background?: boolean
/**
* Create the index using the CONCURRENTLY modifier
* Works only in postgres.
*/
concurrent?: boolean
/**
* Specifies a time to live, in seconds.
* This option is only supported for mongodb database.

View File

@ -4257,9 +4257,9 @@ export class PostgresQueryRunner
.map((columnName) => `"${columnName}"`)
.join(", ")
return new Query(
`CREATE ${index.isUnique ? "UNIQUE " : ""}INDEX "${
index.name
}" ON ${this.escapePath(table)} ${
`CREATE ${index.isUnique ? "UNIQUE " : ""}${
index.isConcurrent ? "CONCURRENTLY " : ""
}INDEX "${index.name}" ON ${this.escapePath(table)} ${
index.isSpatial ? "USING GiST " : ""
}(${columns}) ${index.where ? "WHERE " + index.where : ""}`,
)
@ -4291,10 +4291,21 @@ export class PostgresQueryRunner
let indexName = InstanceChecker.isTableIndex(indexOrName)
? indexOrName.name
: indexOrName
const concurrent = InstanceChecker.isTableIndex(indexOrName)
? indexOrName.isConcurrent
: false
const { schema } = this.driver.parseTableName(table)
return schema
? new Query(`DROP INDEX "${schema}"."${indexName}"`)
: new Query(`DROP INDEX "${indexName}"`)
? new Query(
`DROP INDEX ${
concurrent ? "CONCURRENTLY" : ""
}"${schema}"."${indexName}"`,
)
: new Query(
`DROP INDEX ${
concurrent ? "CONCURRENTLY" : ""
}"${indexName}"`,
)
}
/**

View File

@ -72,6 +72,12 @@ export interface IndexMetadataArgs {
*/
background?: boolean
/**
* Builds the index using the concurrently option.
* This option is only supported for postgres database.
*/
concurrent?: boolean
/**
* Specifies a time to live, in seconds.
* This option is only supported for mongodb database.

View File

@ -73,6 +73,12 @@ export class IndexMetadata {
*/
isBackground?: boolean
/**
* Builds the index using the concurrently option.
* This options is only supported for postgres database.
*/
isConcurrent?: boolean
/**
* Specifies a time to live, in seconds.
* This option is only supported for mongodb database.
@ -148,6 +154,7 @@ export class IndexMetadata {
this.where = options.args.where
this.isSparse = options.args.sparse
this.isBackground = options.args.background
this.isConcurrent = options.args.concurrent
this.expireAfterSeconds = options.args.expireAfterSeconds
this.givenName = options.args.name
this.givenColumnNames = options.args.columns

View File

@ -27,6 +27,12 @@ export interface TableIndexOptions {
*/
isSpatial?: boolean
/**
* Builds the index using the concurrently option.
* This options is only supported for postgres database.
*/
isConcurrent?: boolean
/**
* The FULLTEXT modifier indexes the entire column and does not allow prefixing.
* Supported only in MySQL & SAP HANA.

View File

@ -32,6 +32,12 @@ export class TableIndex {
*/
isSpatial: boolean
/**
* Create the index using the CONCURRENTLY modifier
* Works only in postgres.
*/
isConcurrent: boolean
/**
* The FULLTEXT modifier indexes the entire column and does not allow prefixing.
* Works only in MySQL.
@ -67,6 +73,7 @@ export class TableIndex {
this.columnNames = options.columnNames
this.isUnique = !!options.isUnique
this.isSpatial = !!options.isSpatial
this.isConcurrent = !!options.isConcurrent
this.isFulltext = !!options.isFulltext
this.isNullFiltered = !!options.isNullFiltered
this.parser = options.parser
@ -86,6 +93,7 @@ export class TableIndex {
columnNames: [...this.columnNames],
isUnique: this.isUnique,
isSpatial: this.isSpatial,
isConcurrent: this.isConcurrent,
isFulltext: this.isFulltext,
isNullFiltered: this.isNullFiltered,
parser: this.parser,
@ -108,6 +116,7 @@ export class TableIndex {
),
isUnique: indexMetadata.isUnique,
isSpatial: indexMetadata.isSpatial,
isConcurrent: indexMetadata.isConcurrent,
isFulltext: indexMetadata.isFulltext,
isNullFiltered: indexMetadata.isNullFiltered,
parser: indexMetadata.parser,