*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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;
junkfilter->jf_cleanTupType = cleanTupType;
junkfilter->jf_cleanMap = cleanMap;
junkfilter->jf_junkContext = junkContext;
+ junkfilter->jf_resultSlot = slot;
+
+ if (slot)
+ ExecSetSlotDescriptor(slot, cleanTupType, false);
MemoryContextSwitchTo(oldContext);
void
ExecFreeJunkFilter(JunkFilter *junkfilter)
{
-
/*
* Since the junkfilter is inside its own context, we just have to
* delete the context and we're set.
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
/*
- * 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 */
JunkFilter *j;
j = ExecInitJunkFilter(subplan->targetlist,
- ExecGetTupType(subplan));
+ ExecGetTupType(subplan),
+ ExecAllocTableSlot(estate->es_tupleTable));
resultRelInfo->ri_junkFilter = j;
resultRelInfo++;
subplans = lnext(subplans);
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;
* 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.
*/
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 */
{
*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;
}
}
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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);
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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.
- *
- * 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...
+ * resultSlot: tuple slot that can be used to hold cleaned tuple.
+ *
+ * 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
TupleDesc jf_cleanTupType;
AttrNumber *jf_cleanMap;
MemoryContext jf_junkContext;
+ TupleTableSlot *jf_resultSlot;
} JunkFilter;
/* ----------------