Further refine _SPI_execute_plan's rule for atomic execution.
[pgsql.git] / contrib / bloom / blscan.c
blob0a303a49b24d82cf59f86f8df53a2bce835685c5
1 /*-------------------------------------------------------------------------
3 * blscan.c
4 * Bloom index scan functions.
6 * Copyright (c) 2016-2024, PostgreSQL Global Development Group
8 * IDENTIFICATION
9 * contrib/bloom/blscan.c
11 *-------------------------------------------------------------------------
13 #include "postgres.h"
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"
25 * Begin scan of bloom index.
27 IndexScanDesc
28 blbeginscan(Relation r, int nkeys, int norderbys)
30 IndexScanDesc scan;
31 BloomScanOpaque so;
33 scan = RelationGetIndexScan(r, nkeys, norderbys);
35 so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
36 initBloomState(&so->state, scan->indexRelation);
37 so->sign = NULL;
39 scan->opaque = so;
41 return scan;
45 * Rescan a bloom index.
47 void
48 blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
49 ScanKey orderbys, int norderbys)
51 BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
53 if (so->sign)
54 pfree(so->sign);
55 so->sign = NULL;
57 if (scankey && scan->numberOfKeys > 0)
59 memmove(scan->keyData, scankey,
60 scan->numberOfKeys * sizeof(ScanKeyData));
65 * End scan of bloom index.
67 void
68 blendscan(IndexScanDesc scan)
70 BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
72 if (so->sign)
73 pfree(so->sign);
74 so->sign = NULL;
78 * Insert all matching tuples into a bitmap.
80 int64
81 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
83 int64 ntids = 0;
84 BlockNumber blkno = BLOOM_HEAD_BLKNO,
85 npages;
86 int i;
87 BufferAccessStrategy bas;
88 BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
90 if (so->sign == NULL)
92 /* New search: have to calculate search signature */
93 ScanKey skey = scan->keyData;
95 so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
97 for (i = 0; i < scan->numberOfKeys; i++)
100 * Assume bloom-indexable operators to be strict, so nothing could
101 * be found for NULL key.
103 if (skey->sk_flags & SK_ISNULL)
105 pfree(so->sign);
106 so->sign = NULL;
107 return 0;
110 /* Add next value to the signature */
111 signValue(&so->state, so->sign, skey->sk_argument,
112 skey->sk_attno - 1);
114 skey++;
119 * We're going to read the whole index. This is why we use appropriate
120 * buffer access strategy.
122 bas = GetAccessStrategy(BAS_BULKREAD);
123 npages = RelationGetNumberOfBlocks(scan->indexRelation);
125 for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
127 Buffer buffer;
128 Page page;
130 buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
131 blkno, RBM_NORMAL, bas);
133 LockBuffer(buffer, BUFFER_LOCK_SHARE);
134 page = BufferGetPage(buffer);
136 if (!PageIsNew(page) && !BloomPageIsDeleted(page))
138 OffsetNumber offset,
139 maxOffset = BloomPageGetMaxOffset(page);
141 for (offset = 1; offset <= maxOffset; offset++)
143 BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
144 bool res = true;
146 /* Check index signature with scan signature */
147 for (i = 0; i < so->state.opts.bloomLength; i++)
149 if ((itup->sign[i] & so->sign[i]) != so->sign[i])
151 res = false;
152 break;
156 /* Add matching tuples to bitmap */
157 if (res)
159 tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
160 ntids++;
165 UnlockReleaseBuffer(buffer);
166 CHECK_FOR_INTERRUPTS();
168 FreeAccessStrategy(bas);
170 return ntids;