Hello!

After some investigation I ended up with a much simpler fix.
It is self-explanatory in code and a commit message.

Best regards,
Mikhail.
From de4fcbcbd35912cea70f0f00f81878ea8b94416c Mon Sep 17 00:00:00 2001
From: Mikhail Nikalayeu <[email protected]>
Date: Tue, 9 Dec 2025 19:39:06 +0100
Subject: [PATCH v1] Fix infer_arbiter_index for partitioned tables
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The fix for concurrent index operations in bc32a12e0db started considering indexes that are not yet marked indisvalid. However, for partitioned tables this is incorrect because partitioned tables don't store data themselves; the actual arbiter indexes are inferred later at the leaf partition level.  Considering non-valid indexes on partitioned tables (such as those created with CREATE INDEX ... ON ONLY) led to incorrect arbiter selection and resulted in an error.

Skip non-valid indexes when processing partitioned tables, restoring the previous behavior for them while preserving the concurrent index operation fix for regular tables.

Author: Mihail Nikalayeu <[email protected]>
Reported-by: Alexander Lakhin <[email protected]>
Reviewed-by: Álvaro Herrera <[email protected]>
Discussion: https://postgr.es/m/17622f79-117a-4a44-aa8e-0374e53faaf0%40gmail.com
---
 src/backend/optimizer/util/plancat.c         | 7 ++++++-
 src/test/regress/expected/partition_info.out | 7 +++++++
 src/test/regress/sql/partition_info.sql      | 8 ++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index ed0dac37f51..4775669f868 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -995,8 +995,13 @@ infer_arbiter_indexes(PlannerInfo *root)
 		 * wouldn't detect possible duplicate rows.  In order to prevent false
 		 * negatives, we require that we include in the set of inferred
 		 * indexes at least one index that is marked valid.
+		 *
+		 * Also, in the case of partitioned table - only valid indexes are
+		 * considered because real arbiters inferred later.
 		 */
-		if (!idxForm->indisready)
+		if (!idxForm->indisready ||
+				(relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE &&
+					!idxForm->indisvalid))
 			continue;
 
 		/*
diff --git a/src/test/regress/expected/partition_info.out b/src/test/regress/expected/partition_info.out
index 42b6bc77cad..4defa66e5b3 100644
--- a/src/test/regress/expected/partition_info.out
+++ b/src/test/regress/expected/partition_info.out
@@ -349,3 +349,10 @@ SELECT pg_partition_root('ptif_li_child');
 DROP VIEW ptif_test_view;
 DROP MATERIALIZED VIEW ptif_test_matview;
 DROP TABLE ptif_li_parent, ptif_li_child;
+-- Test about selection of arbiter indexes for partitioned tables with
+-- non-valid index on the parent table
+CREATE TABLE pt (a int PRIMARY KEY) PARTITION BY RANGE (a);
+CREATE TABLE p1 PARTITION OF pt FOR VALUES FROM (1) to (2) PARTITION BY RANGE (a);
+CREATE TABLE p1_1 PARTITION OF p1 FOR VALUES FROM (1) TO (2);
+CREATE UNIQUE INDEX ON ONLY p1 (a);
+INSERT INTO p1 VALUES (1) ON CONFLICT (a) DO NOTHING;
diff --git a/src/test/regress/sql/partition_info.sql b/src/test/regress/sql/partition_info.sql
index b5060bec7f0..2ef65292bab 100644
--- a/src/test/regress/sql/partition_info.sql
+++ b/src/test/regress/sql/partition_info.sql
@@ -127,3 +127,11 @@ SELECT pg_partition_root('ptif_li_child');
 DROP VIEW ptif_test_view;
 DROP MATERIALIZED VIEW ptif_test_matview;
 DROP TABLE ptif_li_parent, ptif_li_child;
+
+-- Test about selection of arbiter indexes for partitioned tables with
+-- non-valid index on the parent table
+CREATE TABLE pt (a int PRIMARY KEY) PARTITION BY RANGE (a);
+CREATE TABLE p1 PARTITION OF pt FOR VALUES FROM (1) to (2) PARTITION BY RANGE (a);
+CREATE TABLE p1_1 PARTITION OF p1 FOR VALUES FROM (1) TO (2);
+CREATE UNIQUE INDEX ON ONLY p1 (a);
+INSERT INTO p1 VALUES (1) ON CONFLICT (a) DO NOTHING;
-- 
2.52.0

Reply via email to