aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/sort/tuplestore.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/sort/tuplestore.c')
-rw-r--r--src/backend/utils/sort/tuplestore.c130
1 files changed, 104 insertions, 26 deletions
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index 6ff6b72082c..a2ed330ccc6 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -36,7 +36,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.27 2006/03/05 15:58:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/sort/tuplestore.c,v 1.28 2006/06/27 02:51:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -195,6 +195,7 @@ struct Tuplestorestate
static Tuplestorestate *tuplestore_begin_common(bool randomAccess,
bool interXact,
int maxKBytes);
+static void tuplestore_puttuple_common(Tuplestorestate *state, void *tuple);
static void dumptuples(Tuplestorestate *state);
static unsigned int getlen(Tuplestorestate *state, bool eofOK);
static void *copytup_heap(Tuplestorestate *state, void *tup);
@@ -304,15 +305,45 @@ tuplestore_ateof(Tuplestorestate *state)
* If the read status is currently "AT EOF" then it remains so (the read
* pointer advances along with the write pointer); otherwise the read
* pointer is unchanged. This is for the convenience of nodeMaterial.c.
+ *
+ * tuplestore_puttupleslot() is a convenience routine to collect data from
+ * a TupleTableSlot without an extra copy operation.
*/
void
-tuplestore_puttuple(Tuplestorestate *state, void *tuple)
+tuplestore_puttupleslot(Tuplestorestate *state,
+ TupleTableSlot *slot)
+{
+ MinimalTuple tuple;
+
+ /*
+ * Form a MinimalTuple in working memory
+ */
+ tuple = ExecCopySlotMinimalTuple(slot);
+ USEMEM(state, GetMemoryChunkSpace(tuple));
+
+ tuplestore_puttuple_common(state, (void *) tuple);
+}
+
+/*
+ * "Standard" case to copy from a HeapTuple. This is actually now somewhat
+ * deprecated, but not worth getting rid of in view of the number of callers.
+ * (Consider adding something that takes a tupdesc+values/nulls arrays so
+ * that we can use heap_form_minimal_tuple() and avoid a copy step.)
+ */
+void
+tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
{
/*
* Copy the tuple. (Must do this even in WRITEFILE case.)
*/
tuple = COPYTUP(state, tuple);
+ tuplestore_puttuple_common(state, (void *) tuple);
+}
+
+static void
+tuplestore_puttuple_common(Tuplestorestate *state, void *tuple)
+{
switch (state->status)
{
case TSS_INMEM:
@@ -389,7 +420,7 @@ tuplestore_puttuple(Tuplestorestate *state, void *tuple)
* Returns NULL if no more tuples. If should_free is set, the
* caller must pfree the returned tuple when done with it.
*/
-void *
+static void *
tuplestore_gettuple(Tuplestorestate *state, bool forward,
bool *should_free)
{
@@ -526,6 +557,59 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
}
/*
+ * tuplestore_gettupleslot - exported function to fetch a MinimalTuple
+ *
+ * If successful, put tuple in slot and return TRUE; else, clear the slot
+ * and return FALSE.
+ */
+bool
+tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
+ TupleTableSlot *slot)
+{
+ MinimalTuple tuple;
+ bool should_free;
+
+ tuple = (MinimalTuple) tuplestore_gettuple(state, forward, &should_free);
+
+ if (tuple)
+ {
+ ExecStoreMinimalTuple(tuple, slot, should_free);
+ return true;
+ }
+ else
+ {
+ ExecClearTuple(slot);
+ return false;
+ }
+}
+
+/*
+ * tuplestore_advance - exported function to adjust position without fetching
+ *
+ * We could optimize this case to avoid palloc/pfree overhead, but for the
+ * moment it doesn't seem worthwhile.
+ */
+bool
+tuplestore_advance(Tuplestorestate *state, bool forward)
+{
+ void *tuple;
+ bool should_free;
+
+ tuple = tuplestore_gettuple(state, forward, &should_free);
+
+ if (tuple)
+ {
+ if (should_free)
+ pfree(tuple);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/*
* dumptuples - remove tuples from memory and write to tape
*
* As a side effect, we must set readpos and markpos to the value
@@ -672,34 +756,31 @@ getlen(Tuplestorestate *state, bool eofOK)
/*
* Routines specialized for HeapTuple case
+ *
+ * The stored form is actually a MinimalTuple, but for largely historical
+ * reasons we allow COPYTUP to work from a HeapTuple.
+ *
+ * Since MinimalTuple already has length in its first word, we don't need
+ * to write that separately.
*/
static void *
copytup_heap(Tuplestorestate *state, void *tup)
{
- HeapTuple tuple = (HeapTuple) tup;
+ MinimalTuple tuple;
- tuple = heap_copytuple(tuple);
+ tuple = minimal_tuple_from_heap_tuple((HeapTuple) tup);
USEMEM(state, GetMemoryChunkSpace(tuple));
return (void *) tuple;
}
-/*
- * We don't bother to write the HeapTupleData part of the tuple.
- */
-
static void
writetup_heap(Tuplestorestate *state, void *tup)
{
- HeapTuple tuple = (HeapTuple) tup;
- unsigned int tuplen;
+ MinimalTuple tuple = (MinimalTuple) tup;
+ unsigned int tuplen = tuple->t_len;
- tuplen = tuple->t_len + sizeof(tuplen);
- if (BufFileWrite(state->myfile, (void *) &tuplen,
- sizeof(tuplen)) != sizeof(tuplen))
- elog(ERROR, "write failed");
- if (BufFileWrite(state->myfile, (void *) tuple->t_data,
- tuple->t_len) != (size_t) tuple->t_len)
+ if (BufFileWrite(state->myfile, (void *) tuple, tuplen) != (size_t) tuplen)
elog(ERROR, "write failed");
if (state->randomAccess) /* need trailing length word? */
if (BufFileWrite(state->myfile, (void *) &tuplen,
@@ -707,23 +788,20 @@ writetup_heap(Tuplestorestate *state, void *tup)
elog(ERROR, "write failed");
FREEMEM(state, GetMemoryChunkSpace(tuple));
- heap_freetuple(tuple);
+ heap_free_minimal_tuple(tuple);
}
static void *
readtup_heap(Tuplestorestate *state, unsigned int len)
{
- unsigned int tuplen = len - sizeof(unsigned int) + HEAPTUPLESIZE;
- HeapTuple tuple = (HeapTuple) palloc(tuplen);
+ MinimalTuple tuple = (MinimalTuple) palloc(len);
+ unsigned int tuplen;
USEMEM(state, GetMemoryChunkSpace(tuple));
- /* reconstruct the HeapTupleData portion */
- tuple->t_len = len - sizeof(unsigned int);
- ItemPointerSetInvalid(&(tuple->t_self));
- tuple->t_data = (HeapTupleHeader) (((char *) tuple) + HEAPTUPLESIZE);
/* read in the tuple proper */
- if (BufFileRead(state->myfile, (void *) tuple->t_data,
- tuple->t_len) != (size_t) tuple->t_len)
+ tuple->t_len = len;
+ if (BufFileRead(state->myfile, (void *) ((char *) tuple + sizeof(int)),
+ len - sizeof(int)) != (size_t) (len - sizeof(int)))
elog(ERROR, "unexpected end of data");
if (state->randomAccess) /* need trailing length word? */
if (BufFileRead(state->myfile, (void *) &tuplen,