*/
SortTupleComparator comparetup;
- /*
- * Function to copy a supplied input tuple into palloc'd space and set up
- * its SortTuple representation (ie, set tuple/datum1/isnull1). Also,
- * state->availMem must be decreased by the amount of space used for the
- * tuple copy (note the SortTuple struct itself is not counted).
- */
- void (*copytup) (Tuplesortstate *state, SortTuple *stup, void *tup);
-
/*
* 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
} while(0)
#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
-#define COPYTUP(state,stup,tup) ((*(state)->copytup) (state, stup, tup))
#define WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
* a lot better than what we were doing before 7.3. As of 9.6, a
* separate memory context is used for caller passed tuples. Resetting
* it at certain key increments significantly ameliorates fragmentation.
- * Note that this places a responsibility on copytup routines to use the
- * correct memory context for these tuples (and to not use the reset
- * context for anything whose lifetime needs to span multiple external
- * sort runs). readtup routines use the slab allocator (they cannot use
+ * readtup routines use the slab allocator (they cannot use
* the reset context because it gets deleted at the point that merging
* begins).
*/
static void *readtup_alloc(Tuplesortstate *state, Size tuplen);
static int comparetup_heap(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
-static void copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_heap(Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
static void readtup_heap(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len);
static int comparetup_cluster(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
-static void copytup_cluster(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_cluster(Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
static void readtup_cluster(Tuplesortstate *state, SortTuple *stup,
Tuplesortstate *state);
static int comparetup_index_hash(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
-static void copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_index(Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
static void readtup_index(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len);
static int comparetup_datum(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
-static void copytup_datum(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_datum(Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
PARALLEL_SORT(state));
state->comparetup = comparetup_heap;
- state->copytup = copytup_heap;
state->writetup = writetup_heap;
state->readtup = readtup_heap;
state->haveDatum1 = true;
PARALLEL_SORT(state));
state->comparetup = comparetup_cluster;
- state->copytup = copytup_cluster;
state->writetup = writetup_cluster;
state->readtup = readtup_cluster;
state->abbrevNext = 10;
PARALLEL_SORT(state));
state->comparetup = comparetup_index_btree;
- state->copytup = copytup_index;
state->writetup = writetup_index;
state->readtup = readtup_index;
state->abbrevNext = 10;
state->nKeys = 1; /* Only one sort column, the hash code */
state->comparetup = comparetup_index_hash;
- state->copytup = copytup_index;
state->writetup = writetup_index;
state->readtup = readtup_index;
state->haveDatum1 = true;
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
state->comparetup = comparetup_index_btree;
- state->copytup = copytup_index;
state->writetup = writetup_index;
state->readtup = readtup_index;
state->haveDatum1 = true;
PARALLEL_SORT(state));
state->comparetup = comparetup_datum;
- state->copytup = copytup_datum;
state->writetup = writetup_datum;
state->readtup = readtup_datum;
state->abbrevNext = 10;
void
tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
SortTuple stup;
+ Datum original;
+ MinimalTuple tuple;
+ HeapTupleData htup;
- /*
- * Copy the given tuple into memory we control, and decrease availMem.
- * Then call the common code.
- */
- COPYTUP(state, &stup, (void *) slot);
+ /* 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);
+ original = heap_getattr(&htup,
+ state->sortKeys[0].ssup_attno,
+ state->tupDesc,
+ &stup.isnull1);
+
+ MemoryContextSwitchTo(state->sortcontext);
+
+ if (!state->sortKeys->abbrev_converter || stup.isnull1)
+ {
+ /*
+ * Store ordinary Datum representation, or NULL value. If there is a
+ * converter it won't expect NULL values, and cost model is not
+ * required to account for NULL, so in that case we avoid calling
+ * converter and just set datum1 to zeroed representation (to be
+ * consistent, and to support cheap inequality tests for NULL
+ * abbreviated keys).
+ */
+ stup.datum1 = original;
+ }
+ else if (!consider_abort_common(state))
+ {
+ /* Store abbreviated key representation */
+ stup.datum1 = state->sortKeys->abbrev_converter(original,
+ state->sortKeys);
+ }
+ else
+ {
+ /* Abort abbreviation */
+ int i;
+
+ stup.datum1 = original;
+
+ /*
+ * Set state to be consistent with never trying abbreviation.
+ *
+ * Alter datum1 representation in already-copied tuples, so as to
+ * ensure a consistent representation (current tuple was just
+ * handled). It does not matter if some dumped tuples are already
+ * sorted on tape, since serialized tuples lack abbreviated keys
+ * (TSS_BUILDRUNS state prevents control reaching here in any case).
+ */
+ for (i = 0; i < state->memtupcount; i++)
+ {
+ SortTuple *mtup = &state->memtuples[i];
+
+ htup.t_len = ((MinimalTuple) mtup->tuple)->t_len +
+ MINIMAL_TUPLE_OFFSET;
+ htup.t_data = (HeapTupleHeader) ((char *) mtup->tuple -
+ MINIMAL_TUPLE_OFFSET);
+
+ mtup->datum1 = heap_getattr(&htup,
+ state->sortKeys[0].ssup_attno,
+ state->tupDesc,
+ &mtup->isnull1);
+ }
+ }
puttuple_common(state, &stup);
void
tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
SortTuple stup;
+ Datum original;
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
+
+ /* copy the tuple into sort storage */
+ tup = heap_copytuple(tup);
+ stup.tuple = (void *) tup;
+ USEMEM(state, GetMemoryChunkSpace(tup));
+
+ MemoryContextSwitchTo(state->sortcontext);
/*
- * Copy the given tuple into memory we control, and decrease availMem.
- * Then call the common code.
+ * set up first-column key value, and potentially abbreviate, if it's a
+ * simple column
*/
- COPYTUP(state, &stup, (void *) tup);
+ if (state->haveDatum1)
+ {
+ original = heap_getattr(tup,
+ state->indexInfo->ii_IndexAttrNumbers[0],
+ state->tupDesc,
+ &stup.isnull1);
+
+ if (!state->sortKeys->abbrev_converter || stup.isnull1)
+ {
+ /*
+ * Store ordinary Datum representation, or NULL value. If there
+ * is a converter it won't expect NULL values, and cost model is
+ * not required to account for NULL, so in that case we avoid
+ * calling converter and just set datum1 to zeroed representation
+ * (to be consistent, and to support cheap inequality tests for
+ * NULL abbreviated keys).
+ */
+ stup.datum1 = original;
+ }
+ else if (!consider_abort_common(state))
+ {
+ /* Store abbreviated key representation */
+ stup.datum1 = state->sortKeys->abbrev_converter(original,
+ state->sortKeys);
+ }
+ else
+ {
+ /* Abort abbreviation */
+ int i;
+
+ stup.datum1 = original;
+
+ /*
+ * Set state to be consistent with never trying abbreviation.
+ *
+ * Alter datum1 representation in already-copied tuples, so as to
+ * ensure a consistent representation (current tuple was just
+ * handled). It does not matter if some dumped tuples are already
+ * sorted on tape, since serialized tuples lack abbreviated keys
+ * (TSS_BUILDRUNS state prevents control reaching here in any
+ * case).
+ */
+ for (i = 0; i < state->memtupcount; i++)
+ {
+ SortTuple *mtup = &state->memtuples[i];
+
+ tup = (HeapTuple) mtup->tuple;
+ mtup->datum1 = heap_getattr(tup,
+ state->indexInfo->ii_IndexAttrNumbers[0],
+ state->tupDesc,
+ &mtup->isnull1);
+ }
+ }
+ }
puttuple_common(state, &stup);
return 0;
}
-static void
-copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup)
-{
- /*
- * We expect the passed "tup" to be a TupleTableSlot, and form a
- * MinimalTuple using the exported interface for that.
- */
- TupleTableSlot *slot = (TupleTableSlot *) tup;
- Datum original;
- MinimalTuple tuple;
- HeapTupleData htup;
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
-
- /* 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);
- original = heap_getattr(&htup,
- state->sortKeys[0].ssup_attno,
- state->tupDesc,
- &stup->isnull1);
-
- MemoryContextSwitchTo(oldcontext);
-
- if (!state->sortKeys->abbrev_converter || stup->isnull1)
- {
- /*
- * Store ordinary Datum representation, or NULL value. If there is a
- * converter it won't expect NULL values, and cost model is not
- * required to account for NULL, so in that case we avoid calling
- * converter and just set datum1 to zeroed representation (to be
- * consistent, and to support cheap inequality tests for NULL
- * abbreviated keys).
- */
- stup->datum1 = original;
- }
- else if (!consider_abort_common(state))
- {
- /* Store abbreviated key representation */
- stup->datum1 = state->sortKeys->abbrev_converter(original,
- state->sortKeys);
- }
- else
- {
- /* Abort abbreviation */
- int i;
-
- stup->datum1 = original;
-
- /*
- * Set state to be consistent with never trying abbreviation.
- *
- * Alter datum1 representation in already-copied tuples, so as to
- * ensure a consistent representation (current tuple was just
- * handled). It does not matter if some dumped tuples are already
- * sorted on tape, since serialized tuples lack abbreviated keys
- * (TSS_BUILDRUNS state prevents control reaching here in any case).
- */
- for (i = 0; i < state->memtupcount; i++)
- {
- SortTuple *mtup = &state->memtuples[i];
-
- htup.t_len = ((MinimalTuple) mtup->tuple)->t_len +
- MINIMAL_TUPLE_OFFSET;
- htup.t_data = (HeapTupleHeader) ((char *) mtup->tuple -
- MINIMAL_TUPLE_OFFSET);
-
- mtup->datum1 = heap_getattr(&htup,
- state->sortKeys[0].ssup_attno,
- state->tupDesc,
- &mtup->isnull1);
- }
- }
-}
-
static void
writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
return 0;
}
-static void
-copytup_cluster(Tuplesortstate *state, SortTuple *stup, void *tup)
-{
- HeapTuple tuple = (HeapTuple) tup;
- Datum original;
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
-
- /* copy the tuple into sort storage */
- tuple = heap_copytuple(tuple);
- stup->tuple = (void *) tuple;
- USEMEM(state, GetMemoryChunkSpace(tuple));
-
- MemoryContextSwitchTo(oldcontext);
-
- /*
- * set up first-column key value, and potentially abbreviate, if it's a
- * simple column
- */
- if (!state->haveDatum1)
- return;
-
- original = heap_getattr(tuple,
- state->indexInfo->ii_IndexAttrNumbers[0],
- state->tupDesc,
- &stup->isnull1);
-
- if (!state->sortKeys->abbrev_converter || stup->isnull1)
- {
- /*
- * Store ordinary Datum representation, or NULL value. If there is a
- * converter it won't expect NULL values, and cost model is not
- * required to account for NULL, so in that case we avoid calling
- * converter and just set datum1 to zeroed representation (to be
- * consistent, and to support cheap inequality tests for NULL
- * abbreviated keys).
- */
- stup->datum1 = original;
- }
- else if (!consider_abort_common(state))
- {
- /* Store abbreviated key representation */
- stup->datum1 = state->sortKeys->abbrev_converter(original,
- state->sortKeys);
- }
- else
- {
- /* Abort abbreviation */
- int i;
-
- stup->datum1 = original;
-
- /*
- * Set state to be consistent with never trying abbreviation.
- *
- * Alter datum1 representation in already-copied tuples, so as to
- * ensure a consistent representation (current tuple was just
- * handled). It does not matter if some dumped tuples are already
- * sorted on tape, since serialized tuples lack abbreviated keys
- * (TSS_BUILDRUNS state prevents control reaching here in any case).
- */
- for (i = 0; i < state->memtupcount; i++)
- {
- SortTuple *mtup = &state->memtuples[i];
-
- tuple = (HeapTuple) mtup->tuple;
- mtup->datum1 = heap_getattr(tuple,
- state->indexInfo->ii_IndexAttrNumbers[0],
- state->tupDesc,
- &mtup->isnull1);
- }
- }
-}
-
static void
writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
return 0;
}
-static void
-copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup)
-{
- /* Not currently needed */
- elog(ERROR, "copytup_index() should not be called");
-}
-
static void
writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
return compare;
}
-static void
-copytup_datum(Tuplesortstate *state, SortTuple *stup, void *tup)
-{
- /* Not currently needed */
- elog(ERROR, "copytup_datum() should not be called");
-}
-
static void
writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{