1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-08 11:42:09 +03:00

Create infrastructure for 'MinimalTuple' representation of in-memory

tuples with less header overhead than a regular HeapTuple, per my
recent proposal.  Teach TupleTableSlot code how to deal with these.
As proof of concept, change tuplestore.c to store MinimalTuples instead
of HeapTuples.  Future patches will expand the concept to other places
where it is useful.
This commit is contained in:
Tom Lane
2006-06-27 02:51:40 +00:00
parent fe491fb9af
commit 3f50ba27cf
13 changed files with 558 additions and 129 deletions

View File

@ -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;
@ -438,6 +450,63 @@ ExecStoreTuple(HeapTuple tuple,
return slot;
}
/* --------------------------------
* 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
*
@ -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.
@ -570,12 +650,47 @@ ExecCopySlotTuple(TupleTableSlot *slot)
slot->tts_isnull);
}
/* --------------------------------
* 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;
/*