LCOV - code coverage report
Current view: top level - contrib/bloom - blscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 93.4 % 61 57
Test Date: 2026-02-28 09:15:17 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * blscan.c
       4              :  *      Bloom index scan functions.
       5              :  *
       6              :  * Copyright (c) 2016-2026, PostgreSQL Global Development Group
       7              :  *
       8              :  * IDENTIFICATION
       9              :  *    contrib/bloom/blscan.c
      10              :  *
      11              :  *-------------------------------------------------------------------------
      12              :  */
      13              : #include "postgres.h"
      14              : 
      15              : #include "access/relscan.h"
      16              : #include "bloom.h"
      17              : #include "executor/instrument_node.h"
      18              : #include "miscadmin.h"
      19              : #include "pgstat.h"
      20              : #include "storage/bufmgr.h"
      21              : 
      22              : /*
      23              :  * Begin scan of bloom index.
      24              :  */
      25              : IndexScanDesc
      26          387 : blbeginscan(Relation r, int nkeys, int norderbys)
      27              : {
      28              :     IndexScanDesc scan;
      29              :     BloomScanOpaque so;
      30              : 
      31          387 :     scan = RelationGetIndexScan(r, nkeys, norderbys);
      32              : 
      33          387 :     so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData);
      34          387 :     initBloomState(&so->state, scan->indexRelation);
      35          387 :     so->sign = NULL;
      36              : 
      37          387 :     scan->opaque = so;
      38              : 
      39          387 :     return scan;
      40              : }
      41              : 
      42              : /*
      43              :  * Rescan a bloom index.
      44              :  */
      45              : void
      46          387 : blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
      47              :          ScanKey orderbys, int norderbys)
      48              : {
      49          387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      50              : 
      51          387 :     if (so->sign)
      52            0 :         pfree(so->sign);
      53          387 :     so->sign = NULL;
      54              : 
      55          387 :     if (scankey && scan->numberOfKeys > 0)
      56          387 :         memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
      57          387 : }
      58              : 
      59              : /*
      60              :  * End scan of bloom index.
      61              :  */
      62              : void
      63          387 : blendscan(IndexScanDesc scan)
      64              : {
      65          387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      66              : 
      67          387 :     if (so->sign)
      68          387 :         pfree(so->sign);
      69          387 :     so->sign = NULL;
      70          387 : }
      71              : 
      72              : /*
      73              :  * Insert all matching tuples into a bitmap.
      74              :  */
      75              : int64
      76          387 : blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
      77              : {
      78          387 :     int64       ntids = 0;
      79          387 :     BlockNumber blkno = BLOOM_HEAD_BLKNO,
      80              :                 npages;
      81              :     int         i;
      82              :     BufferAccessStrategy bas;
      83          387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      84              : 
      85          387 :     if (so->sign == NULL)
      86              :     {
      87              :         /* New search: have to calculate search signature */
      88          387 :         ScanKey     skey = scan->keyData;
      89              : 
      90          387 :         so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength);
      91              : 
      92          903 :         for (i = 0; i < scan->numberOfKeys; i++)
      93              :         {
      94              :             /*
      95              :              * Assume bloom-indexable operators to be strict, so nothing could
      96              :              * be found for NULL key.
      97              :              */
      98          516 :             if (skey->sk_flags & SK_ISNULL)
      99              :             {
     100            0 :                 pfree(so->sign);
     101            0 :                 so->sign = NULL;
     102            0 :                 return 0;
     103              :             }
     104              : 
     105              :             /* Add next value to the signature */
     106          516 :             signValue(&so->state, so->sign, skey->sk_argument,
     107          516 :                       skey->sk_attno - 1);
     108              : 
     109          516 :             skey++;
     110              :         }
     111              :     }
     112              : 
     113              :     /*
     114              :      * We're going to read the whole index. This is why we use appropriate
     115              :      * buffer access strategy.
     116              :      */
     117          387 :     bas = GetAccessStrategy(BAS_BULKREAD);
     118          387 :     npages = RelationGetNumberOfBlocks(scan->indexRelation);
     119          387 :     pgstat_count_index_scan(scan->indexRelation);
     120          387 :     if (scan->instrument)
     121          387 :         scan->instrument->nsearches++;
     122              : 
     123        29334 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
     124              :     {
     125              :         Buffer      buffer;
     126              :         Page        page;
     127              : 
     128        28947 :         buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
     129              :                                     blkno, RBM_NORMAL, bas);
     130              : 
     131        28947 :         LockBuffer(buffer, BUFFER_LOCK_SHARE);
     132        28947 :         page = BufferGetPage(buffer);
     133              : 
     134        28947 :         if (!PageIsNew(page) && !BloomPageIsDeleted(page))
     135              :         {
     136              :             OffsetNumber offset,
     137        28926 :                         maxOffset = BloomPageGetMaxOffset(page);
     138              : 
     139     14161176 :             for (offset = 1; offset <= maxOffset; offset++)
     140              :             {
     141     14132250 :                 BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
     142     14132250 :                 bool        res = true;
     143              : 
     144              :                 /* Check index signature with scan signature */
     145     35371848 :                 for (i = 0; i < so->state.opts.bloomLength; i++)
     146              :                 {
     147     34486186 :                     if ((itup->sign[i] & so->sign[i]) != so->sign[i])
     148              :                     {
     149     13246588 :                         res = false;
     150     13246588 :                         break;
     151              :                     }
     152              :                 }
     153              : 
     154              :                 /* Add matching tuples to bitmap */
     155     14132250 :                 if (res)
     156              :                 {
     157       885662 :                     tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
     158       885662 :                     ntids++;
     159              :                 }
     160              :             }
     161              :         }
     162              : 
     163        28947 :         UnlockReleaseBuffer(buffer);
     164        28947 :         CHECK_FOR_INTERRUPTS();
     165              :     }
     166          387 :     FreeAccessStrategy(bas);
     167              : 
     168          387 :     return ntids;
     169              : }
        

Generated by: LCOV version 2.0-1