Commit 4eaea3db authored by Jeff Davis's avatar Jeff Davis

Introduce TupleHashTableHash() and LookupTupleHashEntryHash().

Expose two new entry points: one for only calculating the hash value
of a tuple, and another for looking up a hash entry when the hash
value is already known. This will be useful for disk-based Hash
Aggregation to avoid recomputing the hash value for the same tuple
after saving and restoring it from disk.

Discussion: https://postgr.es/m/37091115219dd522fd9ed67333ee8ed1b7e09443.camel%40j-davis.com
parent e6f86f8d
...@@ -25,8 +25,9 @@ ...@@ -25,8 +25,9 @@
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
#include "utils/memutils.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 int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2);
static TupleHashEntry LookupTupleHashEntry_internal(
TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash);
/* /*
* Define parameters for tuple hash table code generation. The interface is * Define parameters for tuple hash table code generation. The interface is
...@@ -300,10 +301,9 @@ TupleHashEntry ...@@ -300,10 +301,9 @@ TupleHashEntry
LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
bool *isnew) bool *isnew)
{ {
TupleHashEntryData *entry; TupleHashEntry entry;
MemoryContext oldContext; MemoryContext oldContext;
bool found; uint32 hash;
MinimalTuple key;
/* Need to run the hash functions in short-lived context */ /* Need to run the hash functions in short-lived context */
oldContext = MemoryContextSwitchTo(hashtable->tempcxt); oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
...@@ -313,32 +313,34 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ...@@ -313,32 +313,34 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
hashtable->in_hash_funcs = hashtable->tab_hash_funcs; hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
hashtable->cur_eq_func = hashtable->tab_eq_func; hashtable->cur_eq_func = hashtable->tab_eq_func;
key = NULL; /* flag to reference inputslot */ hash = TupleHashTableHash(hashtable->hashtab, NULL);
entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
if (isnew) MemoryContextSwitchTo(oldContext);
{
entry = tuplehash_insert(hashtable->hashtab, key, &found);
if (found) return entry;
{ }
/* found pre-existing entry */
*isnew = false; /*
} * A variant of LookupTupleHashEntry for callers that have already computed
else * the hash value.
{ */
/* created new entry */ TupleHashEntry
*isnew = true; LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot,
/* zero caller data */ bool *isnew, uint32 hash)
entry->additional = NULL; {
MemoryContextSwitchTo(hashtable->tablecxt); TupleHashEntry entry;
/* Copy the first tuple into the table context */ MemoryContext oldContext;
entry->firstTuple = ExecCopySlotMinimalTuple(slot);
} /* Need to run the hash functions in short-lived context */
} oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
else
{ /* set up data needed by hash and match functions */
entry = tuplehash_lookup(hashtable->hashtab, key); hashtable->inputslot = slot;
} hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
hashtable->cur_eq_func = hashtable->tab_eq_func;
entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
...@@ -389,7 +391,7 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ...@@ -389,7 +391,7 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
* Also, the caller must select an appropriate memory context for running * Also, the caller must select an appropriate memory context for running
* the hash functions. (dynahash.c doesn't change CurrentMemoryContext.) * the hash functions. (dynahash.c doesn't change CurrentMemoryContext.)
*/ */
static uint32 uint32
TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple) TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
{ {
TupleHashTable hashtable = (TupleHashTable) tb->private_data; TupleHashTable hashtable = (TupleHashTable) tb->private_data;
...@@ -450,6 +452,52 @@ TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple) ...@@ -450,6 +452,52 @@ TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
return murmurhash32(hashkey); return murmurhash32(hashkey);
} }
/*
* Does the work of LookupTupleHashEntry and LookupTupleHashEntryHash. Useful
* so that we can avoid switching the memory context multiple times for
* LookupTupleHashEntry.
*
* NB: This function may or may not change the memory context. Caller is
* expected to change it back.
*/
static TupleHashEntry
LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
bool *isnew, uint32 hash)
{
TupleHashEntryData *entry;
bool found;
MinimalTuple key;
key = NULL; /* flag to reference inputslot */
if (isnew)
{
entry = tuplehash_insert_hash(hashtable->hashtab, key, hash, &found);
if (found)
{
/* found pre-existing entry */
*isnew = false;
}
else
{
/* 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);
}
}
else
{
entry = tuplehash_lookup_hash(hashtable->hashtab, key, hash);
}
return entry;
}
/* /*
* See whether two tuples (presumably of the same hash value) match * See whether two tuples (presumably of the same hash value) match
*/ */
......
...@@ -140,6 +140,11 @@ extern TupleHashTable BuildTupleHashTableExt(PlanState *parent, ...@@ -140,6 +140,11 @@ extern TupleHashTable BuildTupleHashTableExt(PlanState *parent,
extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
TupleTableSlot *slot, TupleTableSlot *slot,
bool *isnew); bool *isnew);
extern uint32 TupleHashTableHash(struct tuplehash_hash *tb,
const MinimalTuple tuple);
extern TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable,
TupleTableSlot *slot,
bool *isnew, uint32 hash);
extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
TupleTableSlot *slot, TupleTableSlot *slot,
ExprState *eqcomp, ExprState *eqcomp,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment