summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/sort/tuplestore.c73
1 files changed, 71 insertions, 2 deletions
diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index bcba30e5981..a5a56be91b2 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -57,6 +57,7 @@
#include "access/htup_details.h"
#include "commands/tablespace.h"
#include "executor/executor.h"
+#include "miscadmin.h"
#include "storage/buffile.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
@@ -1065,8 +1066,7 @@ tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
* 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. (XXX this probably needs to be
- * reconsidered given the needs of window functions.)
+ * moment it doesn't seem worthwhile.
*/
bool
tuplestore_advance(Tuplestorestate *state, bool forward)
@@ -1089,6 +1089,75 @@ tuplestore_advance(Tuplestorestate *state, bool forward)
}
/*
+ * Advance over N tuples in either forward or back direction,
+ * without returning any data. N<=0 is a no-op.
+ * Returns TRUE if successful, FALSE if ran out of tuples.
+ */
+bool
+tuplestore_skiptuples(Tuplestorestate *state, int64 ntuples, bool forward)
+{
+ TSReadPointer *readptr = &state->readptrs[state->activeptr];
+
+ Assert(forward || (readptr->eflags & EXEC_FLAG_BACKWARD));
+
+ if (ntuples <= 0)
+ return true;
+
+ switch (state->status)
+ {
+ case TSS_INMEM:
+ if (forward)
+ {
+ if (readptr->eof_reached)
+ return false;
+ if (state->memtupcount - readptr->current >= ntuples)
+ {
+ readptr->current += ntuples;
+ return true;
+ }
+ readptr->current = state->memtupcount;
+ readptr->eof_reached = true;
+ return false;
+ }
+ else
+ {
+ if (readptr->eof_reached)
+ {
+ readptr->current = state->memtupcount;
+ readptr->eof_reached = false;
+ ntuples--;
+ }
+ if (readptr->current - state->memtupdeleted > ntuples)
+ {
+ readptr->current -= ntuples;
+ return true;
+ }
+ Assert(!state->truncated);
+ readptr->current = state->memtupdeleted;
+ return false;
+ }
+ break;
+
+ default:
+ /* We don't currently try hard to optimize other cases */
+ while (ntuples-- > 0)
+ {
+ void *tuple;
+ bool should_free;
+
+ tuple = tuplestore_gettuple(state, forward, &should_free);
+
+ if (tuple == NULL)
+ return false;
+ if (should_free)
+ pfree(tuple);
+ CHECK_FOR_INTERRUPTS();
+ }
+ return true;
+ }
+}
+
+/*
* dumptuples - remove tuples from memory and write to tape
*
* As a side effect, we must convert each read pointer's position from