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 : }