aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execTuples.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execTuples.c')
-rw-r--r--src/backend/executor/execTuples.c388
1 files changed, 47 insertions, 341 deletions
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
*