/*
* Function to write a stored tuple onto tape. The representation of the
- * tuple on tape need not be the same as it is in memory; requirements on
- * the tape representation are given below. Unless the slab allocator is
- * used, after writing the tuple, pfree() the out-of-line data (not the
- * SortTuple struct!), and increase state->availMem by the amount of
- * memory space thereby released.
+ * tuple on tape need not be the same as it is in memory.
*/
void (*writetup) (Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
#define REMOVEABBREV(state,stup,count) ((*(state)->removeabbrev) (state, stup, count))
#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
-#define WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
+#define WRITETUP(state,tape,stup) (writetuple(state, tape, stup))
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
#define USEMEM(state,amt) ((state)->availMem -= (amt))
static void tuplesort_begin_batch(Tuplesortstate *state);
static void puttuple_common(Tuplesortstate *state, SortTuple *tuple,
bool useAbbrev);
+static void writetuple(Tuplesortstate *state, LogicalTape *tape,
+ SortTuple *stup);
static bool consider_abort_common(Tuplesortstate *state);
static void inittapes(Tuplesortstate *state, bool mergeruns);
static void inittapestate(Tuplesortstate *state, int maxTapes);
/* copy the tuple into sort storage */
tuple = ExecCopySlotMinimalTuple(slot);
stup.tuple = (void *) tuple;
- USEMEM(state, GetMemoryChunkSpace(tuple));
/* set up first-column key value */
htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET;
htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET);
state->tupDesc,
&stup.isnull1);
- MemoryContextSwitchTo(state->sortcontext);
-
puttuple_common(state, &stup,
state->sortKeys->abbrev_converter && !stup.isnull1);
/* copy the tuple into sort storage */
tup = heap_copytuple(tup);
stup.tuple = (void *) tup;
- USEMEM(state, GetMemoryChunkSpace(tup));
-
- MemoryContextSwitchTo(state->sortcontext);
/*
* set up first-column key value, and potentially abbreviate, if it's a
ItemPointer self, Datum *values,
bool *isnull)
{
- MemoryContext oldcontext;
SortTuple stup;
IndexTuple tuple;
isnull, state->tuplecontext);
tuple = ((IndexTuple) stup.tuple);
tuple->t_tid = *self;
- USEMEM(state, GetMemoryChunkSpace(stup.tuple));
/* set up first-column key value */
stup.datum1 = index_getattr(tuple,
1,
RelationGetDescr(state->indexRel),
&stup.isnull1);
- oldcontext = MemoryContextSwitchTo(state->sortcontext);
-
puttuple_common(state, &stup,
state->sortKeys && state->sortKeys->abbrev_converter && !stup.isnull1);
-
- MemoryContextSwitchTo(oldcontext);
}
/*
stup.datum1 = !isNull ? val : (Datum) 0;
stup.isnull1 = isNull;
stup.tuple = NULL; /* no separate storage */
- MemoryContextSwitchTo(state->sortcontext);
}
else
{
stup.isnull1 = false;
stup.datum1 = datumCopy(val, false, state->datumTypeLen);
stup.tuple = DatumGetPointer(stup.datum1);
- USEMEM(state, GetMemoryChunkSpace(stup.tuple));
- MemoryContextSwitchTo(state->sortcontext);
}
puttuple_common(state, &stup,
static void
puttuple_common(Tuplesortstate *state, SortTuple *tuple, bool useAbbrev)
{
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+
Assert(!LEADER(state));
+ /* Count the size of the out-of-line data */
+ if (tuple->tuple != NULL)
+ USEMEM(state, GetMemoryChunkSpace(tuple->tuple));
+
if (!useAbbrev)
{
/*
pg_rusage_show(&state->ru_start));
#endif
make_bounded_heap(state);
+ MemoryContextSwitchTo(oldcontext);
return;
}
* Done if we still fit in available memory and have array slots.
*/
if (state->memtupcount < state->memtupsize && !LACKMEM(state))
+ {
+ MemoryContextSwitchTo(oldcontext);
return;
+ }
/*
* Nope; time to switch to tape-based operation.
elog(ERROR, "invalid tuplesort state");
break;
}
+ MemoryContextSwitchTo(oldcontext);
+}
+
+/*
+ * Write a stored tuple onto tape.tuple. Unless the slab allocator is
+ * used, after writing the tuple, pfree() the out-of-line data (not the
+ * SortTuple struct!), and increase state->availMem by the amount of
+ * memory space thereby released.
+ */
+static void
+writetuple(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
+{
+ state->writetup(state, tape, stup);
+
+ if (!state->slabAllocatorUsed && stup->tuple)
+ {
+ FREEMEM(state, GetMemoryChunkSpace(stup->tuple));
+ pfree(stup->tuple);
+ }
}
static bool
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
-
- if (!state->slabAllocatorUsed)
- {
- FREEMEM(state, GetMemoryChunkSpace(tuple));
- heap_free_minimal_tuple(tuple);
- }
}
static void
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
-
- if (!state->slabAllocatorUsed)
- {
- FREEMEM(state, GetMemoryChunkSpace(tuple));
- heap_freetuple(tuple);
- }
}
static void
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
-
- if (!state->slabAllocatorUsed)
- {
- FREEMEM(state, GetMemoryChunkSpace(tuple));
- pfree(tuple);
- }
}
static void
if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
-
- if (!state->slabAllocatorUsed && stup->tuple)
- {
- FREEMEM(state, GetMemoryChunkSpace(stup->tuple));
- pfree(stup->tuple);
- }
}
static void