1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-28 05:21:27 +03:00

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 375aed36ad83f0e021e9bdd3a0034c0c992c66dc introduced
maintenance of partitioned table pg_class.reltuples.

Reported by Alexander Lakhin.

Discussion: https://postgr.es/m/a295b499-dcab-6a99-c06e-01cf60593344@gmail.com
This commit is contained in:
Noah Misch 2024-07-13 08:09:33 -07:00
parent 6f55b4f112
commit 2b4a2a79ed
3 changed files with 82 additions and 1 deletions

View File

@ -637,7 +637,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
visibilitymap_count(onerel, &relallvisible, NULL);
/* Update pg_class for table relation */
/*
* Update pg_class for table relation. CCI first, in case acquirefunc
* updated pg_class.
*/
CommandCounterIncrement();
vac_update_relstats(onerel,
relpages,
totalrows,
@ -672,6 +676,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
* Partitioned tables don't have storage, so we don't set any fields
* in their pg_class entries except for reltuples and relhasindex.
*/
CommandCounterIncrement();
vac_update_relstats(onerel, -1, totalrows,
0, hasindex, InvalidTransactionId,
InvalidMultiXactId,

View File

@ -82,6 +82,53 @@ BEGIN;
INSERT INTO vactst SELECT generate_series(301, 400);
DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
ANALYZE vactst;
COMMIT;
-- Test ANALYZE setting relhassubclass=f for non-partitioning inheritance
BEGIN;
CREATE TABLE past_inh_parent ();
CREATE TABLE past_inh_child () INHERITS (past_inh_parent);
INSERT INTO past_inh_child DEFAULT VALUES;
INSERT INTO past_inh_child DEFAULT VALUES;
ANALYZE past_inh_parent;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
reltuples | relhassubclass
-----------+----------------
0 | t
(1 row)
DROP TABLE past_inh_child;
ANALYZE past_inh_parent;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
reltuples | relhassubclass
-----------+----------------
0 | f
(1 row)
COMMIT;
-- Test ANALYZE setting relhassubclass=f for partitioning
BEGIN;
CREATE TABLE past_parted (i int) PARTITION BY LIST(i);
CREATE TABLE past_part PARTITION OF past_parted FOR VALUES IN (1);
INSERT INTO past_parted VALUES (1),(1);
ANALYZE past_parted;
DROP TABLE past_part;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_parted'::regclass;
reltuples | relhassubclass
-----------+----------------
2 | t
(1 row)
ANALYZE past_parted;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_parted'::regclass;
reltuples | relhassubclass
-----------+----------------
0 | f
(1 row)
COMMIT;
VACUUM FULL pg_am;
VACUUM FULL pg_class;

View File

@ -67,6 +67,35 @@ DELETE FROM vactst WHERE i % 5 <> 0; -- delete a few rows inside
ANALYZE vactst;
COMMIT;
-- Test ANALYZE setting relhassubclass=f for non-partitioning inheritance
BEGIN;
CREATE TABLE past_inh_parent ();
CREATE TABLE past_inh_child () INHERITS (past_inh_parent);
INSERT INTO past_inh_child DEFAULT VALUES;
INSERT INTO past_inh_child DEFAULT VALUES;
ANALYZE past_inh_parent;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
DROP TABLE past_inh_child;
ANALYZE past_inh_parent;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_inh_parent'::regclass;
COMMIT;
-- Test ANALYZE setting relhassubclass=f for partitioning
BEGIN;
CREATE TABLE past_parted (i int) PARTITION BY LIST(i);
CREATE TABLE past_part PARTITION OF past_parted FOR VALUES IN (1);
INSERT INTO past_parted VALUES (1),(1);
ANALYZE past_parted;
DROP TABLE past_part;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_parted'::regclass;
ANALYZE past_parted;
SELECT reltuples, relhassubclass
FROM pg_class WHERE oid = 'past_parted'::regclass;
COMMIT;
VACUUM FULL pg_am;
VACUUM FULL pg_class;
VACUUM FULL pg_database;