TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * blscan.c
4 : * Bloom index scan functions.
5 : *
6 : * Copyright (c) 2016-2023, 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 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 :
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 :
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 : {
51 387 : BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
52 :
53 387 : if (so->sign)
54 UBC 0 : pfree(so->sign);
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 :
90 387 : if (so->sign == NULL)
91 : {
92 : /* New search: have to calculate search signature */
93 387 : ScanKey skey = scan->keyData;
94 :
95 387 : so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
96 :
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 : {
105 UBC 0 : pfree(so->sign);
106 0 : so->sign = NULL;
107 0 : return 0;
108 : }
109 :
110 : /* Add next value to the signature */
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 73758 : for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
126 : {
127 : Buffer buffer;
128 : Page page;
129 :
130 73371 : buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
131 : blkno, RBM_NORMAL, bas);
132 :
133 73371 : LockBuffer(buffer, BUFFER_LOCK_SHARE);
134 73371 : page = BufferGetPage(buffer);
135 73371 : TestForOldSnapshot(scan->xs_snapshot, scan->indexRelation, page);
136 :
137 73371 : if (!PageIsNew(page) && !BloomPageIsDeleted(page))
138 : {
139 : OffsetNumber offset,
140 73350 : maxOffset = BloomPageGetMaxOffset(page);
141 :
142 31161624 : for (offset = 1; offset <= maxOffset; offset++)
143 : {
144 31088274 : BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
145 31088274 : bool res = true;
146 :
147 : /* Check index signature with scan signature */
148 77930242 : for (i = 0; i < so->state.opts.bloomLength; i++)
149 : {
150 75952758 : if ((itup->sign[i] & so->sign[i]) != so->sign[i])
151 : {
152 29110790 : res = false;
153 29110790 : break;
154 : }
155 : }
156 :
157 : /* Add matching tuples to bitmap */
158 31088274 : if (res)
159 : {
160 1977484 : tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
161 1977484 : ntids++;
162 : }
163 : }
164 : }
165 :
166 73371 : UnlockReleaseBuffer(buffer);
167 73371 : CHECK_FOR_INTERRUPTS();
168 : }
169 387 : FreeAccessStrategy(bas);
170 :
171 387 : return ntids;
172 : }
|