From 6ed4f2ef380921ae2382f03321b15efc04002a04 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Thu, 4 Dec 2025 22:19:59 -0500 Subject: [PATCH] parser: fix parsing insert select on conflict We were parsing the on conflict as a join. rel: https://github.com/sbdchd/squawk/issues/718 --- crates/squawk_parser/src/grammar.rs | 2 +- crates/squawk_parser/tests/data/ok/insert.sql | 9 ++++ .../tests/snapshots/tests__insert_ok.snap | 51 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 1e0b739f..2e6ed586 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -3456,7 +3456,7 @@ fn join(p: &mut Parser<'_>) { if !opt_from_item(p) { p.error("expected from_item"); } - if p.at(ON_KW) { + if p.at(ON_KW) && !p.nth_at(1, CONFLICT_KW) { on_clause(p); } else if p.at(USING_KW) { join_using_clause(p); diff --git a/crates/squawk_parser/tests/data/ok/insert.sql b/crates/squawk_parser/tests/data/ok/insert.sql index b4e2f8c2..d805d2dc 100644 --- a/crates/squawk_parser/tests/data/ok/insert.sql +++ b/crates/squawk_parser/tests/data/ok/insert.sql @@ -91,3 +91,12 @@ INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International') -- with schema insert into s.t (c) values (1); + + +-- regression check for issue #718 +-- we were parsing the `on conflict` as the start of a `join on` +INSERT INTO t +SELECT * +FROM t +CROSS JOIN f +ON CONFLICT DO NOTHING; diff --git a/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap b/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap index 14c8e826..d337aeea 100644 --- a/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap @@ -1463,4 +1463,55 @@ SOURCE_FILE INT_NUMBER "1" R_PAREN ")" SEMICOLON ";" + WHITESPACE "\n\n\n" + COMMENT "-- regression check for issue #718" + WHITESPACE "\n" + COMMENT "-- we were parsing the `on conflict` as the start of a `join on`" + WHITESPACE "\n" + INSERT + INSERT_KW "INSERT" + WHITESPACE " " + INTO_KW "INTO" + WHITESPACE " " + PATH + PATH_SEGMENT + NAME_REF + IDENT "t" + WHITESPACE "\n" + SELECT + SELECT_CLAUSE + SELECT_KW "SELECT" + WHITESPACE " " + TARGET_LIST + TARGET + STAR "*" + WHITESPACE "\n" + FROM_CLAUSE + FROM_KW "FROM" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "t" + WHITESPACE "\n" + JOIN + JOIN_CROSS + CROSS_KW "CROSS" + WHITESPACE " " + JOIN_KW "JOIN" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "f" + WHITESPACE "\n" + ON_CONFLICT_CLAUSE + ON_KW "ON" + WHITESPACE " " + CONFLICT_KW "CONFLICT" + WHITESPACE " " + CONFLICT_DO_NOTHING + DO_KW "DO" + WHITESPACE " " + NOTHING_KW "NOTHING" + SEMICOLON ";" WHITESPACE "\n"