mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Remove Tuplesortstate.copytup function
It's currently unclear how do we split functionality between Tuplesortstate.copytup() function and tuplesort_put*() functions. For instance, copytup_index() and copytup_datum() return error while tuplesort_putindextuplevalues() and tuplesort_putdatum() do their work. This commit removes Tuplesortstate.copytup() altogether, putting the corresponding code into tuplesort_put*(). Discussion: https://postgr.es/m/CAPpHfdvjix0Ahx-H3Jp1M2R%2B_74P-zKnGGygx4OWr%3DbUQ8BNdw%40mail.gmail.com Author: Alexander Korotkov Reviewed-by: Pavel Borisov, Maxim Orlov, Matthias van de Meent Reviewed-by: Andres Freund, John Naylor
This commit is contained in:
parent
ffd1b6bb6f
commit
d47da3162b
@ -279,14 +279,6 @@ struct Tuplesortstate
|
|||||||
*/
|
*/
|
||||||
SortTupleComparator comparetup;
|
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
|
* 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
|
* tuple on tape need not be the same as it is in memory; requirements on
|
||||||
@ -549,7 +541,6 @@ struct Sharedsort
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
|
#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 WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
|
||||||
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
|
#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
|
||||||
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
|
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
|
||||||
@ -600,10 +591,7 @@ struct Sharedsort
|
|||||||
* a lot better than what we were doing before 7.3. As of 9.6, a
|
* 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
|
* separate memory context is used for caller passed tuples. Resetting
|
||||||
* it at certain key increments significantly ameliorates fragmentation.
|
* it at certain key increments significantly ameliorates fragmentation.
|
||||||
* Note that this places a responsibility on copytup routines to use the
|
* readtup routines use the slab allocator (they cannot use
|
||||||
* 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
|
|
||||||
* the reset context because it gets deleted at the point that merging
|
* the reset context because it gets deleted at the point that merging
|
||||||
* begins).
|
* begins).
|
||||||
*/
|
*/
|
||||||
@ -643,14 +631,12 @@ static void markrunend(LogicalTape *tape);
|
|||||||
static void *readtup_alloc(Tuplesortstate *state, Size tuplen);
|
static void *readtup_alloc(Tuplesortstate *state, Size tuplen);
|
||||||
static int comparetup_heap(const SortTuple *a, const SortTuple *b,
|
static int comparetup_heap(const SortTuple *a, const SortTuple *b,
|
||||||
Tuplesortstate *state);
|
Tuplesortstate *state);
|
||||||
static void copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup);
|
|
||||||
static void writetup_heap(Tuplesortstate *state, LogicalTape *tape,
|
static void writetup_heap(Tuplesortstate *state, LogicalTape *tape,
|
||||||
SortTuple *stup);
|
SortTuple *stup);
|
||||||
static void readtup_heap(Tuplesortstate *state, SortTuple *stup,
|
static void readtup_heap(Tuplesortstate *state, SortTuple *stup,
|
||||||
LogicalTape *tape, unsigned int len);
|
LogicalTape *tape, unsigned int len);
|
||||||
static int comparetup_cluster(const SortTuple *a, const SortTuple *b,
|
static int comparetup_cluster(const SortTuple *a, const SortTuple *b,
|
||||||
Tuplesortstate *state);
|
Tuplesortstate *state);
|
||||||
static void copytup_cluster(Tuplesortstate *state, SortTuple *stup, void *tup);
|
|
||||||
static void writetup_cluster(Tuplesortstate *state, LogicalTape *tape,
|
static void writetup_cluster(Tuplesortstate *state, LogicalTape *tape,
|
||||||
SortTuple *stup);
|
SortTuple *stup);
|
||||||
static void readtup_cluster(Tuplesortstate *state, SortTuple *stup,
|
static void readtup_cluster(Tuplesortstate *state, SortTuple *stup,
|
||||||
@ -659,14 +645,12 @@ static int comparetup_index_btree(const SortTuple *a, const SortTuple *b,
|
|||||||
Tuplesortstate *state);
|
Tuplesortstate *state);
|
||||||
static int comparetup_index_hash(const SortTuple *a, const SortTuple *b,
|
static int comparetup_index_hash(const SortTuple *a, const SortTuple *b,
|
||||||
Tuplesortstate *state);
|
Tuplesortstate *state);
|
||||||
static void copytup_index(Tuplesortstate *state, SortTuple *stup, void *tup);
|
|
||||||
static void writetup_index(Tuplesortstate *state, LogicalTape *tape,
|
static void writetup_index(Tuplesortstate *state, LogicalTape *tape,
|
||||||
SortTuple *stup);
|
SortTuple *stup);
|
||||||
static void readtup_index(Tuplesortstate *state, SortTuple *stup,
|
static void readtup_index(Tuplesortstate *state, SortTuple *stup,
|
||||||
LogicalTape *tape, unsigned int len);
|
LogicalTape *tape, unsigned int len);
|
||||||
static int comparetup_datum(const SortTuple *a, const SortTuple *b,
|
static int comparetup_datum(const SortTuple *a, const SortTuple *b,
|
||||||
Tuplesortstate *state);
|
Tuplesortstate *state);
|
||||||
static void copytup_datum(Tuplesortstate *state, SortTuple *stup, void *tup);
|
|
||||||
static void writetup_datum(Tuplesortstate *state, LogicalTape *tape,
|
static void writetup_datum(Tuplesortstate *state, LogicalTape *tape,
|
||||||
SortTuple *stup);
|
SortTuple *stup);
|
||||||
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
|
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
|
||||||
@ -1059,7 +1043,6 @@ tuplesort_begin_heap(TupleDesc tupDesc,
|
|||||||
PARALLEL_SORT(state));
|
PARALLEL_SORT(state));
|
||||||
|
|
||||||
state->comparetup = comparetup_heap;
|
state->comparetup = comparetup_heap;
|
||||||
state->copytup = copytup_heap;
|
|
||||||
state->writetup = writetup_heap;
|
state->writetup = writetup_heap;
|
||||||
state->readtup = readtup_heap;
|
state->readtup = readtup_heap;
|
||||||
state->haveDatum1 = true;
|
state->haveDatum1 = true;
|
||||||
@ -1135,7 +1118,6 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
|
|||||||
PARALLEL_SORT(state));
|
PARALLEL_SORT(state));
|
||||||
|
|
||||||
state->comparetup = comparetup_cluster;
|
state->comparetup = comparetup_cluster;
|
||||||
state->copytup = copytup_cluster;
|
|
||||||
state->writetup = writetup_cluster;
|
state->writetup = writetup_cluster;
|
||||||
state->readtup = readtup_cluster;
|
state->readtup = readtup_cluster;
|
||||||
state->abbrevNext = 10;
|
state->abbrevNext = 10;
|
||||||
@ -1240,7 +1222,6 @@ tuplesort_begin_index_btree(Relation heapRel,
|
|||||||
PARALLEL_SORT(state));
|
PARALLEL_SORT(state));
|
||||||
|
|
||||||
state->comparetup = comparetup_index_btree;
|
state->comparetup = comparetup_index_btree;
|
||||||
state->copytup = copytup_index;
|
|
||||||
state->writetup = writetup_index;
|
state->writetup = writetup_index;
|
||||||
state->readtup = readtup_index;
|
state->readtup = readtup_index;
|
||||||
state->abbrevNext = 10;
|
state->abbrevNext = 10;
|
||||||
@ -1317,7 +1298,6 @@ tuplesort_begin_index_hash(Relation heapRel,
|
|||||||
state->nKeys = 1; /* Only one sort column, the hash code */
|
state->nKeys = 1; /* Only one sort column, the hash code */
|
||||||
|
|
||||||
state->comparetup = comparetup_index_hash;
|
state->comparetup = comparetup_index_hash;
|
||||||
state->copytup = copytup_index;
|
|
||||||
state->writetup = writetup_index;
|
state->writetup = writetup_index;
|
||||||
state->readtup = readtup_index;
|
state->readtup = readtup_index;
|
||||||
state->haveDatum1 = true;
|
state->haveDatum1 = true;
|
||||||
@ -1358,7 +1338,6 @@ tuplesort_begin_index_gist(Relation heapRel,
|
|||||||
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
|
state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
|
||||||
|
|
||||||
state->comparetup = comparetup_index_btree;
|
state->comparetup = comparetup_index_btree;
|
||||||
state->copytup = copytup_index;
|
|
||||||
state->writetup = writetup_index;
|
state->writetup = writetup_index;
|
||||||
state->readtup = readtup_index;
|
state->readtup = readtup_index;
|
||||||
state->haveDatum1 = true;
|
state->haveDatum1 = true;
|
||||||
@ -1422,7 +1401,6 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
|
|||||||
PARALLEL_SORT(state));
|
PARALLEL_SORT(state));
|
||||||
|
|
||||||
state->comparetup = comparetup_datum;
|
state->comparetup = comparetup_datum;
|
||||||
state->copytup = copytup_datum;
|
|
||||||
state->writetup = writetup_datum;
|
state->writetup = writetup_datum;
|
||||||
state->readtup = readtup_datum;
|
state->readtup = readtup_datum;
|
||||||
state->abbrevNext = 10;
|
state->abbrevNext = 10;
|
||||||
@ -1839,14 +1817,75 @@ noalloc:
|
|||||||
void
|
void
|
||||||
tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
|
tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
|
||||||
{
|
{
|
||||||
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
|
MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
|
||||||
SortTuple stup;
|
SortTuple stup;
|
||||||
|
Datum original;
|
||||||
|
MinimalTuple tuple;
|
||||||
|
HeapTupleData htup;
|
||||||
|
|
||||||
/*
|
/* copy the tuple into sort storage */
|
||||||
* Copy the given tuple into memory we control, and decrease availMem.
|
tuple = ExecCopySlotMinimalTuple(slot);
|
||||||
* Then call the common code.
|
stup.tuple = (void *) tuple;
|
||||||
*/
|
USEMEM(state, GetMemoryChunkSpace(tuple));
|
||||||
COPYTUP(state, &stup, (void *) slot);
|
/* 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);
|
puttuple_common(state, &stup);
|
||||||
|
|
||||||
@ -1861,14 +1900,75 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
|
|||||||
void
|
void
|
||||||
tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
|
tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
|
||||||
{
|
{
|
||||||
MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
|
|
||||||
SortTuple stup;
|
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.
|
* set up first-column key value, and potentially abbreviate, if it's a
|
||||||
* Then call the common code.
|
* 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);
|
puttuple_common(state, &stup);
|
||||||
|
|
||||||
@ -3947,84 +4047,6 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
|
|||||||
return 0;
|
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
|
static void
|
||||||
writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
||||||
{
|
{
|
||||||
@ -4193,79 +4215,6 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
|
|||||||
return 0;
|
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
|
static void
|
||||||
writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
||||||
{
|
{
|
||||||
@ -4512,13 +4461,6 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
|
|||||||
return 0;
|
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
|
static void
|
||||||
writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
||||||
{
|
{
|
||||||
@ -4583,13 +4525,6 @@ comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
|
|||||||
return compare;
|
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
|
static void
|
||||||
writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user