PostgreSQL Source Code  git master
hashutil.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * hashutil.c
4  * Utility code for Postgres hash implementation.
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/access/hash/hashutil.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/hash.h"
18 #include "access/reloptions.h"
19 #include "access/relscan.h"
20 #include "utils/lsyscache.h"
21 #include "utils/rel.h"
22 #include "storage/buf_internals.h"
23 
24 #define CALC_NEW_BUCKET(old_bucket, lowmask) \
25  old_bucket | (lowmask + 1)
26 
27 /*
28  * _hash_checkqual -- does the index tuple satisfy the scan conditions?
29  */
30 bool
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 }
74 
75 /*
76  * _hash_datum2hashkey -- given a Datum, call the index's hash procedure
77  *
78  * The Datum is assumed to be of the index's column type, so we can use the
79  * "primary" hash procedure that's tracked for us by the generic index code.
80  */
81 uint32
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 }
93 
94 /*
95  * _hash_datum2hashkey_type -- given a Datum of a specified type,
96  * hash it in a fashion compatible with this index
97  *
98  * This is much more expensive than _hash_datum2hashkey, so use it only in
99  * cross-type situations.
100  */
101 uint32
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 }
120 
121 /*
122  * _hash_hashkey2bucket -- determine which bucket the hashkey maps to.
123  */
124 Bucket
125 _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
126  uint32 highmask, uint32 lowmask)
127 {
128  Bucket bucket;
129 
130  bucket = hashkey & highmask;
131  if (bucket > maxbucket)
132  bucket = bucket & lowmask;
133 
134  return bucket;
135 }
136 
137 /*
138  * _hash_log2 -- returns ceil(lg2(num))
139  */
140 uint32
142 {
143  uint32 i,
144  limit;
145 
146  limit = 1;
147  for (i = 0; limit < num; limit <<= 1, i++)
148  ;
149  return i;
150 }
151 
152 /*
153  * _hash_spareindex -- returns spare index / global splitpoint phase of the
154  * bucket
155  */
156 uint32
158 {
159  uint32 splitpoint_group;
160  uint32 splitpoint_phases;
161 
162  splitpoint_group = _hash_log2(num_bucket);
163 
164  if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
165  return splitpoint_group;
166 
167  /* account for single-phase groups */
168  splitpoint_phases = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
169 
170  /* account for multi-phase groups before splitpoint_group */
171  splitpoint_phases +=
172  ((splitpoint_group - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) <<
174 
175  /* account for phases within current group */
176  splitpoint_phases +=
177  (((num_bucket - 1) >>
178  (splitpoint_group - (HASH_SPLITPOINT_PHASE_BITS + 1))) &
179  HASH_SPLITPOINT_PHASE_MASK); /* to 0-based value. */
180 
181  return splitpoint_phases;
182 }
183 
184 /*
185  * _hash_get_totalbuckets -- returns total number of buckets allocated till
186  * the given splitpoint phase.
187  */
188 uint32
190 {
191  uint32 splitpoint_group;
192  uint32 total_buckets;
193  uint32 phases_within_splitpoint_group;
194 
195  if (splitpoint_phase < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
196  return (1 << splitpoint_phase);
197 
198  /* get splitpoint's group */
199  splitpoint_group = HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE;
200  splitpoint_group +=
201  ((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) >>
203 
204  /* account for buckets before splitpoint_group */
205  total_buckets = (1 << (splitpoint_group - 1));
206 
207  /* account for buckets within splitpoint_group */
208  phases_within_splitpoint_group =
209  (((splitpoint_phase - HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE) &
210  HASH_SPLITPOINT_PHASE_MASK) + 1); /* from 0-based to 1-based */
211  total_buckets +=
212  (((1 << (splitpoint_group - 1)) >> HASH_SPLITPOINT_PHASE_BITS) *
213  phases_within_splitpoint_group);
214 
215  return total_buckets;
216 }
217 
218 /*
219  * _hash_checkpage -- sanity checks on the format of all hash pages
220  *
221  * If flags is not zero, it is a bitwise OR of the acceptable page types
222  * (values of hasho_flag & LH_PAGE_TYPE).
223  */
224 void
226 {
227  Page page = BufferGetPage(buf);
228 
229  /*
230  * ReadBuffer verifies that every newly-read page passes
231  * PageHeaderIsValid, which means it either contains a reasonably sane
232  * page header or is all-zero. We have to defend against the all-zero
233  * case, however.
234  */
235  if (PageIsNew(page))
236  ereport(ERROR,
237  (errcode(ERRCODE_INDEX_CORRUPTED),
238  errmsg("index \"%s\" contains unexpected zero page at block %u",
240  BufferGetBlockNumber(buf)),
241  errhint("Please REINDEX it.")));
242 
243  /*
244  * Additionally check that the special area looks sane.
245  */
246  if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData)))
247  ereport(ERROR,
248  (errcode(ERRCODE_INDEX_CORRUPTED),
249  errmsg("index \"%s\" contains corrupted page at block %u",
251  BufferGetBlockNumber(buf)),
252  errhint("Please REINDEX it.")));
253 
254  if (flags)
255  {
257 
258  if ((opaque->hasho_flag & flags) == 0)
259  ereport(ERROR,
260  (errcode(ERRCODE_INDEX_CORRUPTED),
261  errmsg("index \"%s\" contains corrupted page at block %u",
263  BufferGetBlockNumber(buf)),
264  errhint("Please REINDEX it.")));
265  }
266 
267  /*
268  * When checking the metapage, also verify magic number and version.
269  */
270  if (flags == LH_META_PAGE)
271  {
272  HashMetaPage metap = HashPageGetMeta(page);
273 
274  if (metap->hashm_magic != HASH_MAGIC)
275  ereport(ERROR,
276  (errcode(ERRCODE_INDEX_CORRUPTED),
277  errmsg("index \"%s\" is not a hash index",
278  RelationGetRelationName(rel))));
279 
280  if (metap->hashm_version != HASH_VERSION)
281  ereport(ERROR,
282  (errcode(ERRCODE_INDEX_CORRUPTED),
283  errmsg("index \"%s\" has wrong hash version",
285  errhint("Please REINDEX it.")));
286  }
287 }
288 
289 bytea *
290 hashoptions(Datum reloptions, bool validate)
291 {
292  return default_reloptions(reloptions, validate, RELOPT_KIND_HASH);
293 }
294 
295 /*
296  * _hash_get_indextuple_hashkey - get the hash index tuple's hash key value
297  */
298 uint32
300 {
301  char *attp;
302 
303  /*
304  * We assume the hash key is the first attribute and can't be null, so
305  * this can be done crudely but very very cheaply ...
306  */
307  attp = (char *) itup + IndexInfoFindDataOffset(itup->t_info);
308  return *((uint32 *) attp);
309 }
310 
311 /*
312  * _hash_convert_tuple - convert raw index data to hash key
313  *
314  * Inputs: values and isnull arrays for the user data column(s)
315  * Outputs: values and isnull arrays for the index tuple, suitable for
316  * passing to index_form_tuple().
317  *
318  * Returns true if successful, false if not (because there are null values).
319  * On a false result, the given data need not be indexed.
320  *
321  * Note: callers know that the index-column arrays are always of length 1.
322  * In principle, there could be more than one input column, though we do not
323  * currently support that.
324  */
325 bool
327  Datum *user_values, bool *user_isnull,
328  Datum *index_values, bool *index_isnull)
329 {
330  uint32 hashkey;
331 
332  /*
333  * We do not insert null values into hash indexes. This is okay because
334  * the only supported search operator is '=', and we assume it is strict.
335  */
336  if (user_isnull[0])
337  return false;
338 
339  hashkey = _hash_datum2hashkey(index, user_values[0]);
340  index_values[0] = UInt32GetDatum(hashkey);
341  index_isnull[0] = false;
342  return true;
343 }
344 
345 /*
346  * _hash_binsearch - Return the offset number in the page where the
347  * specified hash value should be sought or inserted.
348  *
349  * We use binary search, relying on the assumption that the existing entries
350  * are ordered by hash key.
351  *
352  * Returns the offset of the first index entry having hashkey >= hash_value,
353  * or the page's max offset plus one if hash_value is greater than all
354  * existing hash keys in the page. This is the appropriate place to start
355  * a search, or to insert a new item.
356  */
358 _hash_binsearch(Page page, uint32 hash_value)
359 {
362 
363  /* Loop invariant: lower <= desired place <= upper */
364  upper = PageGetMaxOffsetNumber(page) + 1;
365  lower = FirstOffsetNumber;
366 
367  while (upper > lower)
368  {
369  OffsetNumber off;
370  IndexTuple itup;
371  uint32 hashkey;
372 
373  off = (upper + lower) / 2;
375 
376  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
377  hashkey = _hash_get_indextuple_hashkey(itup);
378  if (hashkey < hash_value)
379  lower = off + 1;
380  else
381  upper = off;
382  }
383 
384  return lower;
385 }
386 
387 /*
388  * _hash_binsearch_last
389  *
390  * Same as above, except that if there are multiple matching items in the
391  * page, we return the offset of the last one instead of the first one,
392  * and the possible range of outputs is 0..maxoffset not 1..maxoffset+1.
393  * This is handy for starting a new page in a backwards scan.
394  */
397 {
400 
401  /* Loop invariant: lower <= desired place <= upper */
402  upper = PageGetMaxOffsetNumber(page);
403  lower = FirstOffsetNumber - 1;
404 
405  while (upper > lower)
406  {
407  IndexTuple itup;
408  OffsetNumber off;
409  uint32 hashkey;
410 
411  off = (upper + lower + 1) / 2;
413 
414  itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off));
415  hashkey = _hash_get_indextuple_hashkey(itup);
416  if (hashkey > hash_value)
417  upper = off - 1;
418  else
419  lower = off;
420  }
421 
422  return lower;
423 }
424 
425 /*
426  * _hash_get_oldblock_from_newbucket() -- get the block number of a bucket
427  * from which current (new) bucket is being split.
428  */
431 {
432  Bucket old_bucket;
433  uint32 mask;
434  Buffer metabuf;
435  HashMetaPage metap;
436  BlockNumber blkno;
437 
438  /*
439  * To get the old bucket from the current bucket, we need a mask to modulo
440  * into lower half of table. This mask is stored in meta page as
441  * hashm_lowmask, but here we can't rely on the same, because we need a
442  * value of lowmask that was prevalent at the time when bucket split was
443  * started. Masking the most significant bit of new bucket would give us
444  * old bucket.
445  */
446  mask = (((uint32) 1) << (fls(new_bucket) - 1)) - 1;
447  old_bucket = new_bucket & mask;
448 
450  metap = HashPageGetMeta(BufferGetPage(metabuf));
451 
452  blkno = BUCKET_TO_BLKNO(metap, old_bucket);
453 
454  _hash_relbuf(rel, metabuf);
455 
456  return blkno;
457 }
458 
459 /*
460  * _hash_get_newblock_from_oldbucket() -- get the block number of a bucket
461  * that will be generated after split from old bucket.
462  *
463  * This is used to find the new bucket from old bucket based on current table
464  * half. It is mainly required to finish the incomplete splits where we are
465  * sure that not more than one bucket could have split in progress from old
466  * bucket.
467  */
470 {
471  Bucket new_bucket;
472  Buffer metabuf;
473  HashMetaPage metap;
474  BlockNumber blkno;
475 
477  metap = HashPageGetMeta(BufferGetPage(metabuf));
478 
479  new_bucket = _hash_get_newbucket_from_oldbucket(rel, old_bucket,
480  metap->hashm_lowmask,
481  metap->hashm_maxbucket);
482  blkno = BUCKET_TO_BLKNO(metap, new_bucket);
483 
484  _hash_relbuf(rel, metabuf);
485 
486  return blkno;
487 }
488 
489 /*
490  * _hash_get_newbucket_from_oldbucket() -- get the new bucket that will be
491  * generated after split from current (old) bucket.
492  *
493  * This is used to find the new bucket from old bucket. New bucket can be
494  * obtained by OR'ing old bucket with most significant bit of current table
495  * half (lowmask passed in this function can be used to identify msb of
496  * current table half). There could be multiple buckets that could have
497  * been split from current bucket. We need the first such bucket that exists.
498  * Caller must ensure that no more than one split has happened from old
499  * bucket.
500  */
501 Bucket
503  uint32 lowmask, uint32 maxbucket)
504 {
505  Bucket new_bucket;
506 
507  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
508  if (new_bucket > maxbucket)
509  {
510  lowmask = lowmask >> 1;
511  new_bucket = CALC_NEW_BUCKET(old_bucket, lowmask);
512  }
513 
514  return new_bucket;
515 }
516 
517 /*
518  * _hash_kill_items - set LP_DEAD state for items an indexscan caller has
519  * told us were killed.
520  *
521  * scan->opaque, referenced locally through so, contains information about the
522  * current page and killed tuples thereon (generally, this should only be
523  * called if so->numKilled > 0).
524  *
525  * The caller does not have a lock on the page and may or may not have the
526  * page pinned in a buffer. Note that read-lock is sufficient for setting
527  * LP_DEAD status (which is only a hint).
528  *
529  * The caller must have pin on bucket buffer, but may or may not have pin
530  * on overflow buffer, as indicated by HashScanPosIsPinned(so->currPos).
531  *
532  * We match items by heap TID before assuming they are the right ones to
533  * delete.
534  *
535  * There are never any scans active in a bucket at the time VACUUM begins,
536  * because VACUUM takes a cleanup lock on the primary bucket page and scans
537  * hold a pin. A scan can begin after VACUUM leaves the primary bucket page
538  * but before it finishes the entire bucket, but it can never pass VACUUM,
539  * because VACUUM always locks the next page before releasing the lock on
540  * the previous one. Therefore, we don't have to worry about accidentally
541  * killing a TID that has been reused for an unrelated tuple.
542  */
543 void
545 {
546  HashScanOpaque so = (HashScanOpaque) scan->opaque;
547  Relation rel = scan->indexRelation;
548  BlockNumber blkno;
549  Buffer buf;
550  Page page;
551  HashPageOpaque opaque;
552  OffsetNumber offnum,
553  maxoff;
554  int numKilled = so->numKilled;
555  int i;
556  bool killedsomething = false;
557  bool havePin = false;
558 
559  Assert(so->numKilled > 0);
560  Assert(so->killedItems != NULL);
562 
563  /*
564  * Always reset the scan state, so we don't look for same items on other
565  * pages.
566  */
567  so->numKilled = 0;
568 
569  blkno = so->currPos.currPage;
570  if (HashScanPosIsPinned(so->currPos))
571  {
572  /*
573  * We already have pin on this buffer, so, all we need to do is
574  * acquire lock on it.
575  */
576  havePin = true;
577  buf = so->currPos.buf;
579  }
580  else
581  buf = _hash_getbuf(rel, blkno, HASH_READ, LH_OVERFLOW_PAGE);
582 
583  page = BufferGetPage(buf);
584  opaque = (HashPageOpaque) PageGetSpecialPointer(page);
585  maxoff = PageGetMaxOffsetNumber(page);
586 
587  for (i = 0; i < numKilled; i++)
588  {
589  int itemIndex = so->killedItems[i];
590  HashScanPosItem *currItem = &so->currPos.items[itemIndex];
591 
592  offnum = currItem->indexOffset;
593 
594  Assert(itemIndex >= so->currPos.firstItem &&
595  itemIndex <= so->currPos.lastItem);
596 
597  while (offnum <= maxoff)
598  {
599  ItemId iid = PageGetItemId(page, offnum);
600  IndexTuple ituple = (IndexTuple) PageGetItem(page, iid);
601 
602  if (ItemPointerEquals(&ituple->t_tid, &currItem->heapTid))
603  {
604  /* found the item */
605  ItemIdMarkDead(iid);
606  killedsomething = true;
607  break; /* out of inner search loop */
608  }
609  offnum = OffsetNumberNext(offnum);
610  }
611  }
612 
613  /*
614  * Since this can be redone later if needed, mark as dirty hint. Whenever
615  * we mark anything LP_DEAD, we also set the page's
616  * LH_PAGE_HAS_DEAD_TUPLES flag, which is likewise just a hint.
617  */
618  if (killedsomething)
619  {
620  opaque->hasho_flag |= LH_PAGE_HAS_DEAD_TUPLES;
621  MarkBufferDirtyHint(buf, true);
622  }
623 
624  if (so->hashso_bucket_buf == so->currPos.buf ||
625  havePin)
627  else
628  _hash_relbuf(rel, buf);
629 }
bytea * hashoptions(Datum reloptions, bool validate)
Definition: hashutil.c:290
HashScanOpaqueData * HashScanOpaque
Definition: hash.h:200
#define DatumGetUInt32(X)
Definition: postgres.h:492
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
Definition: fmgr.h:56
#define IndexInfoFindDataOffset(t_info)
Definition: itup.h:80
int errhint(const char *fmt,...)
Definition: elog.c:987
OffsetNumber _hash_binsearch_last(Page page, uint32 hash_value)
Definition: hashutil.c:396
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
Definition: indexam.c:855
static void test(void)
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
#define RelationGetDescr(relation)
Definition: rel.h:437
#define ItemIdMarkDead(itemId)
Definition: itemid.h:178
Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, uint32 highmask, uint32 lowmask)
Definition: hashutil.c:125
#define HashScanPosIsPinned(scanpos)
Definition: hash.h:138
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:44
#define LH_META_PAGE
Definition: hash.h:67
#define HashScanPosIsValid(scanpos)
Definition: hash.h:145
ItemPointerData t_tid
Definition: itup.h:37
regproc RegProcedure
Definition: c.h:453
uint32 hashm_magic
Definition: hash.h:251
int errcode(int sqlerrcode)
Definition: elog.c:575
#define HASH_SPLITPOINT_PHASE_MASK
Definition: hash.h:239
uint32 BlockNumber
Definition: block.h:31
uint32 _hash_datum2hashkey(Relation rel, Datum key)
Definition: hashutil.c:82
#define CALC_NEW_BUCKET(old_bucket, lowmask)
Definition: hashutil.c:24
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:75
Buffer _hash_getbuf(Relation rel, BlockNumber blkno, int access, int flags)
Definition: hashpage.c:78
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1042
#define HASH_VERSION
Definition: hash.h:209
unsigned int Oid
Definition: postgres_ext.h:31
uint32 hashm_lowmask
Definition: hash.h:261
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
#define BUCKET_TO_BLKNO(metap, B)
Definition: hash.h:38
Relation indexRelation
Definition: relscan.h:90
int fls(int mask)
Definition: fls.c:55
uint16 OffsetNumber
Definition: off.h:24
#define HASH_MAGIC
Definition: hash.h:208
Definition: type.h:89
#define HASH_READ
Definition: hash.h:329
uint32 Bucket
Definition: hash.h:34
bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup)
Definition: hashutil.c:31
int * killedItems
Definition: hash.h:190
Oid * rd_indcollation
Definition: rel.h:193
#define ERROR
Definition: elog.h:43
uint32 _hash_get_indextuple_hashkey(IndexTuple itup)
Definition: hashutil.c:299
uint32 _hash_spareindex(uint32 num_bucket)
Definition: hashutil.c:157
#define HASH_SPLITPOINT_PHASE_BITS
Definition: hash.h:237
uint32 _hash_get_totalbuckets(uint32 splitpoint_phase)
Definition: hashutil.c:189
uint32 hashm_version
Definition: hash.h:252
bool _hash_convert_tuple(Relation index, Datum *user_values, bool *user_isnull, Datum *index_values, bool *index_isnull)
Definition: hashutil.c:326
static char * buf
Definition: pg_test_fsync.c:67
#define RegProcedureIsValid(p)
Definition: c.h:588
#define FirstOffsetNumber
Definition: off.h:27
IndexTupleData * IndexTuple
Definition: itup.h:53
Bucket _hash_get_newbucket_from_oldbucket(Relation rel, Bucket old_bucket, uint32 lowmask, uint32 maxbucket)
Definition: hashutil.c:502
FmgrInfo sk_func
Definition: skey.h:71
#define DatumGetBool(X)
Definition: postgres.h:399
#define RelationGetRelationName(relation)
Definition: rel.h:445
unsigned int uint32
Definition: c.h:306
#define UInt32GetDatum(X)
Definition: postgres.h:499
Oid * rd_opfamily
Definition: rel.h:182
BlockNumber currPage
Definition: hash.h:120
#define HASHSTANDARD_PROC
Definition: hash.h:351
#define SK_ISNULL
Definition: skey.h:115
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
Buffer hashso_bucket_buf
Definition: hash.h:172
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void _hash_checkpage(Relation rel, Buffer buf, int flags)
Definition: hashutil.c:225
#define HASH_METAPAGE
Definition: hash.h:206
uintptr_t Datum
Definition: postgres.h:372
Buffer buf
Definition: hash.h:119
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1022
#define LH_OVERFLOW_PAGE
Definition: hash.h:64
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:274
BlockNumber _hash_get_newblock_from_oldbucket(Relation rel, Bucket old_bucket)
Definition: hashutil.c:469
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition: fmgr.c:1314
OffsetNumber _hash_binsearch(Page page, uint32 hash_value)
Definition: hashutil.c:358
int sk_flags
Definition: skey.h:66
#define Assert(condition)
Definition: c.h:680
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:744
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
#define PageGetSpecialPointer(page)
Definition: bufpage.h:322
HashPageOpaqueData * HashPageOpaque
Definition: hash.h:96
void _hash_kill_items(IndexScanDesc scan)
Definition: hashutil.c:544
#define MAXALIGN(LEN)
Definition: c.h:633
#define index_getattr(tup, attnum, tupleDesc, isnull)
Definition: itup.h:100
ScanKey keyData
Definition: relscan.h:94
#define PageGetSpecialSize(page)
Definition: bufpage.h:296
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
Definition: itemptr.c:29
uint32 hashm_maxbucket
Definition: hash.h:259
BlockNumber _hash_get_oldblock_from_newbucket(Relation rel, Bucket new_bucket)
Definition: hashutil.c:430
HashScanPosData currPos
Definition: hash.h:197
uint16 hasho_flag
Definition: hash.h:92
bytea * default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
Definition: reloptions.c:1326
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define PageIsNew(page)
Definition: bufpage.h:225
#define HashPageGetMeta(page)
Definition: hash.h:313
uint32 _hash_log2(uint32 num)
Definition: hashutil.c:141
int errmsg(const char *fmt,...)
Definition: elog.c:797
OffsetNumber indexOffset
Definition: hash.h:114
Oid sk_collation
Definition: skey.h:70
int i
#define OffsetNumberIsValid(offsetNumber)
Definition: off.h:40
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
Definition: c.h:497
ItemPointerData heapTid
Definition: hash.h:113
uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype)
Definition: hashutil.c:102
#define elog
Definition: elog.h:219
unsigned short t_info
Definition: itup.h:49
#define HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE
Definition: hash.h:240
int firstItem
Definition: hash.h:131
int Buffer
Definition: buf.h:23
Datum sk_argument
Definition: skey.h:72
#define LH_PAGE_HAS_DEAD_TUPLES
Definition: hash.h:71
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
AttrNumber sk_attno
Definition: skey.h:67
Pointer Page
Definition: bufpage.h:74
HashScanPosItem items[MaxIndexTuplesPerPage]
Definition: hash.h:135