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