LCOV - code coverage report
Current view: top level - contrib/bloom - blscan.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 92.2 % 64 59
Test Date: 2026-07-13 12:15:38 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 65.8 % 38 25

             Branch data     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                 :             : #include "storage/read_stream.h"
      22                 :             : 
      23                 :             : /*
      24                 :             :  * Begin scan of bloom index.
      25                 :             :  */
      26                 :             : IndexScanDesc
      27                 :         387 : blbeginscan(Relation r, int nkeys, int norderbys)
      28                 :             : {
      29                 :             :     IndexScanDesc scan;
      30                 :             :     BloomScanOpaque so;
      31                 :             : 
      32                 :         387 :     scan = RelationGetIndexScan(r, nkeys, norderbys);
      33                 :             : 
      34                 :         387 :     so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData);
      35                 :         387 :     initBloomState(&so->state, scan->indexRelation);
      36                 :         387 :     so->sign = NULL;
      37                 :             : 
      38                 :         387 :     scan->opaque = so;
      39                 :             : 
      40                 :         387 :     return scan;
      41                 :             : }
      42                 :             : 
      43                 :             : /*
      44                 :             :  * Rescan a bloom index.
      45                 :             :  */
      46                 :             : void
      47                 :         387 : blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
      48                 :             :          ScanKey orderbys, int norderbys)
      49                 :             : {
      50                 :         387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      51                 :             : 
      52         [ -  + ]:         387 :     if (so->sign)
      53                 :           0 :         pfree(so->sign);
      54                 :         387 :     so->sign = NULL;
      55                 :             : 
      56   [ +  -  +  - ]:         387 :     if (scankey && scan->numberOfKeys > 0)
      57                 :         387 :         memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
      58                 :         387 : }
      59                 :             : 
      60                 :             : /*
      61                 :             :  * End scan of bloom index.
      62                 :             :  */
      63                 :             : void
      64                 :         387 : blendscan(IndexScanDesc scan)
      65                 :             : {
      66                 :         387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      67                 :             : 
      68         [ +  - ]:         387 :     if (so->sign)
      69                 :         387 :         pfree(so->sign);
      70                 :         387 :     so->sign = NULL;
      71                 :         387 : }
      72                 :             : 
      73                 :             : /*
      74                 :             :  * Insert all matching tuples into a bitmap.
      75                 :             :  */
      76                 :             : int64
      77                 :         387 : blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
      78                 :             : {
      79                 :         387 :     int64       ntids = 0;
      80                 :             :     BlockNumber blkno,
      81                 :             :                 npages;
      82                 :             :     int         i;
      83                 :             :     BufferAccessStrategy bas;
      84                 :         387 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      85                 :             :     BlockRangeReadStreamPrivate p;
      86                 :             :     ReadStream *stream;
      87                 :             : 
      88         [ +  - ]:         387 :     if (so->sign == NULL)
      89                 :             :     {
      90                 :             :         /* New search: have to calculate search signature */
      91                 :         387 :         ScanKey     skey = scan->keyData;
      92                 :             : 
      93                 :         387 :         so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength);
      94                 :             : 
      95         [ +  + ]:         903 :         for (i = 0; i < scan->numberOfKeys; i++)
      96                 :             :         {
      97                 :             :             /*
      98                 :             :              * Assume bloom-indexable operators to be strict, so nothing could
      99                 :             :              * be found for NULL key.
     100                 :             :              */
     101         [ -  + ]:         516 :             if (skey->sk_flags & SK_ISNULL)
     102                 :             :             {
     103                 :           0 :                 pfree(so->sign);
     104                 :           0 :                 so->sign = NULL;
     105                 :           0 :                 return 0;
     106                 :             :             }
     107                 :             : 
     108                 :             :             /* Add next value to the signature */
     109                 :         516 :             signValue(&so->state, so->sign, skey->sk_argument,
     110                 :         516 :                       skey->sk_attno - 1);
     111                 :             : 
     112                 :         516 :             skey++;
     113                 :             :         }
     114                 :             :     }
     115                 :             : 
     116                 :             :     /*
     117                 :             :      * We're going to read the whole index. This is why we use appropriate
     118                 :             :      * buffer access strategy.
     119                 :             :      */
     120                 :         387 :     bas = GetAccessStrategy(BAS_BULKREAD);
     121                 :         387 :     npages = RelationGetNumberOfBlocks(scan->indexRelation);
     122   [ -  +  -  -  :         387 :     pgstat_count_index_scan(scan->indexRelation);
                   +  - ]
     123         [ -  + ]:         387 :     if (scan->instrument)
     124                 :           0 :         scan->instrument->nsearches++;
     125                 :             : 
     126                 :             :     /* Scan all blocks except the metapage using streaming reads */
     127                 :         387 :     p.current_blocknum = BLOOM_HEAD_BLKNO;
     128                 :         387 :     p.last_exclusive = npages;
     129                 :             : 
     130                 :             :     /*
     131                 :             :      * It is safe to use batchmode as block_range_read_stream_cb takes no
     132                 :             :      * locks.
     133                 :             :      */
     134                 :         387 :     stream = read_stream_begin_relation(READ_STREAM_FULL |
     135                 :             :                                         READ_STREAM_USE_BATCHING,
     136                 :             :                                         bas,
     137                 :             :                                         scan->indexRelation,
     138                 :             :                                         MAIN_FORKNUM,
     139                 :             :                                         block_range_read_stream_cb,
     140                 :             :                                         &p,
     141                 :             :                                         0);
     142                 :             : 
     143         [ +  + ]:       29334 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
     144                 :             :     {
     145                 :             :         Buffer      buffer;
     146                 :             :         Page        page;
     147                 :             : 
     148                 :       28947 :         buffer = read_stream_next_buffer(stream, NULL);
     149                 :       28947 :         LockBuffer(buffer, BUFFER_LOCK_SHARE);
     150                 :       28947 :         page = BufferGetPage(buffer);
     151                 :             : 
     152   [ +  -  +  + ]:       28947 :         if (!PageIsNew(page) && !BloomPageIsDeleted(page))
     153                 :             :         {
     154                 :             :             OffsetNumber offset,
     155                 :       28926 :                         maxOffset = BloomPageGetMaxOffset(page);
     156                 :             : 
     157         [ +  + ]:    14161176 :             for (offset = 1; offset <= maxOffset; offset++)
     158                 :             :             {
     159                 :    14132250 :                 BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
     160                 :    14132250 :                 bool        res = true;
     161                 :             : 
     162                 :             :                 /* Check index signature with scan signature */
     163         [ +  + ]:    35371848 :                 for (i = 0; i < so->state.opts.bloomLength; i++)
     164                 :             :                 {
     165         [ +  + ]:    34486186 :                     if ((itup->sign[i] & so->sign[i]) != so->sign[i])
     166                 :             :                     {
     167                 :    13246588 :                         res = false;
     168                 :    13246588 :                         break;
     169                 :             :                     }
     170                 :             :                 }
     171                 :             : 
     172                 :             :                 /* Add matching tuples to bitmap */
     173         [ +  + ]:    14132250 :                 if (res)
     174                 :             :                 {
     175                 :      885662 :                     tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
     176                 :      885662 :                     ntids++;
     177                 :             :                 }
     178                 :             :             }
     179                 :             :         }
     180                 :             : 
     181                 :       28947 :         UnlockReleaseBuffer(buffer);
     182         [ -  + ]:       28947 :         CHECK_FOR_INTERRUPTS();
     183                 :             :     }
     184                 :             : 
     185                 :             :     Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
     186                 :         387 :     read_stream_end(stream);
     187                 :         387 :     FreeAccessStrategy(bas);
     188                 :             : 
     189                 :         387 :     return ntids;
     190                 :             : }
        

Generated by: LCOV version 2.0-1