Age Owner Branch data TLA 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
3635 teodor@sigaev.ru 27 :CBC 387 : blbeginscan(Relation r, int nkeys, int norderbys)
28 : : {
29 : : IndexScanDesc scan;
30 : : BloomScanOpaque so;
31 : :
32 : 387 : scan = RelationGetIndexScan(r, nkeys, norderbys);
33 : :
100 michael@paquier.xyz 34 :GNC 387 : so = (BloomScanOpaque) palloc_object(BloomScanOpaqueData);
3589 tgl@sss.pgh.pa.us 35 :CBC 387 : initBloomState(&so->state, scan->indexRelation);
36 : 387 : so->sign = NULL;
37 : :
38 : 387 : scan->opaque = so;
39 : :
3635 teodor@sigaev.ru 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 : : {
3589 tgl@sss.pgh.pa.us 50 : 387 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
51 : :
52 [ - + ]: 387 : if (so->sign)
3589 tgl@sss.pgh.pa.us 53 :UBC 0 : pfree(so->sign);
3635 teodor@sigaev.ru 54 :CBC 387 : so->sign = NULL;
55 : :
56 [ + - + - ]: 387 : if (scankey && scan->numberOfKeys > 0)
550 peter@eisentraut.org 57 : 387 : memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
3635 teodor@sigaev.ru 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 : :
3633 tgl@sss.pgh.pa.us 88 [ + - ]: 387 : if (so->sign == NULL)
89 : : {
90 : : /* New search: have to calculate search signature */
3635 teodor@sigaev.ru 91 : 387 : ScanKey skey = scan->keyData;
92 : :
100 michael@paquier.xyz 93 :GNC 387 : so->sign = palloc0_array(BloomSignatureWord, so->state.opts.bloomLength);
94 : :
3635 teodor@sigaev.ru 95 [ + + ]:CBC 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 : : {
3635 teodor@sigaev.ru 103 :UBC 0 : pfree(so->sign);
104 : 0 : so->sign = NULL;
105 : 0 : return 0;
106 : : }
107 : :
108 : : /* Add next value to the signature */
3635 teodor@sigaev.ru 109 :CBC 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);
488 pg@bowt.ie 122 [ - + - - : 387 : pgstat_count_index_scan(scan->indexRelation);
+ - ]
369 123 [ + - ]: 387 : if (scan->instrument)
124 : 387 : scan->instrument->nsearches++;
125 : :
126 : : /* Scan all blocks except the metapage using streaming reads */
4 michael@paquier.xyz 127 :GNC 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 : :
3635 teodor@sigaev.ru 143 [ + + ]:CBC 29334 : for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
144 : : {
145 : : Buffer buffer;
146 : : Page page;
147 : :
4 michael@paquier.xyz 148 :GNC 28947 : buffer = read_stream_next_buffer(stream, NULL);
3635 teodor@sigaev.ru 149 :CBC 28947 : LockBuffer(buffer, BUFFER_LOCK_SHARE);
3616 kgrittn@postgresql.o 150 : 28947 : page = BufferGetPage(buffer);
151 : :
3501 tgl@sss.pgh.pa.us 152 [ + - + + ]: 28947 : if (!PageIsNew(page) && !BloomPageIsDeleted(page))
153 : : {
154 : : OffsetNumber offset,
3635 teodor@sigaev.ru 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 */
3633 tgl@sss.pgh.pa.us 163 [ + + ]: 35371848 : for (i = 0; i < so->state.opts.bloomLength; i++)
164 : : {
3635 teodor@sigaev.ru 165 [ + + ]: 34486186 : if ((itup->sign[i] & so->sign[i]) != so->sign[i])
166 : : {
167 : 13246588 : res = false;
3633 tgl@sss.pgh.pa.us 168 : 13246588 : break;
169 : : }
170 : : }
171 : :
172 : : /* Add matching tuples to bitmap */
3635 teodor@sigaev.ru 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 : :
4 michael@paquier.xyz 185 [ - + ]:GNC 387 : Assert(read_stream_next_buffer(stream, NULL) == InvalidBuffer);
186 : 387 : read_stream_end(stream);
3635 teodor@sigaev.ru 187 :CBC 387 : FreeAccessStrategy(bas);
188 : :
189 : 387 : return ntids;
190 : : }
|