diff options
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 110 |
1 files changed, 100 insertions, 10 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index edf7d034bd3..4927e212176 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -149,7 +149,7 @@ ExecHashSubPlan(SubPlanState *node, if (node->havehashrows && FindTupleHashEntry(node->hashtable, slot, - node->cur_eq_funcs, + node->cur_eq_comp, node->lhs_hash_funcs) != NULL) { ExecClearTuple(slot); @@ -494,9 +494,11 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) if (nbuckets < 1) nbuckets = 1; - node->hashtable = BuildTupleHashTable(ncols, + node->hashtable = BuildTupleHashTable(node->parent, + node->descRight, + ncols, node->keyColIdx, - node->tab_eq_funcs, + node->tab_eq_funcoids, node->tab_hash_funcs, nbuckets, 0, @@ -514,9 +516,11 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) if (nbuckets < 1) nbuckets = 1; } - node->hashnulls = BuildTupleHashTable(ncols, + node->hashnulls = BuildTupleHashTable(node->parent, + node->descRight, + ncols, node->keyColIdx, - node->tab_eq_funcs, + node->tab_eq_funcoids, node->tab_hash_funcs, nbuckets, 0, @@ -599,6 +603,77 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext) } /* + * execTuplesUnequal + * Return true if two tuples are definitely unequal in the indicated + * fields. + * + * Nulls are neither equal nor unequal to anything else. A true result + * is obtained only if there are non-null fields that compare not-equal. + * + * slot1, slot2: the tuples to compare (must have same columns!) + * numCols: the number of attributes to be examined + * matchColIdx: array of attribute column numbers + * eqFunctions: array of fmgr lookup info for the equality functions to use + * evalContext: short-term memory context for executing the functions + */ +static bool +execTuplesUnequal(TupleTableSlot *slot1, + TupleTableSlot *slot2, + int numCols, + AttrNumber *matchColIdx, + FmgrInfo *eqfunctions, + MemoryContext evalContext) +{ + 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; +} + +/* * findPartialMatch: does the hashtable contain an entry that is not * provably distinct from the tuple? * @@ -719,6 +794,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) sstate->hashtempcxt = NULL; sstate->innerecontext = NULL; sstate->keyColIdx = NULL; + sstate->tab_eq_funcoids = NULL; sstate->tab_hash_funcs = NULL; sstate->tab_eq_funcs = NULL; sstate->lhs_hash_funcs = NULL; @@ -757,7 +833,8 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) { int ncols, i; - TupleDesc tupDesc; + TupleDesc tupDescLeft; + TupleDesc tupDescRight; TupleTableSlot *slot; List *oplist, *lefttlist, @@ -815,6 +892,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) Assert(list_length(oplist) == ncols); lefttlist = righttlist = NIL; + sstate->tab_eq_funcoids = (Oid *) palloc(ncols * sizeof(Oid)); sstate->tab_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); sstate->tab_eq_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); sstate->lhs_hash_funcs = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo)); @@ -848,6 +926,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) righttlist = lappend(righttlist, tle); /* Lookup the equality function (potentially cross-type) */ + sstate->tab_eq_funcoids[i - 1] = opexpr->opfuncid; fmgr_info(opexpr->opfuncid, &sstate->cur_eq_funcs[i - 1]); fmgr_info_set_expr((Node *) opexpr, &sstate->cur_eq_funcs[i - 1]); @@ -877,23 +956,34 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent) * (hack alert!). The righthand expressions will be evaluated in our * own innerecontext. */ - tupDesc = ExecTypeFromTL(lefttlist, false); + tupDescLeft = ExecTypeFromTL(lefttlist, false); slot = ExecInitExtraTupleSlot(estate); - ExecSetSlotDescriptor(slot, tupDesc); + ExecSetSlotDescriptor(slot, tupDescLeft); sstate->projLeft = ExecBuildProjectionInfo(lefttlist, NULL, slot, parent, NULL); - tupDesc = ExecTypeFromTL(righttlist, false); + sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false); slot = ExecInitExtraTupleSlot(estate); - ExecSetSlotDescriptor(slot, tupDesc); + ExecSetSlotDescriptor(slot, tupDescRight); sstate->projRight = ExecBuildProjectionInfo(righttlist, sstate->innerecontext, slot, sstate->planstate, NULL); + + /* + * Create comparator for lookups of rows in the table (potentially + * across-type comparison). + */ + sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight, + ncols, + sstate->keyColIdx, + sstate->tab_eq_funcoids, + parent); + } return sstate; |