aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execTuples.c139
-rw-r--r--src/backend/executor/nodeFunctionscan.c15
-rw-r--r--src/backend/executor/nodeMaterial.c44
-rw-r--r--src/backend/executor/tstoreReceiver.c4
4 files changed, 154 insertions, 48 deletions
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 971822525f0..f03d738619d 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.94 2006/06/16 18:42:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.95 2006/06/27 02:51:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,6 +25,8 @@
* TABLE CREATE/DELETE
* ExecCreateTupleTable - create a new tuple table
* ExecDropTupleTable - destroy a table
+ * MakeSingleTupleTableSlot - make a single-slot table
+ * ExecDropSingleTupleTableSlot - destroy same
*
* SLOT RESERVATION
* ExecAllocTableSlot - find an available slot in the table
@@ -32,9 +34,11 @@
* SLOT ACCESSORS
* ExecSetSlotDescriptor - set a slot's tuple descriptor
* ExecStoreTuple - store a physical tuple in the slot
+ * ExecStoreMinimalTuple - store a minimal physical tuple in the slot
* ExecClearTuple - clear contents of a slot
* ExecStoreVirtualTuple - mark slot as containing a virtual tuple
* ExecCopySlotTuple - build a physical tuple from a slot
+ * ExecCopySlotMinimalTuple - build a minimal physical tuple from a slot
* ExecMaterializeSlot - convert virtual to physical storage
* ExecCopySlot - copy one slot's contents to another
*
@@ -150,6 +154,7 @@ ExecCreateTupleTable(int tableSize)
slot->tts_nvalid = 0;
slot->tts_values = NULL;
slot->tts_isnull = NULL;
+ slot->tts_mintuple = NULL;
}
return newtable;
@@ -227,6 +232,7 @@ MakeSingleTupleTableSlot(TupleDesc tupdesc)
slot->tts_nvalid = 0;
slot->tts_values = NULL;
slot->tts_isnull = NULL;
+ slot->tts_mintuple = NULL;
ExecSetSlotDescriptor(slot, tupdesc);
@@ -405,7 +411,12 @@ ExecStoreTuple(HeapTuple tuple,
* Free any old physical tuple belonging to the slot.
*/
if (slot->tts_shouldFree)
- heap_freetuple(slot->tts_tuple);
+ {
+ if (slot->tts_mintuple)
+ heap_free_minimal_tuple(slot->tts_mintuple);
+ else
+ heap_freetuple(slot->tts_tuple);
+ }
/*
* Store the new tuple into the specified slot.
@@ -413,6 +424,7 @@ ExecStoreTuple(HeapTuple tuple,
slot->tts_isempty = false;
slot->tts_shouldFree = shouldFree;
slot->tts_tuple = tuple;
+ slot->tts_mintuple = NULL;
/* Mark extracted state invalid */
slot->tts_nvalid = 0;
@@ -439,6 +451,63 @@ ExecStoreTuple(HeapTuple tuple,
}
/* --------------------------------
+ * ExecStoreMinimalTuple
+ *
+ * Like ExecStoreTuple, but insert a "minimal" tuple into the slot.
+ *
+ * No 'buffer' parameter since minimal tuples are never stored in relations.
+ * --------------------------------
+ */
+TupleTableSlot *
+ExecStoreMinimalTuple(MinimalTuple mtup,
+ TupleTableSlot *slot,
+ bool shouldFree)
+{
+ /*
+ * sanity checks
+ */
+ Assert(mtup != NULL);
+ Assert(slot != NULL);
+ Assert(slot->tts_tupleDescriptor != NULL);
+
+ /*
+ * Free any old physical tuple belonging to the slot.
+ */
+ if (slot->tts_shouldFree)
+ {
+ if (slot->tts_mintuple)
+ heap_free_minimal_tuple(slot->tts_mintuple);
+ else
+ heap_freetuple(slot->tts_tuple);
+ }
+
+ /*
+ * Drop the pin on the referenced buffer, if there is one.
+ */
+ if (BufferIsValid(slot->tts_buffer))
+ ReleaseBuffer(slot->tts_buffer);
+
+ slot->tts_buffer = InvalidBuffer;
+
+ /*
+ * Store the new tuple into the specified slot.
+ */
+ slot->tts_isempty = false;
+ slot->tts_shouldFree = shouldFree;
+ slot->tts_tuple = &slot->tts_minhdr;
+ slot->tts_mintuple = mtup;
+
+ slot->tts_minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+ slot->tts_minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+ /* no need to set t_self or t_tableOid since we won't allow access */
+
+ /* Mark extracted state invalid */
+ slot->tts_nvalid = 0;
+
+ return slot;
+}
+
+/* --------------------------------
* ExecClearTuple
*
* This function is used to clear out a slot in the tuple table.
@@ -458,9 +527,15 @@ ExecClearTuple(TupleTableSlot *slot) /* slot in which to store tuple */
* Free the old physical tuple if necessary.
*/
if (slot->tts_shouldFree)
- heap_freetuple(slot->tts_tuple);
+ {
+ if (slot->tts_mintuple)
+ heap_free_minimal_tuple(slot->tts_mintuple);
+ else
+ heap_freetuple(slot->tts_tuple);
+ }
slot->tts_tuple = NULL;
+ slot->tts_mintuple = NULL;
slot->tts_shouldFree = false;
/*
@@ -540,10 +615,10 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
/* --------------------------------
* ExecCopySlotTuple
- * Obtain a copy of a slot's physical tuple. The copy is
+ * Obtain a copy of a slot's regular physical tuple. The copy is
* palloc'd in the current memory context.
*
- * This works even if the slot contains a virtual tuple;
+ * This works even if the slot contains a virtual or minimal tuple;
* however the "system columns" of the result will not be meaningful.
* --------------------------------
*/
@@ -560,7 +635,12 @@ ExecCopySlotTuple(TupleTableSlot *slot)
* If we have a physical tuple then just copy it.
*/
if (slot->tts_tuple)
- return heap_copytuple(slot->tts_tuple);
+ {
+ if (slot->tts_mintuple)
+ return heap_tuple_from_minimal_tuple(slot->tts_mintuple);
+ else
+ return heap_copytuple(slot->tts_tuple);
+ }
/*
* Otherwise we need to build a tuple from the Datum array.
@@ -571,11 +651,46 @@ ExecCopySlotTuple(TupleTableSlot *slot)
}
/* --------------------------------
+ * ExecCopySlotMinimalTuple
+ * Obtain a copy of a slot's minimal physical tuple. The copy is
+ * palloc'd in the current memory context.
+ * --------------------------------
+ */
+MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+ /*
+ * sanity checks
+ */
+ Assert(slot != NULL);
+ Assert(!slot->tts_isempty);
+
+ /*
+ * If we have a physical tuple then just copy it.
+ */
+ if (slot->tts_tuple)
+ {
+ if (slot->tts_mintuple)
+ return heap_copy_minimal_tuple(slot->tts_mintuple);
+ else
+ return minimal_tuple_from_heap_tuple(slot->tts_tuple);
+ }
+
+ /*
+ * Otherwise we need to build a tuple from the Datum array.
+ */
+ return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
+ slot->tts_values,
+ slot->tts_isnull);
+}
+
+/* --------------------------------
* ExecFetchSlotTuple
- * Fetch the slot's physical tuple.
+ * Fetch the slot's regular physical tuple.
*
* If the slot contains a virtual tuple, we convert it to physical
* form. The slot retains ownership of the physical tuple.
+ * Likewise, if it contains a minimal tuple we convert to regular form.
*
* The difference between this and ExecMaterializeSlot() is that this
* does not guarantee that the contained tuple is local storage.
@@ -592,9 +707,9 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
Assert(!slot->tts_isempty);
/*
- * If we have a physical tuple then just return it.
+ * If we have a regular physical tuple then just return it.
*/
- if (slot->tts_tuple)
+ if (slot->tts_tuple && slot->tts_mintuple == NULL)
return slot->tts_tuple;
/*
@@ -629,10 +744,10 @@ ExecMaterializeSlot(TupleTableSlot *slot)
Assert(!slot->tts_isempty);
/*
- * If we have a physical tuple, and it's locally palloc'd, we have nothing
- * to do.
+ * If we have a regular physical tuple, and it's locally palloc'd,
+ * we have nothing to do.
*/
- if (slot->tts_tuple && slot->tts_shouldFree)
+ if (slot->tts_tuple && slot->tts_shouldFree && slot->tts_mintuple == NULL)
return slot->tts_tuple;
/*
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 0c77e821690..90ab0188743 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.39 2006/06/16 18:42:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.40 2006/06/27 02:51:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,8 +48,6 @@ FunctionNext(FunctionScanState *node)
EState *estate;
ScanDirection direction;
Tuplestorestate *tuplestorestate;
- bool should_free;
- HeapTuple heapTuple;
/*
* get information from the estate and scan state
@@ -86,14 +84,11 @@ FunctionNext(FunctionScanState *node)
/*
* Get the next tuple from tuplestore. Return NULL if no more tuples.
*/
- heapTuple = tuplestore_getheaptuple(tuplestorestate,
- ScanDirectionIsForward(direction),
- &should_free);
slot = node->ss.ss_ScanTupleSlot;
- if (heapTuple)
- return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
- else
- return ExecClearTuple(slot);
+ (void) tuplestore_gettupleslot(tuplestorestate,
+ ScanDirectionIsForward(direction),
+ slot);
+ return slot;
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index eca769a86cc..94a07013854 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.54 2006/03/05 15:58:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.55 2006/06/27 02:51:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,8 +44,6 @@ ExecMaterial(MaterialState *node)
ScanDirection dir;
bool forward;
Tuplestorestate *tuplestorestate;
- HeapTuple heapTuple = NULL;
- bool should_free = false;
bool eof_tuplestore;
TupleTableSlot *slot;
@@ -80,27 +78,25 @@ ExecMaterial(MaterialState *node)
{
/*
* When reversing direction at tuplestore EOF, the first
- * getheaptuple call will fetch the last-added tuple; but we want
+ * gettupleslot call will fetch the last-added tuple; but we want
* to return the one before that, if possible. So do an extra
* fetch.
*/
- heapTuple = tuplestore_getheaptuple(tuplestorestate,
- forward,
- &should_free);
- if (heapTuple == NULL)
+ if (!tuplestore_advance(tuplestorestate, forward))
return NULL; /* the tuplestore must be empty */
- if (should_free)
- heap_freetuple(heapTuple);
}
eof_tuplestore = false;
}
+ /*
+ * If we can fetch another tuple from the tuplestore, return it.
+ */
+ slot = node->ss.ps.ps_ResultTupleSlot;
if (!eof_tuplestore)
{
- heapTuple = tuplestore_getheaptuple(tuplestorestate,
- forward,
- &should_free);
- if (heapTuple == NULL && forward)
+ if (tuplestore_gettupleslot(tuplestorestate, forward, slot))
+ return slot;
+ if (forward)
eof_tuplestore = true;
}
@@ -128,26 +124,26 @@ ExecMaterial(MaterialState *node)
node->eof_underlying = true;
return NULL;
}
- heapTuple = ExecFetchSlotTuple(outerslot);
- should_free = false;
/*
- * Append returned tuple to tuplestore, too. NOTE: because the
+ * Append returned tuple to tuplestore. NOTE: because the
* tuplestore is certainly in EOF state, its read position will move
* forward over the added tuple. This is what we want.
*/
if (tuplestorestate)
- tuplestore_puttuple(tuplestorestate, (void *) heapTuple);
+ tuplestore_puttupleslot(tuplestorestate, outerslot);
+
+ /*
+ * And return a copy of the tuple. (XXX couldn't we just return
+ * the outerslot?)
+ */
+ return ExecCopySlot(slot, outerslot);
}
/*
- * Return the obtained tuple, if any.
+ * Nothing left ...
*/
- slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot;
- if (heapTuple)
- return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
- else
- return ExecClearTuple(slot);
+ return ExecClearTuple(slot);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index dffc8899b23..8ebf5b7fd1d 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/tstoreReceiver.c,v 1.16 2006/03/05 15:58:27 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/tstoreReceiver.c,v 1.17 2006/06/27 02:51:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,7 +45,7 @@ tstoreReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TStoreState *myState = (TStoreState *) self;
MemoryContext oldcxt = MemoryContextSwitchTo(myState->cxt);
- tuplestore_puttuple(myState->tstore, ExecFetchSlotTuple(slot));
+ tuplestore_puttupleslot(myState->tstore, slot);
MemoryContextSwitchTo(oldcxt);
}