From a43e8967bcd35b41e94fbf548fb455c7587eaa69 Mon Sep 17 00:00:00 2001 From: Harry Brundage Date: Mon, 8 Jan 2024 08:15:04 -0500 Subject: [PATCH] Add support for concurrent index creation statements (#148) PG supports a `CONCURRENTLY` keyword on index creation that changes how the indexing proceeds under the hood. It caused a parse error before, now it doesn't! See https://www.postgresql.org/docs/current/sql-createindex.html --- src/syntax/ast.ts | 1 + src/syntax/create-index.ne | 18 ++++++++++-------- src/syntax/create-index.spec.ts | 27 +++++++++++++++++++++++++++ src/to-sql.ts | 3 +++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/syntax/ast.ts b/src/syntax/ast.ts index 285ae60..b505c93 100644 --- a/src/syntax/ast.ts +++ b/src/syntax/ast.ts @@ -410,6 +410,7 @@ export interface CreateIndexStatement extends PGNode { where?: Expr; unique?: true; ifNotExists?: true; + concurrently?: true; indexName?: Name; tablespace?: string; with?: CreateIndexWith[]; diff --git a/src/syntax/create-index.ne b/src/syntax/create-index.ne index 87a4c5c..5c5f784 100644 --- a/src/syntax/create-index.ne +++ b/src/syntax/create-index.ne @@ -10,6 +10,7 @@ createindex_statement -> %kw_create %kw_unique:? kw_index + %kw_concurrently:? kw_ifnotexists:? word:? %kw_on @@ -24,14 +25,15 @@ createindex_statement {% x => track(x, { type: 'create index', ...x[1] && { unique: true }, - ...x[3] && { ifNotExists: true }, - ...x[4] && { indexName: asName(x[4]) }, - table: x[6], - ...x[7] && { using: asName(x[7]) }, - expressions: x[9], - ...x[11] && { with: x[11] }, - ...x[12] && { tablespace: unwrap(x[12]) }, - ...x[13] && { where: unwrap(x[13]) }, + ...x[3] && { concurrently: true }, + ...x[4] && { ifNotExists: true }, + ...x[5] && { indexName: asName(x[5]) }, + table: x[7], + ...x[8] && { using: asName(x[8]) }, + expressions: x[10], + ...x[12] && { with: x[12] }, + ...x[13] && { tablespace: unwrap(x[13]) }, + ...x[14] && { where: unwrap(x[14]) }, }) %} createindex_expressions -> createindex_expression (comma createindex_expression {% last %}):* {% ([head, tail]) => { diff --git a/src/syntax/create-index.spec.ts b/src/syntax/create-index.spec.ts index 088ebb9..a8efcc0 100644 --- a/src/syntax/create-index.spec.ts +++ b/src/syntax/create-index.spec.ts @@ -215,4 +215,31 @@ describe('Create index', () => { }], tablespace: 'abc', }); + + checkCreateIndex(['create index concurrently blah on test(col)'], { + type: 'create index', + indexName: { name: 'blah' }, + table: { name: 'test' }, + concurrently: true, + expressions: [{ + expression: { type: 'ref', name: 'col' }, + }], + }); + checkCreateIndex(['create index concurrently on test(col)'], { + type: 'create index', + table: { name: 'test', }, + concurrently: true, + expressions: [{ + expression: { type: 'ref', name: 'col' }, + }], + }); + checkCreateIndex(['create unique index concurrently on test(col)'], { + type: 'create index', + table: { name: 'test', }, + concurrently: true, + unique: true, + expressions: [{ + expression: { type: 'ref', name: 'col' }, + }], + }); }); \ No newline at end of file diff --git a/src/to-sql.ts b/src/to-sql.ts index 65e87b6..8296447 100644 --- a/src/to-sql.ts +++ b/src/to-sql.ts @@ -880,6 +880,9 @@ const visitor = astVisitor(m => ({ createIndex: c => { ret.push(c.unique ? 'CREATE UNIQUE INDEX ' : 'CREATE INDEX '); + if (c.concurrently) { + ret.push('CONCURRENTLY '); + } if (c.ifNotExists) { ret.push(' IF NOT EXISTS '); }