From 705e795b5754295280edb26a3caf3627119c0e0e Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 13 Aug 2021 14:41:47 -0400
Subject: [PATCH 2/2] Have expand_vacuum_rel put the parent table last

---
 src/backend/commands/vacuum.c        | 29 ++++++++++++++++++----------
 src/test/regress/expected/vacuum.out |  6 +++---
 2 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 5c4bc15b44..d94d32af2c 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -760,6 +760,7 @@ expand_vacuum_rel(VacuumRelation *vrel, int options)
 		Oid			relid;
 		HeapTuple	tuple;
 		Form_pg_class classForm;
+		bool		include_toprel = false;
 		bool		include_parts;
 		int			rvr_opts;
 
@@ -809,20 +810,15 @@ expand_vacuum_rel(VacuumRelation *vrel, int options)
 		classForm = (Form_pg_class) GETSTRUCT(tuple);
 
 		/*
-		 * Make a returnable VacuumRelation for this rel if user is a proper
-		 * owner.
+		 * Decide whether to include the relation itself.  We'll put it at
+		 * the end of the list, if partitions are involved.
 		 */
 		if (vacuum_is_relation_owner(relid, classForm, options))
-		{
-			oldcontext = MemoryContextSwitchTo(vac_context);
-			vacrels = lappend(vacrels, makeVacuumRelation(vrel->relation,
-														  relid,
-														  vrel->va_cols));
-			MemoryContextSwitchTo(oldcontext);
-		}
-
+			include_toprel = true;
 
+		/* Decide if processing partitions is necessary */
 		include_parts = (classForm->relkind == RELKIND_PARTITIONED_TABLE);
+
 		ReleaseSysCache(tuple);
 
 		/*
@@ -859,6 +855,19 @@ expand_vacuum_rel(VacuumRelation *vrel, int options)
 			}
 		}
 
+		/*
+		 * Make a returnable VacuumRelation for this rel, if deemed possible
+		 * above.
+		 */
+		if (include_toprel)
+		{
+			oldcontext = MemoryContextSwitchTo(vac_context);
+			vacrels = lappend(vacrels, makeVacuumRelation(vrel->relation,
+														  relid,
+														  vrel->va_cols));
+			MemoryContextSwitchTo(oldcontext);
+		}
+
 		/*
 		 * Release lock again.  This means that by the time we actually try to
 		 * process the table, it might be gone or renamed.  In the former case
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index 3e70e4c788..ee4e3fbf0a 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -196,9 +196,9 @@ VACUUM (FULL) vacparted;
 VACUUM (FREEZE) vacparted;
 -- check behavior with duplicate column mentions
 VACUUM ANALYZE vacparted(a,b,a);
-ERROR:  column "a" of relation "vacparted" appears more than once
+ERROR:  column "a" of relation "vacparted1" appears more than once
 ANALYZE vacparted(a,b,b);
-ERROR:  column "b" of relation "vacparted" appears more than once
+ERROR:  column "b" of relation "vacparted1" appears more than once
 -- partitioned table with index
 CREATE TABLE vacparted_i (a int primary key, b varchar(100))
   PARTITION BY HASH (a);
@@ -239,7 +239,7 @@ ANALYZE vacparted (b), vactst;
 ANALYZE vactst, does_not_exist, vacparted;
 ERROR:  relation "does_not_exist" does not exist
 ANALYZE vactst (i), vacparted (does_not_exist);
-ERROR:  column "does_not_exist" of relation "vacparted" does not exist
+ERROR:  column "does_not_exist" of relation "vacparted1" does not exist
 ANALYZE vactst, vactst;
 BEGIN;  -- ANALYZE behaves differently inside a transaction block
 ANALYZE vactst, vactst;
-- 
2.20.1

