diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c index 271bba17e4..c651084b57 100644 --- a/src/backend/executor/execGrouping.c +++ b/src/backend/executor/execGrouping.c @@ -138,7 +138,8 @@ execTuplesHashPrepare(int numCols, * hashfunctions: datatype-specific hashing functions to use * nbuckets: initial estimate of hashtable size * additionalsize: size of data stored in ->additional - * tablecxt: memory context in which to store table and table entries + * metacxt: memory context for long-lived allocation, but not per-entry data + * tablecxt: memory context in which to store table entries * tempcxt: short-lived context for evaluation hash and comparison functions * * The function arrays may be made with execTuplesHashPrepare(). Note they @@ -149,14 +150,16 @@ execTuplesHashPrepare(int numCols, * storage that will live as long as the hashtable does. */ TupleHashTable -BuildTupleHashTable(PlanState *parent, - TupleDesc inputDesc, - int numCols, AttrNumber *keyColIdx, - Oid *eqfuncoids, - FmgrInfo *hashfunctions, - long nbuckets, Size additionalsize, - MemoryContext tablecxt, MemoryContext tempcxt, - bool use_variable_hash_iv) +BuildTupleHashTableExt(PlanState *parent, + TupleDesc inputDesc, + int numCols, AttrNumber *keyColIdx, + Oid *eqfuncoids, + FmgrInfo *hashfunctions, + long nbuckets, Size additionalsize, + MemoryContext metacxt, + MemoryContext tablecxt, + MemoryContext tempcxt, + bool use_variable_hash_iv) { TupleHashTable hashtable; Size entrysize = sizeof(TupleHashEntryData) + additionalsize; @@ -167,8 +170,9 @@ BuildTupleHashTable(PlanState *parent, /* 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)); + oldcontext = MemoryContextSwitchTo(metacxt); + + hashtable = (TupleHashTable) palloc(sizeof(TupleHashTableData)); hashtable->numCols = numCols; hashtable->keyColIdx = keyColIdx; @@ -194,9 +198,7 @@ BuildTupleHashTable(PlanState *parent, else hashtable->hash_iv = 0; - hashtable->hashtab = tuplehash_create(tablecxt, nbuckets, hashtable); - - oldcontext = MemoryContextSwitchTo(hashtable->tablecxt); + hashtable->hashtab = tuplehash_create(metacxt, nbuckets, hashtable); /* * We copy the input tuple descriptor just for safety --- we assume all @@ -223,6 +225,46 @@ BuildTupleHashTable(PlanState *parent, return hashtable; } +/* + * BuildTupleHashTable is a backwards-compatibilty wrapper for + * BuildTupleHashTableExt(), that allocates the hashtable's metadata in + * tablecxt. Note that hashtables created this way cannot be reset leak-free + * with ResetTupleHashTable(). + */ +TupleHashTable +BuildTupleHashTable(PlanState *parent, + TupleDesc inputDesc, + int numCols, AttrNumber *keyColIdx, + Oid *eqfuncoids, + FmgrInfo *hashfunctions, + long nbuckets, Size additionalsize, + MemoryContext tablecxt, + MemoryContext tempcxt, + bool use_variable_hash_iv) +{ + return BuildTupleHashTableExt(parent, + inputDesc, + numCols, keyColIdx, + eqfuncoids, + hashfunctions, + nbuckets, additionalsize, + tablecxt, + tablecxt, + tempcxt, + use_variable_hash_iv); +} + +/* + * Reset contents of the hashtable to be empty, preserving all the non-content + * state. Note that the tablecxt passed to BuildTupleHashTableExt() should + * also be reset, otherwise there will be leaks. + */ +void +ResetTupleHashTable(TupleHashTable hashtable) +{ + tuplehash_reset(hashtable->hashtab); +} + /* * Find or create a hashtable entry for the tuple group containing the * given tuple. The tuple must be the same type as the hashtable entries. diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index f82b51667f..97b1c0f67d 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -129,6 +129,15 @@ extern TupleHashTable BuildTupleHashTable(PlanState *parent, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv); +extern TupleHashTable BuildTupleHashTableExt(PlanState *parent, + TupleDesc inputDesc, + int numCols, AttrNumber *keyColIdx, + Oid *eqfuncoids, + FmgrInfo *hashfunctions, + long nbuckets, Size additionalsize, + MemoryContext metacxt, + MemoryContext tablecxt, + MemoryContext tempcxt, bool use_variable_hash_iv); extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew); @@ -136,6 +145,7 @@ extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, ExprState *eqcomp, FmgrInfo *hashfunctions); +extern void ResetTupleHashTable(TupleHashTable hashtable); /* * prototypes from functions in execJunk.c