Skip to content

Commit 2b4a2a7

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 6f55b4f commit 2b4a2a7

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

src/backend/commands/analyze.c

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

638638
visibilitymap_count(onerel, &relallvisible, NULL);
639639

640-
/* Update pg_class for table relation */
640+
/*
641+
* Update pg_class for table relation. CCI first, in case acquirefunc
642+
* updated pg_class.
643+
*/
644+
CommandCounterIncrement();
641645
vac_update_relstats(onerel,
642646
relpages,
643647
totalrows,
@@ -672,6 +676,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
672676
* Partitioned tables don't have storage, so we don't set any fields
673677
* in their pg_class entries except for reltuples and relhasindex.
674678
*/
679+
CommandCounterIncrement();
675680
vac_update_relstats(onerel, -1, totalrows,
676681
0, hasindex, InvalidTransactionId,
677682
InvalidMultiXactId,

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)