@ -169,6 +169,7 @@ BuildTupleHashTableExt(PlanState *parent,
Size hash_mem_limit ;
MemoryContext oldcontext ;
bool allow_jit ;
uint32 hash_iv = 0 ;
Assert ( nbuckets > 0 ) ;
@ -183,14 +184,13 @@ BuildTupleHashTableExt(PlanState *parent,
hashtable - > numCols = numCols ;
hashtable - > keyColIdx = keyColIdx ;
hashtable - > tab_hash_funcs = hashfunctions ;
hashtable - > tab_collations = collations ;
hashtable - > tablecxt = tablecxt ;
hashtable - > tempcxt = tempcxt ;
hashtable - > entrysize = entrysize ;
hashtable - > tableslot = NULL ; /* will be made on first lookup */
hashtable - > inputslot = NULL ;
hashtable - > in_hash_funcs = NULL ;
hashtable - > in_hash_expr = NULL ;
hashtable - > cur_eq_func = NULL ;
/*
@ -202,9 +202,7 @@ BuildTupleHashTableExt(PlanState *parent,
* underestimated .
*/
if ( use_variable_hash_iv )
hashtable - > hash_iv = murmurhash32 ( ParallelWorkerNumber ) ;
else
hashtable - > hash_iv = 0 ;
hash_iv = murmurhash32 ( ParallelWorkerNumber ) ;
hashtable - > hashtab = tuplehash_create ( metacxt , nbuckets , hashtable ) ;
@ -225,6 +223,16 @@ BuildTupleHashTableExt(PlanState *parent,
*/
allow_jit = metacxt ! = tablecxt ;
/* build hash ExprState for all columns */
hashtable - > tab_hash_expr = ExecBuildHash32FromAttrs ( inputDesc ,
& TTSOpsMinimalTuple ,
hashfunctions ,
collations ,
numCols ,
keyColIdx ,
allow_jit ? parent : NULL ,
hash_iv ) ;
/* build comparator for all columns */
/* XXX: should we support non-minimal tuples for the inputslot? */
hashtable - > tab_eq_func = ExecBuildGroupingEqual ( inputDesc , inputDesc ,
@ -316,7 +324,7 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
/* set up data needed by hash and match functions */
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashtable - > tab_hash_funcs ;
hashtable - > in_hash_expr = hashtable - > tab_hash_expr ;
hashtable - > cur_eq_func = hashtable - > tab_eq_func ;
local_hash = TupleHashTableHash_internal ( hashtable - > hashtab , NULL ) ;
@ -342,7 +350,7 @@ TupleHashTableHash(TupleHashTable hashtable, TupleTableSlot *slot)
uint32 hash ;
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashtable - > tab_hash_funcs ;
hashtable - > in_hash_expr = hashtable - > tab_hash_expr ;
/* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo ( hashtable - > tempcxt ) ;
@ -370,7 +378,7 @@ LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot,
/* set up data needed by hash and match functions */
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashtable - > tab_hash_funcs ;
hashtable - > in_hash_expr = hashtable - > tab_hash_expr ;
hashtable - > cur_eq_func = hashtable - > tab_eq_func ;
entry = LookupTupleHashEntry_internal ( hashtable , slot , isnew , hash ) ;
@ -386,14 +394,14 @@ LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot,
* created if there ' s not a match . This is similar to the non - creating
* case of LookupTupleHashEntry , except that it supports cross - type
* comparisons , in which the given tuple is not of the same type as the
* table entries . The caller must provide the hash functions to use for
* the input tuple , as well as the equality functions , since these may be
* table entries . The caller must provide the hash ExprState to use for
* the input tuple , as well as the equality ExprState , since these may be
* different from the table ' s internal functions .
*/
TupleHashEntry
FindTupleHashEntry ( TupleHashTable hashtable , TupleTableSlot * slot ,
ExprState * eqcomp ,
FmgrInfo * hashfunctions )
ExprState * hashexpr )
{
TupleHashEntry entry ;
MemoryContext oldContext ;
@ -404,7 +412,7 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
/* Set up data needed by hash and match functions */
hashtable - > inputslot = slot ;
hashtable - > in_hash_funcs = hashfunctions ;
hashtable - > in_hash_expr = hashexpr ;
hashtable - > cur_eq_func = eqcomp ;
/* Search the hash table */
@ -421,25 +429,24 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
* copied into the table .
*
* Also , the caller must select an appropriate memory context for running
* the hash functions . ( dynahash . c doesn ' t change CurrentMemoryContext . )
* the hash functions .
*/
static uint32
TupleHashTableHash_internal ( struct tuplehash_hash * tb ,
const MinimalTuple tuple )
{
TupleHashTable hashtable = ( TupleHashTable ) tb - > private_data ;
int numCols = hashtable - > numCols ;
AttrNumber * keyColIdx = hashtable - > keyColIdx ;
uint32 hashkey = hashtable - > hash_iv ;
uint32 hashkey ;
TupleTableSlot * slot ;
FmgrInfo * hashfunctions ;
int i ;
bool isnull ;
if ( tuple = = NULL )
{
/* Process the current input tuple for the table */
slot = hashtable - > inputslot ;
hashfunctions = hashtable - > in_hash_funcs ;
hashtable - > exprcontext - > ecxt_innertuple = hashtable - > inputslot ;
hashkey = DatumGetUInt32 ( ExecEvalExpr ( hashtable - > in_hash_expr ,
hashtable - > exprcontext ,
& isnull ) ) ;
}
else
{
@ -449,38 +456,17 @@ TupleHashTableHash_internal(struct tuplehash_hash *tb,
* ( 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 ;
slot = hashtable - > exprcontext - > ecxt_innertuple = hashtable - > tableslot ;
ExecStoreMinimalTuple ( tuple , slot , false ) ;
hashfunctions = hashtable - > tab_hash_funcs ;
}
for ( i = 0 ; i < numCols ; i + + )
{
AttrNumber att = keyColIdx [ i ] ;
Datum attr ;
bool isNull ;
/* combine successive hashkeys by rotating */
hashkey = pg_rotate_left32 ( hashkey , 1 ) ;
attr = slot_getattr ( slot , att , & isNull ) ;
if ( ! isNull ) /* treat nulls as having hash key 0 */
{
uint32 hkey ;
hkey = DatumGetUInt32 ( FunctionCall1Coll ( & hashfunctions [ i ] ,
hashtable - > tab_collations [ i ] ,
attr ) ) ;
hashkey ^ = hkey ;
}
hashkey = DatumGetUInt32 ( ExecEvalExpr ( hashtable - > tab_hash_expr ,
hashtable - > exprcontext ,
& isnull ) ) ;
}
/*
* The way hashes are combined above , among each other and with the IV ,
* doesn ' t lead to good bit perturbation . As the IV ' s goal is to lead to
* achieve that , perform a round of hashing of the combined hash -
* resulting in near perfect perturbation .
* The hashing done above , even with an initial value , doesn ' t tend to
* result in good hash perturbation . Running the value produced above
* through murmurhash32 leads to near perfect hash perturbation .
*/
return murmurhash32 ( hashkey ) ;
}