aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-01-26 19:33:50 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-01-26 19:33:50 -0500
commit7ab6f2da23516e48174f3f144ee9ef19bdc287fb (patch)
tree82a5dcd267ec5a31a6df93585a4ea780a508b655 /src
parent8b6f5f25102f9e2503ce18af77b6fd547a2192ca (diff)
downloadpostgresql-7ab6f2da23516e48174f3f144ee9ef19bdc287fb.tar.gz
postgresql-7ab6f2da23516e48174f3f144ee9ef19bdc287fb.zip
Change inv_truncate() to not repeat its systable_getnext_ordered() scan.
In the case where the initial call of systable_getnext_ordered() returned NULL, this function would nonetheless call it again. That's undefined behavior that only by chance failed to not give visibly incorrect results. Put an if-test around the final loop to prevent that, and in passing improve some comments. No back-patch since there's no actual failure. Per report from YAMAMOTO Takashi.
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/large_object/inv_api.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index f06bf650756..01e3492cb83 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -762,6 +762,9 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
indstate = CatalogOpenIndexes(lo_heap_r);
+ /*
+ * Set up to find all pages with desired loid and pageno >= target
+ */
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
BTEqualStrategyNumber, F_OIDEQ,
@@ -841,10 +844,14 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
{
/*
* If the first page we found was after the truncation point, we're in
- * a hole that we'll fill, but we need to delete the later page.
+ * a hole that we'll fill, but we need to delete the later page because
+ * the loop below won't visit it again.
*/
- if (olddata != NULL && olddata->pageno > pageno)
+ if (olddata != NULL)
+ {
+ Assert(olddata->pageno > pageno);
simple_heap_delete(lo_heap_r, &oldtuple->t_self);
+ }
/*
* Write a brand new page.
@@ -873,11 +880,15 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
}
/*
- * Delete any pages after the truncation point
+ * Delete any pages after the truncation point. If the initial search
+ * didn't find a page, then of course there's nothing more to do.
*/
- while ((oldtuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL)
+ if (olddata != NULL)
{
- simple_heap_delete(lo_heap_r, &oldtuple->t_self);
+ while ((oldtuple = systable_getnext_ordered(sd, ForwardScanDirection)) != NULL)
+ {
+ simple_heap_delete(lo_heap_r, &oldtuple->t_self);
+ }
}
systable_endscan_ordered(sd);