1/*-------------------------------------------------------------------------
4 * Bloom index utilities.
6 * Portions Copyright (c) 2016-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1990-1993, Regents of the University of California
10 * contrib/bloom/blutils.c
12 *-------------------------------------------------------------------------
26/* Signature dealing macros - note i is assumed to be of type int */
27 #define GETWORD(x,i) ( *( (BloomSignatureWord *)(x) + ( (i) / SIGNWORDBITS ) ) )
28 #define CLRBIT(x,i) GETWORD(x,i) &= ~( 0x01 << ( (i) % SIGNWORDBITS ) )
29 #define SETBIT(x,i) GETWORD(x,i) |= ( 0x01 << ( (i) % SIGNWORDBITS ) )
30 #define GETBIT(x,i) ( (GETWORD(x,i) >> ( (i) % SIGNWORDBITS )) & 0x01 )
34/* Kind of relation options for bloom index */
37/* parse table for fillRelOptions */
44 * Module initialize function: initialize info about Bloom relation options.
46 * Note: keep this in sync with makeDefaultBloomOptions().
56 /* Option for length of signature */
58 "Length of signature in bits",
65 /* Number of bits for each possible index column: col1, col2, ... */
70 "Number of bits generated for each index column",
81 * Construct a default set of Bloom options.
90 /* Convert DEFAULT_BLOOM_LENGTH from # of bits to # of words */
99 * Bloom handler function: return IndexAmRoutine with access method parameters
163 * Fill BloomState structure for particular index.
172 /* Initialize hash function for each attribute */
173 for (
i = 0;
i <
index->rd_att->natts;
i++)
181 /* Initialize amcache if needed with options from metapage */
182 if (!
index->rd_amcache)
197 elog(
ERROR,
"Relation is not a bloom index");
201 elog(
ERROR,
"Relation is not a bloom index");
216 * Random generator copied from FreeBSD. Using own random generator here for
219 * 1) In this case random numbers are used for on-disk storage. Usage of
220 * PostgreSQL number generator would obstruct it from all possible changes.
221 * 2) Changing seed of PostgreSQL random generator would be undesirable side
230 * Compute x = (7^5 * x) mod (2^31 - 1)
231 * without overflowing 31 bits:
232 * (2^31 - 1) = 127773 * (7^5) + 2836
233 * From "Random number generators: good ones are hard to find",
234 * Park and Miller, Communications of the ACM, vol. 31, no. 10,
235 * October 1988, p. 1195.
242 /* Must be in [1, 0x7ffffffe] range at this point. */
245 x = 16807 * lo - 2836 * hi;
249 /* Transform to [0, 0x7ffffffd] range. */
257 /* Transform to [1, 0x7ffffffe] range. */
262 * Add bits of given value to the signature.
272 * init generator with "column's" number to get "hashed" seed for new
273 * value. We don't want to map the same numbers from different columns
274 * into the same bits!
279 * Init hash sequence to map our value into bits. the same values in
280 * different columns will be mapped into different bits because of step
286 for (
j = 0;
j <
state->opts.bitSize[attno];
j++)
288 /* prevent multiple evaluation in SETBIT macro */
295 * Make bloom tuple from values.
305 /* Blooming each column */
306 for (
i = 0;
i <
state->nColumns;
i++)
319 * Add new bloom tuple to the page. Returns true if new tuple was successfully
320 * added to the page. Returns false if it doesn't fit on the page.
329 /* We shouldn't be pointed to an invalid page */
332 /* Does new tuple fit on the page? */
336 /* Copy new tuple to the end of page */
341 /* Adjust maxoff and pd_lower */
346 /* Assert we didn't overrun available space */
353 * Allocate a new page (either by recycling, or by extending the index file)
354 * The returned buffer is already pinned and exclusive-locked
355 * Caller is responsible for initializing the page by calling BloomInitPage
362 /* First, try to get a page from FSM */
373 * We have to guard against the possibility that someone else already
374 * recycled this page; the buffer may be locked if so.
381 return buffer;
/* OK to use, if never initialized */
384 return buffer;
/* OK to use */
389 /* Can't use it, so release buffer and try again */
393 /* Must extend the file */
401 * Initialize any page of a bloom index.
411 opaque->
flags = flags;
416 * Fill in metapage for bloom index.
425 * Choose the index's options. If reloptions have been assigned, use
426 * those, otherwise create default options.
433 * Initialize contents of meta page, including a copy of the options,
434 * which are now frozen for the life of the index.
443 /* If this fails, probably FreeBlockNumberArray size calc is wrong: */
448 * Initialize metapage for bloom index.
458 * Make a new page; since it is first page it should be associated with
459 * block number 0 (BLOOM_METAPAGE_BLKNO). No need to hold the extension
460 * lock because there cannot be concurrent inserters yet.
466 /* Initialize contents of meta page */
477 * Parse reloptions for bloom index, producing a BloomOptions struct.
484 /* Parse the user-given reloptions */
491 /* Convert signature length from # of bits to # to words, rounding up */
495 return (
bytea *) rdopts;
static bool validate(Port *port, const char *auth)
void blcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
void blbuildempty(Relation index)
IndexBuildResult * blbuild(Relation heap, Relation index, IndexInfo *indexInfo)
bool blinsert(Relation index, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
#define InvalidBlockNumber
#define BloomPageGetOpaque(page)
#define BloomPageGetFreeSpace(state, page)
bool blvalidate(Oid opclassoid)
int64 blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
#define BloomPageGetMeta(page)
IndexScanDesc blbeginscan(Relation r, int nkeys, int norderbys)
#define DEFAULT_BLOOM_BITS
struct BloomMetaPageData BloomMetaPageData
#define BLOOM_MAGICK_NUMBER
IndexBulkDeleteResult * blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
#define BloomPageGetTuple(state, page, offset)
#define BLOOM_NSTRATEGIES
IndexBulkDeleteResult * blvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
#define BLOOM_OPTIONS_PROC
uint16 BloomSignatureWord
#define BloomPageIsDeleted(page)
#define DEFAULT_BLOOM_LENGTH
void blendscan(IndexScanDesc scan)
#define BLOOM_METAPAGE_BLKNO
#define BloomPageIsMeta(page)
void blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys, ScanKey orderbys, int norderbys)
static int32 myRand(void)
void BloomInitPage(Page page, uint16 flags)
Datum blhandler(PG_FUNCTION_ARGS)
BloomTuple * BloomFormTuple(BloomState *state, ItemPointer iptr, Datum *values, bool *isnull)
PG_FUNCTION_INFO_V1(blhandler)
static BloomOptions * makeDefaultBloomOptions(void)
bool BloomPageAddItem(BloomState *state, Page page, BloomTuple *tuple)
static relopt_kind bl_relopt_kind
Buffer BloomNewBuffer(Relation index)
void BloomFillMetapage(Relation index, Page metaPage)
void BloomInitMetapage(Relation index, ForkNumber forknum)
bytea * bloptions(Datum reloptions, bool validate)
void signValue(BloomState *state, BloomSignatureWord *sign, Datum value, int attno)
static void mySrand(uint32 seed)
void initBloomState(BloomState *state, Relation index)
static relopt_parse_elt bl_relopt_tab[INDEX_MAX_KEYS+1]
static Datum values[MAXATTR]
BlockNumber BufferGetBlockNumber(Buffer buffer)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
bool ConditionalLockBuffer(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void UnlockReleaseBuffer(Buffer buffer)
void LockBuffer(Buffer buffer, int mode)
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define BUFFER_LOCK_UNLOCK
#define BUFFER_LOCK_SHARE
static Page BufferGetPage(Buffer buffer)
#define BUFFER_LOCK_EXCLUSIVE
void PageInit(Page page, Size pageSize, Size specialSize)
PageHeaderData * PageHeader
static bool PageIsNew(const PageData *page)
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define PG_RETURN_POINTER(x)
Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags)
GenericXLogState * GenericXLogStart(Relation relation)
XLogRecPtr GenericXLogFinish(GenericXLogState *state)
#define GENERIC_XLOG_FULL_IMAGE
Assert(PointerIsAligned(start, uint64))
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
BlockNumber GetFreeIndexPage(Relation rel)
if(TABLE==NULL||TABLE_index==NULL)
#define AccessExclusiveLock
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
void * palloc0(Size size)
MemoryContext TopMemoryContext
MemoryContext CurrentMemoryContext
static AmcheckOptions opts
static int32 DatumGetInt32(Datum X)
void add_int_reloption(bits32 kinds, const char *name, const char *desc, int default_val, int min_val, int max_val, LOCKMODE lockmode)
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
relopt_kind add_reloption_kind(void)
BloomSignatureWord sign[FLEXIBLE_ARRAY_MEMBER]
ambuildphasename_function ambuildphasename
ambuildempty_function ambuildempty
amvacuumcleanup_function amvacuumcleanup
amoptions_function amoptions
amestimateparallelscan_function amestimateparallelscan
amrestrpos_function amrestrpos
aminsert_function aminsert
amendscan_function amendscan
amtranslate_strategy_function amtranslatestrategy
amparallelrescan_function amparallelrescan
bool amconsistentordering
amtranslate_cmptype_function amtranslatecmptype
amcostestimate_function amcostestimate
amadjustmembers_function amadjustmembers
amgettuple_function amgettuple
amcanreturn_function amcanreturn
amgetbitmap_function amgetbitmap
amproperty_function amproperty
ambulkdelete_function ambulkdelete
amvalidate_function amvalidate
ammarkpos_function ammarkpos
bool amusemaintenanceworkmem
ambeginscan_function ambeginscan
amrescan_function amrescan
aminitparallelscan_function aminitparallelscan
uint8 amparallelvacuumoptions
aminsertcleanup_function aminsertcleanup
amgettreeheight_function amgettreeheight
bool amconsistentequality
#define VACUUM_OPTION_PARALLEL_CLEANUP
#define VACUUM_OPTION_PARALLEL_BULKDEL
static void SET_VARSIZE(void *PTR, Size len)