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 774 : blbeginscan(Relation r, int nkeys, int norderbys) 27 : { 28 : IndexScanDesc scan; 29 : BloomScanOpaque so; 30 : 31 774 : scan = RelationGetIndexScan(r, nkeys, norderbys); 32 : 33 774 : so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData); 34 774 : initBloomState(&so->state, scan->indexRelation); 35 774 : so->sign = NULL; 36 : 37 774 : scan->opaque = so; 38 : 39 774 : return scan; 40 : } 41 : 42 : /* 43 : * Rescan a bloom index. 44 : */ 45 : void 46 774 : blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, 47 : ScanKey orderbys, int norderbys) 48 : { 49 774 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque; 50 : 51 774 : if (so->sign) 52 0 : pfree(so->sign); 53 774 : so->sign = NULL; 54 : 55 774 : if (scankey && scan->numberOfKeys > 0) 56 774 : memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); 57 774 : } 58 : 59 : /* 60 : * End scan of bloom index. 61 : */ 62 : void 63 774 : blendscan(IndexScanDesc scan) 64 : { 65 774 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque; 66 : 67 774 : if (so->sign) 68 774 : pfree(so->sign); 69 774 : so->sign = NULL; 70 774 : } 71 : 72 : /* 73 : * Insert all matching tuples into a bitmap. 74 : */ 75 : int64 76 774 : blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm) 77 : { 78 774 : int64 ntids = 0; 79 774 : BlockNumber blkno = BLOOM_HEAD_BLKNO, 80 : npages; 81 : int i; 82 : BufferAccessStrategy bas; 83 774 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque; 84 : 85 774 : if (so->sign == NULL) 86 : { 87 : /* New search: have to calculate search signature */ 88 774 : ScanKey skey = scan->keyData; 89 : 90 774 : so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength); 91 : 92 1806 : 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 1032 : 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 1032 : signValue(&so->state, so->sign, skey->sk_argument, 107 1032 : skey->sk_attno - 1); 108 : 109 1032 : 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 774 : bas = GetAccessStrategy(BAS_BULKREAD); 118 774 : npages = RelationGetNumberOfBlocks(scan->indexRelation); 119 774 : pgstat_count_index_scan(scan->indexRelation); 120 774 : if (scan->instrument) 121 774 : scan->instrument->nsearches++; 122 : 123 58668 : for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++) 124 : { 125 : Buffer buffer; 126 : Page page; 127 : 128 57894 : buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM, 129 : blkno, RBM_NORMAL, bas); 130 : 131 57894 : LockBuffer(buffer, BUFFER_LOCK_SHARE); 132 57894 : page = BufferGetPage(buffer); 133 : 134 57894 : if (!PageIsNew(page) && !BloomPageIsDeleted(page)) 135 : { 136 : OffsetNumber offset, 137 57852 : maxOffset = BloomPageGetMaxOffset(page); 138 : 139 28322352 : for (offset = 1; offset <= maxOffset; offset++) 140 : { 141 28264500 : BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset); 142 28264500 : bool res = true; 143 : 144 : /* Check index signature with scan signature */ 145 70743696 : for (i = 0; i < so->state.opts.bloomLength; i++) 146 : { 147 68972372 : if ((itup->sign[i] & so->sign[i]) != so->sign[i]) 148 : { 149 26493176 : res = false; 150 26493176 : break; 151 : } 152 : } 153 : 154 : /* Add matching tuples to bitmap */ 155 28264500 : if (res) 156 : { 157 1771324 : tbm_add_tuples(tbm, &itup->heapPtr, 1, true); 158 1771324 : ntids++; 159 : } 160 : } 161 : } 162 : 163 57894 : UnlockReleaseBuffer(buffer); 164 57894 : CHECK_FOR_INTERRUPTS(); 165 : } 166 774 : FreeAccessStrategy(bas); 167 : 168 774 : return ntids; 169 : }