summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane2005-03-16 21:38:10 +0000
committerTom Lane2005-03-16 21:38:10 +0000
commitf97aebd162987d00bd9b9f592ff54e9e90f11843 (patch)
tree78c6ff493070f92e7fda262a2c25e2545f0d2b21 /src/include
parent712f053587b552769d1d3f6fe0ec03ab79c05d26 (diff)
Revise TupleTableSlot code to avoid unnecessary construction and disassembly
of tuples when passing data up through multiple plan nodes. A slot can now hold either a normal "physical" HeapTuple, or a "virtual" tuple consisting of Datum/isnull arrays. Upper plan levels can usually just copy the Datum arrays, avoiding heap_formtuple() and possible subsequent nocachegetattr() calls to extract the data again. This work extends Atsushi Ogawa's earlier patch, which provided the key idea of adding Datum arrays to TupleTableSlots. (I believe however that something like this was foreseen way back in Berkeley days --- see the old comment on ExecProject.) A test case involving many levels of join of fairly wide tables (about 80 columns altogether) showed about 3x overall speedup, though simple queries will probably not be helped very much. I have also duplicated some code in heaptuple.c in order to provide versions of heap_formtuple and friends that use "bool" arrays to indicate null attributes, instead of the old convention of "char" arrays containing either 'n' or ' '. This provides a better match to the convention used by ExecEvalExpr. While I have not made a concerted effort to get rid of uses of the old routines, I think they should be deprecated and eventually removed.
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/heapam.h21
-rw-r--r--src/include/access/printtup.h8
-rw-r--r--src/include/catalog/index.h5
-rw-r--r--src/include/executor/execdebug.h6
-rw-r--r--src/include/executor/executor.h53
-rw-r--r--src/include/executor/tuptable.h126
-rw-r--r--src/include/nodes/execnodes.h45
-rw-r--r--src/include/tcop/dest.h17
8 files changed, 176 insertions, 105 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 3b73d5ea8a1..5c58f32c43e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.95 2005/03/14 04:41:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.96 2005/03/16 21:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -178,27 +178,42 @@ extern XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf,
Buffer newbuf, HeapTuple newtup);
/* in common/heaptuple.c */
+extern Size heap_compute_data_size(TupleDesc tupleDesc,
+ Datum *values, bool *isnull);
extern Size ComputeDataSize(TupleDesc tupleDesc, Datum *values, char *nulls);
+extern void heap_fill_tuple(TupleDesc tupleDesc,
+ Datum *values, bool *isnull,
+ char *data, uint16 *infomask, bits8 *bit);
extern void DataFill(char *data, TupleDesc tupleDesc,
Datum *values, char *nulls, uint16 *infomask,
bits8 *bit);
-extern int heap_attisnull(HeapTuple tup, int attnum);
+extern bool heap_attisnull(HeapTuple tup, int attnum);
extern Datum nocachegetattr(HeapTuple tup, int attnum,
TupleDesc att, bool *isnull);
extern Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
bool *isnull);
extern HeapTuple heap_copytuple(HeapTuple tuple);
extern void heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest);
+extern HeapTuple heap_form_tuple(TupleDesc tupleDescriptor,
+ Datum *values, bool *isnull);
extern HeapTuple heap_formtuple(TupleDesc tupleDescriptor,
Datum *values, char *nulls);
+extern HeapTuple heap_modify_tuple(HeapTuple tuple,
+ TupleDesc tupleDesc,
+ Datum *replValues,
+ bool *replIsnull,
+ bool *doReplace);
extern HeapTuple heap_modifytuple(HeapTuple tuple,
TupleDesc tupleDesc,
Datum *replValues,
char *replNulls,
char *replActions);
+extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
+ Datum *values, bool *isnull);
extern void heap_deformtuple(HeapTuple tuple, TupleDesc tupleDesc,
Datum *values, char *nulls);
extern void heap_freetuple(HeapTuple tuple);
-extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure);
+extern HeapTuple heap_addheader(int natts, bool withoid,
+ Size structlen, void *structure);
#endif /* HEAPAM_H */
diff --git a/src/include/access/printtup.h b/src/include/access/printtup.h
index 7e534d41bf8..aa7989f98f0 100644
--- a/src/include/access/printtup.h
+++ b/src/include/access/printtup.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/printtup.h,v 1.32 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/printtup.h,v 1.33 2005/03/16 21:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,13 +23,11 @@ extern void SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist,
extern void debugStartup(DestReceiver *self, int operation,
TupleDesc typeinfo);
-extern void debugtup(HeapTuple tuple, TupleDesc typeinfo,
- DestReceiver *self);
+extern void debugtup(TupleTableSlot *slot, DestReceiver *self);
/* XXX these are really in executor/spi.c */
extern void spi_dest_startup(DestReceiver *self, int operation,
TupleDesc typeinfo);
-extern void spi_printtup(HeapTuple tuple, TupleDesc typeinfo,
- DestReceiver *self);
+extern void spi_printtup(TupleTableSlot *slot, DestReceiver *self);
#endif /* PRINTTUP_H */
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 86ca9e0e8b2..b7484f4450b 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.59 2004/12/31 22:03:24 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.60 2005/03/16 21:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -46,8 +46,7 @@ extern void index_drop(Oid indexId);
extern IndexInfo *BuildIndexInfo(Relation index);
extern void FormIndexDatum(IndexInfo *indexInfo,
- HeapTuple heapTuple,
- TupleDesc heapDescriptor,
+ TupleTableSlot *slot,
EState *estate,
Datum *datum,
char *nullv);
diff --git a/src/include/executor/execdebug.h b/src/include/executor/execdebug.h
index 9d846042b67..58a987107de 100644
--- a/src/include/executor/execdebug.h
+++ b/src/include/executor/execdebug.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/execdebug.h,v 1.25 2004/12/31 22:03:29 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/executor/execdebug.h,v 1.26 2005/03/16 21:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -256,7 +256,7 @@ extern int NIndexTupleInserted;
#define MJ_printf(s) printf(s)
#define MJ1_printf(s, p) printf(s, p)
#define MJ2_printf(s, p1, p2) printf(s, p1, p2)
-#define MJ_debugtup(tuple, type) debugtup(tuple, type, NULL)
+#define MJ_debugtup(slot) debugtup(slot, NULL)
#define MJ_dump(state) ExecMergeTupleDump(state)
#define MJ_DEBUG_QUAL(clause, res) \
MJ2_printf(" ExecQual(%s, econtext) returns %s\n", \
@@ -276,7 +276,7 @@ extern int NIndexTupleInserted;
#define MJ_printf(s)
#define MJ1_printf(s, p)
#define MJ2_printf(s, p1, p2)
-#define MJ_debugtup(tuple, type)
+#define MJ_debugtup(slot)
#define MJ_dump(state)
#define MJ_DEBUG_QUAL(clause, res)
#define MJ_DEBUG_MERGE_COMPARE(qual, res)
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 8eb357636ad..0d3e18ce0ac 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.116 2005/03/14 04:41:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.117 2005/03/16 21:38:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,17 +18,6 @@
/*
- * TupIsNull
- *
- * This is used mainly to detect when there are no more
- * tuples to process.
- */
-/* return: true if tuple in slot is NULL, slot is slot to test */
-#define TupIsNull(slot) \
- ((slot) == NULL || (slot)->val == NULL)
-
-
-/*
* ExecEvalExpr was formerly a function containing a switch statement;
* now it's just a macro invoking the function pointed to by an ExprState
* node. Beware of double evaluation of the ExprState argument!
@@ -50,20 +39,18 @@ extern bool ExecMayReturnRawTuples(PlanState *node);
/*
* prototypes from functions in execGrouping.c
*/
-extern bool execTuplesMatch(HeapTuple tuple1,
- HeapTuple tuple2,
- TupleDesc tupdesc,
- int numCols,
- AttrNumber *matchColIdx,
- FmgrInfo *eqfunctions,
- MemoryContext evalContext);
-extern bool execTuplesUnequal(HeapTuple tuple1,
- HeapTuple tuple2,
- TupleDesc tupdesc,
- int numCols,
- AttrNumber *matchColIdx,
- FmgrInfo *eqfunctions,
- MemoryContext evalContext);
+extern bool execTuplesMatch(TupleTableSlot *slot1,
+ TupleTableSlot *slot2,
+ int numCols,
+ AttrNumber *matchColIdx,
+ FmgrInfo *eqfunctions,
+ MemoryContext evalContext);
+extern bool execTuplesUnequal(TupleTableSlot *slot1,
+ TupleTableSlot *slot2,
+ int numCols,
+ AttrNumber *matchColIdx,
+ FmgrInfo *eqfunctions,
+ MemoryContext evalContext);
extern FmgrInfo *execTuplesMatchPrepare(TupleDesc tupdesc,
int numCols,
AttrNumber *matchColIdx);
@@ -92,6 +79,8 @@ extern JunkFilter *ExecInitJunkFilterConversion(List *targetList,
TupleTableSlot *slot);
extern bool ExecGetJunkAttribute(JunkFilter *junkfilter, TupleTableSlot *slot,
char *attrName, Datum *value, bool *isNull);
+extern TupleTableSlot *ExecFilterJunk(JunkFilter *junkfilter,
+ TupleTableSlot *slot);
extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
@@ -158,17 +147,6 @@ extern void ExecAssignScanProjectionInfo(ScanState *node);
/*
* prototypes from functions in execTuples.c
*/
-extern TupleTable ExecCreateTupleTable(int tableSize);
-extern void ExecDropTupleTable(TupleTable table, bool shouldFree);
-extern TupleTableSlot *MakeTupleTableSlot(void);
-extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
-extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
- TupleTableSlot *slot,
- Buffer buffer,
- bool shouldFree);
-extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
-extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
- TupleDesc tupdesc, bool shouldFree);
extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate);
extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate);
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
@@ -183,6 +161,7 @@ typedef struct TupOutputState
{
/* use "struct" here to allow forward reference */
struct AttInMetadata *metadata;
+ TupleTableSlot *slot;
DestReceiver *dest;
} TupOutputState;
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 90791366ffb..a5193683a28 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.27 2005/03/14 04:41:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.28 2005/03/16 21:38:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,43 +17,86 @@
#include "access/htup.h"
-/*
- * The executor stores pointers to tuples in a "tuple table"
- * which is composed of TupleTableSlots. Sometimes the tuples
- * are pointers to buffer pages, while others are pointers to
- * palloc'ed memory; the shouldFree variable tells us whether
- * we may call pfree() on a tuple. When shouldFree is true,
- * the tuple is "owned" by the TupleTableSlot and should be
- * freed when the slot's reference to the tuple is dropped.
+/*----------
+ * The executor stores tuples in a "tuple table" which is composed of
+ * independent TupleTableSlots. There are several cases we need to handle:
+ * 1. physical tuple in a disk buffer page
+ * 2. physical tuple constructed in palloc'ed memory
+ * 3. "virtual" tuple consisting of Datum/isnull arrays
+ *
+ * The first two cases are similar in that they both deal with "materialized"
+ * tuples, but resource management is different. For a tuple in a disk page
+ * we need to hold a pin on the buffer until the TupleTableSlot's reference
+ * to the tuple is dropped; while for a palloc'd tuple we usually want the
+ * tuple pfree'd when the TupleTableSlot's reference is dropped.
+ *
+ * A "virtual" tuple is an optimization used to minimize physical data
+ * copying in a nest of plan nodes. Any pass-by-reference Datums in the
+ * tuple point to storage that is not directly associated with the
+ * TupleTableSlot; generally they will point to part of a tuple stored in
+ * a lower plan node's output TupleTableSlot, or to a function result
+ * constructed in a plan node's per-tuple econtext. It is the responsibility
+ * of the generating plan node to be sure these resources are not released
+ * for as long as the virtual tuple needs to be valid. We only use virtual
+ * tuples in the result slots of plan nodes --- tuples to be copied anywhere
+ * else need to be "materialized" into physical tuples. Note also that a
+ * virtual tuple does not have any "system columns".
+ *
+ * The Datum/isnull arrays of a TupleTableSlot serve double duty. When the
+ * slot contains a virtual tuple, they are the authoritative data. When the
+ * slot contains a physical tuple, the arrays contain data extracted from
+ * the tuple. (In this state, any pass-by-reference Datums point into
+ * the physical tuple.) The extracted information is built "lazily",
+ * ie, only as needed. This serves to avoid repeated extraction of data
+ * from the physical tuple.
+ *
+ * A TupleTableSlot can also be "empty", holding no valid data. This is
+ * the only valid state for a freshly-created slot that has not yet had a
+ * tuple descriptor assigned to it. In this state, tts_isempty must be
+ * TRUE, tts_shouldFree FALSE, tts_tuple NULL, tts_buffer InvalidBuffer,
+ * and tts_nvalid zero.
+ *
+ * When tts_shouldFree is true, the physical tuple is "owned" by the slot
+ * and should be freed when the slot's reference to the tuple is dropped.
*
- * shouldFreeDesc is similar to shouldFree: if it's true, then the
+ * tts_shouldFreeDesc is similar to tts_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.
*
- * If buffer is not InvalidBuffer, then the slot is holding a pin
+ * If tts_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. (shouldFree should always be
- * false in such a case, since presumably val is pointing at the
+ * slot's reference to that buffer. (tts_shouldFree should always be
+ * false in such a case, since presumably tts_tuple is pointing at the
* buffer page.)
*
- * The slot_getattr() routine allows extraction of attribute values from
- * a TupleTableSlot's current tuple. It is equivalent to heap_getattr()
- * except that it can optimize fetching of multiple values more efficiently.
- * The cache_xxx fields of TupleTableSlot are support for slot_getattr().
+ * tts_nvalid indicates the number of valid columns in the tts_values/isnull
+ * arrays. When the slot is holding a "virtual" tuple this must be equal
+ * to the descriptor's natts. When the slot is holding a physical tuple
+ * this is equal to the number of columns we have extracted (we always
+ * extract columns from left to right, so there are no holes).
+ *
+ * tts_values/tts_isnull are allocated when a descriptor is assigned to the
+ * slot; they are of length equal to the descriptor's natts.
+ *
+ * tts_slow/tts_off are saved state for slot_deform_tuple, and should not
+ * be touched by any other code.
+ *----------
*/
typedef struct TupleTableSlot
{
NodeTag type; /* vestigial ... allows IsA tests */
- HeapTuple val; /* current tuple, or NULL if none */
- TupleDesc ttc_tupleDescriptor; /* tuple's descriptor */
- bool ttc_shouldFree; /* should pfree tuple? */
- bool ttc_shouldFreeDesc; /* should pfree descriptor? */
- Buffer ttc_buffer; /* tuple's buffer, or InvalidBuffer */
- MemoryContext ttc_mcxt; /* slot itself is in this context */
- Datum *cache_values; /* currently extracted values */
- int cache_natts; /* # of valid values in cache_values */
- bool cache_slow; /* saved state for slot_getattr */
- long cache_off; /* saved state for slot_getattr */
+ bool tts_isempty; /* true = slot is empty */
+ bool tts_shouldFree; /* should pfree tuple? */
+ bool tts_shouldFreeDesc; /* should pfree descriptor? */
+ bool tts_slow; /* saved state for slot_deform_tuple */
+ HeapTuple tts_tuple; /* physical tuple, or NULL if none */
+ TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
+ MemoryContext tts_mcxt; /* slot itself is in this context */
+ Buffer tts_buffer; /* tuple's buffer, or InvalidBuffer */
+ int tts_nvalid; /* # of valid values in tts_values */
+ Datum *tts_values; /* current per-attribute values */
+ bool *tts_isnull; /* current per-attribute isnull flags */
+ long tts_off; /* saved state for slot_deform_tuple */
} TupleTableSlot;
/*
@@ -69,7 +112,36 @@ typedef struct TupleTableData
typedef TupleTableData *TupleTable;
+/*
+ * TupIsNull -- is a TupleTableSlot empty?
+ */
+#define TupIsNull(slot) \
+ ((slot) == NULL || (slot)->tts_isempty)
+
+/* in executor/execTuples.c */
+extern TupleTable ExecCreateTupleTable(int tableSize);
+extern void ExecDropTupleTable(TupleTable table, bool shouldFree);
+extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
+extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
+extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
+extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
+ TupleDesc tupdesc, bool shouldFree);
+extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
+ TupleTableSlot *slot,
+ Buffer buffer,
+ bool shouldFree);
+extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
+extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
+extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
+extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot);
+extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot);
+extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot);
+extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
+ TupleTableSlot *srcslot);
/* in access/common/heaptuple.c */
extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull);
+extern void slot_getallattrs(TupleTableSlot *slot);
+extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
+extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
#endif /* TUPTABLE_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 6cc43342997..8e5404b5078 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.123 2005/03/06 22:15:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.124 2005/03/16 21:38:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -175,20 +175,28 @@ typedef struct ReturnSetInfo
* This is all the information needed to perform projections ---
* that is, form new tuples by evaluation of targetlist expressions.
* Nodes which need to do projections create one of these.
- * In theory, when a node wants to perform a projection
- * it should just update this information as necessary and then
- * call ExecProject(). -cim 6/3/91
*
* ExecProject() evaluates the tlist, forms a tuple, and stores it
- * in the given slot. As a side-effect, the actual datum values and
- * null indicators are placed in the work arrays tupValues/tupNulls.
+ * in the given slot. Note that the result will be a "virtual" tuple
+ * unless ExecMaterializeSlot() is then called to force it to be
+ * converted to a physical tuple. The slot must have a tupledesc
+ * that matches the output of the tlist!
+ *
+ * The planner very often produces tlists that consist entirely of
+ * simple Var references (lower levels of a plan tree almost always
+ * look like that). So we have an optimization to handle that case
+ * with minimum overhead.
*
* targetlist target list for projection
* exprContext expression context in which to evaluate targetlist
* slot slot to place projection result in
- * tupValues array of computed values
- * tupNull array of null indicators
* itemIsDone workspace for ExecProject
+ * isVarList TRUE if simple-Var-list optimization applies
+ * varSlotOffsets array indicating which slot each simple Var is from
+ * varNumbers array indicating attr numbers of simple Vars
+ * lastInnerVar highest attnum from inner tuple slot (0 if none)
+ * lastOuterVar highest attnum from outer tuple slot (0 if none)
+ * lastScanVar highest attnum from scan tuple slot (0 if none)
* ----------------
*/
typedef struct ProjectionInfo
@@ -197,9 +205,13 @@ typedef struct ProjectionInfo
List *pi_targetlist;
ExprContext *pi_exprContext;
TupleTableSlot *pi_slot;
- Datum *pi_tupValues;
- char *pi_tupNulls;
ExprDoneCond *pi_itemIsDone;
+ bool pi_isVarList;
+ int *pi_varSlotOffsets;
+ int *pi_varNumbers;
+ int pi_lastInnerVar;
+ int pi_lastOuterVar;
+ int pi_lastScanVar;
} ProjectionInfo;
/* ----------------
@@ -222,7 +234,7 @@ typedef struct ProjectionInfo
* cleanMap: A map with the correspondence between the non-junk
* attribute numbers of the "original" tuple and the
* attribute numbers of the "clean" tuple.
- * resultSlot: tuple slot that can be used to hold cleaned tuple.
+ * resultSlot: tuple slot used to hold cleaned tuple.
* ----------------
*/
typedef struct JunkFilter
@@ -354,7 +366,8 @@ typedef struct TupleHashTableData
MemoryContext tablecxt; /* memory context containing table */
MemoryContext tempcxt; /* context for function evaluations */
Size entrysize; /* actual size to make each hash entry */
- TupleDesc tupdesc; /* tuple descriptor */
+ TupleTableSlot *tableslot; /* slot for referencing table entries */
+ TupleTableSlot *inputslot; /* current input tuple's slot */
} TupleHashTableData;
typedef HASH_SEQ_STATUS TupleHashIterator;
@@ -589,9 +602,9 @@ typedef struct ConvertRowtypeExprState
TupleDesc outdesc; /* tupdesc for result rowtype */
AttrNumber *attrMap; /* indexes of input fields, or 0 for null */
Datum *invalues; /* workspace for deconstructing source */
- char *innulls;
+ bool *inisnull;
Datum *outvalues; /* workspace for constructing result */
- char *outnulls;
+ bool *outisnull;
} ConvertRowtypeExprState;
/* ----------------
@@ -1065,7 +1078,6 @@ typedef struct GroupState
{
ScanState ss; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
- HeapTuple grp_firstTuple; /* copy of first tuple of current group */
bool grp_done; /* indicates completion of Group scan */
} GroupState;
@@ -1111,7 +1123,7 @@ typedef struct AggState
* Unique nodes are used "on top of" sort nodes to discard
* duplicate tuples returned from the sort phase. Basically
* all it does is compare the current tuple from the subplan
- * with the previously fetched tuple stored in priorTuple.
+ * with the previously fetched tuple (stored in its result slot).
* If the two are identical in all interesting fields, then
* we just fetch another tuple from the sort and try again.
* ----------------
@@ -1120,7 +1132,6 @@ typedef struct UniqueState
{
PlanState ps; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
- HeapTuple priorTuple; /* most recently returned tuple, or NULL */
MemoryContext tempContext; /* short-term context for comparisons */
} UniqueState;
diff --git a/src/include/tcop/dest.h b/src/include/tcop/dest.h
index 0308a4c8d2c..3efb1924c59 100644
--- a/src/include/tcop/dest.h
+++ b/src/include/tcop/dest.h
@@ -31,7 +31,7 @@
* destination. The executor, as well as utility statements that can return
* tuples, are passed the resulting DestReceiver* pointer. Each executor run
* or utility execution calls the receiver's rStartup method, then the
- * receiveTuple method (zero or more times), then the rShutdown method.
+ * receiveSlot method (zero or more times), then the rShutdown method.
* The same receiver object may be re-used multiple times; eventually it is
* destroyed by calling its rDestroy method.
*
@@ -54,14 +54,14 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/tcop/dest.h,v 1.45 2004/12/31 22:03:44 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/tcop/dest.h,v 1.46 2005/03/16 21:38:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef DEST_H
#define DEST_H
-#include "access/htup.h"
+#include "executor/tuptable.h"
/* buffer size to use for command completion tags */
@@ -92,10 +92,8 @@ typedef enum
* In the simplest cases, there is no state info, just the function
* pointers that the executor must call.
*
- * Note: the receiveTuple routine must be passed a TupleDesc identical to the
- * one given to the rStartup routine. The reason for passing it again is just
- * that some destinations would otherwise need dynamic state merely to
- * remember the tupledesc pointer.
+ * Note: the receiveSlot routine must be passed a slot containing a TupleDesc
+ * identical to the one given to the rStartup routine.
* ----------------
*/
typedef struct _DestReceiver DestReceiver;
@@ -103,9 +101,8 @@ typedef struct _DestReceiver DestReceiver;
struct _DestReceiver
{
/* Called for each tuple to be output: */
- void (*receiveTuple) (HeapTuple tuple,
- TupleDesc typeinfo,
- DestReceiver *self);
+ void (*receiveSlot) (TupleTableSlot *slot,
+ DestReceiver *self);
/* Per-executor-run initialization and shutdown: */
void (*rStartup) (DestReceiver *self,
int operation,