diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execJunk.c | 65 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 37 | ||||
-rw-r--r-- | src/backend/executor/execProcnode.c | 187 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 16 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 388 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 242 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 63 | ||||
-rw-r--r-- | src/backend/executor/nodeHashjoin.c | 5 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 12 | ||||
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 5 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 9 | ||||
-rw-r--r-- | src/backend/executor/nodeSort.c | 17 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 7 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 9 |
14 files changed, 358 insertions, 704 deletions
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index e9556900ca4..f23ba273462 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -8,12 +8,10 @@ * * * 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 "access/heapam.h" @@ -37,7 +35,7 @@ * called 'resjunk'. If the value of this attribute is true then the * 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 * EState. * @@ -63,6 +61,8 @@ JunkFilter * ExecInitJunkFilter(List *targetList, TupleDesc tupType) { + MemoryContext oldContext; + MemoryContext junkContext; JunkFilter *junkfilter; List *cleanTargetList; int len, @@ -75,9 +75,21 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) bool resjunk; AttrNumber cleanResno; AttrNumber *cleanMap; - Size size; 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 * in the original target list which have a false 'resjunk' @@ -166,7 +178,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) 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. * * The "map" is an array of "cleanLength" attribute numbers, i.e. @@ -177,8 +189,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) */ if (cleanLength > 0) { - size = cleanLength * sizeof(AttrNumber); - cleanMap = (AttrNumber *) palloc(size); + cleanMap = (AttrNumber *) palloc(cleanLength * sizeof(AttrNumber)); cleanResno = 1; foreach(t, targetList) { @@ -226,7 +237,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) cleanMap = NULL; /* --------------------- - * Finally create and initialize the JunkFilter. + * Finally create and initialize the JunkFilter struct. * --------------------- */ junkfilter = makeNode(JunkFilter); @@ -238,20 +249,36 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType) junkfilter->jf_cleanLength = cleanLength; junkfilter->jf_cleanTupType = cleanTupType; junkfilter->jf_cleanMap = cleanMap; + junkfilter->jf_junkContext = junkContext; + + MemoryContextSwitchTo(oldContext); 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 * * 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. - * - * NOTE: isNull might be NULL ! *------------------------------------------------------------------------- */ bool @@ -304,7 +331,7 @@ ExecGetJunkAttribute(JunkFilter *junkfilter, * --------------------- */ tuple = slot->val; - tupType = (TupleDesc) junkfilter->jf_tupType; + tupType = junkfilter->jf_tupType; *value = heap_getattr(tuple, resno, tupType, isNull); @@ -328,7 +355,6 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) int cleanLength; bool isNull; int i; - Size size; Datum *values; char *nulls; Datum values_array[64]; @@ -340,8 +366,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) */ tuple = slot->val; - tupType = (TupleDesc) junkfilter->jf_tupType; - cleanTupType = (TupleDesc) junkfilter->jf_cleanTupType; + tupType = junkfilter->jf_tupType; + cleanTupType = junkfilter->jf_cleanTupType; cleanLength = junkfilter->jf_cleanLength; cleanMap = junkfilter->jf_cleanMap; @@ -363,11 +389,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) */ if (cleanLength > 64) { - size = cleanLength * sizeof(Datum); - values = (Datum *) palloc(size); - - size = cleanLength * sizeof(char); - nulls = (char *) palloc(size); + values = (Datum *) palloc(cleanLength * sizeof(Datum)); + nulls = (char *) palloc(cleanLength * sizeof(char)); } else { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 77af5e7ecce..929134209ba 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.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) /* ---------------------------------------------------------------- * 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 - * - * returns (AttrInfo*) which describes the attributes of the tuples to - * be returned by the query. - * * ---------------------------------------------------------------- */ void @@ -268,23 +264,15 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate) EndPlan(queryDesc->plantree, estate); - /* XXX - clean up some more from ExecutorStart() - er1p */ - if (NULL == estate->es_snapshot) - { - /* nothing to free */ - } - else + if (estate->es_snapshot != NULL) { if (estate->es_snapshot->xcnt > 0) pfree(estate->es_snapshot->xip); pfree(estate->es_snapshot); + estate->es_snapshot = NULL; } - if (NULL == estate->es_param_exec_vals) - { - /* nothing to free */ - } - else + if (estate->es_param_exec_vals != NULL) { pfree(estate->es_param_exec_vals); estate->es_param_exec_vals = NULL; @@ -870,7 +858,7 @@ EndPlan(Plan *plan, EState *estate) /* * 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; for (i = estate->es_num_result_relations; i > 0; i--) @@ -878,6 +866,9 @@ EndPlan(Plan *plan, EState *estate) /* Close indices and then the relation itself */ ExecCloseIndices(resultRelInfo); heap_close(resultRelInfo->ri_RelationDesc, NoLock); + /* Delete the junkfilter if any */ + if (resultRelInfo->ri_junkFilter != NULL) + ExecFreeJunkFilter(resultRelInfo->ri_junkFilter); resultRelInfo++; } @@ -888,6 +879,16 @@ EndPlan(Plan *plan, EState *estate) 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 */ foreach(l, estate->es_rowMark) diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 549f612d7eb..bc1b6d0b2f7 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -12,7 +12,7 @@ * * * 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 @@ * ExecInitNode - initialize a plan node and its subplans * ExecProcNode - get a tuple by executing the plan node * 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 * This used to be three files. It is now all combined into @@ -218,7 +220,8 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) break; default: - elog(ERROR, "ExecInitNode: node %d unsupported", nodeTag(node)); + elog(ERROR, "ExecInitNode: node type %d unsupported", + (int) nodeTag(node)); result = FALSE; } @@ -347,7 +350,8 @@ ExecProcNode(Plan *node, Plan *parent) break; default: - elog(ERROR, "ExecProcNode: node %d unsupported", nodeTag(node)); + elog(ERROR, "ExecProcNode: node type %d unsupported", + (int) nodeTag(node)); result = NULL; } @@ -430,8 +434,8 @@ ExecCountSlotsNode(Plan *node) return ExecCountSlotsAgg((Agg *) node); default: - elog(ERROR, "ExecCountSlotsNode: node not yet supported: %d", - nodeTag(node)); + elog(ERROR, "ExecCountSlotsNode: node type %d unsupported", + (int) nodeTag(node)); break; } return 0; @@ -558,7 +562,178 @@ ExecEndNode(Plan *node, Plan *parent) break; default: - elog(ERROR, "ExecEndNode: node %d unsupported", nodeTag(node)); + elog(ERROR, "ExecEndNode: node type %d unsupported", + (int) nodeTag(node)); 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; +} diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index f0721f57bd5..bab2851df9d 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * 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) /* * 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 - * 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) { - TupleTableSlot *tempSlot; + TupleTableSlot *tempSlot = MakeTupleTableSlot(); TupleDesc td; 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); td = CreateTupleDescCopy(tuple_type); - ExecSetSlotDescriptor(tempSlot, td); - + ExecSetSlotDescriptor(tempSlot, td, true); ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); return PointerGetDatum(tempSlot); } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index ecb8ae48b50..e5f1a269d81 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.45 2001/01/24 19:42:54 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.46 2001/01/29 00:39:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,26 +24,20 @@ * * TABLE CREATE/DELETE * ExecCreateTupleTable - create a new tuple table - * ExecDropTupleTable - destroy a table + * ExecDropTupleTable - destroy a table * - * SLOT RESERVERATION + * SLOT RESERVATION * ExecAllocTableSlot - find an available slot in the table * * SLOT ACCESSORS * ExecStoreTuple - store a tuple in the table * ExecFetchTuple - fetch a tuple from the table * ExecClearTuple - clear contents of a table slot - * ExecSlotPolicy - return slot's tuple pfree policy - * ExecSetSlotPolicy - diddle the slot policy - * ExecSlotDescriptor - type of tuple in a slot * ExecSetSlotDescriptor - set a slot's tuple descriptor * ExecSetSlotDescriptorIsNew - diddle the slot-desc-is-new flag - * ExecSetNewSlotDescriptor - set a desc and the is-new-flag all at once * * SLOT STATUS PREDICATES * TupIsNull - true when slot contains no tuple(Macro) - * ExecSlotDescriptorIsNew - true if we're now storing a different - * type of tuple in a slot * * CONVENIENCE INITIALIZATION ROUTINES * ExecInitResultTupleSlot \ convenience routines to initialize @@ -51,8 +45,7 @@ * ExecInitExtraTupleSlot / which store copies of tuples. * ExecInitNullTupleSlot / * - * old routines: - * ExecGetTupType - get type of tuple returned by this node + * Routines that probably belong somewhere else: * ExecTypeFromTL - form a TupleDesc from a target list * * EXAMPLE OF HOW TABLE ROUTINES WORK @@ -112,16 +105,11 @@ * and the TupleTableSlot node in execnodes.h. * */ - #include "postgres.h" -#include "executor/executor.h" - -#undef ExecStoreTuple -#include "catalog/pg_type.h" #include "access/heapam.h" - -static TupleTableSlot *NodeGetResultTupleSlot(Plan *node); +#include "catalog/pg_type.h" +#include "executor/executor.h" /* ---------------------------------------------------------------- @@ -212,23 +200,17 @@ ExecDropTupleTable(TupleTable table, /* tuple table */ * and drop refcounts of any referenced buffers, * if that's what the caller wants. (There is probably * no good reason for the caller ever not to want it!) - * - * Note: we do nothing about the Tuple Descriptor's - * we store in the slots. This may have to change (ex: we should - * probably worry about pfreeing tuple descs too) -cim 3/14/91 - * - * Right now, the handling of tuple pointers and buffer refcounts - * is clean, but the handling of tuple descriptors is NOT; they - * are copied around with wild abandon. It would take some work - * to make tuple descs pfree'able. Fortunately, since they're - * normally only made once per scan, it's probably not worth - * worrying about... tgl 9/21/99 * ---------------- */ if (shouldFree) { for (i = 0; i < next; i++) + { ExecClearTuple(&array[i]); + if (array[i].ttc_shouldFreeDesc && + array[i].ttc_tupleDescriptor != NULL) + FreeTupleDesc(array[i].ttc_tupleDescriptor); + } } /* ---------------- @@ -301,6 +283,32 @@ ExecAllocTableSlot(TupleTable table) slot->val = (HeapTuple) NULL; slot->ttc_shouldFree = true; slot->ttc_descIsNew = true; + slot->ttc_shouldFreeDesc = true; + slot->ttc_tupleDescriptor = (TupleDesc) NULL; + slot->ttc_buffer = InvalidBuffer; + + return slot; +} + +/* -------------------------------- + * MakeTupleTableSlot + * + * This routine makes an empty standalone TupleTableSlot. + * It really shouldn't exist, but there are a few places + * that do this, so we may as well centralize the knowledge + * of what's in one ... + * -------------------------------- + */ +TupleTableSlot * +MakeTupleTableSlot(void) +{ + TupleTableSlot *slot = makeNode(TupleTableSlot); + + /* This should match ExecAllocTableSlot() */ + slot->val = (HeapTuple) NULL; + slot->ttc_shouldFree = true; + slot->ttc_descIsNew = true; + slot->ttc_shouldFreeDesc = true; slot->ttc_tupleDescriptor = (TupleDesc) NULL; slot->ttc_buffer = InvalidBuffer; @@ -384,6 +392,8 @@ ExecStoreTuple(HeapTuple tuple, * ExecClearTuple * * This function is used to clear out a slot in the tuple table. + * + * NB: only the tuple is cleared, not the tuple descriptor (if any). * -------------------------------- */ TupleTableSlot * /* return: slot passed */ @@ -426,57 +436,6 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */ return slot; } - -/* -------------------------------- - * ExecSlotPolicy - * - * This function is used to get the call/don't call pfree - * setting of a slot. Most executor routines don't need this. - * It's only when you do tricky things like marking tuples for - * merge joins that you need to diddle the slot policy. - * -------------------------------- - */ -#ifdef NOT_USED -bool /* return: slot policy */ -ExecSlotPolicy(TupleTableSlot *slot) /* slot to inspect */ -{ - return slot->ttc_shouldFree; -} - - -/* -------------------------------- - * ExecSetSlotPolicy - * - * This function is used to change the call/don't call pfree - * setting of a slot. Most executor routines don't need this. - * It's only when you do tricky things like marking tuples for - * merge joins that you need to diddle the slot policy. - * -------------------------------- - */ -bool /* return: old slot policy */ -ExecSetSlotPolicy(TupleTableSlot *slot, /* slot to change */ - bool shouldFree) /* true if we call pfree() when we - * gc. */ -{ - bool old_shouldFree = slot->ttc_shouldFree; - - slot->ttc_shouldFree = shouldFree; - - return old_shouldFree; -} - -#endif - -/* -------------------------------- - * ExecSlotDescriptor - * - * This function is used to get the tuple descriptor associated - * with the slot's tuple. - * - * Now a macro in tuptable.h -mer 5 March 1992 - * -------------------------------- - */ - /* -------------------------------- * ExecSetSlotDescriptor * @@ -484,14 +443,17 @@ ExecSetSlotPolicy(TupleTableSlot *slot, /* slot to change */ * with the slot's tuple. * -------------------------------- */ -TupleDesc /* return: old slot tuple descriptor */ +void ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */ - TupleDesc tupdesc) /* tuple descriptor */ + TupleDesc tupdesc, /* new tuple descriptor */ + bool shouldFree) /* is desc owned by slot? */ { - TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; + if (slot->ttc_shouldFreeDesc && + slot->ttc_tupleDescriptor != NULL) + FreeTupleDesc(slot->ttc_tupleDescriptor); slot->ttc_tupleDescriptor = tupdesc; - return old_tupdesc; + slot->ttc_shouldFreeDesc = shouldFree; } /* -------------------------------- @@ -507,52 +469,11 @@ ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */ slot->ttc_descIsNew = isNew; } -/* -------------------------------- - * ExecSetNewSlotDescriptor - * - * This function is used to set the tuple descriptor associated - * with the slot's tuple, and set the "isNew" flag at the same time. - * -------------------------------- - */ -#ifdef NOT_USED -TupleDesc /* return: old slot tuple descriptor */ -ExecSetNewSlotDescriptor(TupleTableSlot *slot, /* slot to change */ - TupleDesc tupdesc) /* tuple descriptor */ -{ - TupleDesc old_tupdesc = slot->ttc_tupleDescriptor; - - slot->ttc_tupleDescriptor = tupdesc; - slot->ttc_descIsNew = true; - - return old_tupdesc; -} - -#endif - /* ---------------------------------------------------------------- * tuple table slot status predicates * ---------------------------------------------------------------- */ -/* -------------------------------- - * ExecSlotDescriptorIsNew - * - * This function is used to check if the tuple descriptor - * associated with this slot has just changed. ie: we are - * now storing a new type of tuple in this slot - * -------------------------------- - */ -#ifdef NOT_USED -bool /* return: descriptor "is new" */ -ExecSlotDescriptorIsNew(TupleTableSlot *slot) /* slot to inspect */ -{ -/* bool isNew = SlotTupleDescriptorIsNew((TupleTableSlot*) slot); - return isNew; */ - return slot->ttc_descIsNew; -} - -#endif - /* ---------------------------------------------------------------- * convenience initialization routines * ---------------------------------------------------------------- @@ -632,228 +553,13 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) static struct tupleDesc NullTupleDesc; /* we assume this inits to * zeroes */ - ExecSetSlotDescriptor(slot, tupType); + ExecSetSlotDescriptor(slot, tupType, false); nullTuple = heap_formtuple(&NullTupleDesc, values, nulls); return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true); } - -static TupleTableSlot * -NodeGetResultTupleSlot(Plan *node) -{ - TupleTableSlot *slot; - - 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, "NodeGetResultTupleSlot: node not yet supported: %d", - (int) nodeTag(node)); - - return NULL; - } - return slot; -} - -/* ---------------------------------------------------------------- - * 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. - * - * Soon, the system will have to adapt to deal with changing - * tuple descriptors as we deal with dynamic tuple types - * being returned from procedure nodes. Perhaps then this - * routine can be retired. -cim 6/3/91 - * - * old comments - * This routine just gets the type information out of the - * node's state. If you already have a node's state, you - * can get this information directly, but this is a useful - * routine if you want to get the type information from - * the node's inner or outer subplan easily without having - * to inspect the subplan.. -cim 10/16/89 - * - * ---------------------------------------------------------------- - */ - -TupleDesc -ExecGetTupType(Plan *node) -{ - TupleTableSlot *slot; - TupleDesc tupType; - - if (node == NULL) - return NULL; - - slot = NodeGetResultTupleSlot(node); - tupType = slot->ttc_tupleDescriptor; - return tupType; -} - -#ifdef NOT_USED -TupleDesc -ExecCopyTupType(TupleDesc td, int natts) -{ - TupleDesc newTd; - int i; - - newTd = CreateTemplateTupleDesc(natts); - i = 0; - while (i < natts) - { - newTd[i] = (Form_pg_attribute)palloc(sizeof(FormData_pg_attribute)); - memmove(newTd[i], td[i], sizeof(FormData_pg_attribute)); - i++; - } - return newTd; -} -#endif - /* ---------------------------------------------------------------- * ExecTypeFromTL * diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 703767cb715..6b030b64a0e 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * 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 @@ * INTERFACE 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 \ * ExecCloseIndices | referenced by InitPlan, EndPlan, * ExecInsertIndexTuples / ExecAppend, ExecReplace @@ -261,12 +250,11 @@ MakePerTupleExprContext(EState *estate) */ void ExecAssignResultType(CommonState *commonstate, - TupleDesc tupDesc) + TupleDesc tupDesc, bool shouldFree) { - TupleTableSlot *slot; + TupleTableSlot *slot = commonstate->cs_ResultTupleSlot; - slot = commonstate->cs_ResultTupleSlot; - slot->ttc_tupleDescriptor = tupDesc; + ExecSetSlotDescriptor(slot, tupDesc, shouldFree); } /* ---------------- @@ -282,7 +270,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) outerPlan = outerPlan(node); tupDesc = ExecGetTupType(outerPlan); - ExecAssignResultType(commonstate, tupDesc); + ExecAssignResultType(commonstate, tupDesc, false); } /* ---------------- @@ -292,12 +280,10 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) { - List *targetList; TupleDesc tupDesc; - targetList = node->targetlist; - tupDesc = ExecTypeFromTL(targetList); - ExecAssignResultType(commonstate, tupDesc); + tupDesc = ExecTypeFromTL(node->targetlist); + ExecAssignResultType(commonstate, tupDesc, true); } /* ---------------- @@ -313,25 +299,6 @@ ExecGetResultType(CommonState *commonstate) } /* ---------------- - * ExecFreeResultType - * ---------------- - */ -#ifdef NOT_USED -void -ExecFreeResultType(CommonState *commonstate) -{ - TupleTableSlot *slot; - TupleDesc tupType; - - slot = commonstate->cs_ResultTupleSlot; - tupType = slot->ttc_tupleDescriptor; - - ExecFreeTypeInfo(tupType); -} - -#endif - -/* ---------------- * ExecAssignProjectionInfo forms the projection information from the node's targetlist * ---------------- @@ -413,29 +380,6 @@ ExecFreeExprContext(CommonState *commonstate) 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 * those nodes which are stubborn and return tuples in @@ -459,36 +403,16 @@ ExecGetScanType(CommonScanState *csstate) } /* ---------------- - * ExecFreeScanType - * ---------------- - */ -#ifdef NOT_USED -void -ExecFreeScanType(CommonScanState *csstate) -{ - TupleTableSlot *slot; - TupleDesc tupType; - - slot = csstate->css_ScanTupleSlot; - tupType = slot->ttc_tupleDescriptor; - - ExecFreeTypeInfo(tupType); -} - -#endif - -/* ---------------- * ExecAssignScanType * ---------------- */ void ExecAssignScanType(CommonScanState *csstate, - TupleDesc tupDesc) + TupleDesc tupDesc, bool shouldFree) { - TupleTableSlot *slot; + TupleTableSlot *slot = csstate->css_ScanTupleSlot; - slot = (TupleTableSlot *) csstate->css_ScanTupleSlot; - slot->ttc_tupleDescriptor = tupDesc; + ExecSetSlotDescriptor(slot, tupDesc, shouldFree); } /* ---------------- @@ -504,155 +428,11 @@ ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate) outerPlan = outerPlan(node); 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 * ---------------------------------------------------------------- */ diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 18a0e0cbb3b..575f33d84b6 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * 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 @@ #include "tcop/tcopprot.h" #include "tcop/utility.h" #include "utils/builtins.h" -#include "utils/datum.h" #include "utils/syscache.h" @@ -73,7 +72,7 @@ typedef SQLFunctionCache *SQLFunctionCachePtr; static execution_state *init_execution_state(char *src, Oid *argOidVect, int nargs); 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 void postquel_end(execution_state *es); static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo); @@ -82,24 +81,6 @@ static Datum postquel_execute(execution_state *es, 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 * init_execution_state(char *src, Oid *argOidVect, int nargs) { @@ -240,18 +221,7 @@ init_sql_fcache(FmgrInfo *finfo) * allocated by the executor (i.e. slots and tuples) is freed. */ if (!finfo->fn_retset && !fcache->typbyval) - { - 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; - } + fcache->funcSlot = MakeTupleTableSlot(); else fcache->funcSlot = NULL; @@ -289,7 +259,7 @@ init_sql_fcache(FmgrInfo *finfo) } -static TupleDesc +static void postquel_start(execution_state *es) { @@ -298,8 +268,8 @@ postquel_start(execution_state *es) * 30-8-1996 */ if (es->qd->operation == CMD_UTILITY) - return (TupleDesc) NULL; - return ExecutorStart(es->qd, es->estate); + return; + ExecutorStart(es->qd, es->estate); } static TupleTableSlot * @@ -379,11 +349,11 @@ copy_function_result(SQLFunctionCachePtr fcache, * If first time through, we have to initialize the funcSlot's * tuple descriptor. */ - if (TupIsNull(funcSlot)) + if (funcSlot->ttc_tupleDescriptor == NULL) { - resultTd = resultSlot->ttc_tupleDescriptor; - funcSlot->ttc_tupleDescriptor = CreateTupleDescCopy(resultTd); - funcSlot->ttc_descIsNew = true; + resultTd = CreateTupleDescCopy(resultSlot->ttc_tupleDescriptor); + ExecSetSlotDescriptor(funcSlot, resultTd, true); + ExecSetSlotDescriptorIsNew(funcSlot, true); } newTuple = heap_copytuple(resultTuple); @@ -460,10 +430,15 @@ postquel_execute(execution_state *es, } else { - value = ProjectAttribute(resSlot->val, - 1, - resSlot->ttc_tupleDescriptor, - &fcinfo->isnull); + value = heap_getattr(resSlot->val, + 1, + resSlot->ttc_tupleDescriptor, + &(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. + */ } /* diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 0c6703fb70c..a3fc2f545cb 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -8,7 +8,7 @@ * * * 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) ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate); ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot, - ExecGetTupType(outerNode)); + ExecGetTupType(outerNode), + false); /* ---------------- * initialize hash-specific info diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 7ed93de0848..c0369e8f4cd 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * 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) if (estate->es_evTupleNull[node->scan.scanrelid - 1]) return slot; /* return empty slot */ - /* probably ought to use ExecStoreTuple here... */ - slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; - slot->ttc_shouldFree = false; - - econtext->ecxt_scantuple = slot; + ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], + slot, InvalidBuffer, false); /* Does the tuple meet any of the OR'd indxqual conditions? */ + econtext->ecxt_scantuple = slot; ResetExprContext(econtext); @@ -1043,7 +1041,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) * get the scan type from the relation descriptor. * ---------------- */ - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); + ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); /* ---------------- diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 359d0c7bc5d..fd8868a4a54 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * 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) mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate); ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot, - ExecGetTupType(innerPlan((Plan *) node))); + ExecGetTupType(innerPlan((Plan *) node)), + false); switch (node->join.jointype) { diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index a10e8d4ed96..a39128ff2f0 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -8,7 +8,7 @@ * * * 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) if (estate->es_evTupleNull[node->scanrelid - 1]) return slot; /* return empty slot */ - /* probably ought to use ExecStoreTuple here... */ - slot->val = estate->es_evTuple[node->scanrelid - 1]; - slot->ttc_shouldFree = false; + ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1], + slot, InvalidBuffer, false); /* * Note that unlike IndexScan, SeqScan never use keys in @@ -181,7 +180,7 @@ InitScanRelation(SeqScan *node, EState *estate, scanstate->css_currentRelation = currentRelation; scanstate->css_currentScanDesc = currentScanDesc; - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); + ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); return reloid; } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 99bd3b76437..b8c057c3397 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -8,7 +8,7 @@ * * * 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) break; tuplesort_puttuple(tuplesortstate, (void *) slot->val); - ExecClearTuple(slot); } /* ---------------- @@ -188,11 +187,10 @@ ExecSort(Sort *node) 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; - slot->ttc_tupleDescriptor = tupDesc; + ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false); /* ---------------- * finally set the sorted flag to true @@ -201,8 +199,6 @@ ExecSort(Sort *node) sortstate->sort_Done = true; SO1_printf(stderr, "ExecSort: sorting done.\n"); } - else - slot = (TupleTableSlot *) sortstate->csstate.cstate.cs_ResultTupleSlot; SO1_printf("ExecSort: %s\n", "retrieving tuple from tuplesort"); @@ -216,6 +212,7 @@ ExecSort(Sort *node) ScanDirectionIsForward(dir), &should_free); + slot = sortstate->csstate.cstate.cs_ResultTupleSlot; return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); } @@ -347,6 +344,12 @@ ExecEndSort(Sort *node) tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); sortstate->tuplesortstate = NULL; + if (sortstate->sort_Keys != NULL) + pfree(sortstate->sort_Keys); + + pfree(sortstate); + node->sortstate = NULL; + SO1_printf("ExecEndSort: %s\n", "sort node shutdown"); } diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 617a41d447d..4c9144bc3a8 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -12,7 +12,7 @@ * * * 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) if (estate->es_evTupleNull[node->scan.scanrelid - 1]) return slot; /* return empty slot */ - /* probably ought to use ExecStoreTuple here... */ - slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; - slot->ttc_shouldFree = false; + ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], + slot, InvalidBuffer, false); /* Flag for the next call that no more tuples */ estate->es_evTupleNull[node->scan.scanrelid - 1] = true; diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 49f7594c6f7..a5c0299d289 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -8,7 +8,7 @@ * * * 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) if (estate->es_evTupleNull[node->scan.scanrelid - 1]) return slot; /* return empty slot */ - /* probably ought to use ExecStoreTuple here... */ - slot->val = estate->es_evTuple[node->scan.scanrelid - 1]; - slot->ttc_shouldFree = false; + ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], + slot, InvalidBuffer, false); /* Flag for the next call that no more tuples */ estate->es_evTupleNull[node->scan.scanrelid - 1] = true; @@ -487,7 +486,7 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) * get the scan type from the relation descriptor. * ---------------- */ - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation)); + ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); /* |