Skip to content

Commit d34b671

Browse files
committed
Avoid ERROR at ON COMMIT DELETE ROWS after relhassubclass=f.
Commit 7102070 fixed a similar bug, but it missed the case of database-wide ANALYZE ("use_own_xacts" mode). Commit a07e03f changed consequences from silent discard of a pg_class stats (relpages et al.) update to ERROR "tuple to be updated was already modified". Losing a relpages update of an ON COMMIT DELETE ROWS table was negligible, but a COMMIT-time error isn't negligible. Back-patch to v13 (all supported versions). Reported-by: Richard Guo <guofenglinux@gmail.com Reported-by: Robins Tharakan <tharakan@gmail.com> Discussion: https://postgr.es/m/CAMbWs4-XwMKMKJ_GT=p3_-_=j9rQSEs1FbDFUnW9zHuKPsPNEQ@mail.gmail.com Backpatch-through: 13
1 parent 3f9132e commit d34b671

File tree

4 files changed

+65
-0
lines changed

4 files changed

+65
-0
lines changed

src/backend/commands/vacuum.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ vacuum(List *relations, VacuumParams *params,
470470
if (use_own_xacts)
471471
{
472472
PopActiveSnapshot();
473+
/* standard_ProcessUtility() does CCI if !use_own_xacts */
474+
CommandCounterIncrement();
473475
CommitTransactionCommand();
474476
}
475477
else
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
-- Test maintenance commands that visit every eligible relation. Run as a
2+
-- non-superuser, to skip other users' tables.
3+
CREATE ROLE regress_maintain;
4+
SET ROLE regress_maintain;
5+
-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f
6+
-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an
7+
-- empty index.
8+
CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts"
9+
CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS;
10+
CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent);
11+
CREATE INDEX ON past_inh_db_parent ((1));
12+
ANALYZE past_inh_db_parent;
13+
SELECT reltuples, relhassubclass
14+
FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
15+
reltuples | relhassubclass
16+
-----------+----------------
17+
0 | t
18+
(1 row)
19+
20+
DROP TABLE past_inh_db_child;
21+
SET client_min_messages = error; -- hide WARNINGs for other users' tables
22+
ANALYZE;
23+
RESET client_min_messages;
24+
SELECT reltuples, relhassubclass
25+
FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
26+
reltuples | relhassubclass
27+
-----------+----------------
28+
0 | f
29+
(1 row)
30+
31+
DROP TABLE past_inh_db_parent, past_inh_db_other;
32+
RESET ROLE;
33+
DROP ROLE regress_maintain;

src/test/regress/parallel_schedule

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ test: rules psql psql_crosstab amutils stats_ext collate.linux.utf8
8989
test: select_parallel
9090
test: write_parallel
9191

92+
# Run this alone, because concurrent DROP TABLE would make non-superuser
93+
# "ANALYZE;" fail with "relation with OID $n does not exist".
94+
test: maintain_every
95+
9296
# no relation related tests can be put in this group
9397
test: publication subscription
9498

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
-- Test maintenance commands that visit every eligible relation. Run as a
2+
-- non-superuser, to skip other users' tables.
3+
4+
CREATE ROLE regress_maintain;
5+
SET ROLE regress_maintain;
6+
7+
-- Test database-wide ANALYZE ("use_own_xacts" mode) setting relhassubclass=f
8+
-- for non-partitioning inheritance, w/ ON COMMIT DELETE ROWS building an
9+
-- empty index.
10+
CREATE TEMP TABLE past_inh_db_other (); -- need 2 tables for "use_own_xacts"
11+
CREATE TEMP TABLE past_inh_db_parent () ON COMMIT DELETE ROWS;
12+
CREATE TEMP TABLE past_inh_db_child () INHERITS (past_inh_db_parent);
13+
CREATE INDEX ON past_inh_db_parent ((1));
14+
ANALYZE past_inh_db_parent;
15+
SELECT reltuples, relhassubclass
16+
FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
17+
DROP TABLE past_inh_db_child;
18+
SET client_min_messages = error; -- hide WARNINGs for other users' tables
19+
ANALYZE;
20+
RESET client_min_messages;
21+
SELECT reltuples, relhassubclass
22+
FROM pg_class WHERE oid = 'past_inh_db_parent'::regclass;
23+
DROP TABLE past_inh_db_parent, past_inh_db_other;
24+
25+
RESET ROLE;
26+
DROP ROLE regress_maintain;

0 commit comments

Comments
 (0)