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 */
137137static 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 );
139140static const PagetableEntry * tbm_find_pageentry (const TIDBitmap * tbm ,
140141BlockNumber pageno );
141142static 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 */
383384if (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 */
388389Assert (!a -> entry1 .ischunk );
@@ -401,7 +402,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b)
401402hash_seq_init (& status ,a -> pagetable );
402403while ((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 */
407408if (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 */
426427static bool
427- tbm_intersect_page (PagetableEntry * apage ,const TIDBitmap * b )
428+ tbm_intersect_page (TIDBitmap * a , PagetableEntry * apage ,const TIDBitmap * b )
428429{
429430const PagetableEntry * bpage ;
430431int wordnum ;
@@ -470,7 +471,23 @@ tbm_intersect_page(PagetableEntry *apage, const TIDBitmap *b)
470471}
471472else 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+ */
474491return false;
475492}
476493else