From 51d3f1259b76afc97de086110fc6e213b31bce93 Mon Sep 17 00:00:00 2001 From: Zach Paden Date: Tue, 2 Jun 2026 22:02:46 -0500 Subject: [PATCH] test(#454): add test for improper conflict resolution These tests demonstrate how the current conflict building mechanism can fail if a postgres table has had columns dropped or reordered in certain ways. As described in #454 --- .../attach_on_conflict_dropped_column.test | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/sql/storage/attach_on_conflict_dropped_column.test diff --git a/test/sql/storage/attach_on_conflict_dropped_column.test b/test/sql/storage/attach_on_conflict_dropped_column.test new file mode 100644 index 000000000..560aa9902 --- /dev/null +++ b/test/sql/storage/attach_on_conflict_dropped_column.test @@ -0,0 +1,61 @@ +# name: test/sql/storage/attach_on_conflict_dropped_column.test +# description: ON CONFLICT must resolve UNIQUE constraints correctly after DROP COLUMN (issue #454) +# group: [storage] + +require postgres_scanner + +require-env POSTGRES_TEST_DATABASE_AVAILABLE + +statement ok +PRAGMA enable_verification + +statement ok +ATTACH 'dbname=postgresscanner' AS s1 (TYPE POSTGRES) + +# Postgres does not renumber attnums after DROP COLUMN, so a column dropped +# physically before the key columns leaves a gap between the constraint's +# attnums and the remaining columns. UNIQUE(a, b, c) has attnums {3, 4, 5}, and +# dropping 'e' (attnum 2) must not break resolution of the conflict target. +statement ok +CREATE OR REPLACE TABLE s1.tbl(d INTEGER, e INTEGER, a INTEGER, b INTEGER, c INTEGER, UNIQUE(a, b, c)); + +statement ok +ALTER TABLE s1.tbl DROP COLUMN e; + +statement ok +INSERT INTO s1.tbl(a, b, c, d) VALUES (1, 2, 3, 4); + +# DO NOTHING leaves the existing row untouched +statement ok +INSERT INTO s1.tbl(a, b, c, d) VALUES (1, 2, 3, 99) ON CONFLICT (a, b, c) DO NOTHING; + +query IIII +SELECT d, a, b, c FROM s1.tbl +---- +4 1 2 3 + +# DO UPDATE targets the conflicting row +statement ok +INSERT INTO s1.tbl(a, b, c, d) VALUES (1, 2, 3, 7) ON CONFLICT (a, b, c) DO UPDATE SET d = excluded.d; + +query IIII +SELECT d, a, b, c FROM s1.tbl +---- +7 1 2 3 + +# The same attnum gap must not silently shift the key onto the wrong in-range +# columns: the real UNIQUE key is (a, b) (attnums {3, 4}), so (b, c) is not a +# valid conflict target while (a, b) is. +statement ok +CREATE OR REPLACE TABLE s1.tbl2(d INTEGER, e INTEGER, a INTEGER, b INTEGER, c INTEGER, f INTEGER, UNIQUE(a, b)); + +statement ok +ALTER TABLE s1.tbl2 DROP COLUMN e; + +statement error +INSERT INTO s1.tbl2(a, b, c) VALUES (1, 2, 3) ON CONFLICT (b, c) DO NOTHING; +---- +The specified columns as conflict target are not referenced by a UNIQUE/PRIMARY KEY CONSTRAINT + +statement ok +INSERT INTO s1.tbl2(a, b, c) VALUES (1, 2, 3) ON CONFLICT (a, b) DO NOTHING;