Skip to content

Commit d700518

Browse files
committed
Don't reset relhasindex for partitioned tables on ANALYZE
Commit 0e69f70 introduced code to analyze partitioned table; however, that code fails to preserve pg_class.relhasindex correctly. Fix by observing whether any indexes exist rather than accidentally falling through to assuming none do. Backpatch to 14. Author: Alexander Pyhalov <[email protected]> Reviewed-by: Álvaro Herrera <[email protected]> Reviewed-by: Zhihong Yu <[email protected]> Discussion: https://postgr.es/m/CALNJ-vS1R3Qoe5t4tbzxrkpBtzRbPq1dDcW4RmA_a+oqweF30w@mail.gmail.com
1 parent 2f7bae2 commit d700518

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

src/backend/commands/analyze.c

+23-9
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,34 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
420420
/*
421421
* Open all indexes of the relation, and see if there are any analyzable
422422
* columns in the indexes. We do not analyze index columns if there was
423-
* an explicit column list in the ANALYZE command, however. If we are
424-
* doing a recursive scan, we don't want to touch the parent's indexes at
425-
* all.
423+
* an explicit column list in the ANALYZE command, however.
424+
*
425+
* If we are doing a recursive scan, we don't want to touch the parent's
426+
* indexes at all. If we're processing a partitioned table, we need to
427+
* know if there are any indexes, but we don't want to process them.
426428
*/
427-
if (!inh)
429+
if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
430+
{
431+
List *idxs = RelationGetIndexList(onerel);
432+
433+
Irel = NULL;
434+
nindexes = 0;
435+
hasindex = idxs != NIL;
436+
list_free(idxs);
437+
}
438+
else if (!inh)
439+
{
428440
vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
441+
hasindex = nindexes > 0;
442+
}
429443
else
430444
{
431445
Irel = NULL;
432446
nindexes = 0;
447+
hasindex = false;
433448
}
434-
hasindex = (nindexes > 0);
435449
indexdata = NULL;
436-
if (hasindex)
450+
if (nindexes > 0)
437451
{
438452
indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
439453
for (ind = 0; ind < nindexes; ind++)
@@ -572,7 +586,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
572586
MemoryContextResetAndDeleteChildren(col_context);
573587
}
574588

575-
if (hasindex)
589+
if (nindexes > 0)
576590
compute_index_stats(onerel, totalrows,
577591
indexdata, nindexes,
578592
rows, numrows,
@@ -660,10 +674,10 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
660674
/*
661675
* Partitioned tables don't have storage, so we don't set any fields
662676
* in their pg_class entries except for reltuples, which is necessary
663-
* for auto-analyze to work properly.
677+
* for auto-analyze to work properly, and relhasindex.
664678
*/
665679
vac_update_relstats(onerel, -1, totalrows,
666-
0, false, InvalidTransactionId,
680+
0, hasindex, InvalidTransactionId,
667681
InvalidMultiXactId,
668682
in_outer_xact);
669683
}

src/test/regress/expected/vacuum.out

+22
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,28 @@ VACUUM ANALYZE vacparted(a,b,a);
199199
ERROR: column "a" of relation "vacparted" appears more than once
200200
ANALYZE vacparted(a,b,b);
201201
ERROR: column "b" of relation "vacparted" appears more than once
202+
-- partitioned table with index
203+
CREATE TABLE vacparted_i (a int primary key, b varchar(100))
204+
PARTITION BY HASH (a);
205+
CREATE TABLE vacparted_i1 PARTITION OF vacparted_i
206+
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
207+
CREATE TABLE vacparted_i2 PARTITION OF vacparted_i
208+
FOR VALUES WITH (MODULUS 2, REMAINDER 1);
209+
INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
210+
VACUUM (ANALYZE) vacparted_i;
211+
VACUUM (FULL) vacparted_i;
212+
VACUUM (FREEZE) vacparted_i;
213+
SELECT relname, relhasindex FROM pg_class
214+
WHERE relname LIKE 'vacparted_i%' AND relkind IN ('p','r')
215+
ORDER BY relname;
216+
relname | relhasindex
217+
--------------+-------------
218+
vacparted_i | t
219+
vacparted_i1 | t
220+
vacparted_i2 | t
221+
(3 rows)
222+
223+
DROP TABLE vacparted_i;
202224
-- multiple tables specified
203225
VACUUM vaccluster, vactst;
204226
VACUUM vacparted, does_not_exist;

src/test/regress/sql/vacuum.sql

+16
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,22 @@ VACUUM (FREEZE) vacparted;
170170
VACUUM ANALYZE vacparted(a,b,a);
171171
ANALYZE vacparted(a,b,b);
172172

173+
-- partitioned table with index
174+
CREATE TABLE vacparted_i (a int primary key, b varchar(100))
175+
PARTITION BY HASH (a);
176+
CREATE TABLE vacparted_i1 PARTITION OF vacparted_i
177+
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
178+
CREATE TABLE vacparted_i2 PARTITION OF vacparted_i
179+
FOR VALUES WITH (MODULUS 2, REMAINDER 1);
180+
INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
181+
VACUUM (ANALYZE) vacparted_i;
182+
VACUUM (FULL) vacparted_i;
183+
VACUUM (FREEZE) vacparted_i;
184+
SELECT relname, relhasindex FROM pg_class
185+
WHERE relname LIKE 'vacparted_i%' AND relkind IN ('p','r')
186+
ORDER BY relname;
187+
DROP TABLE vacparted_i;
188+
173189
-- multiple tables specified
174190
VACUUM vaccluster, vactst;
175191
VACUUM vacparted, does_not_exist;

0 commit comments

Comments
 (0)