From 75db7db9fae509c64609315b86aa85706e710e2b Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Mon, 28 Feb 2022 10:50:58 +0300
Subject: [PATCH 5/5] Mark intermediate partitioned indexes as valid

---
 src/backend/commands/indexcmds.c       | 33 ++++++++++-
 src/test/regress/expected/indexing.out | 80 +++++++++++++++++++++++++-
 src/test/regress/sql/indexing.sql      |  8 +++
 3 files changed, 118 insertions(+), 3 deletions(-)

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 21f1ceaea63..fabb5b14898 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -3021,6 +3021,7 @@ static void
 ReindexPartitions(Oid relid, ReindexParams *params, bool isTopLevel)
 {
 	List	   *partitions = NIL;
+	List	   *inhpartindexes = NIL;
 	char		relkind = get_rel_relkind(relid);
 	char	   *relname = get_rel_name(relid);
 	char	   *relnamespace = get_namespace_name(get_rel_namespace(relid));
@@ -3075,6 +3076,17 @@ ReindexPartitions(Oid relid, ReindexParams *params, bool isTopLevel)
 		char		partkind = get_rel_relkind(partoid);
 		MemoryContext old_context;
 
+		/* Create a list of invalid inherited partitioned indexes */
+		if (partkind == RELKIND_PARTITIONED_INDEX)
+		{
+			if (partoid == relid || get_index_isvalid(partoid))
+				continue;
+
+			old_context = MemoryContextSwitchTo(reindex_context);
+			inhpartindexes = lappend_oid(inhpartindexes, partoid);
+			MemoryContextSwitchTo(old_context);
+		}
+
 		/*
 		 * This discards partitioned tables, partitioned indexes and foreign
 		 * tables.
@@ -3119,9 +3131,28 @@ ReindexPartitions(Oid relid, ReindexParams *params, bool isTopLevel)
 		Oid	tableoid = IndexGetRelation(relid, false);
 		List	*child_tables = find_all_inheritors(tableoid, ShareLock, NULL);
 
-		/* Both lists include their parent relation as well as any intermediate partitioned rels */
+		/*
+		 * Both lists include their parent relation as well as any
+		 * intermediate partitioned rels
+		 */
 		if (list_length(inhoids) == list_length(child_tables))
+		{
 			index_set_state_flags(relid, INDEX_CREATE_SET_VALID);
+
+			/* Mark any intermediate partitioned index as valid */
+			foreach(lc, inhpartindexes)
+			{
+				Oid         partoid = lfirst_oid(lc);
+
+				Assert(get_rel_relkind(partoid) == RELKIND_PARTITIONED_INDEX);
+				Assert(!get_index_isvalid(partoid));
+
+				/* Can't mark an index valid without marking it ready */
+				index_set_state_flags(partoid, INDEX_CREATE_SET_READY);
+				CommandCounterIncrement();
+				index_set_state_flags(partoid, INDEX_CREATE_SET_VALID);
+			}
+		}
 	}
 
 	/*
diff --git a/src/test/regress/expected/indexing.out b/src/test/regress/expected/indexing.out
index a4ccae50de3..b4f1aea6fca 100644
--- a/src/test/regress/expected/indexing.out
+++ b/src/test/regress/expected/indexing.out
@@ -57,6 +57,8 @@ create table idxpart11 partition of idxpart1 for values from (0) to (10) partiti
 create table idxpart111 partition of idxpart11 default partition by range(a);
 create table idxpart1111 partition of idxpart111 default partition by range(a);
 create table idxpart2 partition of idxpart for values from (10) to (20);
+create table idxpart3 partition of idxpart for values from (30) to (40) partition by range(a);
+create table idxpart31 partition of idxpart3 default;
 insert into idxpart2 values(10),(10); -- not unique
 create index concurrently on idxpart (a); -- partitioned
 create index concurrently on idxpart1 (a); -- partitioned and partition
@@ -76,7 +78,7 @@ Partition key: RANGE (a)
 Indexes:
     "idxpart_a_idx" btree (a)
     "idxpart_a_idx1" UNIQUE, btree (a) INVALID
-Number of partitions: 2 (Use \d+ to list them.)
+Number of partitions: 3 (Use \d+ to list them.)
 
 \d idxpart1
         Partitioned table "public.idxpart1"
@@ -88,11 +90,59 @@ Number of partitions: 2 (Use \d+ to list them.)
 Partition of: idxpart FOR VALUES FROM (0) TO (10)
 Partition key: RANGE (a)
 Indexes:
-    "idxpart1_a_idx" btree (a) INVALID
+    "idxpart1_a_idx" btree (a)
     "idxpart1_a_idx1" btree (a)
     "idxpart1_a_idx2" UNIQUE, btree (a) INVALID
 Number of partitions: 1 (Use \d+ to list them.)
 
+\d idxpart11
+       Partitioned table "public.idxpart11"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+ b      | integer |           |          | 
+ c      | text    |           |          | 
+Partition of: idxpart1 FOR VALUES FROM (0) TO (10)
+Partition key: RANGE (a)
+Indexes:
+    "idxpart11_a_idx" btree (a)
+    "idxpart11_a_idx1" btree (a)
+    "idxpart11_a_idx2" btree (a)
+    "idxpart11_a_idx3" UNIQUE, btree (a) INVALID
+Number of partitions: 1 (Use \d+ to list them.)
+
+\d idxpart111
+       Partitioned table "public.idxpart111"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+ b      | integer |           |          | 
+ c      | text    |           |          | 
+Partition of: idxpart11 DEFAULT
+Partition key: RANGE (a)
+Indexes:
+    "idxpart111_a_idx" btree (a)
+    "idxpart111_a_idx1" btree (a)
+    "idxpart111_a_idx2" btree (a)
+    "idxpart111_a_idx3" UNIQUE, btree (a) INVALID
+Number of partitions: 1 (Use \d+ to list them.)
+
+\d idxpart1111
+      Partitioned table "public.idxpart1111"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+ b      | integer |           |          | 
+ c      | text    |           |          | 
+Partition of: idxpart111 DEFAULT
+Partition key: RANGE (a)
+Indexes:
+    "idxpart1111_a_idx" btree (a)
+    "idxpart1111_a_idx1" btree (a)
+    "idxpart1111_a_idx2" btree (a)
+    "idxpart1111_a_idx3" UNIQUE, btree (a) INVALID
+Number of partitions: 0
+
 \d idxpart2
               Table "public.idxpart2"
  Column |  Type   | Collation | Nullable | Default 
@@ -107,6 +157,32 @@ Indexes:
     "idxpart2_a_idx2" UNIQUE, btree (a) INVALID
     "idxpart2_a_idx2_ccnew" UNIQUE, btree (a) INVALID
 
+\d idxpart3
+        Partitioned table "public.idxpart3"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+ b      | integer |           |          | 
+ c      | text    |           |          | 
+Partition of: idxpart FOR VALUES FROM (30) TO (40)
+Partition key: RANGE (a)
+Indexes:
+    "idxpart3_a_idx" btree (a)
+    "idxpart3_a_idx1" UNIQUE, btree (a) INVALID
+Number of partitions: 1 (Use \d+ to list them.)
+
+\d idxpart31
+             Table "public.idxpart31"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+ b      | integer |           |          | 
+ c      | text    |           |          | 
+Partition of: idxpart3 DEFAULT
+Indexes:
+    "idxpart31_a_idx" btree (a)
+    "idxpart31_a_idx1" UNIQUE, btree (a) INVALID
+
 drop table idxpart;
 -- Verify bugfix with query on indexed partitioned table with no partitions
 -- https://postgr.es/m/20180124162006.pmapfiznhgngwtjf@alvherre.pgsql
diff --git a/src/test/regress/sql/indexing.sql b/src/test/regress/sql/indexing.sql
index 3d4b6e9bc95..06673c15199 100644
--- a/src/test/regress/sql/indexing.sql
+++ b/src/test/regress/sql/indexing.sql
@@ -36,6 +36,9 @@ create table idxpart11 partition of idxpart1 for values from (0) to (10) partiti
 create table idxpart111 partition of idxpart11 default partition by range(a);
 create table idxpart1111 partition of idxpart111 default partition by range(a);
 create table idxpart2 partition of idxpart for values from (10) to (20);
+create table idxpart3 partition of idxpart for values from (30) to (40) partition by range(a);
+create table idxpart31 partition of idxpart3 default;
+
 insert into idxpart2 values(10),(10); -- not unique
 create index concurrently on idxpart (a); -- partitioned
 create index concurrently on idxpart1 (a); -- partitioned and partition
@@ -44,7 +47,12 @@ create index concurrently on idxpart2 (a); -- leaf
 create unique index concurrently on idxpart (a); -- partitioned, unique failure
 \d idxpart
 \d idxpart1
+\d idxpart11
+\d idxpart111
+\d idxpart1111
 \d idxpart2
+\d idxpart3
+\d idxpart31
 drop table idxpart;
 
 -- Verify bugfix with query on indexed partitioned table with no partitions
-- 
2.25.1

