Commit 0d54d6ac authored by Tom Lane's avatar Tom Lane

Clean up handling of tuple descriptors so that result-tuple descriptors

allocated by plan nodes are not leaked at end of query.  This doesn't
really matter for normal queries, but it sure does for queries invoked
repetitively inside SQL functions.  Clean up some other grotty code
associated with tupdescs, and fix a few other memory leaks exposed by
tests with simple SQL functions.
parent 51cd0377
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.68 2001/01/12 00:12:58 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.69 2001/01/29 00:39:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -154,7 +154,7 @@ gistbuild(PG_FUNCTION_ARGS) ...@@ -154,7 +154,7 @@ gistbuild(PG_FUNCTION_ARGS)
{ {
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, htupdesc); ExecSetSlotDescriptor(slot, htupdesc, false);
} }
else else
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.47 2001/01/24 19:42:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.48 2001/01/29 00:39:13 tgl Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
...@@ -92,7 +92,7 @@ hashbuild(PG_FUNCTION_ARGS) ...@@ -92,7 +92,7 @@ hashbuild(PG_FUNCTION_ARGS)
{ {
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, htupdesc); ExecSetSlotDescriptor(slot, htupdesc, false);
} }
else else
{ {
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.76 2001/01/26 01:24:31 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.77 2001/01/29 00:39:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -128,7 +128,7 @@ btbuild(PG_FUNCTION_ARGS) ...@@ -128,7 +128,7 @@ btbuild(PG_FUNCTION_ARGS)
{ {
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, htupdesc); ExecSetSlotDescriptor(slot, htupdesc, false);
/* /*
* we never want to use sort/build if we are extending an existing * we never want to use sort/build if we are extending an existing
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.58 2001/01/24 19:42:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.59 2001/01/29 00:39:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -125,7 +125,7 @@ rtbuild(PG_FUNCTION_ARGS) ...@@ -125,7 +125,7 @@ rtbuild(PG_FUNCTION_ARGS)
{ {
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, htupdesc); ExecSetSlotDescriptor(slot, htupdesc, false);
} }
else else
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.139 2001/01/24 19:42:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.140 2001/01/29 00:39:16 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -1817,7 +1817,7 @@ DefaultBuild(Relation heapRelation, ...@@ -1817,7 +1817,7 @@ DefaultBuild(Relation heapRelation,
{ {
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, heapDescriptor); ExecSetSlotDescriptor(slot, heapDescriptor, false);
} }
else else
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.119 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.120 2001/01/29 00:39:20 tgl Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
...@@ -1102,7 +1102,7 @@ AlterTableAddConstraint(char *relationName, ...@@ -1102,7 +1102,7 @@ AlterTableAddConstraint(char *relationName,
bool successful = true; bool successful = true;
HeapScanDesc scan; HeapScanDesc scan;
ExprContext *econtext; ExprContext *econtext;
TupleTableSlot *slot = makeNode(TupleTableSlot); TupleTableSlot *slot;
HeapTuple tuple; HeapTuple tuple;
RangeTblEntry *rte; RangeTblEntry *rte;
List *qual; List *qual;
...@@ -1169,28 +1169,28 @@ AlterTableAddConstraint(char *relationName, ...@@ -1169,28 +1169,28 @@ AlterTableAddConstraint(char *relationName,
qual = makeList1(expr); qual = makeList1(expr);
/* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
/* Make an expression context for ExecQual */
econtext = MakeExprContext(slot, CurrentMemoryContext);
/* /*
* Scan through the rows now, making the necessary things * Scan through the rows now, checking the expression
* for ExecQual, and then call it to evaluate the * at each row.
* expression.
*/ */
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0))) while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{ {
slot->val = tuple; ExecStoreTuple(tuple, slot, InvalidBuffer, false);
slot->ttc_shouldFree = false;
slot->ttc_descIsNew = true;
slot->ttc_tupleDescriptor = rel->rd_att;
slot->ttc_buffer = InvalidBuffer;
econtext = MakeExprContext(slot, CurrentMemoryContext);
if (!ExecQual(qual, econtext, true)) if (!ExecQual(qual, econtext, true))
{ {
successful=false; successful=false;
break; break;
} }
FreeExprContext(econtext); ResetExprContext(econtext);
} }
FreeExprContext(econtext);
pfree(slot); pfree(slot);
heap_endscan(scan); heap_endscan(scan);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.132 2001/01/24 19:42:52 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.133 2001/01/29 00:39:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -638,7 +638,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, ...@@ -638,7 +638,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp,
/* Set up a dummy tuple table too */ /* Set up a dummy tuple table too */
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, tupDesc); ExecSetSlotDescriptor(slot, tupDesc, false);
if (!binary) if (!binary)
{ {
......
...@@ -8,12 +8,10 @@ ...@@ -8,12 +8,10 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.24 2001/01/24 19:42:53 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execJunk.c,v 1.25 2001/01/29 00:39:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h" #include "access/heapam.h"
...@@ -37,7 +35,7 @@ ...@@ -37,7 +35,7 @@
* called 'resjunk'. If the value of this attribute is true then the * called 'resjunk'. If the value of this attribute is true then the
* corresponding attribute is a "junk" attribute. * corresponding attribute is a "junk" attribute.
* *
* When we initialize a plan we call 'ExecInitJunkFilter' to create * When we initialize a plan we call 'ExecInitJunkFilter' to create
* and store the appropriate information in the 'es_junkFilter' attribute of * and store the appropriate information in the 'es_junkFilter' attribute of
* EState. * EState.
* *
...@@ -63,6 +61,8 @@ ...@@ -63,6 +61,8 @@
JunkFilter * JunkFilter *
ExecInitJunkFilter(List *targetList, TupleDesc tupType) ExecInitJunkFilter(List *targetList, TupleDesc tupType)
{ {
MemoryContext oldContext;
MemoryContext junkContext;
JunkFilter *junkfilter; JunkFilter *junkfilter;
List *cleanTargetList; List *cleanTargetList;
int len, int len,
...@@ -75,9 +75,21 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) ...@@ -75,9 +75,21 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
bool resjunk; bool resjunk;
AttrNumber cleanResno; AttrNumber cleanResno;
AttrNumber *cleanMap; AttrNumber *cleanMap;
Size size;
Node *expr; Node *expr;
/*
* Make a memory context that will hold the JunkFilter as well as all
* the subsidiary structures we are about to create. We use smaller-
* than-default sizing parameters since we don't expect a very large
* volume of stuff here.
*/
junkContext = AllocSetContextCreate(CurrentMemoryContext,
"JunkFilterContext",
1024,
1024,
ALLOCSET_DEFAULT_MAXSIZE);
oldContext = MemoryContextSwitchTo(junkContext);
/* --------------------- /* ---------------------
* First find the "clean" target list, i.e. all the entries * First find the "clean" target list, i.e. all the entries
* in the original target list which have a false 'resjunk' * in the original target list which have a false 'resjunk'
...@@ -166,7 +178,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) ...@@ -166,7 +178,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
cleanLength = ExecTargetListLength(cleanTargetList); cleanLength = ExecTargetListLength(cleanTargetList);
/* --------------------- /* ---------------------
* Now calculate the "map" between the original tuples attributes * Now calculate the "map" between the original tuple's attributes
* and the "clean" tuple's attributes. * and the "clean" tuple's attributes.
* *
* The "map" is an array of "cleanLength" attribute numbers, i.e. * The "map" is an array of "cleanLength" attribute numbers, i.e.
...@@ -177,8 +189,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) ...@@ -177,8 +189,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
*/ */
if (cleanLength > 0) if (cleanLength > 0)
{ {
size = cleanLength * sizeof(AttrNumber); cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber));
cleanMap = (AttrNumber *) palloc(size);
cleanResno = 1; cleanResno = 1;
foreach(t, targetList) foreach(t, targetList)
{ {
...@@ -226,7 +237,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) ...@@ -226,7 +237,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
cleanMap = NULL; cleanMap = NULL;
/* --------------------- /* ---------------------
* Finally create and initialize the JunkFilter. * Finally create and initialize the JunkFilter struct.
* --------------------- * ---------------------
*/ */
junkfilter = makeNode(JunkFilter); junkfilter = makeNode(JunkFilter);
...@@ -238,20 +249,36 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) ...@@ -238,20 +249,36 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType)
junkfilter->jf_cleanLength = cleanLength; junkfilter->jf_cleanLength = cleanLength;
junkfilter->jf_cleanTupType = cleanTupType; junkfilter->jf_cleanTupType = cleanTupType;
junkfilter->jf_cleanMap = cleanMap; junkfilter->jf_cleanMap = cleanMap;
junkfilter->jf_junkContext = junkContext;
MemoryContextSwitchTo(oldContext);
return junkfilter; return junkfilter;
}
/*-------------------------------------------------------------------------
* ExecFreeJunkFilter
*
* Release the data structures created by ExecInitJunkFilter.
*-------------------------------------------------------------------------
*/
void
ExecFreeJunkFilter(JunkFilter *junkfilter)
{
/*
* Since the junkfilter is inside its own context, we just have to
* delete the context and we're set.
*/
MemoryContextDelete(junkfilter->jf_junkContext);
} }
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* ExecGetJunkAttribute * ExecGetJunkAttribute
* *
* Given a tuple (slot), the junk filter and a junk attribute's name, * Given a tuple (slot), the junk filter and a junk attribute's name,
* extract & return the value of this attribute. * extract & return the value and isNull flag of this attribute.
* *
* It returns false iff no junk attribute with such name was found. * It returns false iff no junk attribute with such name was found.
*
* NOTE: isNull might be NULL !
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
bool bool
...@@ -304,7 +331,7 @@ ExecGetJunkAttribute(JunkFilter *junkfilter, ...@@ -304,7 +331,7 @@ ExecGetJunkAttribute(JunkFilter *junkfilter,
* --------------------- * ---------------------
*/ */
tuple = slot->val; tuple = slot->val;
tupType = (TupleDesc) junkfilter->jf_tupType; tupType = junkfilter->jf_tupType;
*value = heap_getattr(tuple, resno, tupType, isNull); *value = heap_getattr(tuple, resno, tupType, isNull);
...@@ -328,7 +355,6 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) ...@@ -328,7 +355,6 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
int cleanLength; int cleanLength;
bool isNull; bool isNull;
int i; int i;
Size size;
Datum *values; Datum *values;
char *nulls; char *nulls;
Datum values_array[64]; Datum values_array[64];
...@@ -340,8 +366,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) ...@@ -340,8 +366,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
*/ */
tuple = slot->val; tuple = slot->val;
tupType = (TupleDesc) junkfilter->jf_tupType; tupType = junkfilter->jf_tupType;
cleanTupType = (TupleDesc) junkfilter->jf_cleanTupType; cleanTupType = junkfilter->jf_cleanTupType;
cleanLength = junkfilter->jf_cleanLength; cleanLength = junkfilter->jf_cleanLength;
cleanMap = junkfilter->jf_cleanMap; cleanMap = junkfilter->jf_cleanMap;
...@@ -363,11 +389,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) ...@@ -363,11 +389,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
*/ */
if (cleanLength > 64) if (cleanLength > 64)
{ {
size = cleanLength * sizeof(Datum); values = (Datum *) palloc(cleanLength * sizeof(Datum));
values = (Datum *) palloc(size); nulls = (char *) palloc(cleanLength * sizeof(char));
size = cleanLength * sizeof(char);
nulls = (char *) palloc(size);
} }
else else
{ {
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.137 2001/01/27 05:16:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.138 2001/01/29 00:39:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -252,12 +252,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, long count) ...@@ -252,12 +252,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, long count)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecutorEnd * ExecutorEnd
* *
* This routine must be called at the end of any execution of any * This routine must be called at the end of execution of any
* query plan * query plan
*
* returns (AttrInfo*) which describes the attributes of the tuples to
* be returned by the query.
*
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
...@@ -268,23 +264,15 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate) ...@@ -268,23 +264,15 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
EndPlan(queryDesc->plantree, estate); EndPlan(queryDesc->plantree, estate);
/* XXX - clean up some more from ExecutorStart() - er1p */ if (estate->es_snapshot != NULL)
if (NULL == estate->es_snapshot)
{
/* nothing to free */
}
else
{ {
if (estate->es_snapshot->xcnt > 0) if (estate->es_snapshot->xcnt > 0)
pfree(estate->es_snapshot->xip); pfree(estate->es_snapshot->xip);
pfree(estate->es_snapshot); pfree(estate->es_snapshot);
estate->es_snapshot = NULL;
} }
if (NULL == estate->es_param_exec_vals) if (estate->es_param_exec_vals != NULL)
{
/* nothing to free */
}
else
{ {
pfree(estate->es_param_exec_vals); pfree(estate->es_param_exec_vals);
estate->es_param_exec_vals = NULL; estate->es_param_exec_vals = NULL;
...@@ -870,7 +858,7 @@ EndPlan(Plan *plan, EState *estate) ...@@ -870,7 +858,7 @@ EndPlan(Plan *plan, EState *estate)
/* /*
* close the result relation(s) if any, but hold locks * close the result relation(s) if any, but hold locks
* until xact commit. * until xact commit. Also clean up junkfilters if present.
*/ */
resultRelInfo = estate->es_result_relations; resultRelInfo = estate->es_result_relations;
for (i = estate->es_num_result_relations; i > 0; i--) for (i = estate->es_num_result_relations; i > 0; i--)
...@@ -878,6 +866,9 @@ EndPlan(Plan *plan, EState *estate) ...@@ -878,6 +866,9 @@ EndPlan(Plan *plan, EState *estate)
/* Close indices and then the relation itself */ /* Close indices and then the relation itself */
ExecCloseIndices(resultRelInfo); ExecCloseIndices(resultRelInfo);
heap_close(resultRelInfo->ri_RelationDesc, NoLock); heap_close(resultRelInfo->ri_RelationDesc, NoLock);
/* Delete the junkfilter if any */
if (resultRelInfo->ri_junkFilter != NULL)
ExecFreeJunkFilter(resultRelInfo->ri_junkFilter);
resultRelInfo++; resultRelInfo++;
} }
...@@ -887,6 +878,16 @@ EndPlan(Plan *plan, EState *estate) ...@@ -887,6 +878,16 @@ EndPlan(Plan *plan, EState *estate)
if (estate->es_into_relation_descriptor != NULL) if (estate->es_into_relation_descriptor != NULL)
heap_close(estate->es_into_relation_descriptor, NoLock); heap_close(estate->es_into_relation_descriptor, NoLock);
/*
* There might be a junkfilter without a result relation.
*/
if (estate->es_num_result_relations == 0 &&
estate->es_junkFilter != NULL)
{
ExecFreeJunkFilter(estate->es_junkFilter);
estate->es_junkFilter = NULL;
}
/* /*
* close any relations selected FOR UPDATE, again keeping locks * close any relations selected FOR UPDATE, again keeping locks
*/ */
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.24 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.25 2001/01/29 00:39:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
* ExecInitNode - initialize a plan node and its subplans * ExecInitNode - initialize a plan node and its subplans
* ExecProcNode - get a tuple by executing the plan node * ExecProcNode - get a tuple by executing the plan node
* ExecEndNode - shut down a plan node and its subplans * ExecEndNode - shut down a plan node and its subplans
* ExecCountSlotsNode - count tuple slots needed by plan tree
* ExecGetTupType - get result tuple type of a plan node
* *
* NOTES * NOTES
* This used to be three files. It is now all combined into * This used to be three files. It is now all combined into
...@@ -218,7 +220,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) ...@@ -218,7 +220,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
break; break;
default: default:
elog(ERROR, "ExecInitNode: node %d unsupported", nodeTag(node)); elog(ERROR, "ExecInitNode: node type %d unsupported",
(int) nodeTag(node));
result = FALSE; result = FALSE;
} }
...@@ -347,7 +350,8 @@ ExecProcNode(Plan *node, Plan *parent) ...@@ -347,7 +350,8 @@ ExecProcNode(Plan *node, Plan *parent)
break; break;
default: default:
elog(ERROR, "ExecProcNode: node %d unsupported", nodeTag(node)); elog(ERROR, "ExecProcNode: node type %d unsupported",
(int) nodeTag(node));
result = NULL; result = NULL;
} }
...@@ -430,8 +434,8 @@ ExecCountSlotsNode(Plan *node) ...@@ -430,8 +434,8 @@ ExecCountSlotsNode(Plan *node)
return ExecCountSlotsAgg((Agg *) node); return ExecCountSlotsAgg((Agg *) node);
default: default:
elog(ERROR, "ExecCountSlotsNode: node not yet supported: %d", elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
nodeTag(node)); (int) nodeTag(node));
break; break;
} }
return 0; return 0;
...@@ -558,7 +562,178 @@ ExecEndNode(Plan *node, Plan *parent) ...@@ -558,7 +562,178 @@ ExecEndNode(Plan *node, Plan *parent)
break; break;
default: default:
elog(ERROR, "ExecEndNode: node %d unsupported", nodeTag(node)); elog(ERROR, "ExecEndNode: node type %d unsupported",
(int) nodeTag(node));
break; break;
} }
} }
/* ----------------------------------------------------------------
* ExecGetTupType
*
* this gives you the tuple descriptor for tuples returned
* by this node. I really wish I could ditch this routine,
* but since not all nodes store their type info in the same
* place, we have to do something special for each node type.
*
* ----------------------------------------------------------------
*/
TupleDesc
ExecGetTupType(Plan *node)
{
TupleTableSlot *slot;
if (node == NULL)
return NULL;
switch (nodeTag(node))
{
case T_Result:
{
ResultState *resstate = ((Result *) node)->resstate;
slot = resstate->cstate.cs_ResultTupleSlot;
}
break;
case T_SeqScan:
{
CommonScanState *scanstate = ((SeqScan *) node)->scanstate;
slot = scanstate->cstate.cs_ResultTupleSlot;
}
break;
case T_NestLoop:
{
NestLoopState *nlstate = ((NestLoop *) node)->nlstate;
slot = nlstate->jstate.cs_ResultTupleSlot;
}
break;
case T_Append:
{
AppendState *appendstate = ((Append *) node)->appendstate;
slot = appendstate->cstate.cs_ResultTupleSlot;
}
break;
case T_IndexScan:
{
CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
slot = scanstate->cstate.cs_ResultTupleSlot;
}
break;
case T_TidScan:
{
CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate;
slot = scanstate->cstate.cs_ResultTupleSlot;
}
break;
case T_SubqueryScan:
{
CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate;
slot = scanstate->cstate.cs_ResultTupleSlot;
}
break;
case T_Material:
{
MaterialState *matstate = ((Material *) node)->matstate;
slot = matstate->csstate.css_ScanTupleSlot;
}
break;
case T_Sort:
{
SortState *sortstate = ((Sort *) node)->sortstate;
slot = sortstate->csstate.css_ScanTupleSlot;
}
break;
case T_Agg:
{
AggState *aggstate = ((Agg *) node)->aggstate;
slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
}
break;
case T_Group:
{
GroupState *grpstate = ((Group *) node)->grpstate;
slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
}
break;
case T_Hash:
{
HashState *hashstate = ((Hash *) node)->hashstate;
slot = hashstate->cstate.cs_ResultTupleSlot;
}
break;
case T_Unique:
{
UniqueState *uniquestate = ((Unique *) node)->uniquestate;
slot = uniquestate->cstate.cs_ResultTupleSlot;
}
break;
case T_SetOp:
{
SetOpState *setopstate = ((SetOp *) node)->setopstate;
slot = setopstate->cstate.cs_ResultTupleSlot;
}
break;
case T_Limit:
{
LimitState *limitstate = ((Limit *) node)->limitstate;
slot = limitstate->cstate.cs_ResultTupleSlot;
}
break;
case T_MergeJoin:
{
MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;
slot = mergestate->jstate.cs_ResultTupleSlot;
}
break;
case T_HashJoin:
{
HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;
slot = hashjoinstate->jstate.cs_ResultTupleSlot;
}
break;
default:
/* ----------------
* should never get here
* ----------------
*/
elog(ERROR, "ExecGetTupType: node type %d unsupported",
(int) nodeTag(node));
return NULL;
}
return slot->ttc_tupleDescriptor;
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.82 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.83 2001/01/29 00:39:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -328,25 +328,19 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull) ...@@ -328,25 +328,19 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
/* /*
* If the attribute number is invalid, then we are supposed to return * If the attribute number is invalid, then we are supposed to return
* the entire tuple, we give back a whole slot so that callers know * the entire tuple, we give back a whole slot so that callers know
* what the tuple looks like. * what the tuple looks like. XXX why copy? Couldn't we just give
* back the existing slot?
*/ */
if (attnum == InvalidAttrNumber) if (attnum == InvalidAttrNumber)
{ {
TupleTableSlot *tempSlot; TupleTableSlot *tempSlot = MakeTupleTableSlot();
TupleDesc td; TupleDesc td;
HeapTuple tup; HeapTuple tup;
tempSlot = makeNode(TupleTableSlot);
tempSlot->ttc_shouldFree = false;
tempSlot->ttc_descIsNew = true;
tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL;
tempSlot->ttc_buffer = InvalidBuffer;
tup = heap_copytuple(heapTuple); tup = heap_copytuple(heapTuple);
td = CreateTupleDescCopy(tuple_type); td = CreateTupleDescCopy(tuple_type);
ExecSetSlotDescriptor(tempSlot, td); ExecSetSlotDescriptor(tempSlot, td, true);
ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);
return PointerGetDatum(tempSlot); return PointerGetDatum(tempSlot);
} }
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.72 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.73 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,17 +16,6 @@ ...@@ -16,17 +16,6 @@
* INTERFACE ROUTINES * INTERFACE ROUTINES
* ExecAssignExprContext Common code for plan node init routines. * ExecAssignExprContext Common code for plan node init routines.
* *
* ExecGetTypeInfo | old execCStructs interface
* ExecMakeTypeInfo | code from the version 1
* ExecOrderTypeInfo | lisp system. These should
* ExecSetTypeInfo | go away or be updated soon.
* ExecFreeTypeInfo | -cim 11/1/89
* ExecTupleAttributes /
*
* QueryDescGetTypeInfo - moved here from main.c
* am not sure what uses it -cim 10/12/89
*
* ExecOpenIndices \ * ExecOpenIndices \
* ExecCloseIndices | referenced by InitPlan, EndPlan, * ExecCloseIndices | referenced by InitPlan, EndPlan,
* ExecInsertIndexTuples / ExecAppend, ExecReplace * ExecInsertIndexTuples / ExecAppend, ExecReplace
...@@ -261,12 +250,11 @@ MakePerTupleExprContext(EState *estate) ...@@ -261,12 +250,11 @@ MakePerTupleExprContext(EState *estate)
*/ */
void void
ExecAssignResultType(CommonState *commonstate, ExecAssignResultType(CommonState *commonstate,
TupleDesc tupDesc) TupleDesc tupDesc, bool shouldFree)
{ {
TupleTableSlot *slot; TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
slot = commonstate->cs_ResultTupleSlot; ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
slot->ttc_tupleDescriptor = tupDesc;
} }
/* ---------------- /* ----------------
...@@ -282,7 +270,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) ...@@ -282,7 +270,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
outerPlan = outerPlan(node); outerPlan = outerPlan(node);
tupDesc = ExecGetTupType(outerPlan); tupDesc = ExecGetTupType(outerPlan);
ExecAssignResultType(commonstate, tupDesc); ExecAssignResultType(commonstate, tupDesc, false);
} }
/* ---------------- /* ----------------
...@@ -292,12 +280,10 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) ...@@ -292,12 +280,10 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
void void
ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
{ {
List *targetList;
TupleDesc tupDesc; TupleDesc tupDesc;
targetList = node->targetlist; tupDesc = ExecTypeFromTL(node->targetlist);
tupDesc = ExecTypeFromTL(targetList); ExecAssignResultType(commonstate, tupDesc, true);
ExecAssignResultType(commonstate, tupDesc);
} }
/* ---------------- /* ----------------
...@@ -312,25 +298,6 @@ ExecGetResultType(CommonState *commonstate) ...@@ -312,25 +298,6 @@ ExecGetResultType(CommonState *commonstate)
return slot->ttc_tupleDescriptor; return slot->ttc_tupleDescriptor;
} }
/* ----------------
* ExecFreeResultType
* ----------------
*/
#ifdef NOT_USED
void
ExecFreeResultType(CommonState *commonstate)
{
TupleTableSlot *slot;
TupleDesc tupType;
slot = commonstate->cs_ResultTupleSlot;
tupType = slot->ttc_tupleDescriptor;
ExecFreeTypeInfo(tupType);
}
#endif
/* ---------------- /* ----------------
* ExecAssignProjectionInfo * ExecAssignProjectionInfo
forms the projection information from the node's targetlist forms the projection information from the node's targetlist
...@@ -413,29 +380,6 @@ ExecFreeExprContext(CommonState *commonstate) ...@@ -413,29 +380,6 @@ ExecFreeExprContext(CommonState *commonstate)
commonstate->cs_ExprContext = NULL; commonstate->cs_ExprContext = NULL;
} }
/* ----------------
* ExecFreeTypeInfo
* ----------------
*/
#ifdef NOT_USED
void
ExecFreeTypeInfo(CommonState *commonstate)
{
TupleDesc tupDesc;
tupDesc = commonstate->cs_ResultTupleSlot->ttc_tupleDescriptor;
if (tupDesc == NULL)
return;
/* ----------------
* clean up memory used.
* ----------------
*/
FreeTupleDesc(tupDesc);
commonstate->cs_ResultTupleSlot->ttc_tupleDescriptor = NULL;
}
#endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* the following scan type support functions are for * the following scan type support functions are for
* those nodes which are stubborn and return tuples in * those nodes which are stubborn and return tuples in
...@@ -458,37 +402,17 @@ ExecGetScanType(CommonScanState *csstate) ...@@ -458,37 +402,17 @@ ExecGetScanType(CommonScanState *csstate)
return slot->ttc_tupleDescriptor; return slot->ttc_tupleDescriptor;
} }
/* ----------------
* ExecFreeScanType
* ----------------
*/
#ifdef NOT_USED
void
ExecFreeScanType(CommonScanState *csstate)
{
TupleTableSlot *slot;
TupleDesc tupType;
slot = csstate->css_ScanTupleSlot;
tupType = slot->ttc_tupleDescriptor;
ExecFreeTypeInfo(tupType);
}
#endif
/* ---------------- /* ----------------
* ExecAssignScanType * ExecAssignScanType
* ---------------- * ----------------
*/ */
void void
ExecAssignScanType(CommonScanState *csstate, ExecAssignScanType(CommonScanState *csstate,
TupleDesc tupDesc) TupleDesc tupDesc, bool shouldFree)
{ {
TupleTableSlot *slot; TupleTableSlot *slot = csstate->css_ScanTupleSlot;
slot = (TupleTableSlot *) csstate->css_ScanTupleSlot; ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
slot->ttc_tupleDescriptor = tupDesc;
} }
/* ---------------- /* ----------------
...@@ -504,154 +428,10 @@ ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate) ...@@ -504,154 +428,10 @@ ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
outerPlan = outerPlan(node); outerPlan = outerPlan(node);
tupDesc = ExecGetTupType(outerPlan); tupDesc = ExecGetTupType(outerPlan);
ExecAssignScanType(csstate, tupDesc); ExecAssignScanType(csstate, tupDesc, false);
} }
/* ----------------------------------------------------------------
* ExecTypeFromTL support routines.
*
* these routines are used mainly from ExecTypeFromTL.
* -cim 6/12/90
*
* old comments
* Routines dealing with the structure 'attribute' which conatains
* the type information about attributes in a tuple:
*
* ExecMakeTypeInfo(noType)
* returns pointer to array of 'noType' structure 'attribute'.
* ExecSetTypeInfo(index, typeInfo, attNum, attLen)
* sets the element indexed by 'index' in typeInfo with
* the values: attNum, attLen.
* ExecFreeTypeInfo(typeInfo)
* frees the structure 'typeInfo'.
* ----------------------------------------------------------------
*/
/* ----------------
* ExecSetTypeInfo
*
* This initializes fields of a single attribute in a
* tuple descriptor from the specified parameters.
*
* XXX this duplicates much of the functionality of TupleDescInitEntry.
* the routines should be moved to the same place and be rewritten
* to share common code.
* ----------------
*/
#ifdef NOT_USED
void
ExecSetTypeInfo(int index,
TupleDesc typeInfo,
Oid typeID,
int attNum,
int attLen,
char *attName,
bool attbyVal,
char attalign)
{
Form_pg_attribute att;
/* ----------------
* get attribute pointer and preform a sanity check..
* ----------------
*/
att = typeInfo[index];
if (att == NULL)
elog(ERROR, "ExecSetTypeInfo: trying to assign through NULL");
/* ----------------
* assign values to the tuple descriptor, being careful not
* to copy a null attName..
*
* XXX it is unknown exactly what information is needed to
* initialize the attribute struct correctly so for now
* we use 0. this should be fixed -- otherwise we run the
* risk of using garbage data. -cim 5/5/91
* ----------------
*/
att->attrelid = 0; /* dummy value */
if (attName != (char *) NULL)
StrNCpy(NameStr(att->attname), attName, NAMEDATALEN);
else
MemSet(NameStr(att->attname), 0, NAMEDATALEN);
att->atttypid = typeID;
att->attdefrel = 0; /* dummy value */
att->attdispersion = 0; /* dummy value */
att->atttyparg = 0; /* dummy value */
att->attlen = attLen;
att->attnum = attNum;
att->attbound = 0; /* dummy value */
att->attbyval = attbyVal;
att->attcanindex = 0; /* dummy value */
att->attproc = 0; /* dummy value */
att->attnelems = 0; /* dummy value */
att->attcacheoff = -1;
att->atttypmod = -1;
att->attisset = false;
att->attstorage = 'p';
att->attalign = attalign;
}
/* ----------------
* ExecFreeTypeInfo frees the array of attributes
* created by ExecMakeTypeInfo and returned by ExecTypeFromTL
* ----------------
*/
void
ExecFreeTypeInfo(TupleDesc typeInfo)
{
/* ----------------
* do nothing if asked to free a null pointer
* ----------------
*/
if (typeInfo == NULL)
return;
/* ----------------
* the entire array of typeinfo pointers created by
* ExecMakeTypeInfo was allocated with a single palloc()
* so we can deallocate the whole array with a single pfree().
* (we should not try and free all the elements in the array)
* -cim 6/12/90
* ----------------
*/
pfree(typeInfo);
}
/* ----------------------------------------------------------------
* QueryDescGetTypeInfo
*
*| I don't know how this is used, all I know is that it
*| appeared one day in main.c so I moved it here. -cim 11/1/89
* ----------------------------------------------------------------
*/
TupleDesc
QueryDescGetTypeInfo(QueryDesc *queryDesc)
{
Plan *plan;
TupleDesc tupleType;
List *targetList;
AttrInfo *attinfo = (AttrInfo *) palloc(sizeof(AttrInfo));
plan = queryDesc->plantree;
tupleType = (TupleDesc) ExecGetTupType(plan);
/*
targetList = plan->targetlist;
attinfo->numAttr = ExecTargetListLength(targetList);
attinfo->attrs = tupleType;
*/
attinfo->numAttr = tupleType->natts;
attinfo->attrs = tupleType->attrs;
return attinfo;
}
#endif
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInsertIndexTuples support * ExecInsertIndexTuples support
* ---------------------------------------------------------------- * ----------------------------------------------------------------
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.42 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.43 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "tcop/utility.h" #include "tcop/utility.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/syscache.h" #include "utils/syscache.h"
...@@ -73,7 +72,7 @@ typedef SQLFunctionCache *SQLFunctionCachePtr; ...@@ -73,7 +72,7 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
static execution_state *init_execution_state(char *src, static execution_state *init_execution_state(char *src,
Oid *argOidVect, int nargs); Oid *argOidVect, int nargs);
static void init_sql_fcache(FmgrInfo *finfo); static void init_sql_fcache(FmgrInfo *finfo);
static TupleDesc postquel_start(execution_state *es); static void postquel_start(execution_state *es);
static TupleTableSlot *postquel_getnext(execution_state *es); static TupleTableSlot *postquel_getnext(execution_state *es);
static void postquel_end(execution_state *es); static void postquel_end(execution_state *es);
static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo); static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
...@@ -82,24 +81,6 @@ static Datum postquel_execute(execution_state *es, ...@@ -82,24 +81,6 @@ static Datum postquel_execute(execution_state *es,
SQLFunctionCachePtr fcache); SQLFunctionCachePtr fcache);
static Datum
ProjectAttribute(HeapTuple tup,
AttrNumber attrno,
TupleDesc TD,
bool *isnullP)
{
Datum val;
val = heap_getattr(tup, attrno, TD, isnullP);
if (*isnullP)
return val;
return datumCopy(val,
TD->attrs[attrno - 1]->attbyval,
TD->attrs[attrno - 1]->attlen);
}
static execution_state * static execution_state *
init_execution_state(char *src, Oid *argOidVect, int nargs) init_execution_state(char *src, Oid *argOidVect, int nargs)
{ {
...@@ -240,18 +221,7 @@ init_sql_fcache(FmgrInfo *finfo) ...@@ -240,18 +221,7 @@ init_sql_fcache(FmgrInfo *finfo)
* allocated by the executor (i.e. slots and tuples) is freed. * allocated by the executor (i.e. slots and tuples) is freed.
*/ */
if (!finfo->fn_retset && !fcache->typbyval) if (!finfo->fn_retset && !fcache->typbyval)
{ fcache->funcSlot = MakeTupleTableSlot();
TupleTableSlot *slot;
slot = makeNode(TupleTableSlot);
slot->val = (HeapTuple) NULL;
slot->ttc_shouldFree = true;
slot->ttc_descIsNew = true;
slot->ttc_tupleDescriptor = (TupleDesc) NULL;
slot->ttc_buffer = InvalidBuffer;
fcache->funcSlot = slot;
}
else else
fcache->funcSlot = NULL; fcache->funcSlot = NULL;
...@@ -289,7 +259,7 @@ init_sql_fcache(FmgrInfo *finfo) ...@@ -289,7 +259,7 @@ init_sql_fcache(FmgrInfo *finfo)
} }
static TupleDesc static void
postquel_start(execution_state *es) postquel_start(execution_state *es)
{ {
...@@ -298,8 +268,8 @@ postquel_start(execution_state *es) ...@@ -298,8 +268,8 @@ postquel_start(execution_state *es)
* 30-8-1996 * 30-8-1996
*/ */
if (es->qd->operation == CMD_UTILITY) if (es->qd->operation == CMD_UTILITY)
return (TupleDesc) NULL; return;
return ExecutorStart(es->qd, es->estate); ExecutorStart(es->qd, es->estate);
} }
static TupleTableSlot * static TupleTableSlot *
...@@ -379,11 +349,11 @@ copy_function_result(SQLFunctionCachePtr fcache, ...@@ -379,11 +349,11 @@ copy_function_result(SQLFunctionCachePtr fcache,
* If first time through, we have to initialize the funcSlot's * If first time through, we have to initialize the funcSlot's
* tuple descriptor. * tuple descriptor.
*/ */
if (TupIsNull(funcSlot)) if (funcSlot->ttc_tupleDescriptor == NULL)
{ {
resultTd = resultSlot->ttc_tupleDescriptor; resultTd = CreateTupleDescCopy(resultSlot->ttc_tupleDescriptor);
funcSlot->ttc_tupleDescriptor = CreateTupleDescCopy(resultTd); ExecSetSlotDescriptor(funcSlot, resultTd, true);
funcSlot->ttc_descIsNew = true; ExecSetSlotDescriptorIsNew(funcSlot, true);
} }
newTuple = heap_copytuple(resultTuple); newTuple = heap_copytuple(resultTuple);
...@@ -460,10 +430,15 @@ postquel_execute(execution_state *es, ...@@ -460,10 +430,15 @@ postquel_execute(execution_state *es,
} }
else else
{ {
value = ProjectAttribute(resSlot->val, value = heap_getattr(resSlot->val,
1, 1,
resSlot->ttc_tupleDescriptor, resSlot->ttc_tupleDescriptor,
&fcinfo->isnull); &(fcinfo->isnull));
/*
* Note: if result type is pass-by-reference then we are
* returning a pointer into the tuple copied by
* copy_function_result. This is OK.
*/
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.35 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.36 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -400,7 +400,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ...@@ -400,7 +400,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate); ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate);
ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot, ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
ExecGetTupType(outerNode)); ExecGetTupType(outerNode),
false);
/* ---------------- /* ----------------
* initialize hash-specific info * initialize hash-specific info
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.56 2001/01/24 19:42:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.57 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -121,13 +121,11 @@ IndexNext(IndexScan *node) ...@@ -121,13 +121,11 @@ IndexNext(IndexScan *node)
if (estate->es_evTupleNull[node->scan.scanrelid - 1]) if (estate->es_evTupleNull[node->scan.scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
/* probably ought to use ExecStoreTuple here... */ ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; slot, InvalidBuffer, false);
slot->ttc_shouldFree = false;
econtext->ecxt_scantuple = slot;
/* Does the tuple meet any of the OR'd indxqual conditions? */ /* Does the tuple meet any of the OR'd indxqual conditions? */
econtext->ecxt_scantuple = slot;
ResetExprContext(econtext); ResetExprContext(econtext);
...@@ -1043,7 +1041,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -1043,7 +1041,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
* get the scan type from the relation descriptor. * get the scan type from the relation descriptor.
* ---------------- * ----------------
*/ */
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
/* ---------------- /* ----------------
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.41 2001/01/24 19:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.42 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1505,7 +1505,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1505,7 +1505,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate); mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot, ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
ExecGetTupType(innerPlan((Plan *) node))); ExecGetTupType(innerPlan((Plan *) node)),
false);
switch (node->join.jointype) switch (node->join.jointype)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.26 2001/01/24 19:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.27 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -77,9 +77,8 @@ SeqNext(SeqScan *node) ...@@ -77,9 +77,8 @@ SeqNext(SeqScan *node)
if (estate->es_evTupleNull[node->scanrelid - 1]) if (estate->es_evTupleNull[node->scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
/* probably ought to use ExecStoreTuple here... */ ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1],
slot->val = estate->es_evTuple[node->scanrelid - 1]; slot, InvalidBuffer, false);
slot->ttc_shouldFree = false;
/* /*
* Note that unlike IndexScan, SeqScan never use keys in * Note that unlike IndexScan, SeqScan never use keys in
...@@ -181,7 +180,7 @@ InitScanRelation(SeqScan *node, EState *estate, ...@@ -181,7 +180,7 @@ InitScanRelation(SeqScan *node, EState *estate,
scanstate->css_currentRelation = currentRelation; scanstate->css_currentRelation = currentRelation;
scanstate->css_currentScanDesc = currentScanDesc; scanstate->css_currentScanDesc = currentScanDesc;
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
return reloid; return reloid;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.30 2001/01/24 19:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.31 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -172,7 +172,6 @@ ExecSort(Sort *node) ...@@ -172,7 +172,6 @@ ExecSort(Sort *node)
break; break;
tuplesort_puttuple(tuplesortstate, (void *) slot->val); tuplesort_puttuple(tuplesortstate, (void *) slot->val);
ExecClearTuple(slot);
} }
/* ---------------- /* ----------------
...@@ -188,11 +187,10 @@ ExecSort(Sort *node) ...@@ -188,11 +187,10 @@ ExecSort(Sort *node)
estate->es_direction = dir; estate->es_direction = dir;
/* ---------------- /* ----------------
* make sure the tuple descriptor is up to date * make sure the tuple descriptor is up to date (is this needed?)
* ---------------- * ----------------
*/ */
slot = (TupleTableSlot *) sortstate->csstate.cstate.cs_ResultTupleSlot; ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false);
slot->ttc_tupleDescriptor = tupDesc;
/* ---------------- /* ----------------
* finally set the sorted flag to true * finally set the sorted flag to true
...@@ -201,8 +199,6 @@ ExecSort(Sort *node) ...@@ -201,8 +199,6 @@ ExecSort(Sort *node)
sortstate->sort_Done = true; sortstate->sort_Done = true;
SO1_printf(stderr, "ExecSort: sorting done.\n"); SO1_printf(stderr, "ExecSort: sorting done.\n");
} }
else
slot = (TupleTableSlot *) sortstate->csstate.cstate.cs_ResultTupleSlot;
SO1_printf("ExecSort: %s\n", SO1_printf("ExecSort: %s\n",
"retrieving tuple from tuplesort"); "retrieving tuple from tuplesort");
...@@ -216,6 +212,7 @@ ExecSort(Sort *node) ...@@ -216,6 +212,7 @@ ExecSort(Sort *node)
ScanDirectionIsForward(dir), ScanDirectionIsForward(dir),
&should_free); &should_free);
slot = sortstate->csstate.cstate.cs_ResultTupleSlot;
return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
} }
...@@ -347,6 +344,12 @@ ExecEndSort(Sort *node) ...@@ -347,6 +344,12 @@ ExecEndSort(Sort *node)
tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
sortstate->tuplesortstate = NULL; sortstate->tuplesortstate = NULL;
if (sortstate->sort_Keys != NULL)
pfree(sortstate->sort_Keys);
pfree(sortstate);
node->sortstate = NULL;
SO1_printf("ExecEndSort: %s\n", SO1_printf("ExecEndSort: %s\n",
"sort node shutdown"); "sort node shutdown");
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.3 2001/01/24 19:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.4 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -77,9 +77,8 @@ SubqueryNext(SubqueryScan *node) ...@@ -77,9 +77,8 @@ SubqueryNext(SubqueryScan *node)
if (estate->es_evTupleNull[node->scan.scanrelid - 1]) if (estate->es_evTupleNull[node->scan.scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
/* probably ought to use ExecStoreTuple here... */ ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; slot, InvalidBuffer, false);
slot->ttc_shouldFree = false;
/* Flag for the next call that no more tuples */ /* Flag for the next call that no more tuples */
estate->es_evTupleNull[node->scan.scanrelid - 1] = true; estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.13 2001/01/24 19:42:55 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.14 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -110,9 +110,8 @@ TidNext(TidScan *node) ...@@ -110,9 +110,8 @@ TidNext(TidScan *node)
if (estate->es_evTupleNull[node->scan.scanrelid - 1]) if (estate->es_evTupleNull[node->scan.scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
/* probably ought to use ExecStoreTuple here... */ ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; slot, InvalidBuffer, false);
slot->ttc_shouldFree = false;
/* Flag for the next call that no more tuples */ /* Flag for the next call that no more tuples */
estate->es_evTupleNull[node->scan.scanrelid - 1] = true; estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
...@@ -487,7 +486,7 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) ...@@ -487,7 +486,7 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
* get the scan type from the relation descriptor. * get the scan type from the relation descriptor.
* ---------------- * ----------------
*/ */
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
/* /*
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.12 2001/01/24 19:43:18 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.13 2001/01/29 00:39:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -546,6 +546,7 @@ tuplesort_end(Tuplesortstate *state) ...@@ -546,6 +546,7 @@ tuplesort_end(Tuplesortstate *state)
} }
if (state->memtupindex) if (state->memtupindex)
pfree(state->memtupindex); pfree(state->memtupindex);
pfree(state);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: executor.h,v 1.55 2001/01/24 19:43:23 momjian Exp $ * $Id: executor.h,v 1.56 2001/01/29 00:39:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,6 +44,7 @@ extern void ExecRestrPos(Plan *node); ...@@ -44,6 +44,7 @@ extern void ExecRestrPos(Plan *node);
* prototypes from functions in execJunk.c * prototypes from functions in execJunk.c
*/ */
extern JunkFilter *ExecInitJunkFilter(List *targetList, TupleDesc tupType); extern JunkFilter *ExecInitJunkFilter(List *targetList, TupleDesc tupType);
extern void ExecFreeJunkFilter(JunkFilter *junkfilter);
extern bool ExecGetJunkAttribute(JunkFilter *junkfilter, TupleTableSlot *slot, extern bool ExecGetJunkAttribute(JunkFilter *junkfilter, TupleTableSlot *slot,
char *attrName, Datum *value, bool *isNull); char *attrName, Datum *value, bool *isNull);
extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot); extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
...@@ -68,6 +69,7 @@ extern bool ExecInitNode(Plan *node, EState *estate, Plan *parent); ...@@ -68,6 +69,7 @@ extern bool ExecInitNode(Plan *node, EState *estate, Plan *parent);
extern TupleTableSlot *ExecProcNode(Plan *node, Plan *parent); extern TupleTableSlot *ExecProcNode(Plan *node, Plan *parent);
extern int ExecCountSlotsNode(Plan *node); extern int ExecCountSlotsNode(Plan *node);
extern void ExecEndNode(Plan *node, Plan *parent); extern void ExecEndNode(Plan *node, Plan *parent);
extern TupleDesc ExecGetTupType(Plan *node);
/* /*
* prototypes from functions in execQual.c * prototypes from functions in execQual.c
...@@ -106,13 +108,14 @@ extern TupleTableSlot *ExecScan(Scan *node, ExecScanAccessMtd accessMtd); ...@@ -106,13 +108,14 @@ extern TupleTableSlot *ExecScan(Scan *node, ExecScanAccessMtd accessMtd);
extern TupleTable ExecCreateTupleTable(int initialSize); extern TupleTable ExecCreateTupleTable(int initialSize);
extern void ExecDropTupleTable(TupleTable table, bool shouldFree); extern void ExecDropTupleTable(TupleTable table, bool shouldFree);
extern TupleTableSlot *ExecAllocTableSlot(TupleTable table); extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
extern TupleTableSlot *MakeTupleTableSlot(void);
extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple, extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
TupleTableSlot *slot, TupleTableSlot *slot,
Buffer buffer, Buffer buffer,
bool shouldFree); bool shouldFree);
extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
extern TupleDesc ExecSetSlotDescriptor(TupleTableSlot *slot, extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
TupleDesc tupdesc); TupleDesc tupdesc, bool shouldFree);
extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew); extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew);
extern void ExecInitResultTupleSlot(EState *estate, CommonState *commonstate); extern void ExecInitResultTupleSlot(EState *estate, CommonState *commonstate);
extern void ExecInitScanTupleSlot(EState *estate, extern void ExecInitScanTupleSlot(EState *estate,
...@@ -120,8 +123,6 @@ extern void ExecInitScanTupleSlot(EState *estate, ...@@ -120,8 +123,6 @@ extern void ExecInitScanTupleSlot(EState *estate,
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType); TupleDesc tupType);
extern TupleDesc ExecGetTupType(Plan *node);
extern TupleDesc ExecTypeFromTL(List *targetList); extern TupleDesc ExecTypeFromTL(List *targetList);
extern void SetChangedParamList(Plan *node, List *newchg); extern void SetChangedParamList(Plan *node, List *newchg);
...@@ -131,7 +132,7 @@ extern void SetChangedParamList(Plan *node, List *newchg); ...@@ -131,7 +132,7 @@ extern void SetChangedParamList(Plan *node, List *newchg);
extern void ResetTupleCount(void); extern void ResetTupleCount(void);
extern void ExecAssignExprContext(EState *estate, CommonState *commonstate); extern void ExecAssignExprContext(EState *estate, CommonState *commonstate);
extern void ExecAssignResultType(CommonState *commonstate, extern void ExecAssignResultType(CommonState *commonstate,
TupleDesc tupDesc); TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignResultTypeFromOuterPlan(Plan *node, extern void ExecAssignResultTypeFromOuterPlan(Plan *node,
CommonState *commonstate); CommonState *commonstate);
extern void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate); extern void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate);
...@@ -141,7 +142,7 @@ extern void ExecFreeProjectionInfo(CommonState *commonstate); ...@@ -141,7 +142,7 @@ extern void ExecFreeProjectionInfo(CommonState *commonstate);
extern void ExecFreeExprContext(CommonState *commonstate); extern void ExecFreeExprContext(CommonState *commonstate);
extern TupleDesc ExecGetScanType(CommonScanState *csstate); extern TupleDesc ExecGetScanType(CommonScanState *csstate);
extern void ExecAssignScanType(CommonScanState *csstate, extern void ExecAssignScanType(CommonScanState *csstate,
TupleDesc tupDesc); TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignScanTypeFromOuterPlan(Plan *node, extern void ExecAssignScanTypeFromOuterPlan(Plan *node,
CommonScanState *csstate); CommonScanState *csstate);
extern Form_pg_attribute ExecGetTypeInfo(Relation relDesc); extern Form_pg_attribute ExecGetTypeInfo(Relation relDesc);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: tuptable.h,v 1.17 2001/01/24 19:43:23 momjian Exp $ * $Id: tuptable.h,v 1.18 2001/01/29 00:39:20 tgl Exp $
* *
* NOTES * NOTES
* The tuple table interface is getting pretty ugly. * The tuple table interface is getting pretty ugly.
...@@ -22,27 +22,36 @@ ...@@ -22,27 +22,36 @@
/* ---------------- /* ----------------
* The executor tuple table is managed and manipulated by special * The executor tuple table is managed and manipulated by special
* code in executor/execTuples.c and tupTable.h * code in executor/execTuples.c.
* *
* TupleTableSlot information * TupleTableSlot information
* *
* shouldFree boolean - should we call pfree() on tuple * val current tuple, or NULL if no tuple
* shouldFree boolean - should we pfree() tuple
* descIsNew boolean - true when tupleDescriptor changes * descIsNew boolean - true when tupleDescriptor changes
* tupleDescriptor type information kept regarding the tuple data * tupleDescriptor type information for the tuple data
* shouldFreeDesc boolean - should we free tupleDescriptor
* buffer the buffer for tuples pointing to disk pages * buffer the buffer for tuples pointing to disk pages
* *
* The executor stores pointers to tuples in a ``tuple table'' * The executor stores pointers to tuples in a ``tuple table''
* which is composed of TupleTableSlot's. Some of the tuples * which is composed of TupleTableSlots. Sometimes the tuples
* are pointers to buffer pages and others are pointers to * are pointers to buffer pages, while others are pointers to
* palloc'ed memory and the shouldFree variable tells us when * palloc'ed memory; the shouldFree variable tells us when
* we may call pfree() on a tuple. -cim 9/23/90 * we may call pfree() on a tuple. -cim 9/23/90
* *
* If buffer is not InvalidBuffer, then the slot is holding a pin
* on the indicated buffer page; drop the pin when we release the
* slot's reference to that buffer.
*
* In the implementation of nested-dot queries such as * In the implementation of nested-dot queries such as
* "retrieve (EMP.hobbies.all)", a single scan may return tuples * "retrieve (EMP.hobbies.all)", a single scan may return tuples
* of many types, so now we return pointers to tuple descriptors * of many types, so now we return pointers to tuple descriptors
* along with tuples returned via the tuple table. -cim 1/18/90 * along with tuples returned via the tuple table. -cim 1/18/90
* *
* Tuple table macros are all excised from the system now. * shouldFreeDesc is similar to shouldFree: if it's true, then the
* tupleDescriptor is "owned" by the TupleTableSlot and should be
* freed when the slot's reference to the descriptor is dropped.
*
* See executor.h for decls of functions defined in execTuples.c * See executor.h for decls of functions defined in execTuples.c
* -jolly * -jolly
* *
...@@ -54,6 +63,7 @@ typedef struct TupleTableSlot ...@@ -54,6 +63,7 @@ typedef struct TupleTableSlot
HeapTuple val; HeapTuple val;
bool ttc_shouldFree; bool ttc_shouldFree;
bool ttc_descIsNew; bool ttc_descIsNew;
bool ttc_shouldFreeDesc;
TupleDesc ttc_tupleDescriptor; TupleDesc ttc_tupleDescriptor;
Buffer ttc_buffer; Buffer ttc_buffer;
} TupleTableSlot; } TupleTableSlot;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: execnodes.h,v 1.55 2001/01/24 19:43:25 momjian Exp $ * $Id: execnodes.h,v 1.56 2001/01/29 00:39:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -164,11 +164,19 @@ typedef struct ProjectionInfo ...@@ -164,11 +164,19 @@ typedef struct ProjectionInfo
* (including the junk attributes). * (including the junk attributes).
* cleanTargetList: the "clean" target list (junk attributes removed). * cleanTargetList: the "clean" target list (junk attributes removed).
* cleanLength: the length of 'cleanTargetList' * cleanLength: the length of 'cleanTargetList'
* cleanTupTyp: the tuple descriptor of the "clean" tuple (with * cleanTupType: the tuple descriptor of the "clean" tuple (with
* junk attributes removed). * junk attributes removed).
* cleanMap: A map with the correspondance between the non junk * cleanMap: A map with the correspondance between the non-junk
* attributes of the "original" tuple and the * attributes of the "original" tuple and the
* attributes of the "clean" tuple. * attributes 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...
* ---------------- * ----------------
*/ */
typedef struct JunkFilter typedef struct JunkFilter
...@@ -181,6 +189,7 @@ typedef struct JunkFilter ...@@ -181,6 +189,7 @@ typedef struct JunkFilter
int jf_cleanLength; int jf_cleanLength;
TupleDesc jf_cleanTupType; TupleDesc jf_cleanTupType;
AttrNumber *jf_cleanMap; AttrNumber *jf_cleanMap;
MemoryContext jf_junkContext;
} JunkFilter; } JunkFilter;
/* ---------------- /* ----------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment