LCOV - code coverage report
Current view: top level - contrib/bloom - blscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 55 59 93.2 %
Date: 2024-04-25 13:11:42 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14