Skip to content

Commit 2b415e9

Browse files
committed
Don't lose partitioned table reltuples=0 after relhassubclass=f.
ANALYZE sets relhassubclass=f when a partitioned table no longer has partitions. An ANALYZE doing that proceeded to apply the inplace update of pg_class.reltuples to the old pg_class tuple instead of the new tuple, losing that reltuples=0 change if the ANALYZE committed. Non-partitioning inheritance trees were unaffected. Back-patch to v14, where commit 375aed3 introduced maintenance of partitioned table pg_class.reltuples. Reported by Alexander Lakhin. Discussion: https://postgr.es/m/a295b499-dcab-6a99-c06e-01cf60593344@gmail.com
1 parent c5b15c4 commit 2b415e9

File tree

4 files changed

+84
-1
lines changed

4 files changed

+84
-1
lines changed

src/backend/commands/analyze.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
658658

659659
visibilitymap_count(onerel, &relallvisible, NULL);
660660

661-
/* Update pg_class for table relation */
661+
/*
662+
* Update pg_class for table relation. CCI first, in case acquirefunc
663+
* updated pg_class.
664+
*/
665+
CommandCounterIncrement();
662666
vac_update_relstats(onerel,
663667
relpages,
664668
totalrows,
@@ -691,6 +695,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
691695
* Partitioned tables don't have storage, so we don't set any fields
692696
* in their pg_class entries except for reltuples and relhasindex.
693697
*/
698+
CommandCounterIncrement();
694699
vac_update_relstats(onerel, -1, totalrows,
695700
0, hasindex, InvalidTransactionId,
696701
InvalidMultiXactId,

src/test/regress/expected/sanity_check.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ nummultirange_test|t
9696
numrange_test|t
9797
onek|t
9898
onek2|t
99+
past_inh_parent|f
100+
past_parted|f
99101
path_tbl|f
100102
person|f
101103
persons|f

src/test/regress/expected/vacuum.out

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,53 @@ BEGIN;
8282
INSERT INTO vactst SELECT generate_series(301, 400);
8383
DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
8484
ANALYZE vactst;
85+
COMMIT;
86+
-- Test ANALYZE setting relhassubclass=f for non-partitioning inheritance
87+
BEGIN;
88+
CREATE TABLE past_inh_parent ();
89+
CREATE TABLE past_inh_child () INHERITS (past_inh_parent);
90+
INSERT INTO past_inh_child DEFAULT VALUES;
91+
INSERT INTO past_inh_child DEFAULT VALUES;
92+
ANALYZE past_inh_parent;
93+
SELECT reltuples, relhassubclass
94+
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
95+
reltuples | relhassubclass
96+
-----------+----------------
97+
0 | t
98+
(1 row)
99+
100+
DROP TABLE past_inh_child;
101+
ANALYZE past_inh_parent;
102+
SELECT reltuples, relhassubclass
103+
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
104+
reltuples | relhassubclass
105+
-----------+----------------
106+
0 | f
107+
(1 row)
108+
109+
COMMIT;
110+
-- Test ANALYZE setting relhassubclass=f for partitioning
111+
BEGIN;
112+
CREATE TABLE past_parted (i int) PARTITION BY LIST(i);
113+
CREATE TABLE past_part PARTITION OF past_parted FOR VALUES IN (1);
114+
INSERT INTO past_parted VALUES (1),(1);
115+
ANALYZE past_parted;
116+
DROP TABLE past_part;
117+
SELECT reltuples, relhassubclass
118+
FROM pg_class WHERE oid = 'past_parted'::regclass;
119+
reltuples | relhassubclass
120+
-----------+----------------
121+
2 | t
122+
(1 row)
123+
124+
ANALYZE past_parted;
125+
SELECT reltuples, relhassubclass
126+
FROM pg_class WHERE oid = 'past_parted'::regclass;
127+
reltuples | relhassubclass
128+
-----------+----------------
129+
0 | f
130+
(1 row)
131+
85132
COMMIT;
86133
VACUUM FULL pg_am;
87134
VACUUM FULL pg_class;

src/test/regress/sql/vacuum.sql

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
6767
ANALYZE vactst;
6868
COMMIT;
6969

70+
-- Test ANALYZE setting relhassubclass=f for non-partitioning inheritance
71+
BEGIN;
72+
CREATE TABLE past_inh_parent ();
73+
CREATE TABLE past_inh_child () INHERITS (past_inh_parent);
74+
INSERT INTO past_inh_child DEFAULT VALUES;
75+
INSERT INTO past_inh_child DEFAULT VALUES;
76+
ANALYZE past_inh_parent;
77+
SELECT reltuples, relhassubclass
78+
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
79+
DROP TABLE past_inh_child;
80+
ANALYZE past_inh_parent;
81+
SELECT reltuples, relhassubclass
82+
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
83+
COMMIT;
84+
85+
-- Test ANALYZE setting relhassubclass=f for partitioning
86+
BEGIN;
87+
CREATE TABLE past_parted (i int) PARTITION BY LIST(i);
88+
CREATE TABLE past_part PARTITION OF past_parted FOR VALUES IN (1);
89+
INSERT INTO past_parted VALUES (1),(1);
90+
ANALYZE past_parted;
91+
DROP TABLE past_part;
92+
SELECT reltuples, relhassubclass
93+
FROM pg_class WHERE oid = 'past_parted'::regclass;
94+
ANALYZE past_parted;
95+
SELECT reltuples, relhassubclass
96+
FROM pg_class WHERE oid = 'past_parted'::regclass;
97+
COMMIT;
98+
7099
VACUUM FULL pg_am;
71100
VACUUM FULL pg_class;
72101
VACUUM FULL pg_database;

0 commit comments

Comments
 (0)