summaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-05-27 20:48:51 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-05-27 20:48:51 +0000
commit9e7243063ccec18819b2935602898e76026682bd (patch)
treef3f18b74b94a48652d4e55bda1ddd2962f73b999 /src/backend/executor
parenta3855c57618b21589b164ea0f15821b4bb644aaa (diff)
downloadpostgresql-9e7243063ccec18819b2935602898e76026682bd.tar.gz
When using a junkfilter, the output tuple should NOT be stored back into
the same tuple slot that the raw tuple came from, because that slot has the wrong tuple descriptor. Store it into its own slot with the correct descriptor, instead. This repairs problems with SPI functions seeing inappropriate tuple descriptors --- for example, plpgsql code failing to cope with SELECT FOR UPDATE.
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execJunk.c15
-rw-r--r--src/backend/executor/execMain.c32
2 files changed, 35 insertions, 12 deletions
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index f716c68810..68dc74a3a8 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 f87b674b07..3ba9b9136f 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;
}
}