#include "postgres.h"#include "executor/executor.h"#include "miscadmin.h"#include "utils/lsyscache.h"#include "utils/memutils.h"
Go to the source code of this file.
Functions | |
| static uint32 | TupleHashTableHash (const void *key, Size keysize) |
| static int | TupleHashTableMatch (const void *key1, const void *key2, Size keysize) |
| bool | execTuplesMatch (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext) |
| bool | execTuplesUnequal (TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext) |
| FmgrInfo * | execTuplesMatchPrepare (int numCols, Oid *eqOperators) |
| void | execTuplesHashPrepare (int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions) |
| TupleHashTable | BuildTupleHashTable (int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions, long nbuckets, Size entrysize, MemoryContext tablecxt, MemoryContext tempcxt) |
| TupleHashEntry | LookupTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew) |
| TupleHashEntry | FindTupleHashEntry (TupleHashTable hashtable, TupleTableSlot *slot, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions) |
Variables | |
| static TupleHashTable | CurTupleHashTable = NULL |
| TupleHashTable BuildTupleHashTable | ( | int | numCols, | |
| AttrNumber * | keyColIdx, | |||
| FmgrInfo * | eqfunctions, | |||
| FmgrInfo * | hashfunctions, | |||
| long | nbuckets, | |||
| Size | entrysize, | |||
| MemoryContext | tablecxt, | |||
| MemoryContext | tempcxt | |||
| ) |
Definition at line 275 of file execGrouping.c.
References Assert, TupleHashTableData::cur_eq_funcs, HASHCTL::entrysize, TupleHashTableData::entrysize, HASHCTL::hash, HASH_COMPARE, HASH_CONTEXT, hash_create(), HASH_ELEM, HASH_FUNCTION, TupleHashTableData::hashtab, HASHCTL::hcxt, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, HASHCTL::keysize, HASHCTL::match, MemoryContextAlloc(), MemSet, Min, TupleHashTableData::numCols, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and work_mem.
Referenced by build_hash_table(), and buildSubPlanHash().
{
TupleHashTable hashtable;
HASHCTL hash_ctl;
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->numCols = numCols;
hashtable->keyColIdx = keyColIdx;
hashtable->tab_hash_funcs = hashfunctions;
hashtable->tab_eq_funcs = eqfunctions;
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->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);
return hashtable;
}
| void execTuplesHashPrepare | ( | int | numCols, | |
| Oid * | eqOperators, | |||
| FmgrInfo ** | eqFunctions, | |||
| FmgrInfo ** | hashFunctions | |||
| ) |
Definition at line 218 of file execGrouping.c.
References Assert, elog, ERROR, fmgr_info(), get_op_hash_functions(), get_opcode(), i, and palloc().
Referenced by ExecInitAgg(), ExecInitRecursiveUnion(), and ExecInitSetOp().
{
int i;
*eqFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
*hashFunctions = (FmgrInfo *) palloc(numCols * sizeof(FmgrInfo));
for (i = 0; i < numCols; i++)
{
Oid eq_opr = eqOperators[i];
Oid eq_function;
Oid left_hash_function;
Oid right_hash_function;
eq_function = get_opcode(eq_opr);
if (!get_op_hash_functions(eq_opr,
&left_hash_function, &right_hash_function))
elog(ERROR, "could not find hash function for hash operator %u",
eq_opr);
/* We're not supporting cross-type cases here */
Assert(left_hash_function == right_hash_function);
fmgr_info(eq_function, &(*eqFunctions)[i]);
fmgr_info(right_hash_function, &(*hashFunctions)[i]);
}
}
| bool execTuplesMatch | ( | TupleTableSlot * | slot1, | |
| TupleTableSlot * | slot2, | |||
| int | numCols, | |||
| AttrNumber * | matchColIdx, | |||
| FmgrInfo * | eqfunctions, | |||
| MemoryContext | evalContext | |||
| ) |
Definition at line 54 of file execGrouping.c.
References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().
Referenced by agg_retrieve_direct(), are_peers(), ExecGroup(), ExecUnique(), process_ordered_aggregate_multi(), setop_retrieve_direct(), spool_tuples(), and TupleHashTableMatch().
{
MemoryContext oldContext;
bool result;
int i;
/* Reset and switch into the temp context. */
MemoryContextReset(evalContext);
oldContext = MemoryContextSwitchTo(evalContext);
/*
* We cannot report a match without checking all the fields, but we can
* report a non-match as soon as we find unequal fields. So, start
* comparing at the last field (least significant sort key). That's the
* most likely to be different if we are dealing with sorted input.
*/
result = true;
for (i = numCols; --i >= 0;)
{
AttrNumber att = matchColIdx[i];
Datum attr1,
attr2;
bool isNull1,
isNull2;
attr1 = slot_getattr(slot1, att, &isNull1);
attr2 = slot_getattr(slot2, att, &isNull2);
if (isNull1 != isNull2)
{
result = false; /* one null and one not; they aren't equal */
break;
}
if (isNull1)
continue; /* both are null, treat as equal */
/* Apply the type-specific equality function */
if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
attr1, attr2)))
{
result = false; /* they aren't equal */
break;
}
}
MemoryContextSwitchTo(oldContext);
return result;
}
Definition at line 189 of file execGrouping.c.
References fmgr_info(), get_opcode(), i, and palloc().
Referenced by ExecInitAgg(), ExecInitGroup(), ExecInitSetOp(), ExecInitUnique(), and ExecInitWindowAgg().
| bool execTuplesUnequal | ( | TupleTableSlot * | slot1, | |
| TupleTableSlot * | slot2, | |||
| int | numCols, | |||
| AttrNumber * | matchColIdx, | |||
| FmgrInfo * | eqfunctions, | |||
| MemoryContext | evalContext | |||
| ) |
Definition at line 124 of file execGrouping.c.
References DatumGetBool, FunctionCall2, i, MemoryContextReset(), MemoryContextSwitchTo(), and slot_getattr().
Referenced by findPartialMatch().
{
MemoryContext oldContext;
bool result;
int i;
/* Reset and switch into the temp context. */
MemoryContextReset(evalContext);
oldContext = MemoryContextSwitchTo(evalContext);
/*
* We cannot report a match without checking all the fields, but we can
* report a non-match as soon as we find unequal fields. So, start
* comparing at the last field (least significant sort key). That's the
* most likely to be different if we are dealing with sorted input.
*/
result = false;
for (i = numCols; --i >= 0;)
{
AttrNumber att = matchColIdx[i];
Datum attr1,
attr2;
bool isNull1,
isNull2;
attr1 = slot_getattr(slot1, att, &isNull1);
if (isNull1)
continue; /* can't prove anything here */
attr2 = slot_getattr(slot2, att, &isNull2);
if (isNull2)
continue; /* can't prove anything here */
/* Apply the type-specific equality function */
if (!DatumGetBool(FunctionCall2(&eqfunctions[i],
attr1, attr2)))
{
result = true; /* they are unequal */
break;
}
}
MemoryContextSwitchTo(oldContext);
return result;
}
| TupleHashEntry FindTupleHashEntry | ( | TupleHashTable | hashtable, | |
| TupleTableSlot * | slot, | |||
| FmgrInfo * | eqfunctions, | |||
| FmgrInfo * | hashfunctions | |||
| ) |
Definition at line 422 of file execGrouping.c.
References TupleHashTableData::cur_eq_funcs, TupleHashEntryData::firstTuple, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MemoryContextSwitchTo(), NULL, and TupleHashTableData::tempcxt.
Referenced by ExecHashSubPlan().
{
TupleHashEntry entry;
MemoryContext oldContext;
TupleHashTable saveCurHT;
TupleHashEntryData dummy;
/* 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.
*/
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;
MemoryContextSwitchTo(oldContext);
return entry;
}
| TupleHashEntry LookupTupleHashEntry | ( | TupleHashTable | hashtable, | |
| TupleTableSlot * | slot, | |||
| bool * | isnew | |||
| ) |
Definition at line 331 of file execGrouping.c.
References CreateTupleDescCopy(), TupleHashTableData::cur_eq_funcs, TupleHashTableData::entrysize, ExecCopySlotMinimalTuple(), TupleHashEntryData::firstTuple, HASH_ENTER, HASH_FIND, hash_search(), TupleHashTableData::hashtab, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, MakeSingleTupleTableSlot(), MemoryContextSwitchTo(), MemSet, NULL, TupleHashTableData::tab_eq_funcs, TupleHashTableData::tab_hash_funcs, TupleHashTableData::tablecxt, TupleHashTableData::tableslot, TupleHashTableData::tempcxt, and TupleTableSlot::tts_tupleDescriptor.
Referenced by buildSubPlanHash(), ExecRecursiveUnion(), lookup_hash_entry(), and setop_fill_hash_table().
{
TupleHashEntry entry;
MemoryContext oldContext;
TupleHashTable saveCurHT;
TupleHashEntryData dummy;
bool found;
/* If first time through, clone the input slot to make table slot */
if (hashtable->tableslot == NULL)
{
TupleDesc tupdesc;
oldContext = MemoryContextSwitchTo(hashtable->tablecxt);
/*
* We copy the input tuple descriptor just for safety --- we assume
* all input tuples will have equivalent descriptors.
*/
tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
hashtable->tableslot = MakeSingleTupleTableSlot(tupdesc);
MemoryContextSwitchTo(oldContext);
}
/* 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.
*/
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);
if (isnew)
{
if (found)
{
/* found pre-existing entry */
*isnew = false;
}
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 */
MemoryContextSwitchTo(hashtable->tablecxt);
entry->firstTuple = ExecCopySlotMinimalTuple(slot);
*isnew = true;
}
}
CurTupleHashTable = saveCurHT;
MemoryContextSwitchTo(oldContext);
return entry;
}
Definition at line 478 of file execGrouping.c.
References DatumGetUInt32, ExecStoreMinimalTuple(), FunctionCall1, i, TupleHashTableData::in_hash_funcs, TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, NULL, TupleHashTableData::numCols, slot_getattr(), TupleHashTableData::tab_hash_funcs, and TupleHashTableData::tableslot.
{
MinimalTuple tuple = ((const TupleHashEntryData *) key)->firstTuple;
TupleTableSlot *slot;
TupleHashTable hashtable = CurTupleHashTable;
int numCols = hashtable->numCols;
AttrNumber *keyColIdx = hashtable->keyColIdx;
FmgrInfo *hashfunctions;
uint32 hashkey = 0;
int i;
if (tuple == NULL)
{
/* Process the current input tuple for the table */
slot = hashtable->inputslot;
hashfunctions = hashtable->in_hash_funcs;
}
else
{
/* Process a tuple already stored in the table */
/* (this case never actually occurs in current dynahash.c code) */
slot = 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;
/* rotate hashkey left 1 bit at each step */
hashkey = (hashkey << 1) | ((hashkey & 0x80000000) ? 1 : 0);
attr = slot_getattr(slot, att, &isNull);
if (!isNull) /* treat nulls as having hash key 0 */
{
uint32 hkey;
hkey = DatumGetUInt32(FunctionCall1(&hashfunctions[i],
attr));
hashkey ^= hkey;
}
}
return hashkey;
}
| static int TupleHashTableMatch | ( | const void * | key1, | |
| const void * | key2, | |||
| Size | keysize | |||
| ) | [static] |
Definition at line 540 of file execGrouping.c.
References Assert, TupleHashTableData::cur_eq_funcs, ExecStoreMinimalTuple(), execTuplesMatch(), TupleHashTableData::inputslot, TupleHashTableData::keyColIdx, NULL, TupleHashTableData::numCols, TupleHashTableData::tableslot, and TupleHashTableData::tempcxt.
{
MinimalTuple tuple1 = ((const TupleHashEntryData *) key1)->firstTuple;
#ifdef USE_ASSERT_CHECKING
MinimalTuple tuple2 = ((const TupleHashEntryData *) key2)->firstTuple;
#endif
TupleTableSlot *slot1;
TupleTableSlot *slot2;
TupleHashTable hashtable = CurTupleHashTable;
/*
* We assume that dynahash.c 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.
*/
Assert(tuple1 != NULL);
slot1 = hashtable->tableslot;
ExecStoreMinimalTuple(tuple1, slot1, false);
Assert(tuple2 == NULL);
slot2 = hashtable->inputslot;
/* For crosstype comparisons, the inputslot must be first */
if (execTuplesMatch(slot2,
slot1,
hashtable->numCols,
hashtable->keyColIdx,
hashtable->cur_eq_funcs,
hashtable->tempcxt))
return 0;
else
return 1;
}
TupleHashTable CurTupleHashTable = NULL [static] |
Definition at line 27 of file execGrouping.c.
1.7.1