diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index f716c688101..68dc74a3a86 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.27 2001/03/22 06:16:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.28 2001/05/27 20:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,10 +56,12 @@ * Initialize the Junk filter. * * The initial targetlist and associated tuple descriptor are passed in. + * An optional resultSlot can be passed as well. *------------------------------------------------------------------------- */ JunkFilter * -ExecInitJunkFilter(List *targetList, TupleDesc tupType) +ExecInitJunkFilter(List *targetList, TupleDesc tupType, + TupleTableSlot *slot) { MemoryContext oldContext; MemoryContext junkContext; @@ -245,6 +247,10 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) junkfilter->jf_cleanTupType = cleanTupType; junkfilter->jf_cleanMap = cleanMap; junkfilter->jf_junkContext = junkContext; + junkfilter->jf_resultSlot = slot; + + if (slot) + ExecSetSlotDescriptor(slot, cleanTupType, false); MemoryContextSwitchTo(oldContext); @@ -260,7 +266,6 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) void ExecFreeJunkFilter(JunkFilter *junkfilter) { - /* * Since the junkfilter is inside its own context, we just have to * delete the context and we're set. @@ -336,6 +341,10 @@ ExecGetJunkAttribute(JunkFilter *junkfilter, * ExecRemoveJunk * * Construct and return a tuple with all the junk attributes removed. + * + * Note: for historical reasons, this does not store the constructed + * tuple into the junkfilter's resultSlot. The caller should do that + * if it wants to. *------------------------------------------------------------------------- */ HeapTuple diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index f87b674b074..3ba9b9136f5 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.141 2001/05/27 09:59:29 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.142 2001/05/27 20:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -598,12 +598,19 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) } /* - * initialize the executor "tuple" table. + * initialize the executor "tuple" table. We need slots for all the + * plan nodes, plus possibly output slots for the junkfilter(s). + * At this point we aren't sure if we need junkfilters, so just add + * slots for them unconditionally. */ { int nSlots = ExecCountSlotsNode(plan); - estate->es_tupleTable = ExecCreateTupleTable(nSlots + 10); /* why add ten? - jolly */ + if (parseTree->resultRelations != NIL) + nSlots += length(parseTree->resultRelations); + else + nSlots += 1; + estate->es_tupleTable = ExecCreateTupleTable(nSlots); } /* mark EvalPlanQual not active */ @@ -686,7 +693,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) JunkFilter *j; j = ExecInitJunkFilter(subplan->targetlist, - ExecGetTupType(subplan)); + ExecGetTupType(subplan), + ExecAllocTableSlot(estate->es_tupleTable)); resultRelInfo->ri_junkFilter = j; resultRelInfo++; subplans = lnext(subplans); @@ -702,9 +710,11 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) else { /* Normal case with just one JunkFilter */ - JunkFilter *j = ExecInitJunkFilter(plan->targetlist, - tupType); + JunkFilter *j; + j = ExecInitJunkFilter(plan->targetlist, + tupType, + ExecAllocTableSlot(estate->es_tupleTable)); estate->es_junkFilter = j; if (estate->es_result_relation_info) estate->es_result_relation_info->ri_junkFilter = j; @@ -986,7 +996,9 @@ lnext: ; * if we have a junk filter, then project a new tuple with the * junk removed. * - * Store this new "clean" tuple in the place of the original tuple. + * Store this new "clean" tuple in the junkfilter's resultSlot. + * (Formerly, we stored it back over the "dirty" tuple, which is + * WRONG because that tuple slot has the wrong descriptor.) * * Also, extract all the junk information we need. */ @@ -1088,7 +1100,7 @@ lnext: ; newTuple = ExecRemoveJunk(junkfilter, slot); slot = ExecStoreTuple(newTuple, /* tuple to store */ - slot, /* destination slot */ + junkfilter->jf_resultSlot, /* dest slot */ InvalidBuffer, /* this tuple has no * buffer */ true); /* tuple should be pfreed */ @@ -1467,7 +1479,9 @@ lreplace:; { *tupleid = ctid; tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot); - slot = ExecStoreTuple(tuple, slot, InvalidBuffer, true); + slot = ExecStoreTuple(tuple, + estate->es_junkFilter->jf_resultSlot, + InvalidBuffer, true); goto lreplace; } } diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 787296f0e5c..a72594982cb 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: executor.h,v 1.57 2001/03/22 04:00:44 momjian Exp $ + * $Id: executor.h,v 1.58 2001/05/27 20:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,8 @@ extern void ExecRestrPos(Plan *node); /* * prototypes from functions in execJunk.c */ -extern JunkFilter *ExecInitJunkFilter(List *targetList, TupleDesc tupType); +extern JunkFilter *ExecInitJunkFilter(List *targetList, TupleDesc tupType, + TupleTableSlot *slot); extern void ExecFreeJunkFilter(JunkFilter *junkfilter); extern bool ExecGetJunkAttribute(JunkFilter *junkfilter, TupleTableSlot *slot, char *attrName, Datum *value, bool *isNull); diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 180e26639f8..18903369c17 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execnodes.h,v 1.59 2001/05/15 00:33:36 tgl Exp $ + * $Id: execnodes.h,v 1.60 2001/05/27 20:48:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -166,17 +166,19 @@ typedef struct ProjectionInfo * cleanLength: the length of 'cleanTargetList' * cleanTupType: the tuple descriptor of the "clean" tuple (with * junk attributes removed). - * cleanMap: A map with the correspondance between the non-junk - * attributes of the "original" tuple and the - * attributes of the "clean" tuple. + * cleanMap: A map with the correspondence between the non-junk + * attribute numbers of the "original" tuple and the + * attribute numbers of the "clean" tuple. * junkContext: memory context holding the JunkFilter node and all * its subsidiary data structures. + * resultSlot: tuple slot that can be used to hold cleaned tuple. * - * NOTE: the original targetList and tupType are passed to ExecInitJunkFilter - * and do not belong to the JunkFilter. All the other subsidiary structures - * are created during ExecInitJunkFilter, and all of them can be freed by - * deleting the memory context junkContext. This would not be needed if we - * had a cleaner approach to managing query-lifetime data structures... + * NOTE: the original targetList and tupType are passed to ExecInitJunkFilter, + * as is the resultSlot. These items do not belong to the JunkFilter. All + * the other subsidiary structures are created during ExecInitJunkFilter, + * and all of them can be freed by deleting the memory context junkContext. + * This would not be needed if we had a cleaner approach to managing + * query-lifetime data structures... * ---------------- */ typedef struct JunkFilter @@ -190,6 +192,7 @@ typedef struct JunkFilter TupleDesc jf_cleanTupType; AttrNumber *jf_cleanMap; MemoryContext jf_junkContext; + TupleTableSlot *jf_resultSlot; } JunkFilter; /* ----------------