PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hashutil.c File Reference
#include "postgres.h"
#include "access/hash.h"
#include "access/reloptions.h"
#include "access/relscan.h"
#include "port/pg_bitutils.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
Include dependency graph for hashutil.c:

Go to the source code of this file.

Macros

#define CALC_NEW_BUCKET(old_bucket, lowmask)    old_bucket | (lowmask + 1)
 

Functions

bool _hash_checkqual (IndexScanDesc scan, IndexTuple itup)
 
uint32 _hash_datum2hashkey (Relation rel, Datum key)
 
uint32 _hash_datum2hashkey_type (Relation rel, Datum key, Oid keytype)
 
Bucket _hash_hashkey2bucket (uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask)
 
uint32 _hash_spareindex (uint32 num_bucket)
 
uint32 _hash_get_totalbuckets (uint32 splitpoint_phase)
 
void _hash_checkpage (Relation rel, Buffer buf, int flags)
 
byteahashoptions (Datum reloptions, bool validate)
 
uint32 _hash_get_indextuple_hashkey (IndexTuple itup)
 
bool _hash_convert_tuple (Relation index, Datum *user_values, bool *user_isnull, Datum *index_values, bool *index_isnull)
 
OffsetNumber _hash_binsearch (Page page, uint32 hash_value)
 
OffsetNumber _hash_binsearch_last (Page page, uint32 hash_value)
 
BlockNumber _hash_get_oldblock_from_newbucket (Relation rel, Bucket new_bucket)
 
BlockNumber _hash_get_newblock_from_oldbucket (Relation rel, Bucket old_bucket)
 
Bucket _hash_get_newbucket_from_oldbucket (Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket)
 
void _hash_kill_items (IndexScanDesc scan)
 

Macro Definition Documentation

◆ CALC_NEW_BUCKET

#define CALC_NEW_BUCKET (   old_bucket,
  lowmask 
)     old_bucket | (lowmask + 1)

Definition at line 24 of file hashutil.c.

Function Documentation

◆ _hash_binsearch()

OffsetNumber _hash_binsearch ( Page  page,
uint32  hash_value 
)

Definition at line 350 of file hashutil.c.

351 {
354 
355  /* Loop invariant: lower <= desired place <= upper */
356  upper = PageGetMaxOffsetNumber(page) + 1;
358 
359  while (upper > lower)
360  {
361  OffsetNumber off;
362  IndexTuple itup;
363  uint32 hashkey;
364 
365  off = (upper + lower) / 2;
367 
368  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
369  hashkey = _hash_get_indextuple_hashkey(itup);
370  if (hashkey < hash_value)
371  lower = off + 1;
372  else
373  upper = off;
374  }
375 
376  return lower;
377 }
static Item PageGetItem(Page page, ItemId itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:243
static OffsetNumber PageGetMaxOffsetNumber(Page page)
Definition: bufpage.h:372
unsigned int uint32
Definition: c.h:492
#define Assert(condition)
Definition: c.h:837
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:291
IndexTupleData * IndexTuple
Definition: itup.h:53
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:39
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80

References _hash_get_indextuple_hashkey(), Assert, FirstOffsetNumber, lower(), OffsetNumberIsValid, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), and upper().

Referenced by _hash_pgaddmultitup(), _hash_pgaddtup(), and _hash_readpage().

◆ _hash_binsearch_last()

OffsetNumber _hash_binsearch_last ( Page  page,
uint32  hash_value 
)

Definition at line 388 of file hashutil.c.

389 {
392 
393  /* Loop invariant: lower <= desired place <= upper */
395  lower = FirstOffsetNumber - 1;
396 
397  while (upper > lower)
398  {
399  IndexTuple itup;
400  OffsetNumber off;
401  uint32 hashkey;
402 
403  off = (upper + lower + 1) / 2;
405 
406  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
407  hashkey = _hash_get_indextuple_hashkey(itup);
408  if (hashkey > hash_value)
409  upper = off - 1;
410  else
411  lower = off;
412  }
413 
414  return lower;
415 }

References _hash_get_indextuple_hashkey(), Assert, FirstOffsetNumber, lower(), OffsetNumberIsValid, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), and upper().

Referenced by _hash_readpage().

◆ _hash_checkpage()

void _hash_checkpage ( Relation  rel,
Buffer  buf,
int  flags 
)

Definition at line 210 of file hashutil.c.

211 {
212  Page page = BufferGetPage(buf);
213 
214  /*
215  * ReadBuffer verifies that every newly-read page passes
216  * PageHeaderIsValid, which means it either contains a reasonably sane
217  * page header or is all-zero. We have to defend against the all-zero
218  * case, however.
219  */
220  if (PageIsNew(page))
221  ereport(ERROR,
222  (errcode(ERRCODE_INDEX_CORRUPTED),
223  errmsg("index \"%s\" contains unexpected zero page at block %u",
226  errhint("Please REINDEX it.")));
227 
228  /*
229  * Additionally check that the special area looks sane.
230  */
231  if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData)))
232  ereport(ERROR,
233  (errcode(ERRCODE_INDEX_CORRUPTED),
234  errmsg("index \"%s\" contains corrupted page at block %u",
237  errhint("Please REINDEX it.")));
238 
239  if (flags)
240  {
241  HashPageOpaque opaque = HashPageGetOpaque(page);
242 
243  if ((opaque->hasho_flag & flags) == 0)
244  ereport(ERROR,
245  (errcode(ERRCODE_INDEX_CORRUPTED),
246  errmsg("index \"%s\" contains corrupted page at block %u",
249  errhint("Please REINDEX it.")));
250  }
251 
252  /*
253  * When checking the metapage, also verify magic number and version.
254  */
255  if (flags == LH_META_PAGE)
256  {
257  HashMetaPage metap = HashPageGetMeta(page);
258 
259  if (metap->hashm_magic != HASH_MAGIC)
260  ereport(ERROR,
261  (errcode(ERRCODE_INDEX_CORRUPTED),
262  errmsg("index \"%s\" is not a hash index",
263  RelationGetRelationName(rel))));
264 
265  if (metap->hashm_version != HASH_VERSION)
266  ereport(ERROR,
267  (errcode(ERRCODE_INDEX_CORRUPTED),
268  errmsg("index \"%s\" has wrong hash version",
270  errhint("Please REINDEX it.")));
271  }
272 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3724
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
Pointer Page
Definition: bufpage.h:81
static bool PageIsNew(Page page)
Definition: bufpage.h:233
static uint16 PageGetSpecialSize(Page page)
Definition: bufpage.h:316
#define MAXALIGN(LEN)
Definition: c.h:790
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define HashPageGetOpaque(page)
Definition: hash.h:88
#define HASH_VERSION
Definition: hash.h:201
#define LH_META_PAGE
Definition: hash.h:57
#define HashPageGetMeta(page)
Definition: hash.h:323
#define HASH_MAGIC
Definition: hash.h:200
static char * buf
Definition: pg_test_fsync.c:72
#define RelationGetRelationName(relation)
Definition: rel.h:539
uint32 hashm_version
Definition: hash.h:247
uint32 hashm_magic
Definition: hash.h:246
uint16 hasho_flag
Definition: hash.h:82

References buf, BufferGetBlockNumber(), BufferGetPage(), ereport, errcode(), errhint(), errmsg(), ERROR, HASH_MAGIC, HASH_VERSION, HashMetaPageData::hashm_magic, HashMetaPageData::hashm_version, HashPageOpaqueData::hasho_flag, HashPageGetMeta, HashPageGetOpaque, LH_META_PAGE, MAXALIGN, PageGetSpecialSize(), PageIsNew(), and RelationGetRelationName.

Referenced by _hash_addovflpage(), _hash_expandtable(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_condlock_cleanup(), _hash_getbuf_with_strategy(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_readpage(), and hashbulkdelete().

◆ _hash_checkqual()

bool _hash_checkqual ( IndexScanDesc  scan,
IndexTuple  itup 
)

Definition at line 31 of file hashutil.c.

32 {
33  /*
34  * Currently, we can't check any of the scan conditions since we do not
35  * have the original index entry value to supply to the sk_func. Always
36  * return true; we expect that hashgettuple already set the recheck flag
37  * to make the main indexscan code do it.
38  */
39 #ifdef NOT_USED
40  TupleDesc tupdesc = RelationGetDescr(scan->indexRelation);
41  ScanKey key = scan->keyData;
42  int scanKeySize = scan->numberOfKeys;
43 
44  while (scanKeySize > 0)
45  {
46  Datum datum;
47  bool isNull;
48  Datum test;
49 
50  datum = index_getattr(itup,
51  key->sk_attno,
52  tupdesc,
53  &isNull);
54 
55  /* assume sk_func is strict */
56  if (isNull)
57  return false;
58  if (key->sk_flags & SK_ISNULL)
59  return false;
60 
61  test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
62  datum, key->sk_argument);
63 
64  if (!DatumGetBool(test))
65  return false;
66 
67  key++;
68  scanKeySize--;
69  }
70 #endif
71 
72  return true;
73 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: itup.h:117
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
uintptr_t Datum
Definition: postgres.h:64
static void test(void)
#define RelationGetDescr(relation)
Definition: rel.h:531
#define SK_ISNULL
Definition: skey.h:115
struct ScanKeyData * keyData
Definition: relscan.h:145
Relation indexRelation
Definition: relscan.h:141

References DatumGetBool(), FunctionCall2Coll(), index_getattr(), IndexScanDescData::indexRelation, sort-test::key, IndexScanDescData::keyData, IndexScanDescData::numberOfKeys, RelationGetDescr, SK_ISNULL, and test().

Referenced by _hash_load_qualified_items().

◆ _hash_convert_tuple()

bool _hash_convert_tuple ( Relation  index,
Datum user_values,
bool *  user_isnull,
Datum index_values,
bool *  index_isnull 
)

Definition at line 318 of file hashutil.c.

321 {
322  uint32 hashkey;
323 
324  /*
325  * We do not insert null values into hash indexes. This is okay because
326  * the only supported search operator is '=', and we assume it is strict.
327  */
328  if (user_isnull[0])
329  return false;
330 
331  hashkey = _hash_datum2hashkey(index, user_values[0]);
332  index_values[0] = UInt32GetDatum(hashkey);
333  index_isnull[0] = false;
334  return true;
335 }
uint32 _hash_datum2hashkey(Relation rel, Datum key)
Definition: hashutil.c:82
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:232
Definition: type.h:96

References _hash_datum2hashkey(), and UInt32GetDatum().

Referenced by hashbuildCallback(), and hashinsert().

◆ _hash_datum2hashkey()

uint32 _hash_datum2hashkey ( Relation  rel,
Datum  key 
)

Definition at line 82 of file hashutil.c.

83 {
84  FmgrInfo *procinfo;
85  Oid collation;
86 
87  /* XXX assumes index has only one attribute */
88  procinfo = index_getprocinfo(rel, 1, HASHSTANDARD_PROC);
89  collation = rel->rd_indcollation[0];
90 
91  return DatumGetUInt32(FunctionCall1Coll(procinfo, collation, key));
92 }
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
#define HASHSTANDARD_PROC
Definition: hash.h:355
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:862
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
unsigned int Oid
Definition: postgres_ext.h:31
Definition: fmgr.h:57
Oid * rd_indcollation
Definition: rel.h:217

References DatumGetUInt32(), FunctionCall1Coll(), HASHSTANDARD_PROC, index_getprocinfo(), sort-test::key, and RelationData::rd_indcollation.

Referenced by _hash_convert_tuple(), and _hash_first().

◆ _hash_datum2hashkey_type()

uint32 _hash_datum2hashkey_type ( Relation  rel,
Datum  key,
Oid  keytype 
)

Definition at line 102 of file hashutil.c.

103 {
104  RegProcedure hash_proc;
105  Oid collation;
106 
107  /* XXX assumes index has only one attribute */
108  hash_proc = get_opfamily_proc(rel->rd_opfamily[0],
109  keytype,
110  keytype,
112  if (!RegProcedureIsValid(hash_proc))
113  elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"",
114  HASHSTANDARD_PROC, keytype, keytype,
116  collation = rel->rd_indcollation[0];
117 
118  return DatumGetUInt32(OidFunctionCall1Coll(hash_proc, collation, key));
119 }
#define RegProcedureIsValid(p)
Definition: c.h:756
regproc RegProcedure
Definition: c.h:629
#define elog(elevel,...)
Definition: elog.h:225
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition: fmgr.c:1411
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:796
Oid * rd_opfamily
Definition: rel.h:207

References DatumGetUInt32(), elog, ERROR, get_opfamily_proc(), HASHSTANDARD_PROC, sort-test::key, OidFunctionCall1Coll(), RelationData::rd_indcollation, RelationData::rd_opfamily, RegProcedureIsValid, and RelationGetRelationName.

Referenced by _hash_first().

◆ _hash_get_indextuple_hashkey()

uint32 _hash_get_indextuple_hashkey ( IndexTuple  itup)

Definition at line 291 of file hashutil.c.

292 {
293  char *attp;
294 
295  /*
296  * We assume the hash key is the first attribute and can't be null, so
297  * this can be done crudely but very very cheaply ...
298  */
299  attp = (char *) itup + IndexInfoFindDataOffset(itup->t_info);
300  return *((uint32 *) attp);
301 }
static Size IndexInfoFindDataOffset(unsigned short t_info)
Definition: itup.h:98
unsigned short t_info
Definition: itup.h:49

References IndexInfoFindDataOffset(), and IndexTupleData::t_info.

Referenced by _h_indexbuild(), _hash_binsearch(), _hash_binsearch_last(), _hash_doinsert(), _hash_load_qualified_items(), _hash_pgaddmultitup(), _hash_pgaddtup(), _hash_splitbucket(), hash_page_items(), and hashbucketcleanup().

◆ _hash_get_newblock_from_oldbucket()

BlockNumber _hash_get_newblock_from_oldbucket ( Relation  rel,
Bucket  old_bucket 
)

Definition at line 461 of file hashutil.c.

462 {
463  Bucket new_bucket;
464  Buffer metabuf;
465  HashMetaPage metap;
466  BlockNumber blkno;
467 
469  metap = HashPageGetMeta(BufferGetPage(metabuf));
470 
471  new_bucket = _hash_get_newbucket_from_oldbucket(rel, old_bucket,
472  metap->hashm_lowmask,
473  metap->hashm_maxbucket);
474  blkno = BUCKET_TO_BLKNO(metap, new_bucket);
475 
476  _hash_relbuf(rel, metabuf);
477 
478  return blkno;
479 }
uint32 BlockNumber
Definition: block.h:31
int Buffer
Definition: buf.h:23
#define HASH_READ
Definition: hash.h:339
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:39
#define HASH_METAPAGE
Definition: hash.h:198
uint32 Bucket
Definition: hash.h:35
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:266
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:70
Bucket _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket)
Definition: hashutil.c:494
uint32 hashm_lowmask
Definition: hash.h:256
uint32 hashm_maxbucket
Definition: hash.h:254

References _hash_get_newbucket_from_oldbucket(), _hash_getbuf(), _hash_relbuf(), BUCKET_TO_BLKNO, BufferGetPage(), HASH_METAPAGE, HASH_READ, HashMetaPageData::hashm_lowmask, HashMetaPageData::hashm_maxbucket, HashPageGetMeta, and LH_META_PAGE.

Referenced by _hash_finish_split().

◆ _hash_get_newbucket_from_oldbucket()

Bucket _hash_get_newbucket_from_oldbucket ( Relation  rel,
Bucket  old_bucket,
uint32  lowmask,
uint32  maxbucket 
)

Definition at line 494 of file hashutil.c.

496 {
497  Bucket new_bucket;
498 
499  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
500  if (new_bucket > maxbucket)
501  {
502  lowmask = lowmask >> 1;
503  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
504  }
505 
506  return new_bucket;
507 }
#define CALC_NEW_BUCKET(old_bucket, lowmask)
Definition: hashutil.c:24

References CALC_NEW_BUCKET.

Referenced by _hash_get_newblock_from_oldbucket(), and hashbucketcleanup().

◆ _hash_get_oldblock_from_newbucket()

BlockNumber _hash_get_oldblock_from_newbucket ( Relation  rel,
Bucket  new_bucket 
)

Definition at line 422 of file hashutil.c.

423 {
424  Bucket old_bucket;
425  uint32 mask;
426  Buffer metabuf;
427  HashMetaPage metap;
428  BlockNumber blkno;
429 
430  /*
431  * To get the old bucket from the current bucket, we need a mask to modulo
432  * into lower half of table. This mask is stored in meta page as
433  * hashm_lowmask, but here we can't rely on the same, because we need a
434  * value of lowmask that was prevalent at the time when bucket split was
435  * started. Masking the most significant bit of new bucket would give us
436  * old bucket.
437  */
438  mask = (((uint32) 1) << pg_leftmost_one_pos32(new_bucket)) - 1;
439  old_bucket = new_bucket & mask;
440 
442  metap = HashPageGetMeta(BufferGetPage(metabuf));
443 
444  blkno = BUCKET_TO_BLKNO(metap, old_bucket);
445 
446  _hash_relbuf(rel, metabuf);
447 
448  return blkno;
449 }
static int pg_leftmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:41

References _hash_getbuf(), _hash_relbuf(), BUCKET_TO_BLKNO, BufferGetPage(), HASH_METAPAGE, HASH_READ, HashPageGetMeta, LH_META_PAGE, and pg_leftmost_one_pos32().

Referenced by _hash_first().

◆ _hash_get_totalbuckets()

uint32 _hash_get_totalbuckets ( uint32  splitpoint_phase)

Definition at line 174 of file hashutil.c.

175 {
176  uint32 splitpoint_group;
177  uint32 total_buckets;
178  uint32 phases_within_splitpoint_group;
179 
180  if (splitpoint_phase < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
181  return (1 << splitpoint_phase);
182 
183  /* get splitpoint's group */
184  splitpoint_group = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
185  splitpoint_group +=
186  ((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) >>
188 
189  /* account for buckets before splitpoint_group */
190  total_buckets = (1 << (splitpoint_group - 1));
191 
192  /* account for buckets within splitpoint_group */
193  phases_within_splitpoint_group =
194  (((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) &
195  HASH_SPLITPOINT_PHASE_MASK) + 1); /* from 0-based to 1-based */
196  total_buckets +=
197  (((1 << (splitpoint_group - 1)) >> HASH_SPLITPOINT_PHASE_BITS) *
198  phases_within_splitpoint_group);
199 
200  return total_buckets;
201 }
#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE
Definition: hash.h:235
#define HASH_SPLITPOINT_PHASE_MASK
Definition: hash.h:234
#define HASH_SPLITPOINT_PHASE_BITS
Definition: hash.h:232

References HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE, HASH_SPLITPOINT_PHASE_BITS, and HASH_SPLITPOINT_PHASE_MASK.

Referenced by _hash_expandtable(), _hash_init_metabuffer(), _hash_ovflblkno_to_bitno(), and bitno_to_blkno().

◆ _hash_hashkey2bucket()

Bucket _hash_hashkey2bucket ( uint32  hashkey,
uint32  maxbucket,
uint32  highmask,
uint32  lowmask 
)

Definition at line 125 of file hashutil.c.

127 {
128  Bucket bucket;
129 
130  bucket = hashkey & highmask;
131  if (bucket > maxbucket)
132  bucket = bucket & lowmask;
133 
134  return bucket;
135 }

Referenced by _h_indexbuild(), _hash_getbucketbuf_from_hashkey(), _hash_splitbucket(), comparetup_index_hash(), and hashbucketcleanup().

◆ _hash_kill_items()

void _hash_kill_items ( IndexScanDesc  scan)

Definition at line 536 of file hashutil.c.

537 {
538  HashScanOpaque so = (HashScanOpaque) scan->opaque;
539  Relation rel = scan->indexRelation;
540  BlockNumber blkno;
541  Buffer buf;
542  Page page;
543  HashPageOpaque opaque;
544  OffsetNumber offnum,
545  maxoff;
546  int numKilled = so->numKilled;
547  int i;
548  bool killedsomething = false;
549  bool havePin = false;
550 
551  Assert(so->numKilled > 0);
552  Assert(so->killedItems != NULL);
554 
555  /*
556  * Always reset the scan state, so we don't look for same items on other
557  * pages.
558  */
559  so->numKilled = 0;
560 
561  blkno = so->currPos.currPage;
562  if (HashScanPosIsPinned(so->currPos))
563  {
564  /*
565  * We already have pin on this buffer, so, all we need to do is
566  * acquire lock on it.
567  */
568  havePin = true;
569  buf = so->currPos.buf;
571  }
572  else
573  buf = _hash_getbuf(rel, blkno, HASH_READ, LH_OVERFLOW_PAGE);
574 
575  page = BufferGetPage(buf);
576  opaque = HashPageGetOpaque(page);
577  maxoff = PageGetMaxOffsetNumber(page);
578 
579  for (i = 0; i < numKilled; i++)
580  {
581  int itemIndex = so->killedItems[i];
582  HashScanPosItem *currItem = &so->currPos.items[itemIndex];
583 
584  offnum = currItem->indexOffset;
585 
586  Assert(itemIndex >= so->currPos.firstItem &&
587  itemIndex <= so->currPos.lastItem);
588 
589  while (offnum <= maxoff)
590  {
591  ItemId iid = PageGetItemId(page, offnum);
592  IndexTuple ituple = (IndexTuple) PageGetItem(page, iid);
593 
594  if (ItemPointerEquals(&ituple->t_tid, &currItem->heapTid))
595  {
596  /* found the item */
597  ItemIdMarkDead(iid);
598  killedsomething = true;
599  break; /* out of inner search loop */
600  }
601  offnum = OffsetNumberNext(offnum);
602  }
603  }
604 
605  /*
606  * Since this can be redone later if needed, mark as dirty hint. Whenever
607  * we mark anything LP_DEAD, we also set the page's
608  * LH_PAGE_HAS_DEAD_TUPLES flag, which is likewise just a hint.
609  */
610  if (killedsomething)
611  {
612  opaque->hasho_flag |= LH_PAGE_HAS_DEAD_TUPLES;
613  MarkBufferDirtyHint(buf, true);
614  }
615 
616  if (so->hashso_bucket_buf == so->currPos.buf ||
617  havePin)
619  else
620  _hash_relbuf(rel, buf);
621 }
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5158
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:4988
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:189
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:190
#define HashScanPosIsPinned(scanpos)
Definition: hash.h:130
HashScanOpaqueData * HashScanOpaque
Definition: hash.h:192
#define HashScanPosIsValid(scanpos)
Definition: hash.h:137
#define LH_PAGE_HAS_DEAD_TUPLES
Definition: hash.h:61
#define LH_OVERFLOW_PAGE
Definition: hash.h:54
int i
Definition: isn.c:72
#define ItemIdMarkDead(itemId)
Definition: itemid.h:179
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:35
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
HashScanPosData currPos
Definition: hash.h:189
Buffer hashso_bucket_buf
Definition: hash.h:164
int * killedItems
Definition: hash.h:182
BlockNumber currPage
Definition: hash.h:112
HashScanPosItem items[MaxIndexTuplesPerPage]
Definition: hash.h:127
int firstItem
Definition: hash.h:123
Buffer buf
Definition: hash.h:111
ItemPointerData heapTid
Definition: hash.h:105
OffsetNumber indexOffset
Definition: hash.h:106
ItemPointerData t_tid
Definition: itup.h:37

References _hash_getbuf(), _hash_relbuf(), Assert, buf, HashScanPosData::buf, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage(), HashScanPosData::currPage, HashScanOpaqueData::currPos, HashScanPosData::firstItem, HASH_READ, HashPageGetOpaque, HashScanPosIsPinned, HashScanPosIsValid, HashScanOpaqueData::hashso_bucket_buf, HashScanPosItem::heapTid, i, HashScanPosItem::indexOffset, IndexScanDescData::indexRelation, ItemIdMarkDead, ItemPointerEquals(), HashScanPosData::items, HashScanOpaqueData::killedItems, LH_OVERFLOW_PAGE, LH_PAGE_HAS_DEAD_TUPLES, LockBuffer(), MarkBufferDirtyHint(), HashScanOpaqueData::numKilled, OffsetNumberNext, IndexScanDescData::opaque, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), and IndexTupleData::t_tid.

Referenced by _hash_next(), _hash_readpage(), hashendscan(), and hashrescan().

◆ _hash_spareindex()

uint32 _hash_spareindex ( uint32  num_bucket)

Definition at line 142 of file hashutil.c.

143 {
144  uint32 splitpoint_group;
145  uint32 splitpoint_phases;
146 
147  splitpoint_group = pg_ceil_log2_32(num_bucket);
148 
149  if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
150  return splitpoint_group;
151 
152  /* account for single-phase groups */
153  splitpoint_phases = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
154 
155  /* account for multi-phase groups before splitpoint_group */
156  splitpoint_phases +=
157  ((splitpoint_group - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) <<
159 
160  /* account for phases within current group */
161  splitpoint_phases +=
162  (((num_bucket - 1) >>
163  (splitpoint_group - (HASH_SPLITPOINT_PHASE_BITS + 1))) &
164  HASH_SPLITPOINT_PHASE_MASK); /* to 0-based value. */
165 
166  return splitpoint_phases;
167 }
static uint32 pg_ceil_log2_32(uint32 num)
Definition: pg_bitutils.h:258

References HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE, HASH_SPLITPOINT_PHASE_BITS, HASH_SPLITPOINT_PHASE_MASK, and pg_ceil_log2_32().

Referenced by _hash_expandtable(), and _hash_init_metabuffer().

◆ hashoptions()

bytea* hashoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 275 of file hashutil.c.

276 {
277  static const relopt_parse_elt tab[] = {
278  {"fillfactor", RELOPT_TYPE_INT, offsetof(HashOptions, fillfactor)},
279  };
280 
281  return (bytea *) build_reloptions(reloptions, validate,
283  sizeof(HashOptions),
284  tab, lengthof(tab));
285 }
#define lengthof(array)
Definition: c.h:767
static int fillfactor
Definition: pgbench.c:187
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1908
@ RELOPT_KIND_HASH
Definition: reloptions.h:45
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
Definition: c.h:666

References build_reloptions(), fillfactor, lengthof, RELOPT_KIND_HASH, and RELOPT_TYPE_INT.

Referenced by hashhandler().