diff options
Diffstat (limited to 'src/backend/access/hash/hashutil.c')
-rw-r--r-- | src/backend/access/hash/hashutil.c | 130 |
1 files changed, 67 insertions, 63 deletions
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c index 83126fccb42..f3ac58085bc 100644 --- a/src/backend/access/hash/hashutil.c +++ b/src/backend/access/hash/hashutil.c @@ -8,11 +8,10 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.33 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.33.2.1 2003/09/07 04:36:47 momjian Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/genam.h" @@ -20,55 +19,19 @@ #include "access/iqual.h" -ScanKey -_hash_mkscankey(Relation rel, IndexTuple itup) -{ - ScanKey skey; - TupleDesc itupdesc; - int natts; - AttrNumber i; - Datum arg; - FmgrInfo *procinfo; - bool isnull; - - natts = rel->rd_rel->relnatts; - itupdesc = RelationGetDescr(rel); - - skey = (ScanKey) palloc(natts * sizeof(ScanKeyData)); - - for (i = 0; i < natts; i++) - { - arg = index_getattr(itup, i + 1, itupdesc, &isnull); - procinfo = index_getprocinfo(rel, i + 1, HASHPROC); - ScanKeyEntryInitializeWithInfo(&skey[i], - 0x0, - (AttrNumber) (i + 1), - procinfo, - CurrentMemoryContext, - arg); - } - - return skey; -} - -void -_hash_freeskey(ScanKey skey) -{ - pfree(skey); -} - - +/* + * _hash_checkqual -- does the index tuple satisfy the scan conditions? + */ bool _hash_checkqual(IndexScanDesc scan, IndexTuple itup) { - if (scan->numberOfKeys > 0) - return (index_keytest(itup, - RelationGetDescr(scan->indexRelation), - scan->numberOfKeys, scan->keyData)); - else - return true; + return index_keytest(itup, RelationGetDescr(scan->indexRelation), + scan->numberOfKeys, scan->keyData); } +/* + * _hash_formitem -- construct a hash index entry + */ HashItem _hash_formitem(IndexTuple itup) { @@ -82,30 +45,49 @@ _hash_formitem(IndexTuple itup) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("hash indexes cannot include null keys"))); - /* make a copy of the index tuple with room for the sequence number */ + /* + * make a copy of the index tuple (XXX do we still need to copy?) + * + * HashItemData used to have more fields than IndexTupleData, but no + * longer... + */ tuplen = IndexTupleSize(itup); nbytes_hitem = tuplen + (sizeof(HashItemData) - sizeof(IndexTupleData)); hitem = (HashItem) palloc(nbytes_hitem); - memmove((char *) &(hitem->hash_itup), (char *) itup, tuplen); + memcpy((char *) &(hitem->hash_itup), (char *) itup, tuplen); return hitem; } -Bucket -_hash_call(Relation rel, HashMetaPage metap, Datum key) +/* + * _hash_datum2hashkey -- given a Datum, call the index's hash procedure + */ +uint32 +_hash_datum2hashkey(Relation rel, Datum key) { FmgrInfo *procinfo; - uint32 n; - Bucket bucket; /* XXX assumes index has only one attribute */ procinfo = index_getprocinfo(rel, 1, HASHPROC); - n = DatumGetUInt32(FunctionCall1(procinfo, key)); - bucket = n & metap->hashm_highmask; - if (bucket > metap->hashm_maxbucket) - bucket = bucket & metap->hashm_lowmask; + + return DatumGetUInt32(FunctionCall1(procinfo, key)); +} + +/* + * _hash_hashkey2bucket -- determine which bucket the hashkey maps to. + */ +Bucket +_hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket, + uint32 highmask, uint32 lowmask) +{ + Bucket bucket; + + bucket = hashkey & highmask; + if (bucket > maxbucket) + bucket = bucket & lowmask; + return bucket; } @@ -119,7 +101,7 @@ _hash_log2(uint32 num) limit; limit = 1; - for (i = 0; limit < num; limit = limit << 1, i++) + for (i = 0; limit < num; limit <<= 1, i++) ; return i; } @@ -128,22 +110,44 @@ _hash_log2(uint32 num) * _hash_checkpage -- sanity checks on the format of all hash pages */ void -_hash_checkpage(Page page, int flags) +_hash_checkpage(Relation rel, Page page, int flags) { - HashPageOpaque opaque; - Assert(page); + /* + * When checking the metapage, always verify magic number and version. + */ + if (flags == LH_META_PAGE) + { + HashMetaPage metap = (HashMetaPage) 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, please REINDEX it", + RelationGetRelationName(rel)))); + } + + /* + * These other checks are for debugging purposes only. + */ +#ifdef USE_ASSERT_CHECKING Assert(((PageHeader) (page))->pd_lower >= SizeOfPageHeaderData); -#if 1 Assert(((PageHeader) (page))->pd_upper <= (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData)))); Assert(((PageHeader) (page))->pd_special == (BLCKSZ - MAXALIGN(sizeof(HashPageOpaqueData)))); Assert(PageGetPageSize(page) == BLCKSZ); -#endif if (flags) { - opaque = (HashPageOpaque) PageGetSpecialPointer(page); + HashPageOpaque opaque = (HashPageOpaque) PageGetSpecialPointer(page); + Assert(opaque->hasho_flag & flags); } +#endif /* USE_ASSERT_CHECKING */ } |