@ -23,12 +23,25 @@
# include "utils/lsyscache.h"
# include "utils/memutils.h"
static uint32 TupleHashTableHash ( struct tuplehash_hash * tb , const MinimalTuple tuple ) ;
static int TupleHashTableMatch ( struct tuplehash_hash * tb , const MinimalTuple tuple1 , const MinimalTuple tuple2 ) ;
static TupleHashTable CurTupleHashTable = NULL ;
static uint32 TupleHashTableHash ( const void * key , Size keysize ) ;
static int TupleHashTableMatch ( const void * key1 , const void * key2 ,
Size keysize ) ;
/*
* Define parameters for tuple hash table code generation . The interface is
* * also * declared in execnodes . h ( to generate the types , which are externally
* visible ) .
*/
# define SH_PREFIX tuplehash
# define SH_ELEMENT_TYPE TupleHashEntryData
# define SH_KEY_TYPE MinimalTuple
# define SH_KEY firstTuple
# define SH_HASH_KEY(tb, key) TupleHashTableHash(tb, key)
# define SH_EQUAL(tb, a, b) TupleHashTableMatch(tb, a, b) == 0
# define SH_SCOPE extern
# define SH_STORE_HASH
# define SH_GET_HASH(tb, a) a->hash
# define SH_DEFINE
# include "lib/simplehash.h"
/*****************************************************************************
@ -260,7 +273,7 @@ execTuplesHashPrepare(int numCols,
* eqfunctions : equality comparison functions to use
* hashfunctions : datatype - specific hashing functions to use
* nbuckets : initial estimate of hashtable size
* entry size: size of each entry ( at least sizeof ( TupleHashEntryData ) )
* additional size: size of data stored in - > additional
* tablecxt : memory context in which to store table and table entries
* tempcxt : short - lived context for evaluation hash and comparison functions
*
@ -275,20 +288,19 @@ TupleHashTable
BuildTupleHashTable ( int numCols , AttrNumber * keyColIdx ,
FmgrInfo * eqfunctions ,
FmgrInfo * hashfunctions ,
long nbuckets , Size entry size,
long nbuckets , Size additional size,
MemoryContext tablecxt , MemoryContext tempcxt )
{
TupleHashTable hashtable ;
HASHCTL hash_ctl ;
Size entrysize = sizeof ( TupleHashEntryData ) + additionalsize ;
Assert ( nbuckets > 0 ) ;
Assert ( entrysize > = sizeof ( TupleHashEntryData ) ) ;
/* Limit initial table size request to not more than work_mem */
nbuckets = Min ( nbuckets , ( long ) ( ( work_mem * 1024L ) / entrysize ) ) ;
hashtable = ( TupleHashTable ) MemoryContextAlloc ( tablecxt ,
sizeof ( TupleHashTableData ) ) ;
hashtable = ( TupleHashTable )
MemoryContextAlloc ( tablecxt , sizeof ( TupleHashTableData ) ) ;
hashtable - > numCols = numCols ;
hashtable - > keyColIdx = keyColIdx ;
@ -302,15 +314,8 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
hashtable - > in_hash_funcs = NULL ;
hashtable - > cur_eq_funcs = NULL ;
MemSet ( & hash_ctl , 0 , sizeof ( hash_ctl ) ) ;
hash_ctl . keysize = sizeof ( TupleHashEntryData ) ;
hash_ctl . entrysize = entrysize ;
hash_ctl . hash = TupleHashTableHash ;
hash_ctl . match = TupleHashTableMatch ;
hash_ctl . hcxt = tablecxt ;
hashtable - > hashtab = hash_create ( " TupleHashTable " , nbuckets ,
& hash_ctl ,
HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT ) ;
hashtable - > hashtab = tuplehash_create ( tablecxt , nbuckets ) ;
hashtable - > hashtab - > private = hashtable ;
return hashtable ;
}
@ -324,18 +329,17 @@ BuildTupleHashTable(int numCols, AttrNumber *keyColIdx,
*
* If isnew isn ' t NULL , then a new entry is created if no existing entry
* matches . On return , * isnew is true if the entry is newly created ,
* false if it existed already . Any extra space in a new entry has been
* zeroed .
* false if it existed already . - > additional_data in the new entry has
* been zeroed .
*/
TupleHashEntry
LookupTupleHashEntry ( TupleHashTable hashtable , TupleTableSlot * slot ,
bool * isnew )
{
TupleHashEntry entry ;
TupleHashEntryData * entry ;
MemoryContext oldContext ;
TupleHashTable saveCurHT ;
TupleHashEntryData dummy ;
bool found ;
MinimalTuple key ;
/* If first time through, clone the input slot to make table slot */
if ( hashtable - > tableslot = = NULL )
@ -356,28 +360,17 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
/* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo ( hashtable - > tempcxt ) ;
/*
* Set up data needed by hash and match functions
*
* We save and restore CurTupleHashTable just in case someone manages to
* invoke this code re - entrantly .
*/
/* set up data needed by hash and match functions */
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashtable - > tab_hash_funcs ;
hashtable - > cur_eq_funcs = hashtable - > tab_eq_funcs ;
saveCurHT = CurTupleHashTable ;
CurTupleHashTable = hashtable ;
/* Search the hash table */
dummy . firstTuple = NULL ; /* flag to reference inputslot */
entry = ( TupleHashEntry ) hash_search ( hashtable - > hashtab ,
& dummy ,
isnew ? HASH_ENTER : HASH_FIND ,
& found ) ;
key = NULL ; /* flag to reference inputslot */
if ( isnew )
{
entry = tuplehash_insert ( hashtable - > hashtab , key , & found ) ;
if ( found )
{
/* found pre-existing entry */
@ -385,24 +378,19 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
}
else
{
/*
* created new entry
*
* Zero any caller - requested space in the entry . ( This zaps the
* " key data " dynahash . c copied into the new entry , but we don ' t
* care since we ' re about to overwrite it anyway . )
*/
MemSet ( entry , 0 , hashtable - > entrysize ) ;
/* Copy the first tuple into the table context */
/* created new entry */
* isnew = true ;
/* zero caller data */
entry - > additional = NULL ;
MemoryContextSwitchTo ( hashtable - > tablecxt ) ;
/* Copy the first tuple into the table context */
entry - > firstTuple = ExecCopySlotMinimalTuple ( slot ) ;
* isnew = true ;
}
}
CurTupleHashTable = saveCurHT ;
else
{
entry = tuplehash_lookup ( hashtable - > hashtab , key ) ;
}
MemoryContextSwitchTo ( oldContext ) ;
@ -425,34 +413,19 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
{
TupleHashEntry entry ;
MemoryContext oldContext ;
TupleHashTable saveCurHT ;
TupleHashEntryData dummy ;
MinimalTuple key ;
/* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo ( hashtable - > tempcxt ) ;
/*
* Set up data needed by hash and match functions
*
* We save and restore CurTupleHashTable just in case someone manages to
* invoke this code re - entrantly .
*/
/* Set up data needed by hash and match functions */
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashfunctions ;
hashtable - > cur_eq_funcs = eqfunctions ;
saveCurHT = CurTupleHashTable ;
CurTupleHashTable = hashtable ;
/* Search the hash table */
dummy . firstTuple = NULL ; /* flag to reference inputslot */
entry = ( TupleHashEntry ) hash_search ( hashtable - > hashtab ,
& dummy ,
HASH_FIND ,
NULL ) ;
CurTupleHashTable = saveCurHT ;
key = NULL ; /* flag to reference inputslot */
entry = tuplehash_lookup ( hashtable - > hashtab , key ) ;
MemoryContextSwitchTo ( oldContext ) ;
return entry ;
@ -468,22 +441,18 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
* This convention avoids the need to materialize virtual input tuples unless
* they actually need to get copied into the table .
*
* CurTupleHashTable must be set before calling this , since dynahash . c
* doesn ' t provide any API that would let us get at the hashtable otherwise .
*
* Also , the caller must select an appropriate memory context for running
* the hash functions . ( dynahash . c doesn ' t change CurrentMemoryContext . )
*/
static uint32
TupleHashTableHash ( const void * key , Size keysiz e)
TupleHashTableHash ( struct tuplehash_hash * tb , const MinimalTuple tupl e)
{
MinimalTuple tuple = ( ( const TupleHashEntryData * ) key ) - > firstTuple ;
TupleTableSlot * slot ;
TupleHashTable hashtable = CurTupleHashTable ;
TupleHashTable hashtable = ( TupleHashTable ) tb - > private ;
int numCols = hashtable - > numCols ;
AttrNumber * keyColIdx = hashtable - > keyColIdx ;
FmgrInfo * hashfunctions ;
uint32 hashkey = 0 ;
TupleTableSlot * slot ;
FmgrInfo * hashfunctions ;
int i ;
if ( tuple = = NULL )
@ -494,8 +463,12 @@ TupleHashTableHash(const void *key, Size keysize)
}
else
{
/* Process a tuple already stored in the table */
/* (this case never actually occurs in current dynahash.c code) */
/*
* Process a tuple already stored in the table .
*
* ( this case never actually occurs due to the way simplehash . h is
* used , as the hash - value is stored in the entries )
*/
slot = hashtable - > tableslot ;
ExecStoreMinimalTuple ( tuple , slot , false ) ;
hashfunctions = hashtable - > tab_hash_funcs ;
@ -530,29 +503,21 @@ TupleHashTableHash(const void *key, Size keysize)
*
* As above , the passed pointers are pointers to TupleHashEntryData .
*
* CurTupleHashTable must be set before calling this , since dynahash . c
* doesn ' t provide any API that would let us get at the hashtable otherwise .
*
* Also , the caller must select an appropriate memory context for running
* the compare functions . ( dynahash . c doesn ' t change CurrentMemoryContext . )
*/
static int
TupleHashTableMatch ( const void * key1 , const void * key2 , Size keysize )
TupleHashTableMatch ( struct tuplehash_hash * tb , const MinimalTuple tuple1 , const MinimalTuple tuple2 )
{
MinimalTuple tuple1 = ( ( const TupleHashEntryData * ) key1 ) - > firstTuple ;
# ifdef USE_ASSERT_CHECKING
MinimalTuple tuple2 = ( ( const TupleHashEntryData * ) key2 ) - > firstTuple ;
# endif
TupleTableSlot * slot1 ;
TupleTableSlot * slot2 ;
TupleHashTable hashtable = Cur TupleHashTable;
TupleHashTable hashtable = ( TupleHashTable ) tb - > private ;
/*
* We assume that dynahash . c will only ever call us with the first
* We assume that simplehash . h will only ever call us with the first
* argument being an actual table entry , and the second argument being
* LookupTupleHashEntry ' s dummy TupleHashEntryData . The other direction
* could be supported too , but is not currently used by dynahash . c .
* could be supported too , but is not currently required .
*/
Assert ( tuple1 ! = NULL ) ;
slot1 = hashtable - > tableslot ;