aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execGrouping.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execGrouping.c')
-rw-r--r--src/backend/executor/execGrouping.c82
1 files changed, 34 insertions, 48 deletions
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 774e4de8828..9a88fc65249 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -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);
}