Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * blscan.c
4 : : * Bloom index scan functions.
5 : : *
6 : : * Copyright (c) 2016-2025, 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
3445 teodor@sigaev.ru 25 :CBC 387 : blbeginscan(Relation r, int nkeys, int norderbys)
26 : : {
27 : : IndexScanDesc scan;
28 : : BloomScanOpaque so;
29 : :
30 : 387 : scan = RelationGetIndexScan(r, nkeys, norderbys);
31 : :
3399 tgl@sss.pgh.pa.us 32 : 387 : so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
33 : 387 : initBloomState(&so->state, scan->indexRelation);
34 : 387 : so->sign = NULL;
35 : :
36 : 387 : scan->opaque = so;
37 : :
3445 teodor@sigaev.ru 38 : 387 : return scan;
39 : : }
40 : :
41 : : /*
42 : : * Rescan a bloom index.
43 : : */
44 : : void
45 : 387 : blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
46 : : ScanKey orderbys, int norderbys)
47 : : {
3399 tgl@sss.pgh.pa.us 48 : 387 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
49 : :
50 [ - + ]: 387 : if (so->sign)
3399 tgl@sss.pgh.pa.us 51 :UBC 0 : pfree(so->sign);
3445 teodor@sigaev.ru 52 :CBC 387 : so->sign = NULL;
53 : :
54 [ + - + - ]: 387 : if (scankey && scan->numberOfKeys > 0)
360 peter@eisentraut.org 55 : 387 : memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
3445 teodor@sigaev.ru 56 : 387 : }
57 : :
58 : : /*
59 : : * End scan of bloom index.
60 : : */
61 : : void
62 : 387 : blendscan(IndexScanDesc scan)
63 : : {
64 : 387 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
65 : :
66 [ + - ]: 387 : if (so->sign)
67 : 387 : pfree(so->sign);
68 : 387 : so->sign = NULL;
69 : 387 : }
70 : :
71 : : /*
72 : : * Insert all matching tuples into a bitmap.
73 : : */
74 : : int64
75 : 387 : blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
76 : : {
77 : 387 : int64 ntids = 0;
78 : 387 : BlockNumber blkno = BLOOM_HEAD_BLKNO,
79 : : npages;
80 : : int i;
81 : : BufferAccessStrategy bas;
82 : 387 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
83 : :
3443 tgl@sss.pgh.pa.us 84 [ + - ]: 387 : if (so->sign == NULL)
85 : : {
86 : : /* New search: have to calculate search signature */
3445 teodor@sigaev.ru 87 : 387 : ScanKey skey = scan->keyData;
88 : :
3382 tgl@sss.pgh.pa.us 89 : 387 : so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
90 : :
3445 teodor@sigaev.ru 91 [ + + ]: 903 : 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 [ - + ]: 516 : if (skey->sk_flags & SK_ISNULL)
98 : : {
3445 teodor@sigaev.ru 99 :UBC 0 : pfree(so->sign);
100 : 0 : so->sign = NULL;
101 : 0 : return 0;
102 : : }
103 : :
104 : : /* Add next value to the signature */
3445 teodor@sigaev.ru 105 :CBC 516 : signValue(&so->state, so->sign, skey->sk_argument,
106 : 516 : skey->sk_attno - 1);
107 : :
108 : 516 : 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 : 387 : bas = GetAccessStrategy(BAS_BULKREAD);
117 : 387 : npages = RelationGetNumberOfBlocks(scan->indexRelation);
298 pg@bowt.ie 118 [ - + - - : 387 : pgstat_count_index_scan(scan->indexRelation);
+ - ]
179 119 [ + - ]: 387 : if (scan->instrument)
120 : 387 : scan->instrument->nsearches++;
121 : :
3445 teodor@sigaev.ru 122 [ + + ]: 29334 : for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
123 : : {
124 : : Buffer buffer;
125 : : Page page;
126 : :
127 : 28947 : buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
128 : : blkno, RBM_NORMAL, bas);
129 : :
130 : 28947 : LockBuffer(buffer, BUFFER_LOCK_SHARE);
3426 kgrittn@postgresql.o 131 : 28947 : page = BufferGetPage(buffer);
132 : :
3311 tgl@sss.pgh.pa.us 133 [ + - + + ]: 28947 : if (!PageIsNew(page) && !BloomPageIsDeleted(page))
134 : : {
135 : : OffsetNumber offset,
3445 teodor@sigaev.ru 136 : 28926 : maxOffset = BloomPageGetMaxOffset(page);
137 : :
138 [ + + ]: 14161176 : for (offset = 1; offset <= maxOffset; offset++)
139 : : {
140 : 14132250 : BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
141 : 14132250 : bool res = true;
142 : :
143 : : /* Check index signature with scan signature */
3443 tgl@sss.pgh.pa.us 144 [ + + ]: 35371848 : for (i = 0; i < so->state.opts.bloomLength; i++)
145 : : {
3445 teodor@sigaev.ru 146 [ + + ]: 34486186 : if ((itup->sign[i] & so->sign[i]) != so->sign[i])
147 : : {
148 : 13246588 : res = false;
3443 tgl@sss.pgh.pa.us 149 : 13246588 : break;
150 : : }
151 : : }
152 : :
153 : : /* Add matching tuples to bitmap */
3445 teodor@sigaev.ru 154 [ + + ]: 14132250 : if (res)
155 : : {
156 : 885662 : tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
157 : 885662 : ntids++;
158 : : }
159 : : }
160 : : }
161 : :
162 : 28947 : UnlockReleaseBuffer(buffer);
163 [ - + ]: 28947 : CHECK_FOR_INTERRUPTS();
164 : : }
165 : 387 : FreeAccessStrategy(bas);
166 : :
167 : 387 : return ntids;
168 : : }
|