aboutsummaryrefslogtreecommitdiff
path: root/src/include/executor
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-03-14 04:41:13 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-03-14 04:41:13 +0000
commita9b05bdc8330b378cd2df7910ca0beaa500223fa (patch)
tree18be88094b6d17df65925023582e84c34bf152db /src/include/executor
parentd1022ce3a1a8b61798028a8fae46e7e458d77cff (diff)
downloadpostgresql-a9b05bdc8330b378cd2df7910ca0beaa500223fa.tar.gz
postgresql-a9b05bdc8330b378cd2df7910ca0beaa500223fa.zip
Avoid O(N^2) overhead in repeated nocachegetattr calls when columns of
a tuple are being accessed via ExecEvalVar and the attcacheoff shortcut isn't usable (due to nulls and/or varlena columns). To do this, cache Datums extracted from a tuple in the associated TupleTableSlot. Also some code cleanup in and around the TupleTable handling. Atsushi Ogawa with some kibitzing by Tom Lane.
Diffstat (limited to 'src/include/executor')
-rw-r--r--src/include/executor/executor.h7
-rw-r--r--src/include/executor/tuptable.h93
2 files changed, 45 insertions, 55 deletions
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index f07bdd89d18..8eb357636ad 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.115 2004/12/31 22:03:29 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.116 2005/03/14 04:41:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -158,10 +158,10 @@ extern void ExecAssignScanProjectionInfo(ScanState *node);
/*
* prototypes from functions in execTuples.c
*/
-extern TupleTable ExecCreateTupleTable(int initialSize);
+extern TupleTable ExecCreateTupleTable(int tableSize);
extern void ExecDropTupleTable(TupleTable table, bool shouldFree);
-extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
extern TupleTableSlot *MakeTupleTableSlot(void);
+extern TupleTableSlot *ExecAllocTableSlot(TupleTable table);
extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
TupleTableSlot *slot,
Buffer buffer,
@@ -169,7 +169,6 @@ extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
TupleDesc tupdesc, bool shouldFree);
-extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew);
extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate);
extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate);
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index e496a666ce4..90791366ffb 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -7,11 +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.26 2004/12/31 22:03:29 pgsql Exp $
- *
- * NOTES
- * The tuple table interface is getting pretty ugly.
- * It should be redesigned soon.
+ * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.27 2005/03/14 04:41:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,65 +16,60 @@
#include "access/htup.h"
-/* ----------------
- * The executor tuple table is managed and manipulated by special
- * code in executor/execTuples.c.
- *
- * TupleTableSlot information
- *
- * val current tuple, or NULL if no tuple
- * shouldFree boolean - should we pfree() tuple
- * descIsNew boolean - true when tupleDescriptor changes
- * tupleDescriptor type information for the tuple data
- * shouldFreeDesc boolean - should we free tupleDescriptor
- * buffer the buffer for tuples pointing to disk pages
- *
- * 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 when
- * 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
- * "retrieve (EMP.hobbies.all)", a single scan may return tuples
- * of many types, so now we return pointers to tuple descriptors
- * along with tuples returned via the tuple table. -cim 1/18/90
+
+/*
+ * 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.
*
- * 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.
+ * 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
- * -jolly
+ * 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. (shouldFree should always be
+ * false in such a case, since presumably val 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().
*/
typedef struct TupleTableSlot
{
- NodeTag type;
- HeapTuple val;
- bool ttc_shouldFree;
- bool ttc_descIsNew;
- bool ttc_shouldFreeDesc;
- TupleDesc ttc_tupleDescriptor;
- Buffer ttc_buffer;
+ 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 */
} TupleTableSlot;
-/* ----------------
- * tuple table data structure
- * ----------------
+/*
+ * Tuple table data structure: an array of TupleTableSlots.
*/
typedef struct TupleTableData
{
- int size; /* size of the table */
+ int size; /* size of the table (number of slots) */
int next; /* next available slot number */
- TupleTableSlot *array; /* array of TupleTableSlot's */
-} TupleTableData;
+ TupleTableSlot array[1]; /* VARIABLE LENGTH ARRAY - must be last */
+} TupleTableData; /* VARIABLE LENGTH STRUCT */
typedef TupleTableData *TupleTable;
+
+/* in access/common/heaptuple.c */
+extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull);
+
#endif /* TUPTABLE_H */