#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.