diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execTuples.c | 139 | ||||
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 15 | ||||
-rw-r--r-- | src/backend/executor/nodeMaterial.c | 44 | ||||
-rw-r--r-- | src/backend/executor/tstoreReceiver.c | 4 |
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); } |