#include "postgres.h"
#include "access/hash.h"
#include "access/reloptions.h"
#include "access/relscan.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
Go to the source code of this file.
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_log2 (uint32 num) |
void | _hash_checkpage (Relation rel, Buffer buf, int flags) |
Datum | hashoptions (PG_FUNCTION_ARGS) |
uint32 | _hash_get_indextuple_hashkey (IndexTuple itup) |
IndexTuple | _hash_form_tuple (Relation index, Datum *values, bool *isnull) |
OffsetNumber | _hash_binsearch (Page page, uint32 hash_value) |
OffsetNumber | _hash_binsearch_last (Page page, uint32 hash_value) |
OffsetNumber _hash_binsearch | ( | Page | page, | |
uint32 | hash_value | |||
) |
Definition at line 287 of file hashutil.c.
References _hash_get_indextuple_hashkey(), Assert, OffsetNumberIsValid, PageGetItem, PageGetItemId, and PageGetMaxOffsetNumber.
Referenced by _hash_pgaddtup(), and _hash_step().
{ OffsetNumber upper; OffsetNumber lower; /* Loop invariant: lower <= desired place <= upper */ upper = PageGetMaxOffsetNumber(page) + 1; lower = FirstOffsetNumber; while (upper > lower) { OffsetNumber off; IndexTuple itup; uint32 hashkey; off = (upper + lower) / 2; Assert(OffsetNumberIsValid(off)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off)); hashkey = _hash_get_indextuple_hashkey(itup); if (hashkey < hash_value) lower = off + 1; else upper = off; } return lower; }
OffsetNumber _hash_binsearch_last | ( | Page | page, | |
uint32 | hash_value | |||
) |
Definition at line 325 of file hashutil.c.
References _hash_get_indextuple_hashkey(), Assert, FirstOffsetNumber, OffsetNumberIsValid, PageGetItem, PageGetItemId, and PageGetMaxOffsetNumber.
Referenced by _hash_step().
{ OffsetNumber upper; OffsetNumber lower; /* Loop invariant: lower <= desired place <= upper */ upper = PageGetMaxOffsetNumber(page); lower = FirstOffsetNumber - 1; while (upper > lower) { IndexTuple itup; OffsetNumber off; uint32 hashkey; off = (upper + lower + 1) / 2; Assert(OffsetNumberIsValid(off)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, off)); hashkey = _hash_get_indextuple_hashkey(itup); if (hashkey > hash_value) upper = off - 1; else lower = off; } return lower; }
Definition at line 156 of file hashutil.c.
References BufferGetBlockNumber(), BufferGetPage, ereport, errcode(), errhint(), errmsg(), ERROR, HASH_MAGIC, HASH_VERSION, HashMetaPageData::hashm_magic, HashMetaPageData::hashm_version, HashPageOpaqueData::hasho_flag, HashPageGetMeta, LH_META_PAGE, MAXALIGN, PageGetSpecialPointer, PageGetSpecialSize, PageIsNew, and RelationGetRelationName.
Referenced by _hash_addovflpage(), _hash_expandtable(), _hash_first(), _hash_freeovflpage(), _hash_getbuf(), _hash_getbuf_with_strategy(), _hash_getovflpage(), _hash_next(), _hash_pgaddtup(), and _hash_step().
{ Page page = BufferGetPage(buf); /* * ReadBuffer verifies that every newly-read page passes * PageHeaderIsValid, which means it either contains a reasonably sane * page header or is all-zero. We have to defend against the all-zero * case, however. */ if (PageIsNew(page)) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" contains unexpected zero page at block %u", RelationGetRelationName(rel), BufferGetBlockNumber(buf)), errhint("Please REINDEX it."))); /* * Additionally check that the special area looks sane. */ if (PageGetSpecialSize(page) != MAXALIGN(sizeof(HashPageOpaqueData))) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" contains corrupted page at block %u", RelationGetRelationName(rel), BufferGetBlockNumber(buf)), errhint("Please REINDEX it."))); if (flags) { HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page); if ((opaque->hasho_flag & flags) == 0) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" contains corrupted page at block %u", RelationGetRelationName(rel), BufferGetBlockNumber(buf)), errhint("Please REINDEX it."))); } /* * When checking the metapage, also verify magic number and version. */ if (flags == LH_META_PAGE) { HashMetaPage metap = HashPageGetMeta(page); if (metap->hashm_magic != HASH_MAGIC) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" is not a hash index", RelationGetRelationName(rel)))); if (metap->hashm_version != HASH_VERSION) ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("index \"%s\" has wrong hash version", RelationGetRelationName(rel)), errhint("Please REINDEX it."))); } }
bool _hash_checkqual | ( | IndexScanDesc | scan, | |
IndexTuple | itup | |||
) |
Definition at line 28 of file hashutil.c.
References DatumGetBool, FunctionCall2Coll(), index_getattr, IndexScanDescData::indexRelation, IndexScanDescData::keyData, IndexScanDescData::numberOfKeys, RelationGetDescr, ScanKeyData::sk_argument, ScanKeyData::sk_attno, ScanKeyData::sk_collation, ScanKeyData::sk_flags, ScanKeyData::sk_func, and SK_ISNULL.
Referenced by _hash_step().
{ /* * Currently, we can't check any of the scan conditions since we do not * have the original index entry value to supply to the sk_func. Always * return true; we expect that hashgettuple already set the recheck flag * to make the main indexscan code do it. */ #ifdef NOT_USED TupleDesc tupdesc = RelationGetDescr(scan->indexRelation); ScanKey key = scan->keyData; int scanKeySize = scan->numberOfKeys; while (scanKeySize > 0) { Datum datum; bool isNull; Datum test; datum = index_getattr(itup, key->sk_attno, tupdesc, &isNull); /* assume sk_func is strict */ if (isNull) return false; if (key->sk_flags & SK_ISNULL) return false; test = FunctionCall2Coll(&key->sk_func, key->sk_collation, datum, key->sk_argument); if (!DatumGetBool(test)) return false; key++; scanKeySize--; } #endif return true; }
Definition at line 79 of file hashutil.c.
References DatumGetUInt32, FunctionCall1Coll(), HASHPROC, index_getprocinfo(), and RelationData::rd_indcollation.
Referenced by _hash_first(), and _hash_form_tuple().
{ FmgrInfo *procinfo; Oid collation; /* XXX assumes index has only one attribute */ procinfo = index_getprocinfo(rel, 1, HASHPROC); collation = rel->rd_indcollation[0]; return DatumGetUInt32(FunctionCall1Coll(procinfo, collation, key)); }
Definition at line 99 of file hashutil.c.
References DatumGetUInt32, elog, ERROR, get_opfamily_proc(), HASHPROC, OidFunctionCall1Coll(), RelationData::rd_indcollation, RelationData::rd_opfamily, RegProcedureIsValid, and RelationGetRelationName.
Referenced by _hash_first().
{ RegProcedure hash_proc; Oid collation; /* XXX assumes index has only one attribute */ hash_proc = get_opfamily_proc(rel->rd_opfamily[0], keytype, keytype, HASHPROC); if (!RegProcedureIsValid(hash_proc)) elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"", HASHPROC, keytype, keytype, RelationGetRelationName(rel)); collation = rel->rd_indcollation[0]; return DatumGetUInt32(OidFunctionCall1Coll(hash_proc, collation, key)); }
IndexTuple _hash_form_tuple | ( | Relation | index, | |
Datum * | values, | |||
bool * | isnull | |||
) |
Definition at line 254 of file hashutil.c.
References _hash_datum2hashkey(), Assert, index_form_tuple(), tupleDesc::natts, RelationGetDescr, and UInt32GetDatum.
Referenced by hashbuildCallback(), and hashinsert().
{ IndexTuple itup; uint32 hashkey; Datum hashkeydatum; TupleDesc hashdesc; if (isnull[0]) hashkeydatum = (Datum) 0; else { hashkey = _hash_datum2hashkey(index, values[0]); hashkeydatum = UInt32GetDatum(hashkey); } hashdesc = RelationGetDescr(index); Assert(hashdesc->natts == 1); itup = index_form_tuple(hashdesc, &hashkeydatum, isnull); return itup; }
uint32 _hash_get_indextuple_hashkey | ( | IndexTuple | itup | ) |
Definition at line 238 of file hashutil.c.
References IndexInfoFindDataOffset, and IndexTupleData::t_info.
Referenced by _hash_binsearch(), _hash_binsearch_last(), _hash_doinsert(), _hash_pgaddtup(), _hash_splitbucket(), and _hash_step().
{ char *attp; /* * We assume the hash key is the first attribute and can't be null, so * this can be done crudely but very very cheaply ... */ attp = (char *) itup + IndexInfoFindDataOffset(itup->t_info); return *((uint32 *) attp); }
Definition at line 122 of file hashutil.c.
Referenced by _hash_doinsert(), _hash_first(), and _hash_splitbucket().
{ Bucket bucket; bucket = hashkey & highmask; if (bucket > maxbucket) bucket = bucket & lowmask; return bucket; }
Definition at line 138 of file hashutil.c.
References i.
Referenced by _h_spoolinit(), _hash_expandtable(), and _hash_metapinit().
Datum hashoptions | ( | PG_FUNCTION_ARGS | ) |
Definition at line 221 of file hashutil.c.
References default_reloptions(), PG_GETARG_BOOL, PG_GETARG_DATUM, PG_RETURN_BYTEA_P, PG_RETURN_NULL, and RELOPT_KIND_HASH.
{ Datum reloptions = PG_GETARG_DATUM(0); bool validate = PG_GETARG_BOOL(1); bytea *result; result = default_reloptions(reloptions, validate, RELOPT_KIND_HASH); if (result) PG_RETURN_BYTEA_P(result); PG_RETURN_NULL(); }