Skip to content

Commit 81f7211

Browse files
committed
Fix infer_arbiter_index for partitioned tables
The fix for concurrent index operations in bc32a12 started considering indexes that are not yet marked indisvalid as arbiters for INSERT ON CONFLICT. For partitioned tables, this leads to including indexes that may not exist in partitions, causing a trivially reproducible "invalid arbiter index list" error to be thrown because of failure to match the index. To fix, it suffices to ignore !indisvalid indexes on partitioned tables. There should be no risk that the set of indexes will change for concurrent transactions, because in order for such an index to be marked valid, an ALTER INDEX ATTACH PARTITION must run which requires AccessExclusiveLock. Author: Mihail Nikalayeu <mihailnikalayeu@gmail.com> Reported-by: Alexander Lakhin <exclusion@gmail.com> Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de> Discussion: https://postgr.es/m/17622f79-117a-4a44-aa8e-0374e53faaf0%40gmail.com
1 parent b65f1ad commit 81f7211

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

src/backend/optimizer/util/plancat.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,15 @@ infer_arbiter_indexes(PlannerInfo *root)
999999
if (!idxForm->indisready)
10001000
continue;
10011001

1002+
/*
1003+
* Ignore invalid indexes for partitioned tables. It's possible that
1004+
* some partitions don't have the index (yet), and then we would not
1005+
* find a match during ExecInitPartitionInfo.
1006+
*/
1007+
if (relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
1008+
!idxForm->indisvalid)
1009+
continue;
1010+
10021011
/*
10031012
* Note that we do not perform a check against indcheckxmin (like e.g.
10041013
* get_relation_info()) here to eliminate candidates, because

src/test/regress/expected/partition_info.out

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,3 +349,10 @@ SELECT pg_partition_root('ptif_li_child');
349349
DROP VIEW ptif_test_view;
350350
DROP MATERIALIZED VIEW ptif_test_matview;
351351
DROP TABLE ptif_li_parent, ptif_li_child;
352+
-- Test about selection of arbiter indexes for partitioned tables with
353+
-- non-valid index on the parent table
354+
CREATE TABLE pt (a int PRIMARY KEY) PARTITION BY RANGE (a);
355+
CREATE TABLE p1 PARTITION OF pt FOR VALUES FROM (1) to (2) PARTITION BY RANGE (a);
356+
CREATE TABLE p1_1 PARTITION OF p1 FOR VALUES FROM (1) TO (2);
357+
CREATE UNIQUE INDEX ON ONLY p1 (a);
358+
INSERT INTO p1 VALUES (1) ON CONFLICT (a) DO NOTHING;

src/test/regress/sql/partition_info.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,11 @@ SELECT pg_partition_root('ptif_li_child');
127127
DROP VIEW ptif_test_view;
128128
DROP MATERIALIZED VIEW ptif_test_matview;
129129
DROP TABLE ptif_li_parent, ptif_li_child;
130+
131+
-- Test about selection of arbiter indexes for partitioned tables with
132+
-- non-valid index on the parent table
133+
CREATE TABLE pt (a int PRIMARY KEY) PARTITION BY RANGE (a);
134+
CREATE TABLE p1 PARTITION OF pt FOR VALUES FROM (1) to (2) PARTITION BY RANGE (a);
135+
CREATE TABLE p1_1 PARTITION OF p1 FOR VALUES FROM (1) TO (2);
136+
CREATE UNIQUE INDEX ON ONLY p1 (a);
137+
INSERT INTO p1 VALUES (1) ON CONFLICT (a) DO NOTHING;

0 commit comments

Comments
 (0)