
The index access methods all had similar code that copied the passed-in scan keys to local storage. They all used memmove() for that, which is not wrong, but it seems confusing not to use memcpy() when that would work. Presumably, this was all once copied from ancient code and never adjusted. Discussion: https://www.postgresql.org/message-id/flat/f8c739d9-f48d-4187-b214-df3391ba41ab@eisentraut.org
169 lines
3.5 KiB
C
169 lines
3.5 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* blscan.c
|
|
* Bloom index scan functions.
|
|
*
|
|
* Copyright (c) 2016-2024, PostgreSQL Global Development Group
|
|
*
|
|
* IDENTIFICATION
|
|
* contrib/bloom/blscan.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres.h"
|
|
|
|
#include "access/relscan.h"
|
|
#include "bloom.h"
|
|
#include "miscadmin.h"
|
|
#include "pgstat.h"
|
|
#include "storage/bufmgr.h"
|
|
#include "storage/lmgr.h"
|
|
#include "utils/memutils.h"
|
|
#include "utils/rel.h"
|
|
|
|
/*
|
|
* Begin scan of bloom index.
|
|
*/
|
|
IndexScanDesc
|
|
blbeginscan(Relation r, int nkeys, int norderbys)
|
|
{
|
|
IndexScanDesc scan;
|
|
BloomScanOpaque so;
|
|
|
|
scan = RelationGetIndexScan(r, nkeys, norderbys);
|
|
|
|
so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
|
|
initBloomState(&so->state, scan->indexRelation);
|
|
so->sign = NULL;
|
|
|
|
scan->opaque = so;
|
|
|
|
return scan;
|
|
}
|
|
|
|
/*
|
|
* Rescan a bloom index.
|
|
*/
|
|
void
|
|
blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
|
|
ScanKey orderbys, int norderbys)
|
|
{
|
|
BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
|
|
|
|
if (so->sign)
|
|
pfree(so->sign);
|
|
so->sign = NULL;
|
|
|
|
if (scankey && scan->numberOfKeys > 0)
|
|
memcpy(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData));
|
|
}
|
|
|
|
/*
|
|
* End scan of bloom index.
|
|
*/
|
|
void
|
|
blendscan(IndexScanDesc scan)
|
|
{
|
|
BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
|
|
|
|
if (so->sign)
|
|
pfree(so->sign);
|
|
so->sign = NULL;
|
|
}
|
|
|
|
/*
|
|
* Insert all matching tuples into a bitmap.
|
|
*/
|
|
int64
|
|
blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
|
|
{
|
|
int64 ntids = 0;
|
|
BlockNumber blkno = BLOOM_HEAD_BLKNO,
|
|
npages;
|
|
int i;
|
|
BufferAccessStrategy bas;
|
|
BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
|
|
|
|
if (so->sign == NULL)
|
|
{
|
|
/* New search: have to calculate search signature */
|
|
ScanKey skey = scan->keyData;
|
|
|
|
so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
|
|
|
|
for (i = 0; i < scan->numberOfKeys; i++)
|
|
{
|
|
/*
|
|
* Assume bloom-indexable operators to be strict, so nothing could
|
|
* be found for NULL key.
|
|
*/
|
|
if (skey->sk_flags & SK_ISNULL)
|
|
{
|
|
pfree(so->sign);
|
|
so->sign = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/* Add next value to the signature */
|
|
signValue(&so->state, so->sign, skey->sk_argument,
|
|
skey->sk_attno - 1);
|
|
|
|
skey++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We're going to read the whole index. This is why we use appropriate
|
|
* buffer access strategy.
|
|
*/
|
|
bas = GetAccessStrategy(BAS_BULKREAD);
|
|
npages = RelationGetNumberOfBlocks(scan->indexRelation);
|
|
|
|
for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
|
|
{
|
|
Buffer buffer;
|
|
Page page;
|
|
|
|
buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
|
|
blkno, RBM_NORMAL, bas);
|
|
|
|
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
|
page = BufferGetPage(buffer);
|
|
|
|
if (!PageIsNew(page) && !BloomPageIsDeleted(page))
|
|
{
|
|
OffsetNumber offset,
|
|
maxOffset = BloomPageGetMaxOffset(page);
|
|
|
|
for (offset = 1; offset <= maxOffset; offset++)
|
|
{
|
|
BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
|
|
bool res = true;
|
|
|
|
/* Check index signature with scan signature */
|
|
for (i = 0; i < so->state.opts.bloomLength; i++)
|
|
{
|
|
if ((itup->sign[i] & so->sign[i]) != so->sign[i])
|
|
{
|
|
res = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Add matching tuples to bitmap */
|
|
if (res)
|
|
{
|
|
tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
|
|
ntids++;
|
|
}
|
|
}
|
|
}
|
|
|
|
UnlockReleaseBuffer(buffer);
|
|
CHECK_FOR_INTERRUPTS();
|
|
}
|
|
FreeAccessStrategy(bas);
|
|
|
|
return ntids;
|
|
}
|