/*-------------------------------------------------------------------------
 *
 * btutils.c--
 *    Utility code for Postgres btree implementation.
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *    /usr/local/devel/pglite/cvs/src/backend/access/hash/hashutil.c,v 1.6 1995/02/13 19:46:53 andrew Exp
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"

#include "storage/bufmgr.h"
#include "storage/bufpage.h"
#include "storage/page.h"

#include "fmgr.h"
#include "utils/elog.h"
#include "utils/palloc.h"
#include "utils/rel.h"
#include "utils/excid.h"

#include "access/heapam.h"
#include "access/genam.h"
#include "access/iqual.h"
#include "access/hash.h"

ScanKey
_hash_mkscankey(Relation rel, IndexTuple itup, HashMetaPage metap)
{
    ScanKey skey;
    TupleDesc itupdesc;
    int natts;
    AttrNumber i;
    Datum arg;
    RegProcedure proc;
    bool null;
    
    natts = rel->rd_rel->relnatts;
    itupdesc = RelationGetTupleDescriptor(rel);
    
    skey = (ScanKey) palloc(natts * sizeof(ScanKeyData));
    
    for (i = 0; i < natts; i++) {
	arg = index_getattr(itup, i + 1, itupdesc, &null);
	proc = metap->hashm_procid;
	ScanKeyEntryInitialize(&skey[i],
			       0x0, (AttrNumber) (i + 1), proc, arg);
    }
    
    return (skey);
}	

void
_hash_freeskey(ScanKey skey)
{
    pfree(skey);
}


bool
_hash_checkqual(IndexScanDesc scan, IndexTuple itup)
{
    if (scan->numberOfKeys > 0)
	return (index_keytest(itup, scan->relation->rd_att,
			      scan->numberOfKeys, scan->keyData));
    else
	return (true);
}

HashItem
_hash_formitem(IndexTuple itup)
{
    int nbytes_hitem;
    HashItem hitem;
    Size tuplen;
    extern Oid newoid();
    
    /* disallow nulls in hash keys */
    if (itup->t_info & INDEX_NULL_MASK)
	elog(WARN, "hash indices cannot include null keys");
    
    /* make a copy of the index tuple with room for the sequence number */
    tuplen = IndexTupleSize(itup);
    nbytes_hitem = tuplen +
	(sizeof(HashItemData) - sizeof(IndexTupleData));
    
    hitem = (HashItem) palloc(nbytes_hitem);
    memmove((char *) &(hitem->hash_itup), (char *) itup, tuplen);
    
    hitem->hash_oid = newoid();
    return (hitem);
}

Bucket
_hash_call(Relation rel, HashMetaPageData *metad, Datum key)
{
    uint32 n;
    Bucket bucket;
    RegProcedure proc;
    
    proc = metad->hashm_procid;
    n = (unsigned long) fmgr(proc, key);
    bucket = n & metad->hashm_highmask;
    if (bucket > metad->hashm_maxbucket)
	bucket = bucket & metad->hashm_lowmask;
    return (bucket);
}

#include <sys/types.h>

uint32
_hash_log2(u_int num)
{
    uint32 i, limit;
    
    limit = 1;
    for (i = 0; limit < num; limit = limit << 1, i++);
    return (i);
}
