Alexander Pyhalov писал 2021-06-30 17:26:
Hi.



Sorry, test had an issue.

--
Best regards,
Alexander Pyhalov,
Postgres Professional
From 2aabf5e8e86d222e6a73b25ccc652fe645e12fc4 Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyha...@postgrespro.ru>
Date: Wed, 30 Jun 2021 17:22:37 +0300
Subject: [PATCH] Set relhasindex for partitioned tables correctly.

The issue appeared after 0e69f705cc1a3df273b38c9883fb5765991e04fe:
in this commit we unconditionally set  nindexes to 0 for partitioned
relations.
---
 src/backend/commands/analyze.c       | 53 ++++++++++++++++------------
 src/test/regress/expected/vacuum.out | 17 +++++++++
 src/test/regress/sql/vacuum.sql      | 12 +++++++
 3 files changed, 59 insertions(+), 23 deletions(-)

diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 426c1e67109..9c8913a1619 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -424,8 +424,10 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 	 * doing a recursive scan, we don't want to touch the parent's indexes at
 	 * all.
 	 */
-	if (!inh)
+	if (!inh || onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+	{
 		vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
+	}
 	else
 	{
 		Irel = NULL;
@@ -433,7 +435,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 	}
 	hasindex = (nindexes > 0);
 	indexdata = NULL;
-	if (hasindex)
+	if (hasindex && !inh)
 	{
 		indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
 		for (ind = 0; ind < nindexes; ind++)
@@ -487,14 +489,17 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 		if (targrows < vacattrstats[i]->minrows)
 			targrows = vacattrstats[i]->minrows;
 	}
-	for (ind = 0; ind < nindexes; ind++)
+	if (!inh)
 	{
-		AnlIndexData *thisdata = &indexdata[ind];
-
-		for (i = 0; i < thisdata->attr_cnt; i++)
+		for (ind = 0; ind < nindexes; ind++)
 		{
-			if (targrows < thisdata->vacattrstats[i]->minrows)
-				targrows = thisdata->vacattrstats[i]->minrows;
+			AnlIndexData *thisdata = &indexdata[ind];
+
+			for (i = 0; i < thisdata->attr_cnt; i++)
+			{
+				if (targrows < thisdata->vacattrstats[i]->minrows)
+					targrows = thisdata->vacattrstats[i]->minrows;
+			}
 		}
 	}
 
@@ -572,7 +577,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 			MemoryContextResetAndDeleteChildren(col_context);
 		}
 
-		if (hasindex)
+		if (hasindex & !inh)
 			compute_index_stats(onerel, totalrows,
 								indexdata, nindexes,
 								rows, numrows,
@@ -589,23 +594,25 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 		update_attstats(RelationGetRelid(onerel), inh,
 						attr_cnt, vacattrstats);
 
-		for (ind = 0; ind < nindexes; ind++)
+		if (!inh)
 		{
-			AnlIndexData *thisdata = &indexdata[ind];
+			for (ind = 0; ind < nindexes; ind++)
+			{
+				AnlIndexData *thisdata = &indexdata[ind];
 
-			update_attstats(RelationGetRelid(Irel[ind]), false,
-							thisdata->attr_cnt, thisdata->vacattrstats);
-		}
+				update_attstats(RelationGetRelid(Irel[ind]), false,
+								thisdata->attr_cnt, thisdata->vacattrstats);
+			}
 
-		/*
-		 * Build extended statistics (if there are any).
-		 *
-		 * For now we only build extended statistics on individual relations,
-		 * not for relations representing inheritance trees.
-		 */
-		if (!inh)
+			/*
+			 * Build extended statistics (if there are any).
+			 *
+			 * For now we only build extended statistics on individual
+			 * relations, not for relations representing inheritance trees.
+			 */
 			BuildRelationExtStatistics(onerel, totalrows, numrows, rows,
 									   attr_cnt, vacattrstats);
+		}
 	}
 
 	pgstat_progress_update_param(PROGRESS_ANALYZE_PHASE,
@@ -663,7 +670,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 		 * for auto-analyze to work properly.
 		 */
 		vac_update_relstats(onerel, -1, totalrows,
-							0, false, InvalidTransactionId,
+							0, hasindex, InvalidTransactionId,
 							InvalidMultiXactId,
 							in_outer_xact);
 	}
@@ -704,7 +711,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
 	 * amvacuumcleanup() when called in ANALYZE-only mode.  The only exception
 	 * among core index AMs is GIN/ginvacuumcleanup().
 	 */
-	if (!(params->options & VACOPT_VACUUM))
+	if (!(params->options & VACOPT_VACUUM) && !inh)
 	{
 		for (ind = 0; ind < nindexes; ind++)
 		{
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index e5771462d57..e3d462b66fa 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -199,6 +199,23 @@ VACUUM ANALYZE vacparted(a,b,a);
 ERROR:  column "a" of relation "vacparted" appears more than once
 ANALYZE vacparted(a,b,b);
 ERROR:  column "b" of relation "vacparted" appears more than once
+-- partitioned table with index
+CREATE TABLE vacparted_i (a int primary key, b varchar(100)) PARTITION BY HASH (a);
+CREATE TABLE vacparted_i1 PARTITION OF vacparted_i FOR VALUES WITH ( MODULUS 2, REMAINDER 0);
+CREATE TABLE vacparted_i2 PARTITION OF vacparted_i FOR VALUES WITH ( MODULUS 2, REMAINDER 1);
+INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
+VACUUM (ANALYZE) vacparted_i;
+VACUUM (FULL) vacparted_i;
+VACUUM (FREEZE) vacparted_i;
+SELECT relname,relhasindex from pg_class where relname LIKE 'vacparted_i%' and relkind in ('p','r') ORDER BY relname;
+   relname    | relhasindex 
+--------------+-------------
+ vacparted_i  | t
+ vacparted_i1 | t
+ vacparted_i2 | t
+(3 rows)
+
+DROP TABLE vacparted_i;
 -- multiple tables specified
 VACUUM vaccluster, vactst;
 VACUUM vacparted, does_not_exist;
diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql
index f220fc28a70..b670612b548 100644
--- a/src/test/regress/sql/vacuum.sql
+++ b/src/test/regress/sql/vacuum.sql
@@ -166,10 +166,22 @@ VACUUM (ANALYZE) vacparted;
 VACUUM (FULL) vacparted;
 VACUUM (FREEZE) vacparted;
 
+
 -- check behavior with duplicate column mentions
 VACUUM ANALYZE vacparted(a,b,a);
 ANALYZE vacparted(a,b,b);
 
+-- partitioned table with index
+CREATE TABLE vacparted_i (a int primary key, b varchar(100)) PARTITION BY HASH (a);
+CREATE TABLE vacparted_i1 PARTITION OF vacparted_i FOR VALUES WITH ( MODULUS 2, REMAINDER 0);
+CREATE TABLE vacparted_i2 PARTITION OF vacparted_i FOR VALUES WITH ( MODULUS 2, REMAINDER 1);
+INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
+VACUUM (ANALYZE) vacparted_i;
+VACUUM (FULL) vacparted_i;
+VACUUM (FREEZE) vacparted_i;
+SELECT relname,relhasindex from pg_class where relname LIKE 'vacparted_i%' and relkind in ('p','r') ORDER BY relname;
+DROP TABLE vacparted_i;
+
 -- multiple tables specified
 VACUUM vaccluster, vactst;
 VACUUM vacparted, does_not_exist;
-- 
2.25.1

Reply via email to