Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 078303f

Browse files
committed
Fix misapplication of pgstat_count_truncate to wrong relation.
The stanza of ExecuteTruncate[Guts] that truncates a target table's toast relation re-used the loop local variable "rel" to reference the toast rel. This was safe enough when written, but commit d42358e added code below that that supposed "rel" still pointed to the parent table. Therefore, the stats counter update was applied to the wrong relcache entry (the toast rel not the user rel); and if we were unlucky and that relcache entry had been flushed during reindex_relation, very bad things could ensue. (I'm surprised that CLOBBER_CACHE_ALWAYS testing hasn't found this. I'm even more surprised that the problem wasn't detected during the development of d42358e; it must not have been tested in any case with a toast table, as the incorrect stats counts are very obvious.) To fix, replace use of "rel" in that code branch with a more local variable. Adjust test cases added by d42358e so that some of them use tables with toast tables. Per bug #15540 from Pan Bian. Back-patch to 9.5 where d42358e came in. Discussion: https://postgr.es/m/15540-01078812338195c0@postgresql.org
1 parent d398119 commit 078303f

File tree

3 files changed

+13
-10
lines changed

3 files changed

+13
-10
lines changed

src/backend/commands/tablecmds.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,19 +1225,22 @@ ExecuteTruncate(TruncateStmt *stmt)
12251225
heap_create_init_fork(rel);
12261226

12271227
heap_relid = RelationGetRelid(rel);
1228-
toast_relid = rel->rd_rel->reltoastrelid;
12291228

12301229
/*
12311230
* The same for the toast table, if any.
12321231
*/
1232+
toast_relid = rel->rd_rel->reltoastrelid;
12331233
if (OidIsValid(toast_relid))
12341234
{
1235-
rel = relation_open(toast_relid, AccessExclusiveLock);
1236-
RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
1235+
Relation toastrel = relation_open(toast_relid,
1236+
AccessExclusiveLock);
1237+
1238+
RelationSetNewRelfilenode(toastrel,
1239+
toastrel->rd_rel->relpersistence,
12371240
RecentXmin, minmulti);
1238-
if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1239-
heap_create_init_fork(rel);
1240-
heap_close(rel, NoLock);
1241+
if (toastrel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
1242+
heap_create_init_fork(toastrel);
1243+
heap_close(toastrel, NoLock);
12411244
}
12421245

12431246
/*

src/test/regress/expected/stats.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ end
8080
$$ language plpgsql;
8181
-- test effects of TRUNCATE on n_live_tup/n_dead_tup counters
8282
CREATE TABLE trunc_stats_test(id serial);
83-
CREATE TABLE trunc_stats_test1(id serial);
83+
CREATE TABLE trunc_stats_test1(id serial, stuff text);
8484
CREATE TABLE trunc_stats_test2(id serial);
85-
CREATE TABLE trunc_stats_test3(id serial);
85+
CREATE TABLE trunc_stats_test3(id serial, stuff text);
8686
CREATE TABLE trunc_stats_test4(id serial);
8787
-- check that n_live_tup is reset to 0 after truncate
8888
INSERT INTO trunc_stats_test DEFAULT VALUES;

src/test/regress/sql/stats.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ $$ language plpgsql;
7676

7777
-- test effects of TRUNCATE on n_live_tup/n_dead_tup counters
7878
CREATE TABLE trunc_stats_test(id serial);
79-
CREATE TABLE trunc_stats_test1(id serial);
79+
CREATE TABLE trunc_stats_test1(id serial, stuff text);
8080
CREATE TABLE trunc_stats_test2(id serial);
81-
CREATE TABLE trunc_stats_test3(id serial);
81+
CREATE TABLE trunc_stats_test3(id serial, stuff text);
8282
CREATE TABLE trunc_stats_test4(id serial);
8383

8484
-- check that n_live_tup is reset to 0 after truncate

0 commit comments

Comments
 (0)