diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 2e6ed586..f54d87d2 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -3456,7 +3456,9 @@ fn join(p: &mut Parser<'_>) { if !opt_from_item(p) { p.error("expected from_item"); } - if p.at(ON_KW) && !p.nth_at(1, CONFLICT_KW) { + // need to check that we're not actually at the on_conflict clause in an + // insert/update statement + if p.at(ON_KW) && !(p.nth_at(1, CONFLICT_KW) && matches!(p.nth(2), DO_KW | ON_KW | L_PAREN)) { 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 d805d2dc..94169cae 100644 --- a/crates/squawk_parser/tests/data/ok/insert.sql +++ b/crates/squawk_parser/tests/data/ok/insert.sql @@ -99,4 +99,23 @@ INSERT INTO t SELECT * FROM t CROSS JOIN f -ON CONFLICT DO NOTHING; +ON CONFLICT + DO NOTHING; + +insert into t +select * from u join i +on conflict = conflict +on conflict + do nothing; + +insert into t +select * from u join i +on conflict = conflict +on conflict (foo) + do nothing; + +insert into t +select * from u join i +on conflict = conflict +on conflict + on constraint temporal_rng_pk 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 d337aeea..c6374af1 100644 --- a/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__insert_ok.snap @@ -1508,10 +1508,197 @@ SOURCE_FILE ON_KW "ON" WHITESPACE " " CONFLICT_KW "CONFLICT" - WHITESPACE " " + WHITESPACE "\n " CONFLICT_DO_NOTHING DO_KW "DO" WHITESPACE " " NOTHING_KW "NOTHING" SEMICOLON ";" + WHITESPACE "\n\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 " " + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "u" + WHITESPACE " " + JOIN + JOIN_INNER + JOIN_KW "join" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "i" + WHITESPACE " \n" + ON_CLAUSE + ON_KW "on" + WHITESPACE " " + BIN_EXPR + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE " " + EQ "=" + WHITESPACE " " + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE "\n" + ON_CONFLICT_CLAUSE + ON_KW "on" + WHITESPACE " " + CONFLICT_KW "conflict" + WHITESPACE "\n " + CONFLICT_DO_NOTHING + DO_KW "do" + WHITESPACE " " + NOTHING_KW "nothing" + SEMICOLON ";" + WHITESPACE "\n\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 " " + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "u" + WHITESPACE " " + JOIN + JOIN_INNER + JOIN_KW "join" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "i" + WHITESPACE " \n" + ON_CLAUSE + ON_KW "on" + WHITESPACE " " + BIN_EXPR + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE " " + EQ "=" + WHITESPACE " " + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE "\n" + ON_CONFLICT_CLAUSE + ON_KW "on" + WHITESPACE " " + CONFLICT_KW "conflict" + WHITESPACE " " + CONFLICT_ON_INDEX + CONFLICT_INDEX_ITEM_LIST + L_PAREN "(" + CONFLICT_INDEX_ITEM + NAME_REF + IDENT "foo" + R_PAREN ")" + WHITESPACE "\n " + CONFLICT_DO_NOTHING + DO_KW "do" + WHITESPACE " " + NOTHING_KW "nothing" + SEMICOLON ";" + WHITESPACE "\n\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 " " + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "u" + WHITESPACE " " + JOIN + JOIN_INNER + JOIN_KW "join" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "i" + WHITESPACE " \n" + ON_CLAUSE + ON_KW "on" + WHITESPACE " " + BIN_EXPR + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE " " + EQ "=" + WHITESPACE " " + NAME_REF + CONFLICT_KW "conflict" + WHITESPACE "\n" + ON_CONFLICT_CLAUSE + ON_KW "on" + WHITESPACE " " + CONFLICT_KW "conflict" + WHITESPACE "\n " + CONFLICT_ON_CONSTRAINT + ON_KW "on" + WHITESPACE " " + CONSTRAINT_KW "constraint" + WHITESPACE " " + NAME_REF + IDENT "temporal_rng_pk" + WHITESPACE " " + CONFLICT_DO_NOTHING + DO_KW "do" + WHITESPACE " " + NOTHING_KW "nothing" + SEMICOLON ";" WHITESPACE "\n"