diff options
Diffstat (limited to 'src/backend/executor/nodeSubplan.c')
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 3dcd03db072..7d40fe8b1ed 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.66 2004/12/31 21:59:45 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.67 2005/03/16 21:38:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,7 +37,8 @@ static Datum ExecScanSubPlan(SubPlanState *node, bool *isNull); static void buildSubPlanHash(SubPlanState *node); static bool findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot); -static bool tupleAllNulls(HeapTuple tuple); +static bool slotAllNulls(TupleTableSlot *slot); +static bool slotNoNulls(TupleTableSlot *slot); /* ---------------------------------------------------------------- @@ -78,7 +79,6 @@ ExecHashSubPlan(SubPlanState *node, PlanState *planstate = node->planstate; ExprContext *innerecontext = node->innerecontext; TupleTableSlot *slot; - HeapTuple tup; /* Shouldn't have any direct correlation Vars */ if (subplan->parParam != NIL || node->args != NIL) @@ -105,7 +105,6 @@ ExecHashSubPlan(SubPlanState *node, */ node->projLeft->pi_exprContext = econtext; slot = ExecProject(node->projLeft, NULL); - tup = slot->val; /* * Note: because we are typically called in a per-tuple context, we @@ -137,7 +136,7 @@ ExecHashSubPlan(SubPlanState *node, * comparison we will not even make, unless there's a chance match of * hash keys. */ - if (HeapTupleNoNulls(tup)) + if (slotNoNulls(slot)) { if (node->havehashrows && LookupTupleHashEntry(node->hashtable, slot, NULL) != NULL) @@ -171,7 +170,7 @@ ExecHashSubPlan(SubPlanState *node, ExecClearTuple(slot); return BoolGetDatum(false); } - if (tupleAllNulls(tup)) + if (slotAllNulls(slot)) { ExecClearTuple(slot); *isNull = true; @@ -271,8 +270,7 @@ ExecScanSubPlan(SubPlanState *node, !TupIsNull(slot); slot = ExecProcNode(planstate)) { - HeapTuple tup = slot->val; - TupleDesc tdesc = slot->ttc_tupleDescriptor; + TupleDesc tdesc = slot->tts_tupleDescriptor; Datum rowresult = BoolGetDatum(!useOr); bool rownull = false; int col = 1; @@ -303,13 +301,12 @@ ExecScanSubPlan(SubPlanState *node, * copied tuple for eventual freeing. */ MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - tup = heap_copytuple(tup); if (node->curTuple) heap_freetuple(node->curTuple); - node->curTuple = tup; + node->curTuple = ExecCopySlotTuple(slot); MemoryContextSwitchTo(node->sub_estate->es_query_cxt); - result = heap_getattr(tup, col, tdesc, isNull); + result = heap_getattr(node->curTuple, col, tdesc, isNull); /* keep scanning subplan to make sure there's only one tuple */ continue; } @@ -321,7 +318,7 @@ ExecScanSubPlan(SubPlanState *node, found = true; /* stash away current value */ - dvalue = heap_getattr(tup, 1, tdesc, &disnull); + dvalue = slot_getattr(slot, 1, &disnull); astate = accumArrayResult(astate, dvalue, disnull, tdesc->attrs[0]->atttypid, oldcontext); @@ -357,7 +354,7 @@ ExecScanSubPlan(SubPlanState *node, */ prmdata = &(econtext->ecxt_param_exec_vals[paramid]); Assert(prmdata->execPlan == NULL); - prmdata->value = heap_getattr(tup, col, tdesc, + prmdata->value = slot_getattr(slot, col, &(prmdata->isnull)); /* @@ -554,8 +551,6 @@ buildSubPlanHash(SubPlanState *node) !TupIsNull(slot); slot = ExecProcNode(planstate)) { - HeapTuple tup = slot->val; - TupleDesc tdesc = slot->ttc_tupleDescriptor; int col = 1; ListCell *plst; bool isnew; @@ -571,20 +566,16 @@ buildSubPlanHash(SubPlanState *node) prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]); Assert(prmdata->execPlan == NULL); - prmdata->value = heap_getattr(tup, col, tdesc, + prmdata->value = slot_getattr(slot, col, &(prmdata->isnull)); col++; } slot = ExecProject(node->projRight, NULL); - tup = slot->val; /* * If result contains any nulls, store separately or not at all. - * (Since we know the projection tuple has no junk columns, we can - * just look at the overall hasnull info bit, instead of groveling - * through the columns.) */ - if (HeapTupleNoNulls(tup)) + if (slotNoNulls(slot)) { (void) LookupTupleHashEntry(node->hashtable, slot, &isnew); node->havehashrows = true; @@ -606,7 +597,8 @@ buildSubPlanHash(SubPlanState *node) * Since the projected tuples are in the sub-query's context and not * the main context, we'd better clear the tuple slot before there's * any chance of a reset of the sub-query's context. Else we will - * have the potential for a double free attempt. + * have the potential for a double free attempt. (XXX possibly + * no longer needed, but can't hurt.) */ ExecClearTuple(node->projRight->pi_slot); @@ -626,17 +618,15 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot) { int numCols = hashtable->numCols; AttrNumber *keyColIdx = hashtable->keyColIdx; - HeapTuple tuple = slot->val; - TupleDesc tupdesc = slot->ttc_tupleDescriptor; TupleHashIterator hashiter; TupleHashEntry entry; ResetTupleHashIterator(hashtable, &hashiter); while ((entry = ScanTupleHashTable(&hashiter)) != NULL) { - if (!execTuplesUnequal(entry->firstTuple, - tuple, - tupdesc, + ExecStoreTuple(entry->firstTuple, hashtable->tableslot, + InvalidBuffer, false); + if (!execTuplesUnequal(hashtable->tableslot, slot, numCols, keyColIdx, hashtable->eqfunctions, hashtable->tempcxt)) @@ -646,17 +636,40 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot) } /* - * tupleAllNulls: is the tuple completely NULL? + * slotAllNulls: is the slot completely NULL? + * + * This does not test for dropped columns, which is OK because we only + * use it on projected tuples. + */ +static bool +slotAllNulls(TupleTableSlot *slot) +{ + int ncols = slot->tts_tupleDescriptor->natts; + int i; + + for (i = 1; i <= ncols; i++) + { + if (!slot_attisnull(slot, i)) + return false; + } + return true; +} + +/* + * slotNoNulls: is the slot entirely not NULL? + * + * This does not test for dropped columns, which is OK because we only + * use it on projected tuples. */ static bool -tupleAllNulls(HeapTuple tuple) +slotNoNulls(TupleTableSlot *slot) { - int ncols = tuple->t_data->t_natts; + int ncols = slot->tts_tupleDescriptor->natts; int i; for (i = 1; i <= ncols; i++) { - if (!heap_attisnull(tuple, i)) + if (slot_attisnull(slot, i)) return false; } return true; @@ -932,8 +945,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) !TupIsNull(slot); slot = ExecProcNode(planstate)) { - HeapTuple tup = slot->val; - TupleDesc tdesc = slot->ttc_tupleDescriptor; + TupleDesc tdesc = slot->tts_tupleDescriptor; int i = 1; if (subLinkType == EXISTS_SUBLINK) @@ -956,7 +968,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) found = true; /* stash away current value */ - dvalue = heap_getattr(tup, 1, tdesc, &disnull); + dvalue = slot_getattr(slot, 1, &disnull); astate = accumArrayResult(astate, dvalue, disnull, tdesc->attrs[0]->atttypid, oldcontext); @@ -981,10 +993,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) * freeing. */ MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - tup = heap_copytuple(tup); if (node->curTuple) heap_freetuple(node->curTuple); - node->curTuple = tup; + node->curTuple = ExecCopySlotTuple(slot); MemoryContextSwitchTo(node->sub_estate->es_query_cxt); /* @@ -996,7 +1007,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]); prm->execPlan = NULL; - prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); + prm->value = heap_getattr(node->curTuple, i, tdesc, + &(prm->isnull)); i++; } } |