Skip to content

Commit c17abc1

Browse files
committed
Fix logic error in tbm_intersect: the intersection of a normal page and
a lossy page has to be lossy, because we don't know exactly which tuples on the page should remain part of the bitmap. Per Jie Zhang.
1 parent eaa5d52 commit c17abc1

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

src/backend/nodes/tidbitmap.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
* Copyright (c) 2003-2005, PostgreSQL Global Development Group
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.4 2005/05/29 04:23:03 tgl Exp $
26+
* $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.5 2005/07/24 02:25:26 tgl Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -135,7 +135,8 @@ struct TIDBitmap
135135

136136
/* Local function prototypes */
137137
static void tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage);
138-
static bool tbm_intersect_page(PagetableEntry *apage, const TIDBitmap *b);
138+
static bool tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage,
139+
const TIDBitmap *b);
139140
static const PagetableEntry *tbm_find_pageentry(const TIDBitmap *tbm,
140141
BlockNumber pageno);
141142
static PagetableEntry *tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno);
@@ -382,7 +383,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
382383
/* Scan through chunks and pages in a, try to match to b */
383384
if (a->status == TBM_ONE_PAGE)
384385
{
385-
if (tbm_intersect_page(&a->entry1, b))
386+
if (tbm_intersect_page(a, &a->entry1, b))
386387
{
387388
/* Page is now empty, remove it from a */
388389
Assert(!a->entry1.ischunk);
@@ -401,7 +402,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
401402
hash_seq_init(&status, a->pagetable);
402403
while ((apage = (PagetableEntry *) hash_seq_search(&status)) != NULL)
403404
{
404-
if (tbm_intersect_page(apage, b))
405+
if (tbm_intersect_page(a, apage, b))
405406
{
406407
/* Page or chunk is now empty, remove it from a */
407408
if (apage->ischunk)
@@ -424,7 +425,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
424425
* Returns TRUE if apage is now empty and should be deleted from a
425426
*/
426427
static bool
427-
tbm_intersect_page(PagetableEntry *apage, const TIDBitmap *b)
428+
tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b)
428429
{
429430
const PagetableEntry *bpage;
430431
int wordnum;
@@ -470,7 +471,23 @@ tbm_intersect_page(PagetableEntry *apage, const TIDBitmap *b)
470471
}
471472
else if (tbm_page_is_lossy(b, apage->blockno))
472473
{
473-
/* page is lossy in b, cannot clear any bits */
474+
/*
475+
* When the page is lossy in b, we have to mark it lossy in a too.
476+
* We know that no bits need be set in bitmap a, but we do not know
477+
* which ones should be cleared, and we have no API for "at most
478+
* these tuples need be checked". (Perhaps it's worth adding that?)
479+
*/
480+
tbm_mark_page_lossy(a, apage->blockno);
481+
482+
/*
483+
* Note: tbm_mark_page_lossy will have removed apage from a, and
484+
* may have inserted a new lossy chunk instead. We can continue the
485+
* same seq_search scan at the caller level, because it does not
486+
* matter whether we visit such a new chunk or not: it will have
487+
* only the bit for apage->blockno set, which is correct.
488+
*
489+
* We must return false here since apage was already deleted.
490+
*/
474491
return false;
475492
}
476493
else

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy