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