diff options
Diffstat (limited to 'src/backend/utils/sort/tuplestore.c')
-rw-r--r-- | src/backend/utils/sort/tuplestore.c | 130 |
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, |