Skip to content

Commit 2017285

Browse files
authored
Add support for PostgreSQL keywords in CREATE CONSTRAINT TRIGGER (#948)
Config: ```js language: 'postgresql', keywordCase: 'upper', identifierCase: 'lower', ``` Before: ```sql CREATE CONSTRAINT TRIGGER example_trigger AFTER insert OR UPDATE of column_a, column_b ON example_table DEFERRABLE INITIALLY deferred FOR each ROW EXECUTE procedure example_function (); CREATE TRIGGER example_trigger AFTER insert OR UPDATE OR delete ON example_table FOR each ROW EXECUTE function example_function (); ``` After: ```sql CREATE CONSTRAINT TRIGGER example_trigger AFTER INSERT OR UPDATE OF column_a, column_b ON example_table DEFERRABLE INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE example_function (); CREATE TRIGGER example_trigger AFTER INSERT OR UPDATE OR DELETE ON example_table FOR EACH ROW EXECUTE FUNCTION example_function (); ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * PostgreSQL formatting now recognizes additional reserved multi-word phrases and variants (improves handling of trigger/constraint event clauses, EXECUTE forms, AFTER/DEFERRABLE variants, and FOR EACH ROW) for more accurate SQL output. * **Tests** * Added regression tests verifying CREATE CONSTRAINT/TRIGGER formatting and correct casing preservation for keywords and identifiers. <!-- review_stack_entry_start --> [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/sql-formatter-org/sql-formatter/pull/948) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents acdb534 + 0668f33 commit 2017285

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

src/languages/postgresql/postgresql.formatter.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,10 @@ const tabularOnelineClauses = expandPhrases([
6262
'TRUNCATE [TABLE] [ONLY]',
6363
// other
6464
'SET SCHEMA',
65-
'AFTER',
65+
'{BEFORE | AFTER | INSTEAD OF} {INSERT | UPDATE [OF] | DELETE | TRUNCATE}',
66+
'[NOT] DEFERRABLE',
67+
'INITIALLY {DEFERRED | IMMEDIATE}',
68+
'[NOT] DEFERRABLE INITIALLY {DEFERRED | IMMEDIATE}',
6669
// https://www.postgresql.org/docs/14/sql-commands.html
6770
'ABORT',
6871
'ALTER AGGREGATE',
@@ -200,7 +203,7 @@ const tabularOnelineClauses = expandPhrases([
200203
'DROP USER',
201204
'DROP USER MAPPING',
202205
'DROP VIEW',
203-
'EXECUTE',
206+
'EXECUTE [FUNCTION | PROCEDURE]',
204207
'EXPLAIN',
205208
'FETCH',
206209
'GRANT',
@@ -255,6 +258,8 @@ const reservedKeywordPhrases = expandPhrases([
255258
'ON {UPDATE | DELETE} [NO ACTION | RESTRICT | CASCADE | SET NULL | SET DEFAULT]',
256259
'DO {NOTHING | UPDATE}',
257260
'AS MATERIALIZED',
261+
'FOR EACH ROW',
262+
'OR {INSERT | UPDATE [OF] | DELETE | TRUNCATE}',
258263
'{ROWS | RANGE | GROUPS} BETWEEN',
259264
// comparison operator
260265
'IS [NOT] DISTINCT FROM',

test/postgresql.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,41 @@ describe('PostgreSqlFormatter', () => {
258258
dedent`COMMENT ON TABLE foo IS 'Hello my table';`
259259
);
260260
});
261+
262+
it('formats keywords in CREATE CONSTRAINT TRIGGER', () => {
263+
expect(
264+
format(
265+
`create constraint trigger Example_Trigger
266+
after insert
267+
or
268+
update of Column_A,
269+
Column_B on Example_Table
270+
deferrable initially deferred for each row
271+
execute procedure Example_Function ();`,
272+
{ keywordCase: 'upper', identifierCase: 'lower' }
273+
)
274+
).toBe(dedent`
275+
CREATE CONSTRAINT TRIGGER example_trigger
276+
AFTER INSERT OR UPDATE OF column_a,
277+
column_b ON example_table
278+
DEFERRABLE INITIALLY DEFERRED FOR EACH ROW
279+
EXECUTE PROCEDURE example_function ();
280+
`);
281+
});
282+
283+
it('formats multiple CREATE TRIGGER events without treating OR as a logical operator', () => {
284+
expect(
285+
format(
286+
`create trigger Example_Trigger
287+
after insert or update or delete on Example_Table
288+
for each row
289+
execute function Example_Function ();`,
290+
{ keywordCase: 'upper', identifierCase: 'lower' }
291+
)
292+
).toBe(dedent`
293+
CREATE TRIGGER example_trigger
294+
AFTER INSERT OR UPDATE OR DELETE ON example_table FOR EACH ROW
295+
EXECUTE FUNCTION example_function ();
296+
`);
297+
});
261298
});

0 commit comments

Comments
 (0)