From 7692813513d259a63872e600753892f5d41afc1f Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Wed, 14 May 2025 23:30:48 -0400 Subject: [PATCH] parser: fix parsing table constraint fk actions https://github.com/sbdchd/squawk/issues/479 --- crates/squawk_parser/src/grammar.rs | 53 ++++++++--------- .../squawk_parser__test__alter_table_ok.snap | 57 +++++++++++++++++++ .../squawk_parser__test__create_table_ok.snap | 52 +++++++++++++++++ .../test_data/ok/alter_table.sql | 5 ++ .../test_data/ok/create_table.sql | 7 +++ 5 files changed, 146 insertions(+), 28 deletions(-) diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 8a3efc65..1955912e 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -3323,24 +3323,7 @@ fn opt_constraint_inner(p: &mut Parser<'_>) -> Option { p.error("expected FULL, PARTIAL, or SIMPLE"); } } - // [ ON DELETE referential_action ] - if p.at(ON_KW) && p.nth_at(1, DELETE_KW) { - p.expect(ON_KW); - p.expect(DELETE_KW); - referential_action(p); - } - // [ ON UPDATE referential_action ] - if p.at(ON_KW) && p.nth_at(1, UPDATE_KW) { - p.expect(ON_KW); - p.expect(UPDATE_KW); - referential_action(p); - } - // [ ON DELETE referential_action ] - if p.at(ON_KW) && p.nth_at(1, DELETE_KW) { - p.expect(ON_KW); - p.expect(DELETE_KW); - referential_action(p); - } + foreign_key_actions(p); REFERENCES_CONSTRAINT } _ => { @@ -3350,6 +3333,29 @@ fn opt_constraint_inner(p: &mut Parser<'_>) -> Option { Some(kind) } +// [ ON DELETE referential_action ] +// [ ON UPDATE referential_action ] +fn foreign_key_actions(p: &mut Parser<'_>) { + // [ ON DELETE referential_action ] + if p.at(ON_KW) && p.nth_at(1, DELETE_KW) { + p.expect(ON_KW); + p.expect(DELETE_KW); + referential_action(p); + } + // [ ON UPDATE referential_action ] + if p.at(ON_KW) && p.nth_at(1, UPDATE_KW) { + p.expect(ON_KW); + p.expect(UPDATE_KW); + referential_action(p); + } + // [ ON DELETE referential_action ] + if p.at(ON_KW) && p.nth_at(1, DELETE_KW) { + p.expect(ON_KW); + p.expect(DELETE_KW); + referential_action(p); + } +} + const LIKE_OPTION: TokenSet = TokenSet::new(&[ COMMENTS_KW, COMPRESSION_KW, @@ -3591,16 +3597,7 @@ fn table_constraint(p: &mut Parser<'_>) -> CompletedMarker { p.error("expected FULL, PARTIAL, or SIMPLE"); } } - // [ ON DELETE referential_action ] - if p.eat(ON_KW) { - p.expect(DELETE_KW); - referential_action(p); - } - // [ ON UPDATE referential_action ] - if p.eat(ON_KW) { - p.expect(UPDATE_KW); - referential_action(p); - } + foreign_key_actions(p); FOREIGN_KEY_CONSTRAINT } }; diff --git a/crates/squawk_parser/src/snapshots/squawk_parser__test__alter_table_ok.snap b/crates/squawk_parser/src/snapshots/squawk_parser__test__alter_table_ok.snap index 50599dfe..176add55 100644 --- a/crates/squawk_parser/src/snapshots/squawk_parser__test__alter_table_ok.snap +++ b/crates/squawk_parser/src/snapshots/squawk_parser__test__alter_table_ok.snap @@ -3619,4 +3619,61 @@ SOURCE_FILE WHITESPACE " " FINALIZE_KW "finalize" SEMICOLON ";" + WHITESPACE "\n\n" + COMMENT "-- references on update on delete" + WHITESPACE "\n" + ALTER_TABLE + ALTER_KW "alter" + WHITESPACE " " + TABLE_KW "table" + WHITESPACE " " + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + WHITESPACE "\n " + ADD_CONSTRAINT + ADD_KW "add" + WHITESPACE " " + FOREIGN_KEY_CONSTRAINT + CONSTRAINT_KW "constraint" + WHITESPACE " " + NAME + IDENT "foo_bar_id_fkey" + WHITESPACE " " + FOREIGN_KW "foreign" + WHITESPACE " " + KEY_KW "key" + WHITESPACE " " + COLUMN_LIST + L_PAREN "(" + COLUMN + NAME_REF + IDENT "bar_id" + R_PAREN ")" + WHITESPACE "\n " + REFERENCES_KW "references" + WHITESPACE " " + PATH + PATH_SEGMENT + NAME_REF + IDENT "bar" + WHITESPACE " " + L_PAREN "(" + NAME_REF + IDENT "id" + R_PAREN ")" + WHITESPACE " " + ON_KW "on" + WHITESPACE " " + UPDATE_KW "update" + WHITESPACE " " + CASCADE_KW "cascade" + WHITESPACE " " + ON_KW "on" + WHITESPACE " " + DELETE_KW "delete" + WHITESPACE " " + CASCADE_KW "cascade" + SEMICOLON ";" WHITESPACE "\n" diff --git a/crates/squawk_parser/src/snapshots/squawk_parser__test__create_table_ok.snap b/crates/squawk_parser/src/snapshots/squawk_parser__test__create_table_ok.snap index 16bcb89b..4390a62a 100644 --- a/crates/squawk_parser/src/snapshots/squawk_parser__test__create_table_ok.snap +++ b/crates/squawk_parser/src/snapshots/squawk_parser__test__create_table_ok.snap @@ -1177,6 +1177,58 @@ SOURCE_FILE R_PAREN ")" SEMICOLON ";" WHITESPACE "\n\n" + CREATE_TABLE + COMMENT "-- order swapped" + WHITESPACE "\n" + CREATE_KW "create" + WHITESPACE " " + TABLE_KW "table" + WHITESPACE " " + PATH + PATH_SEGMENT + NAME + IDENT "t" + WHITESPACE " " + TABLE_ARGS + L_PAREN "(" + WHITESPACE "\n " + COLUMN + NAME_REF + IDENT "b" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + INT_KW "int" + WHITESPACE " " + REFERENCES_CONSTRAINT + REFERENCES_KW "references" + WHITESPACE " " + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + WHITESPACE "\n " + ON_KW "on" + WHITESPACE " " + DELETE_KW "delete" + WHITESPACE " " + NO_KW "no" + WHITESPACE " " + ACTION_KW "action" + WHITESPACE "\n " + ON_KW "on" + WHITESPACE " " + UPDATE_KW "update" + WHITESPACE " " + NO_KW "no" + WHITESPACE " " + ACTION_KW "action" + WHITESPACE "\n" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n\n" CREATE_TABLE COMMENT "-- primary key" WHITESPACE "\n" diff --git a/crates/squawk_parser/test_data/ok/alter_table.sql b/crates/squawk_parser/test_data/ok/alter_table.sql index 37cc0b00..7e275fa3 100644 --- a/crates/squawk_parser/test_data/ok/alter_table.sql +++ b/crates/squawk_parser/test_data/ok/alter_table.sql @@ -264,3 +264,8 @@ alter table t detach partition f concurrently; -- finalize alter table t detach partition f finalize; + +-- references on update on delete +alter table foo + add constraint foo_bar_id_fkey foreign key (bar_id) + references bar (id) on update cascade on delete cascade; diff --git a/crates/squawk_parser/test_data/ok/create_table.sql b/crates/squawk_parser/test_data/ok/create_table.sql index 2390fdee..7d30d4c0 100644 --- a/crates/squawk_parser/test_data/ok/create_table.sql +++ b/crates/squawk_parser/test_data/ok/create_table.sql @@ -140,6 +140,13 @@ create table t ( on delete no action ); +-- order swapped +create table t ( + b int references foo + on delete no action + on update no action +); + -- primary key create table t ( a int primary key with ( autovacuum_enabled ),