diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-01-26 19:33:50 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-01-26 19:33:50 -0500 |
commit | 7ab6f2da23516e48174f3f144ee9ef19bdc287fb (patch) | |
tree | 82a5dcd267ec5a31a6df93585a4ea780a508b655 /src | |
parent | 8b6f5f25102f9e2503ce18af77b6fd547a2192ca (diff) | |
download | postgresql-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.c | 21 |
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); |