v2-0005-Reorganize-data-structures.patch
text/x-patch
Filename: v2-0005-Reorganize-data-structures.patch
Type: text/x-patch
Part: 0
Message:
Re: Custom tuplesorts for extensions
Patch
Format: format-patch
Series: patch v2-0005
Subject: Reorganize data structures
| File | + | − |
|---|---|---|
| src/backend/utils/sort/tuplesort.c | 432 | 330 |
From 3a0e1fa7c7e4da46a86f7d5b9dd0392549f3b460 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Wed, 22 Jun 2022 18:11:26 +0300
Subject: [PATCH v2 5/6] Reorganize data structures
Reported-by:
Bug:
Discussion:
Author:
Reviewed-by:
Tested-by:
Backpatch-through:
---
src/backend/utils/sort/tuplesort.c | 762 ++++++++++++++++-------------
1 file changed, 432 insertions(+), 330 deletions(-)
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 3bf990a1b34..e106e1ff9e2 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -126,8 +126,8 @@
#define CLUSTER_SORT 3
/* Sort parallel code from state for sort__start probes */
-#define PARALLEL_SORT(state) ((state)->shared == NULL ? 0 : \
- (state)->worker >= 0 ? 1 : 2)
+#define PARALLEL_SORT(coordinate) ((coordinate)->sharedsort == NULL ? 0 : \
+ (coordinate)->isWorker >= 0 ? 1 : 2)
/*
* Initial size of memtuples array. We're trying to select this size so that
@@ -236,37 +236,17 @@ typedef enum
#define TAPE_BUFFER_OVERHEAD BLCKSZ
#define MERGE_BUFFER_SIZE (BLCKSZ * 32)
+typedef struct TuplesortOps TuplesortOps;
+
typedef int (*SortTupleComparator) (const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
-/*
- * Private state of a Tuplesort operation.
- */
-struct Tuplesortstate
+struct TuplesortOps
{
- TupSortStatus status; /* enumerated value as shown above */
- int nKeys; /* number of columns in sort key */
- int sortopt; /* Bitmask of flags used to setup sort */
- bool bounded; /* did caller specify a maximum number of
- * tuples to return? */
- bool boundUsed; /* true if we made use of a bounded heap */
- int bound; /* if bounded, the maximum number of tuples */
- bool tuples; /* Can SortTuple.tuple ever be set? */
- int64 availMem; /* remaining memory available, in bytes */
- int64 allowedMem; /* total memory allowed, in bytes */
- int maxTapes; /* max number of input tapes to merge in each
- * pass */
- int64 maxSpace; /* maximum amount of space occupied among sort
- * of groups, either in-memory or on-disk */
- bool isMaxSpaceDisk; /* true when maxSpace is value for on-disk
- * space, false when it's value for in-memory
- * space */
- TupSortStatus maxSpaceStatus; /* sort status when maxSpace was reached */
MemoryContext maincontext; /* memory context for tuple sort metadata that
* persists across multiple batches */
MemoryContext sortcontext; /* memory context holding most sort data */
MemoryContext tuplecontext; /* sub-context of sortcontext for tuple data */
- LogicalTapeSet *tapeset; /* logtape.c object for tapes in a temp file */
/*
* These function pointers decouple the routines that must know what kind
@@ -300,12 +280,116 @@ struct Tuplesortstate
void (*readtup) (Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len);
+ void (*freestate) (Tuplesortstate *state);
+
/*
* Whether SortTuple's datum1 and isnull1 members are maintained by the
* above routines. If not, some sort specializations are disabled.
*/
bool haveDatum1;
+ /*
+ * The sortKeys variable is used by every case other than the hash index
+ * case; it is set by tuplesort_begin_xxx. tupDesc is only used by the
+ * MinimalTuple and CLUSTER routines, though.
+ */
+ int nKeys; /* number of columns in sort key */
+ SortSupport sortKeys; /* array of length nKeys */
+
+ /*
+ * This variable is shared by the single-key MinimalTuple case and the
+ * Datum case (which both use qsort_ssup()). Otherwise, it's NULL. The
+ * presence of a value in this field is also checked by various sort
+ * specialization functions as an optimization when comparing the leading
+ * key in a tiebreak situation to determine if there are any subsequent
+ * keys to sort on.
+ */
+ SortSupport onlyKey;
+
+ int sortopt; /* Bitmask of flags used to setup sort */
+
+ bool tuples; /* Can SortTuple.tuple ever be set? */
+
+ void *arg;
+};
+
+typedef struct
+{
+ TupleDesc tupDesc;
+
+ /*
+ * These variables are specific to the CLUSTER case; they are set by
+ * tuplesort_begin_cluster.
+ */
+ IndexInfo *indexInfo; /* info about index being used for reference */
+ EState *estate; /* for evaluating index expressions */
+} TupleSortClusterArg;
+
+typedef struct
+{
+ /*
+ * These variables are specific to the IndexTuple case; they are set by
+ * tuplesort_begin_index_xxx and used only by the IndexTuple routines.
+ */
+ Relation heapRel; /* table the index is being built on */
+ Relation indexRel; /* index being built */
+} TupleSortIndexArg;
+
+typedef struct
+{
+ TupleSortIndexArg index;
+
+ /* These are specific to the index_btree subcase: */
+ bool enforceUnique; /* complain if we find duplicate tuples */
+ bool uniqueNullsNotDistinct; /* unique constraint null treatment */
+} TupleSortIndexBTreeArg;
+
+typedef struct
+{
+ TupleSortIndexArg index;
+
+ /* These are specific to the index_hash subcase: */
+ uint32 high_mask; /* masks for sortable part of hash code */
+ uint32 low_mask;
+ uint32 max_buckets;
+} TupleSortIndexHashArg;
+
+typedef struct
+{
+ TupleSortIndexArg index;
+
+ /*
+ * These variables are specific to the Datum case; they are set by
+ * tuplesort_begin_datum and used only by the DatumTuple routines.
+ */
+ Oid datumType;
+ /* we need typelen in order to know how to copy the Datums. */
+ int datumTypeLen;
+} TupleSortDatumArg;
+
+/*
+ * Private state of a Tuplesort operation.
+ */
+struct Tuplesortstate
+{
+ TuplesortOps ops;
+ TupSortStatus status; /* enumerated value as shown above */
+ bool bounded; /* did caller specify a maximum number of
+ * tuples to return? */
+ bool boundUsed; /* true if we made use of a bounded heap */
+ int bound; /* if bounded, the maximum number of tuples */
+ int64 availMem; /* remaining memory available, in bytes */
+ int64 allowedMem; /* total memory allowed, in bytes */
+ int maxTapes; /* max number of input tapes to merge in each
+ * pass */
+ int64 maxSpace; /* maximum amount of space occupied among sort
+ * of groups, either in-memory or on-disk */
+ bool isMaxSpaceDisk; /* true when maxSpace is value for on-disk
+ * space, false when it's value for in-memory
+ * space */
+ TupSortStatus maxSpaceStatus; /* sort status when maxSpace was reached */
+ LogicalTapeSet *tapeset; /* logtape.c object for tapes in a temp file */
+
/*
* This array holds the tuples now in sort memory. If we are in state
* INITIAL, the tuples are in no particular order; if we are in state
@@ -420,24 +504,6 @@ struct Tuplesortstate
Sharedsort *shared;
int nParticipants;
- /*
- * The sortKeys variable is used by every case other than the hash index
- * case; it is set by tuplesort_begin_xxx. tupDesc is only used by the
- * MinimalTuple and CLUSTER routines, though.
- */
- TupleDesc tupDesc;
- SortSupport sortKeys; /* array of length nKeys */
-
- /*
- * This variable is shared by the single-key MinimalTuple case and the
- * Datum case (which both use qsort_ssup()). Otherwise, it's NULL. The
- * presence of a value in this field is also checked by various sort
- * specialization functions as an optimization when comparing the leading
- * key in a tiebreak situation to determine if there are any subsequent
- * keys to sort on.
- */
- SortSupport onlyKey;
-
/*
* Additional state for managing "abbreviated key" sortsupport routines
* (which currently may be used by all cases except the hash index case).
@@ -447,37 +513,6 @@ struct Tuplesortstate
int64 abbrevNext; /* Tuple # at which to next check
* applicability */
- /*
- * These variables are specific to the CLUSTER case; they are set by
- * tuplesort_begin_cluster.
- */
- IndexInfo *indexInfo; /* info about index being used for reference */
- EState *estate; /* for evaluating index expressions */
-
- /*
- * These variables are specific to the IndexTuple case; they are set by
- * tuplesort_begin_index_xxx and used only by the IndexTuple routines.
- */
- Relation heapRel; /* table the index is being built on */
- Relation indexRel; /* index being built */
-
- /* These are specific to the index_btree subcase: */
- bool enforceUnique; /* complain if we find duplicate tuples */
- bool uniqueNullsNotDistinct; /* unique constraint null treatment */
-
- /* These are specific to the index_hash subcase: */
- uint32 high_mask; /* masks for sortable part of hash code */
- uint32 low_mask;
- uint32 max_buckets;
-
- /*
- * These variables are specific to the Datum case; they are set by
- * tuplesort_begin_datum and used only by the DatumTuple routines.
- */
- Oid datumType;
- /* we need typelen in order to know how to copy the Datums. */
- int datumTypeLen;
-
/*
* Resource snapshot for time of sort start.
*/
@@ -542,10 +577,13 @@ struct Sharedsort
pfree(buf); \
} while(0)
-#define GETDATUM1(state,stup) ((*(state)->getdatum1) (state, stup))
-#define COMPARETUP(state,a,b) ((*(state)->comparetup) (a, b, state))
-#define WRITETUP(state,tape,stup) ((*(state)->writetup) (state, tape, stup))
-#define READTUP(state,stup,tape,len) ((*(state)->readtup) (state, stup, tape, len))
+#define TuplesortstateGetOps(state) ((TuplesortOps *) state);
+
+#define GETDATUM1(state,stup) ((*(state)->ops.getdatum1) (state, stup))
+#define COMPARETUP(state,a,b) ((*(state)->ops.comparetup) (a, b, state))
+#define WRITETUP(state,tape,stup) ((*(state)->ops.writetup) (state, tape, stup))
+#define READTUP(state,stup,tape,len) ((*(state)->ops.readtup) (state, stup, tape, len))
+#define FREESTATE(state) ((state)->ops.freestate ? (*(state)->ops.freestate) (state) : (void) 0)
#define LACKMEM(state) ((state)->availMem < 0 && !(state)->slabAllocatorUsed)
#define USEMEM(state,amt) ((state)->availMem -= (amt))
#define FREEMEM(state,amt) ((state)->availMem += (amt))
@@ -664,6 +702,7 @@ static void writetup_datum(Tuplesortstate *state, LogicalTape *tape,
SortTuple *stup);
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len);
+static void freestate_cluster(Tuplesortstate *state);
static int worker_get_identifier(Tuplesortstate *state);
static void worker_freeze_result_tape(Tuplesortstate *state);
static void worker_nomergeruns(Tuplesortstate *state);
@@ -694,7 +733,7 @@ qsort_tuple_unsigned_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
compare = ApplyUnsignedSortComparator(a->datum1, a->isnull1,
b->datum1, b->isnull1,
- &state->sortKeys[0]);
+ &state->ops.sortKeys[0]);
if (compare != 0)
return compare;
@@ -702,10 +741,10 @@ qsort_tuple_unsigned_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
* No need to waste effort calling the tiebreak function when there are no
* other keys to sort on.
*/
- if (state->onlyKey != NULL)
+ if (state->ops.onlyKey != NULL)
return 0;
- return state->comparetup(a, b, state);
+ return state->ops.comparetup(a, b, state);
}
#if SIZEOF_DATUM >= 8
@@ -717,7 +756,7 @@ qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
compare = ApplySignedSortComparator(a->datum1, a->isnull1,
b->datum1, b->isnull1,
- &state->sortKeys[0]);
+ &state->ops.sortKeys[0]);
if (compare != 0)
return compare;
@@ -726,10 +765,10 @@ qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
* No need to waste effort calling the tiebreak function when there are no
* other keys to sort on.
*/
- if (state->onlyKey != NULL)
+ if (state->ops.onlyKey != NULL)
return 0;
- return state->comparetup(a, b, state);
+ return state->ops.comparetup(a, b, state);
}
#endif
@@ -741,7 +780,7 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
compare = ApplyInt32SortComparator(a->datum1, a->isnull1,
b->datum1, b->isnull1,
- &state->sortKeys[0]);
+ &state->ops.sortKeys[0]);
if (compare != 0)
return compare;
@@ -750,10 +789,10 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
* No need to waste effort calling the tiebreak function when there are no
* other keys to sort on.
*/
- if (state->onlyKey != NULL)
+ if (state->ops.onlyKey != NULL)
return 0;
- return state->comparetup(a, b, state);
+ return state->ops.comparetup(a, b, state);
}
/*
@@ -880,8 +919,9 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt)
pg_rusage_init(&state->ru_start);
#endif
- state->sortopt = sortopt;
- state->tuples = true;
+ state->ops.sortopt = sortopt;
+ state->ops.tuples = true;
+ state->abbrevNext = 10;
/*
* workMem is forced to be at least 64KB, the current minimum valid value
@@ -890,8 +930,8 @@ tuplesort_begin_common(int workMem, SortCoordinate coordinate, int sortopt)
* with very little memory.
*/
state->allowedMem = Max(workMem, 64) * (int64) 1024;
- state->sortcontext = sortcontext;
- state->maincontext = maincontext;
+ state->ops.sortcontext = sortcontext;
+ state->ops.maincontext = maincontext;
/*
* Initial size of array must be more than ALLOCSET_SEPARATE_THRESHOLD;
@@ -950,7 +990,7 @@ tuplesort_begin_batch(Tuplesortstate *state)
{
MemoryContext oldcontext;
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
/*
* Caller tuple (e.g. IndexTuple) memory context.
@@ -965,12 +1005,12 @@ tuplesort_begin_batch(Tuplesortstate *state)
* generation.c context as this keeps allocations more compact with less
* wastage. Allocations are also slightly more CPU efficient.
*/
- if (state->sortopt & TUPLESORT_ALLOWBOUNDED)
- state->tuplecontext = AllocSetContextCreate(state->sortcontext,
+ if (state->ops.sortopt & TUPLESORT_ALLOWBOUNDED)
+ state->ops.tuplecontext = AllocSetContextCreate(state->ops.sortcontext,
"Caller tuples",
ALLOCSET_DEFAULT_SIZES);
else
- state->tuplecontext = GenerationContextCreate(state->sortcontext,
+ state->ops.tuplecontext = GenerationContextCreate(state->ops.sortcontext,
"Caller tuples",
ALLOCSET_DEFAULT_SIZES);
@@ -1028,10 +1068,11 @@ tuplesort_begin_heap(TupleDesc tupDesc,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
MemoryContext oldcontext;
int i;
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
AssertArg(nkeys > 0);
@@ -1042,30 +1083,28 @@ tuplesort_begin_heap(TupleDesc tupDesc,
nkeys, workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = nkeys;
+ ops->nKeys = nkeys;
TRACE_POSTGRESQL_SORT_START(HEAP_SORT,
false, /* no unique check */
nkeys,
workMem,
sortopt & TUPLESORT_RANDOMACCESS,
- PARALLEL_SORT(state));
+ PARALLEL_SORT(coordinate));
- state->getdatum1 = getdatum1_heap;
- state->comparetup = comparetup_heap;
- state->writetup = writetup_heap;
- state->readtup = readtup_heap;
- state->haveDatum1 = true;
-
- state->tupDesc = tupDesc; /* assume we need not copy tupDesc */
- state->abbrevNext = 10;
+ ops->getdatum1 = getdatum1_heap;
+ ops->comparetup = comparetup_heap;
+ ops->writetup = writetup_heap;
+ ops->readtup = readtup_heap;
+ ops->haveDatum1 = true;
+ ops->arg = tupDesc; /* assume we need not copy tupDesc */
/* Prepare SortSupport data for each column */
- state->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData));
+ ops->sortKeys = (SortSupport) palloc0(nkeys * sizeof(SortSupportData));
for (i = 0; i < nkeys; i++)
{
- SortSupport sortKey = state->sortKeys + i;
+ SortSupport sortKey = ops->sortKeys + i;
AssertArg(attNums[i] != 0);
AssertArg(sortOperators[i] != 0);
@@ -1075,7 +1114,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
sortKey->ssup_nulls_first = nullsFirstFlags[i];
sortKey->ssup_attno = attNums[i];
/* Convey if abbreviation optimization is applicable in principle */
- sortKey->abbreviate = (i == 0 && state->haveDatum1);
+ sortKey->abbreviate = (i == 0 && ops->haveDatum1);
PrepareSortSupportFromOrderingOp(sortOperators[i], sortKey);
}
@@ -1086,8 +1125,8 @@ tuplesort_begin_heap(TupleDesc tupDesc,
* is only of value to pass-by-value types anyway, whereas abbreviated
* keys are typically only of value to pass-by-reference types.
*/
- if (nkeys == 1 && !state->sortKeys->abbrev_converter)
- state->onlyKey = state->sortKeys;
+ if (nkeys == 1 && !ops->sortKeys->abbrev_converter)
+ ops->onlyKey = ops->sortKeys;
MemoryContextSwitchTo(oldcontext);
@@ -1102,13 +1141,16 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
BTScanInsert indexScanKey;
MemoryContext oldcontext;
+ TupleSortClusterArg *arg;
int i;
Assert(indexRel->rd_rel->relam == BTREE_AM_OID);
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
+ arg = (TupleSortClusterArg *) palloc0(sizeof(TupleSortClusterArg));
#ifdef TRACE_SORT
if (trace_sort)
@@ -1118,37 +1160,38 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
+ ops->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
TRACE_POSTGRESQL_SORT_START(CLUSTER_SORT,
false, /* no unique check */
- state->nKeys,
+ ops->nKeys,
workMem,
sortopt & TUPLESORT_RANDOMACCESS,
- PARALLEL_SORT(state));
+ PARALLEL_SORT(coordinate));
- state->getdatum1 = getdatum1_cluster;
- state->comparetup = comparetup_cluster;
- state->writetup = writetup_cluster;
- state->readtup = readtup_cluster;
- state->abbrevNext = 10;
+ ops->getdatum1 = getdatum1_cluster;
+ ops->comparetup = comparetup_cluster;
+ ops->writetup = writetup_cluster;
+ ops->readtup = readtup_cluster;
+ ops->freestate = freestate_cluster;
+ ops->arg = arg;
- state->indexInfo = BuildIndexInfo(indexRel);
+ arg->indexInfo = BuildIndexInfo(indexRel);
/*
* If we don't have a simple leading attribute, we don't currently
* initialize datum1, so disable optimizations that require it.
*/
- if (state->indexInfo->ii_IndexAttrNumbers[0] == 0)
- state->haveDatum1 = false;
+ if (arg->indexInfo->ii_IndexAttrNumbers[0] == 0)
+ ops->haveDatum1 = false;
else
- state->haveDatum1 = true;
+ ops->haveDatum1 = true;
- state->tupDesc = tupDesc; /* assume we need not copy tupDesc */
+ arg->tupDesc = tupDesc; /* assume we need not copy tupDesc */
indexScanKey = _bt_mkscankey(indexRel, NULL);
- if (state->indexInfo->ii_Expressions != NULL)
+ if (arg->indexInfo->ii_Expressions != NULL)
{
TupleTableSlot *slot;
ExprContext *econtext;
@@ -1159,19 +1202,19 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
* TupleTableSlot to put the table tuples into. The econtext's
* scantuple has to point to that slot, too.
*/
- state->estate = CreateExecutorState();
+ arg->estate = CreateExecutorState();
slot = MakeSingleTupleTableSlot(tupDesc, &TTSOpsHeapTuple);
- econtext = GetPerTupleExprContext(state->estate);
+ econtext = GetPerTupleExprContext(arg->estate);
econtext->ecxt_scantuple = slot;
}
/* Prepare SortSupport data for each column */
- state->sortKeys = (SortSupport) palloc0(state->nKeys *
+ ops->sortKeys = (SortSupport) palloc0(ops->nKeys *
sizeof(SortSupportData));
- for (i = 0; i < state->nKeys; i++)
+ for (i = 0; i < ops->nKeys; i++)
{
- SortSupport sortKey = state->sortKeys + i;
+ SortSupport sortKey = ops->sortKeys + i;
ScanKey scanKey = indexScanKey->scankeys + i;
int16 strategy;
@@ -1181,7 +1224,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
sortKey->ssup_attno = scanKey->sk_attno;
/* Convey if abbreviation optimization is applicable in principle */
- sortKey->abbreviate = (i == 0 && state->haveDatum1);
+ sortKey->abbreviate = (i == 0 && ops->haveDatum1);
AssertState(sortKey->ssup_attno != 0);
@@ -1209,11 +1252,14 @@ tuplesort_begin_index_btree(Relation heapRel,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
BTScanInsert indexScanKey;
+ TupleSortIndexBTreeArg *arg;
MemoryContext oldcontext;
int i;
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
+ arg = (TupleSortIndexBTreeArg *) palloc(sizeof(TupleSortIndexBTreeArg));
#ifdef TRACE_SORT
if (trace_sort)
@@ -1223,36 +1269,36 @@ tuplesort_begin_index_btree(Relation heapRel,
workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
+ ops->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
TRACE_POSTGRESQL_SORT_START(INDEX_SORT,
enforceUnique,
state->nKeys,
workMem,
sortopt & TUPLESORT_RANDOMACCESS,
- PARALLEL_SORT(state));
+ PARALLEL_SORT(coordinate));
- state->getdatum1 = getdatum1_index;
- state->comparetup = comparetup_index_btree;
- state->writetup = writetup_index;
- state->readtup = readtup_index;
- state->abbrevNext = 10;
- state->haveDatum1 = true;
+ ops->getdatum1 = getdatum1_index;
+ ops->comparetup = comparetup_index_btree;
+ ops->writetup = writetup_index;
+ ops->readtup = readtup_index;
+ ops->haveDatum1 = true;
+ ops->arg = arg;
- state->heapRel = heapRel;
- state->indexRel = indexRel;
- state->enforceUnique = enforceUnique;
- state->uniqueNullsNotDistinct = uniqueNullsNotDistinct;
+ arg->index.heapRel = heapRel;
+ arg->index.indexRel = indexRel;
+ arg->enforceUnique = enforceUnique;
+ arg->uniqueNullsNotDistinct = uniqueNullsNotDistinct;
indexScanKey = _bt_mkscankey(indexRel, NULL);
/* Prepare SortSupport data for each column */
- state->sortKeys = (SortSupport) palloc0(state->nKeys *
- sizeof(SortSupportData));
+ ops->sortKeys = (SortSupport) palloc0(ops->nKeys *
+ sizeof(SortSupportData));
- for (i = 0; i < state->nKeys; i++)
+ for (i = 0; i < ops->nKeys; i++)
{
- SortSupport sortKey = state->sortKeys + i;
+ SortSupport sortKey = ops->sortKeys + i;
ScanKey scanKey = indexScanKey->scankeys + i;
int16 strategy;
@@ -1262,7 +1308,7 @@ tuplesort_begin_index_btree(Relation heapRel,
(scanKey->sk_flags & SK_BT_NULLS_FIRST) != 0;
sortKey->ssup_attno = scanKey->sk_attno;
/* Convey if abbreviation optimization is applicable in principle */
- sortKey->abbreviate = (i == 0 && state->haveDatum1);
+ sortKey->abbreviate = (i == 0 && ops->haveDatum1);
AssertState(sortKey->ssup_attno != 0);
@@ -1291,9 +1337,12 @@ tuplesort_begin_index_hash(Relation heapRel,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
MemoryContext oldcontext;
+ TupleSortIndexHashArg *arg;
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
+ arg = (TupleSortIndexHashArg *) palloc(sizeof(TupleSortIndexHashArg));
#ifdef TRACE_SORT
if (trace_sort)
@@ -1307,20 +1356,21 @@ tuplesort_begin_index_hash(Relation heapRel,
sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = 1; /* Only one sort column, the hash code */
+ ops->nKeys = 1; /* Only one sort column, the hash code */
- state->getdatum1 = getdatum1_index;
- state->comparetup = comparetup_index_hash;
- state->writetup = writetup_index;
- state->readtup = readtup_index;
- state->haveDatum1 = true;
+ ops->getdatum1 = getdatum1_index;
+ ops->comparetup = comparetup_index_hash;
+ ops->writetup = writetup_index;
+ ops->readtup = readtup_index;
+ ops->haveDatum1 = true;
+ ops->arg = arg;
- state->heapRel = heapRel;
- state->indexRel = indexRel;
+ arg->index.heapRel = heapRel;
+ arg->index.indexRel = indexRel;
- state->high_mask = high_mask;
- state->low_mask = low_mask;
- state->max_buckets = max_buckets;
+ arg->high_mask = high_mask;
+ arg->low_mask = low_mask;
+ arg->max_buckets = max_buckets;
MemoryContextSwitchTo(oldcontext);
@@ -1336,10 +1386,13 @@ tuplesort_begin_index_gist(Relation heapRel,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
MemoryContext oldcontext;
+ TupleSortIndexBTreeArg *arg;
int i;
- oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
+ arg = (TupleSortIndexBTreeArg *) palloc(sizeof(TupleSortIndexBTreeArg));
#ifdef TRACE_SORT
if (trace_sort)
@@ -1348,31 +1401,34 @@ tuplesort_begin_index_gist(Relation heapRel,
workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
+ ops->nKeys = IndexRelationGetNumberOfKeyAttributes(indexRel);
- state->getdatum1 = getdatum1_index;
- state->comparetup = comparetup_index_btree;
- state->writetup = writetup_index;
- state->readtup = readtup_index;
- state->haveDatum1 = true;
+ ops->getdatum1 = getdatum1_index;
+ ops->comparetup = comparetup_index_btree;
+ ops->writetup = writetup_index;
+ ops->readtup = readtup_index;
+ ops->haveDatum1 = true;
+ ops->arg = arg;
- state->heapRel = heapRel;
- state->indexRel = indexRel;
+ arg->index.heapRel = heapRel;
+ arg->index.indexRel = indexRel;
+ arg->enforceUnique = false;
+ arg->uniqueNullsNotDistinct = false;
/* Prepare SortSupport data for each column */
- state->sortKeys = (SortSupport) palloc0(state->nKeys *
- sizeof(SortSupportData));
+ ops->sortKeys = (SortSupport) palloc0(ops->nKeys *
+ sizeof(SortSupportData));
- for (i = 0; i < state->nKeys; i++)
+ for (i = 0; i < ops->nKeys; i++)
{
- SortSupport sortKey = state->sortKeys + i;
+ SortSupport sortKey = ops->sortKeys + i;
sortKey->ssup_cxt = CurrentMemoryContext;
sortKey->ssup_collation = indexRel->rd_indcollation[i];
sortKey->ssup_nulls_first = false;
sortKey->ssup_attno = i + 1;
/* Convey if abbreviation optimization is applicable in principle */
- sortKey->abbreviate = (i == 0 && state->haveDatum1);
+ sortKey->abbreviate = (i == 0 && ops->haveDatum1);
AssertState(sortKey->ssup_attno != 0);
@@ -1392,11 +1448,14 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
{
Tuplesortstate *state = tuplesort_begin_common(workMem, coordinate,
sortopt);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortDatumArg *arg;
MemoryContext oldcontext;
int16 typlen;
bool typbyval;
- oldcontext = MemoryContextSwitchTo(state->maincontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.maincontext);
+ arg = (TupleSortDatumArg *) palloc(sizeof(TupleSortDatumArg));
#ifdef TRACE_SORT
if (trace_sort)
@@ -1405,35 +1464,36 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
workMem, sortopt & TUPLESORT_RANDOMACCESS ? 't' : 'f');
#endif
- state->nKeys = 1; /* always a one-column sort */
+ ops->nKeys = 1; /* always a one-column sort */
TRACE_POSTGRESQL_SORT_START(DATUM_SORT,
false, /* no unique check */
1,
workMem,
sortopt & TUPLESORT_RANDOMACCESS,
- PARALLEL_SORT(state));
+ PARALLEL_SORT(coordinate));
- state->getdatum1 = getdatum1_datum;
- state->comparetup = comparetup_datum;
- state->writetup = writetup_datum;
- state->readtup = readtup_datum;
+ ops->getdatum1 = getdatum1_datum;
+ ops->comparetup = comparetup_datum;
+ ops->writetup = writetup_datum;
+ ops->readtup = readtup_datum;
state->abbrevNext = 10;
- state->haveDatum1 = true;
+ ops->haveDatum1 = true;
+ ops->arg = arg;
- state->datumType = datumType;
+ arg->datumType = datumType;
/* lookup necessary attributes of the datum type */
get_typlenbyval(datumType, &typlen, &typbyval);
- state->datumTypeLen = typlen;
- state->tuples = !typbyval;
+ arg->datumTypeLen = typlen;
+ ops->tuples = !typbyval;
/* Prepare SortSupport data */
- state->sortKeys = (SortSupport) palloc0(sizeof(SortSupportData));
+ ops->sortKeys = (SortSupport) palloc0(sizeof(SortSupportData));
- state->sortKeys->ssup_cxt = CurrentMemoryContext;
- state->sortKeys->ssup_collation = sortCollation;
- state->sortKeys->ssup_nulls_first = nullsFirstFlag;
+ ops->sortKeys->ssup_cxt = CurrentMemoryContext;
+ ops->sortKeys->ssup_collation = sortCollation;
+ ops->sortKeys->ssup_nulls_first = nullsFirstFlag;
/*
* Abbreviation is possible here only for by-reference types. In theory,
@@ -1443,9 +1503,9 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
* can't, because a datum sort only stores a single copy of the datum; the
* "tuple" field of each SortTuple is NULL.
*/
- state->sortKeys->abbreviate = !typbyval;
+ ops->sortKeys->abbreviate = !typbyval;
- PrepareSortSupportFromOrderingOp(sortOperator, state->sortKeys);
+ PrepareSortSupportFromOrderingOp(sortOperator, ops->sortKeys);
/*
* The "onlyKey" optimization cannot be used with abbreviated keys, since
@@ -1453,8 +1513,8 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
* is only of value to pass-by-value types anyway, whereas abbreviated
* keys are typically only of value to pass-by-reference types.
*/
- if (!state->sortKeys->abbrev_converter)
- state->onlyKey = state->sortKeys;
+ if (!ops->sortKeys->abbrev_converter)
+ ops->onlyKey = ops->sortKeys;
MemoryContextSwitchTo(oldcontext);
@@ -1479,7 +1539,7 @@ tuplesort_set_bound(Tuplesortstate *state, int64 bound)
/* Assert we're called before loading any tuples */
Assert(state->status == TSS_INITIAL && state->memtupcount == 0);
/* Assert we allow bounded sorts */
- Assert(state->sortopt & TUPLESORT_ALLOWBOUNDED);
+ Assert(state->ops.sortopt & TUPLESORT_ALLOWBOUNDED);
/* Can't set the bound twice, either */
Assert(!state->bounded);
/* Also, this shouldn't be called in a parallel worker */
@@ -1507,13 +1567,13 @@ tuplesort_set_bound(Tuplesortstate *state, int64 bound)
* optimization. Disable by setting state to be consistent with no
* abbreviation support.
*/
- state->sortKeys->abbrev_converter = NULL;
- if (state->sortKeys->abbrev_full_comparator)
- state->sortKeys->comparator = state->sortKeys->abbrev_full_comparator;
+ state->ops.sortKeys->abbrev_converter = NULL;
+ if (state->ops.sortKeys->abbrev_full_comparator)
+ state->ops.sortKeys->comparator = state->ops.sortKeys->abbrev_full_comparator;
/* Not strictly necessary, but be tidy */
- state->sortKeys->abbrev_abort = NULL;
- state->sortKeys->abbrev_full_comparator = NULL;
+ state->ops.sortKeys->abbrev_abort = NULL;
+ state->ops.sortKeys->abbrev_full_comparator = NULL;
}
/*
@@ -1536,7 +1596,7 @@ static void
tuplesort_free(Tuplesortstate *state)
{
/* context swap probably not needed, but let's be safe */
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
#ifdef TRACE_SORT
long spaceUsed;
@@ -1583,21 +1643,13 @@ tuplesort_free(Tuplesortstate *state)
TRACE_POSTGRESQL_SORT_DONE(state->tapeset != NULL, 0L);
#endif
- /* Free any execution state created for CLUSTER case */
- if (state->estate != NULL)
- {
- ExprContext *econtext = GetPerTupleExprContext(state->estate);
-
- ExecDropSingleTupleTableSlot(econtext->ecxt_scantuple);
- FreeExecutorState(state->estate);
- }
-
+ FREESTATE(state);
MemoryContextSwitchTo(oldcontext);
/*
* Free the per-sort memory context, thereby releasing all working memory.
*/
- MemoryContextReset(state->sortcontext);
+ MemoryContextReset(state->ops.sortcontext);
}
/*
@@ -1618,7 +1670,7 @@ tuplesort_end(Tuplesortstate *state)
* Free the main memory context, including the Tuplesortstate struct
* itself.
*/
- MemoryContextDelete(state->maincontext);
+ MemoryContextDelete(state->ops.maincontext);
}
/*
@@ -1832,7 +1884,9 @@ noalloc:
void
tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.tuplecontext);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleDesc tupDesc = (TupleDesc) ops->arg;
SortTuple stup;
MinimalTuple tuple;
HeapTupleData htup;
@@ -1844,8 +1898,8 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET;
htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET);
stup.datum1 = heap_getattr(&htup,
- state->sortKeys[0].ssup_attno,
- state->tupDesc,
+ ops->sortKeys[0].ssup_attno,
+ tupDesc,
&stup.isnull1);
puttuple_common(state, &stup);
@@ -1862,7 +1916,9 @@ void
tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
{
SortTuple stup;
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.tuplecontext);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortClusterArg *arg = (TupleSortClusterArg *) ops->arg;
/* copy the tuple into sort storage */
tup = heap_copytuple(tup);
@@ -1872,11 +1928,11 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
* set up first-column key value, and potentially abbreviate, if it's a
* simple column
*/
- if (state->haveDatum1)
+ if (ops->haveDatum1)
{
stup.datum1 = heap_getattr(tup,
- state->indexInfo->ii_IndexAttrNumbers[0],
- state->tupDesc,
+ arg->indexInfo->ii_IndexAttrNumbers[0],
+ arg->tupDesc,
&stup.isnull1);
}
@@ -1894,9 +1950,11 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
ItemPointer self, Datum *values,
bool *isnull)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.tuplecontext);
SortTuple stup;
IndexTuple tuple;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortIndexArg *arg = (TupleSortIndexArg *) ops->arg;
stup.tuple = index_form_tuple(RelationGetDescr(rel), values, isnull);
tuple = ((IndexTuple) stup.tuple);
@@ -1904,7 +1962,7 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
/* set up first-column key value */
stup.datum1 = index_getattr(tuple,
1,
- RelationGetDescr(state->indexRel),
+ RelationGetDescr(arg->indexRel),
&stup.isnull1);
puttuple_common(state, &stup);
@@ -1920,7 +1978,9 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
void
tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->tuplecontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.tuplecontext);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortDatumArg *arg = (TupleSortDatumArg *) ops->arg;
SortTuple stup;
/*
@@ -1935,7 +1995,7 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
* identical to stup.tuple.
*/
- if (isNull || !state->tuples)
+ if (isNull || !state->ops.tuples)
{
/*
* Set datum1 to zeroed representation for NULLs (to be consistent,
@@ -1948,7 +2008,7 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
else
{
stup.isnull1 = false;
- stup.datum1 = datumCopy(val, false, state->datumTypeLen);
+ stup.datum1 = datumCopy(val, false, arg->datumTypeLen);
stup.tuple = DatumGetPointer(stup.datum1);
}
@@ -1963,15 +2023,15 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
static void
puttuple_common(Tuplesortstate *state, SortTuple *tuple)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
Assert(!LEADER(state));
if (tuple->tuple != NULL)
USEMEM(state, GetMemoryChunkSpace(tuple->tuple));
- if (!state->sortKeys || !state->haveDatum1 || !state->tuples ||
- !state->sortKeys->abbrev_converter || tuple->isnull1)
+ if (!state->ops.sortKeys || !state->ops.haveDatum1 || !state->ops.tuples ||
+ !state->ops.sortKeys->abbrev_converter || tuple->isnull1)
{
/*
* Store ordinary Datum representation, or NULL value. If there is a
@@ -1985,8 +2045,8 @@ puttuple_common(Tuplesortstate *state, SortTuple *tuple)
else if (!consider_abort_common(state))
{
/* Store abbreviated key representation */
- tuple->datum1 = state->sortKeys->abbrev_converter(tuple->datum1,
- state->sortKeys);
+ tuple->datum1 = state->ops.sortKeys->abbrev_converter(tuple->datum1,
+ state->ops.sortKeys);
}
else
{
@@ -2130,9 +2190,9 @@ writetuple_common(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
static bool
consider_abort_common(Tuplesortstate *state)
{
- Assert(state->sortKeys[0].abbrev_converter != NULL);
- Assert(state->sortKeys[0].abbrev_abort != NULL);
- Assert(state->sortKeys[0].abbrev_full_comparator != NULL);
+ Assert(state->ops.sortKeys[0].abbrev_converter != NULL);
+ Assert(state->ops.sortKeys[0].abbrev_abort != NULL);
+ Assert(state->ops.sortKeys[0].abbrev_full_comparator != NULL);
/*
* Check effectiveness of abbreviation optimization. Consider aborting
@@ -2147,19 +2207,19 @@ consider_abort_common(Tuplesortstate *state)
* Check opclass-supplied abbreviation abort routine. It may indicate
* that abbreviation should not proceed.
*/
- if (!state->sortKeys->abbrev_abort(state->memtupcount,
- state->sortKeys))
+ if (!state->ops.sortKeys->abbrev_abort(state->memtupcount,
+ state->ops.sortKeys))
return false;
/*
* Finally, restore authoritative comparator, and indicate that
* abbreviation is not in play by setting abbrev_converter to NULL
*/
- state->sortKeys[0].comparator = state->sortKeys[0].abbrev_full_comparator;
- state->sortKeys[0].abbrev_converter = NULL;
+ state->ops.sortKeys[0].comparator = state->ops.sortKeys[0].abbrev_full_comparator;
+ state->ops.sortKeys[0].abbrev_converter = NULL;
/* Not strictly necessary, but be tidy */
- state->sortKeys[0].abbrev_abort = NULL;
- state->sortKeys[0].abbrev_full_comparator = NULL;
+ state->ops.sortKeys[0].abbrev_abort = NULL;
+ state->ops.sortKeys[0].abbrev_full_comparator = NULL;
/* Give up - expect original pass-by-value representation */
return true;
@@ -2174,7 +2234,7 @@ consider_abort_common(Tuplesortstate *state)
void
tuplesort_performsort(Tuplesortstate *state)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
#ifdef TRACE_SORT
if (trace_sort)
@@ -2294,7 +2354,7 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
switch (state->status)
{
case TSS_SORTEDINMEM:
- Assert(forward || state->sortopt & TUPLESORT_RANDOMACCESS);
+ Assert(forward || state->ops.sortopt & TUPLESORT_RANDOMACCESS);
Assert(!state->slabAllocatorUsed);
if (forward)
{
@@ -2338,7 +2398,7 @@ tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
break;
case TSS_SORTEDONTAPE:
- Assert(forward || state->sortopt & TUPLESORT_RANDOMACCESS);
+ Assert(forward || state->ops.sortopt & TUPLESORT_RANDOMACCESS);
Assert(state->slabAllocatorUsed);
/*
@@ -2540,7 +2600,7 @@ bool
tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy,
TupleTableSlot *slot, Datum *abbrev)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
SortTuple stup;
if (!tuplesort_gettuple_common(state, forward, &stup))
@@ -2551,7 +2611,7 @@ tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy,
if (stup.tuple)
{
/* Record abbreviated key for caller */
- if (state->sortKeys->abbrev_converter && abbrev)
+ if (state->ops.sortKeys->abbrev_converter && abbrev)
*abbrev = stup.datum1;
if (copy)
@@ -2576,7 +2636,7 @@ tuplesort_gettupleslot(Tuplesortstate *state, bool forward, bool copy,
HeapTuple
tuplesort_getheaptuple(Tuplesortstate *state, bool forward)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
SortTuple stup;
if (!tuplesort_gettuple_common(state, forward, &stup))
@@ -2596,7 +2656,7 @@ tuplesort_getheaptuple(Tuplesortstate *state, bool forward)
IndexTuple
tuplesort_getindextuple(Tuplesortstate *state, bool forward)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
SortTuple stup;
if (!tuplesort_gettuple_common(state, forward, &stup))
@@ -2626,7 +2686,9 @@ bool
tuplesort_getdatum(Tuplesortstate *state, bool forward,
Datum *val, bool *isNull, Datum *abbrev)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortDatumArg *arg = (TupleSortDatumArg *) ops->arg;
SortTuple stup;
if (!tuplesort_gettuple_common(state, forward, &stup))
@@ -2639,10 +2701,10 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
MemoryContextSwitchTo(oldcontext);
/* Record abbreviated key for caller */
- if (state->sortKeys->abbrev_converter && abbrev)
+ if (ops->sortKeys->abbrev_converter && abbrev)
*abbrev = stup.datum1;
- if (stup.isnull1 || !state->tuples)
+ if (stup.isnull1 || !state->ops.tuples)
{
*val = stup.datum1;
*isNull = stup.isnull1;
@@ -2650,7 +2712,7 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
else
{
/* use stup.tuple because stup.datum1 may be an abbreviation */
- *val = datumCopy(PointerGetDatum(stup.tuple), false, state->datumTypeLen);
+ *val = datumCopy(PointerGetDatum(stup.tuple), false, arg->datumTypeLen);
*isNull = false;
}
@@ -2703,7 +2765,7 @@ tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples, bool forward)
* We could probably optimize these cases better, but for now it's
* not worth the trouble.
*/
- oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
while (ntuples-- > 0)
{
SortTuple stup;
@@ -2979,7 +3041,7 @@ mergeruns(Tuplesortstate *state)
Assert(state->status == TSS_BUILDRUNS);
Assert(state->memtupcount == 0);
- if (state->sortKeys != NULL && state->sortKeys->abbrev_converter != NULL)
+ if (state->ops.sortKeys != NULL && state->ops.sortKeys->abbrev_converter != NULL)
{
/*
* If there are multiple runs to be merged, when we go to read back
@@ -2987,19 +3049,19 @@ mergeruns(Tuplesortstate *state)
* we don't care to regenerate them. Disable abbreviation from this
* point on.
*/
- state->sortKeys->abbrev_converter = NULL;
- state->sortKeys->comparator = state->sortKeys->abbrev_full_comparator;
+ state->ops.sortKeys->abbrev_converter = NULL;
+ state->ops.sortKeys->comparator = state->ops.sortKeys->abbrev_full_comparator;
/* Not strictly necessary, but be tidy */
- state->sortKeys->abbrev_abort = NULL;
- state->sortKeys->abbrev_full_comparator = NULL;
+ state->ops.sortKeys->abbrev_abort = NULL;
+ state->ops.sortKeys->abbrev_full_comparator = NULL;
}
/*
* Reset tuple memory. We've freed all the tuples that we previously
* allocated. We will use the slab allocator from now on.
*/
- MemoryContextResetOnly(state->tuplecontext);
+ MemoryContextResetOnly(state->ops.tuplecontext);
/*
* We no longer need a large memtuples array. (We will allocate a smaller
@@ -3022,7 +3084,7 @@ mergeruns(Tuplesortstate *state)
* From this point on, we no longer use the USEMEM()/LACKMEM() mechanism
* to track memory usage of individual tuples.
*/
- if (state->tuples)
+ if (state->ops.tuples)
init_slab_allocator(state, state->nOutputTapes + 1);
else
init_slab_allocator(state, 0);
@@ -3036,7 +3098,7 @@ mergeruns(Tuplesortstate *state)
* number of input tapes will not increase between passes.)
*/
state->memtupsize = state->nOutputTapes;
- state->memtuples = (SortTuple *) MemoryContextAlloc(state->maincontext,
+ state->memtuples = (SortTuple *) MemoryContextAlloc(state->ops.maincontext,
state->nOutputTapes * sizeof(SortTuple));
USEMEM(state, GetMemoryChunkSpace(state->memtuples));
@@ -3113,7 +3175,7 @@ mergeruns(Tuplesortstate *state)
* sorted tape, we can stop at this point and do the final merge
* on-the-fly.
*/
- if ((state->sortopt & TUPLESORT_RANDOMACCESS) == 0
+ if ((state->ops.sortopt & TUPLESORT_RANDOMACCESS) == 0
&& state->nInputRuns <= state->nInputTapes
&& !WORKER(state))
{
@@ -3339,7 +3401,7 @@ dumptuples(Tuplesortstate *state, bool alltuples)
* AllocSetFree's bucketing by size class might be particularly bad if
* this step wasn't taken.
*/
- MemoryContextReset(state->tuplecontext);
+ MemoryContextReset(state->ops.tuplecontext);
markrunend(state->destTape);
@@ -3357,9 +3419,9 @@ dumptuples(Tuplesortstate *state, bool alltuples)
void
tuplesort_rescan(Tuplesortstate *state)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
- Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
+ Assert(state->ops.sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status)
{
@@ -3390,9 +3452,9 @@ tuplesort_rescan(Tuplesortstate *state)
void
tuplesort_markpos(Tuplesortstate *state)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
- Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
+ Assert(state->ops.sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status)
{
@@ -3421,9 +3483,9 @@ tuplesort_markpos(Tuplesortstate *state)
void
tuplesort_restorepos(Tuplesortstate *state)
{
- MemoryContext oldcontext = MemoryContextSwitchTo(state->sortcontext);
+ MemoryContext oldcontext = MemoryContextSwitchTo(state->ops.sortcontext);
- Assert(state->sortopt & TUPLESORT_RANDOMACCESS);
+ Assert(state->ops.sortopt & TUPLESORT_RANDOMACCESS);
switch (state->status)
{
@@ -3639,9 +3701,9 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
* Do we have the leading column's value or abbreviation in datum1,
* and is there a specialization for its comparator?
*/
- if (state->haveDatum1 && state->sortKeys)
+ if (state->ops.haveDatum1 && state->ops.sortKeys)
{
- if (state->sortKeys[0].comparator == ssup_datum_unsigned_cmp)
+ if (state->ops.sortKeys[0].comparator == ssup_datum_unsigned_cmp)
{
qsort_tuple_unsigned(state->memtuples,
state->memtupcount,
@@ -3649,7 +3711,7 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
return;
}
#if SIZEOF_DATUM >= 8
- else if (state->sortKeys[0].comparator == ssup_datum_signed_cmp)
+ else if (state->ops.sortKeys[0].comparator == ssup_datum_signed_cmp)
{
qsort_tuple_signed(state->memtuples,
state->memtupcount,
@@ -3657,7 +3719,7 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
return;
}
#endif
- else if (state->sortKeys[0].comparator == ssup_datum_int32_cmp)
+ else if (state->ops.sortKeys[0].comparator == ssup_datum_int32_cmp)
{
qsort_tuple_int32(state->memtuples,
state->memtupcount,
@@ -3667,16 +3729,16 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
}
/* Can we use the single-key sort function? */
- if (state->onlyKey != NULL)
+ if (state->ops.onlyKey != NULL)
{
qsort_ssup(state->memtuples, state->memtupcount,
- state->onlyKey);
+ state->ops.onlyKey);
}
else
{
qsort_tuple(state->memtuples,
state->memtupcount,
- state->comparetup,
+ state->ops.comparetup,
state);
}
}
@@ -3793,10 +3855,10 @@ tuplesort_heap_replace_top(Tuplesortstate *state, SortTuple *tuple)
static void
reversedirection(Tuplesortstate *state)
{
- SortSupport sortKey = state->sortKeys;
+ SortSupport sortKey = state->ops.sortKeys;
int nkey;
- for (nkey = 0; nkey < state->nKeys; nkey++, sortKey++)
+ for (nkey = 0; nkey < state->ops.nKeys; nkey++, sortKey++)
{
sortKey->ssup_reverse = !sortKey->ssup_reverse;
sortKey->ssup_nulls_first = !sortKey->ssup_nulls_first;
@@ -3847,7 +3909,7 @@ readtup_alloc(Tuplesortstate *state, Size tuplen)
Assert(state->slabFreeHead);
if (tuplen > SLAB_SLOT_SIZE || !state->slabFreeHead)
- return MemoryContextAlloc(state->sortcontext, tuplen);
+ return MemoryContextAlloc(state->ops.sortcontext, tuplen);
else
{
buf = state->slabFreeHead;
@@ -3866,6 +3928,7 @@ readtup_alloc(Tuplesortstate *state, Size tuplen)
static void
getdatum1_heap(Tuplesortstate *state, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
HeapTupleData htup;
htup.t_len = ((MinimalTuple) stup->tuple)->t_len +
@@ -3874,8 +3937,8 @@ getdatum1_heap(Tuplesortstate *state, SortTuple *stup)
MINIMAL_TUPLE_OFFSET);
stup->datum1 = heap_getattr(&htup,
- state->sortKeys[0].ssup_attno,
- state->tupDesc,
+ ops->sortKeys[0].ssup_attno,
+ (TupleDesc) ops->arg,
&stup->isnull1);
}
@@ -3883,7 +3946,8 @@ getdatum1_heap(Tuplesortstate *state, SortTuple *stup)
static int
comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
{
- SortSupport sortKey = state->sortKeys;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ SortSupport sortKey = ops->sortKeys;
HeapTupleData ltup;
HeapTupleData rtup;
TupleDesc tupDesc;
@@ -3908,7 +3972,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
ltup.t_data = (HeapTupleHeader) ((char *) a->tuple - MINIMAL_TUPLE_OFFSET);
rtup.t_len = ((MinimalTuple) b->tuple)->t_len + MINIMAL_TUPLE_OFFSET;
rtup.t_data = (HeapTupleHeader) ((char *) b->tuple - MINIMAL_TUPLE_OFFSET);
- tupDesc = state->tupDesc;
+ tupDesc = (TupleDesc) ops->arg;
if (sortKey->abbrev_converter)
{
@@ -3925,7 +3989,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
}
sortKey++;
- for (nkey = 1; nkey < state->nKeys; nkey++, sortKey++)
+ for (nkey = 1; nkey < ops->nKeys; nkey++, sortKey++)
{
attno = sortKey->ssup_attno;
@@ -3945,6 +4009,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
static void
writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
MinimalTuple tuple = (MinimalTuple) stup->tuple;
/* the part of the MinimalTuple we'll write: */
@@ -3956,7 +4021,7 @@ writetup_heap(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, (void *) tupbody, tupbodylen);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
}
@@ -3969,12 +4034,13 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup,
unsigned int tuplen = tupbodylen + MINIMAL_TUPLE_DATA_OFFSET;
MinimalTuple tuple = (MinimalTuple) readtup_alloc(state, tuplen);
char *tupbody = (char *) tuple + MINIMAL_TUPLE_DATA_OFFSET;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
HeapTupleData htup;
/* read in the tuple proper */
tuple->t_len = tuplen;
LogicalTapeReadExact(tape, tupbody, tupbodylen);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple;
@@ -3982,8 +4048,8 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup,
htup.t_len = tuple->t_len + MINIMAL_TUPLE_OFFSET;
htup.t_data = (HeapTupleHeader) ((char *) tuple - MINIMAL_TUPLE_OFFSET);
stup->datum1 = heap_getattr(&htup,
- state->sortKeys[0].ssup_attno,
- state->tupDesc,
+ ops->sortKeys[0].ssup_attno,
+ (TupleDesc) ops->arg,
&stup->isnull1);
}
@@ -3995,12 +4061,14 @@ readtup_heap(Tuplesortstate *state, SortTuple *stup,
static void
getdatum1_cluster(Tuplesortstate *state, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortClusterArg *arg = (TupleSortClusterArg *) ops->arg;
HeapTuple tup;
tup = (HeapTuple) stup->tuple;
stup->datum1 = heap_getattr(tup,
- state->indexInfo->ii_IndexAttrNumbers[0],
- state->tupDesc,
+ arg->indexInfo->ii_IndexAttrNumbers[0],
+ arg->tupDesc,
&stup->isnull1);
}
@@ -4008,7 +4076,9 @@ static int
comparetup_cluster(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state)
{
- SortSupport sortKey = state->sortKeys;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortClusterArg *arg = (TupleSortClusterArg *) ops->arg;
+ SortSupport sortKey = ops->sortKeys;
HeapTuple ltup;
HeapTuple rtup;
TupleDesc tupDesc;
@@ -4022,10 +4092,10 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
/* Be prepared to compare additional sort keys */
ltup = (HeapTuple) a->tuple;
rtup = (HeapTuple) b->tuple;
- tupDesc = state->tupDesc;
+ tupDesc = arg->tupDesc;
/* Compare the leading sort key, if it's simple */
- if (state->haveDatum1)
+ if (ops->haveDatum1)
{
compare = ApplySortComparator(a->datum1, a->isnull1,
b->datum1, b->isnull1,
@@ -4035,7 +4105,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
if (sortKey->abbrev_converter)
{
- AttrNumber leading = state->indexInfo->ii_IndexAttrNumbers[0];
+ AttrNumber leading = arg->indexInfo->ii_IndexAttrNumbers[0];
datum1 = heap_getattr(ltup, leading, tupDesc, &isnull1);
datum2 = heap_getattr(rtup, leading, tupDesc, &isnull2);
@@ -4044,7 +4114,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
datum2, isnull2,
sortKey);
}
- if (compare != 0 || state->nKeys == 1)
+ if (compare != 0 || ops->nKeys == 1)
return compare;
/* Compare additional columns the hard way */
sortKey++;
@@ -4056,13 +4126,13 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
nkey = 0;
}
- if (state->indexInfo->ii_Expressions == NULL)
+ if (arg->indexInfo->ii_Expressions == NULL)
{
/* If not expression index, just compare the proper heap attrs */
- for (; nkey < state->nKeys; nkey++, sortKey++)
+ for (; nkey < ops->nKeys; nkey++, sortKey++)
{
- AttrNumber attno = state->indexInfo->ii_IndexAttrNumbers[nkey];
+ AttrNumber attno = arg->indexInfo->ii_IndexAttrNumbers[nkey];
datum1 = heap_getattr(ltup, attno, tupDesc, &isnull1);
datum2 = heap_getattr(rtup, attno, tupDesc, &isnull2);
@@ -4089,19 +4159,19 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
TupleTableSlot *ecxt_scantuple;
/* Reset context each time to prevent memory leakage */
- ResetPerTupleExprContext(state->estate);
+ ResetPerTupleExprContext(arg->estate);
- ecxt_scantuple = GetPerTupleExprContext(state->estate)->ecxt_scantuple;
+ ecxt_scantuple = GetPerTupleExprContext(arg->estate)->ecxt_scantuple;
ExecStoreHeapTuple(ltup, ecxt_scantuple, false);
- FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate,
+ FormIndexDatum(arg->indexInfo, ecxt_scantuple, arg->estate,
l_index_values, l_index_isnull);
ExecStoreHeapTuple(rtup, ecxt_scantuple, false);
- FormIndexDatum(state->indexInfo, ecxt_scantuple, state->estate,
+ FormIndexDatum(arg->indexInfo, ecxt_scantuple, arg->estate,
r_index_values, r_index_isnull);
- for (; nkey < state->nKeys; nkey++, sortKey++)
+ for (; nkey < ops->nKeys; nkey++, sortKey++)
{
compare = ApplySortComparator(l_index_values[nkey],
l_index_isnull[nkey],
@@ -4119,6 +4189,7 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
static void
writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
HeapTuple tuple = (HeapTuple) stup->tuple;
unsigned int tuplen = tuple->t_len + sizeof(ItemPointerData) + sizeof(int);
@@ -4126,7 +4197,7 @@ writetup_cluster(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, &tuple->t_self, sizeof(ItemPointerData));
LogicalTapeWrite(tape, tuple->t_data, tuple->t_len);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, &tuplen, sizeof(tuplen));
}
@@ -4135,6 +4206,8 @@ static void
readtup_cluster(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int tuplen)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortClusterArg *arg = (TupleSortClusterArg *) ops->arg;
unsigned int t_len = tuplen - sizeof(ItemPointerData) - sizeof(int);
HeapTuple tuple = (HeapTuple) readtup_alloc(state,
t_len + HEAPTUPLESIZE);
@@ -4147,18 +4220,34 @@ readtup_cluster(Tuplesortstate *state, SortTuple *stup,
tuple->t_tableOid = InvalidOid;
/* Read in the tuple body */
LogicalTapeReadExact(tape, tuple->t_data, tuple->t_len);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple;
/* set up first-column key value, if it's a simple column */
- if (state->haveDatum1)
+ if (ops->haveDatum1)
stup->datum1 = heap_getattr(tuple,
- state->indexInfo->ii_IndexAttrNumbers[0],
- state->tupDesc,
+ arg->indexInfo->ii_IndexAttrNumbers[0],
+ arg->tupDesc,
&stup->isnull1);
}
+static void
+freestate_cluster(Tuplesortstate *state)
+{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortClusterArg *arg = (TupleSortClusterArg *) ops->arg;
+
+ /* Free any execution state created for CLUSTER case */
+ if (arg->estate != NULL)
+ {
+ ExprContext *econtext = GetPerTupleExprContext(arg->estate);
+
+ ExecDropSingleTupleTableSlot(econtext->ecxt_scantuple);
+ FreeExecutorState(arg->estate);
+ }
+}
+
/*
* Routines specialized for IndexTuple case
*
@@ -4170,12 +4259,14 @@ readtup_cluster(Tuplesortstate *state, SortTuple *stup,
static void
getdatum1_index(Tuplesortstate *state, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortIndexArg *arg = (TupleSortIndexArg *) ops->arg;
IndexTuple tuple;
tuple = stup->tuple;
stup->datum1 = index_getattr(tuple,
1,
- RelationGetDescr(state->indexRel),
+ RelationGetDescr(arg->indexRel),
&stup->isnull1);
}
@@ -4188,7 +4279,9 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
* is also special handling for enforcing uniqueness, and special
* treatment for equal keys at the end.
*/
- SortSupport sortKey = state->sortKeys;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortIndexBTreeArg *arg = (TupleSortIndexBTreeArg *) ops->arg;
+ SortSupport sortKey = ops->sortKeys;
IndexTuple tuple1;
IndexTuple tuple2;
int keysz;
@@ -4212,8 +4305,8 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
/* Compare additional sort keys */
tuple1 = (IndexTuple) a->tuple;
tuple2 = (IndexTuple) b->tuple;
- keysz = state->nKeys;
- tupDes = RelationGetDescr(state->indexRel);
+ keysz = ops->nKeys;
+ tupDes = RelationGetDescr(arg->index.indexRel);
if (sortKey->abbrev_converter)
{
@@ -4258,7 +4351,7 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
* sort algorithm wouldn't have checked whether one must appear before the
* other.
*/
- if (state->enforceUnique && !(!state->uniqueNullsNotDistinct && equal_hasnull))
+ if (arg->enforceUnique && !(!arg->uniqueNullsNotDistinct && equal_hasnull))
{
Datum values[INDEX_MAX_KEYS];
bool isnull[INDEX_MAX_KEYS];
@@ -4274,16 +4367,16 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
index_deform_tuple(tuple1, tupDes, values, isnull);
- key_desc = BuildIndexValueDescription(state->indexRel, values, isnull);
+ key_desc = BuildIndexValueDescription(arg->index.indexRel, values, isnull);
ereport(ERROR,
(errcode(ERRCODE_UNIQUE_VIOLATION),
errmsg("could not create unique index \"%s\"",
- RelationGetRelationName(state->indexRel)),
+ RelationGetRelationName(arg->index.indexRel)),
key_desc ? errdetail("Key %s is duplicated.", key_desc) :
errdetail("Duplicate keys exist."),
- errtableconstraint(state->heapRel,
- RelationGetRelationName(state->indexRel))));
+ errtableconstraint(arg->index.heapRel,
+ RelationGetRelationName(arg->index.indexRel))));
}
/*
@@ -4321,6 +4414,8 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
Bucket bucket2;
IndexTuple tuple1;
IndexTuple tuple2;
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortIndexHashArg *arg = (TupleSortIndexHashArg *) ops->arg;
/*
* Fetch hash keys and mask off bits we don't want to sort by. We know
@@ -4328,12 +4423,12 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
*/
Assert(!a->isnull1);
bucket1 = _hash_hashkey2bucket(DatumGetUInt32(a->datum1),
- state->max_buckets, state->high_mask,
- state->low_mask);
+ arg->max_buckets, arg->high_mask,
+ arg->low_mask);
Assert(!b->isnull1);
bucket2 = _hash_hashkey2bucket(DatumGetUInt32(b->datum1),
- state->max_buckets, state->high_mask,
- state->low_mask);
+ arg->max_buckets, arg->high_mask,
+ arg->low_mask);
if (bucket1 > bucket2)
return 1;
else if (bucket1 < bucket2)
@@ -4371,13 +4466,14 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
static void
writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
IndexTuple tuple = (IndexTuple) stup->tuple;
unsigned int tuplen;
tuplen = IndexTupleSize(tuple) + sizeof(tuplen);
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
LogicalTapeWrite(tape, (void *) tuple, IndexTupleSize(tuple));
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &tuplen, sizeof(tuplen));
}
@@ -4386,18 +4482,20 @@ static void
readtup_index(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortIndexArg *arg = (TupleSortIndexArg *) ops->arg;
unsigned int tuplen = len - sizeof(unsigned int);
IndexTuple tuple = (IndexTuple) readtup_alloc(state, tuplen);
LogicalTapeReadExact(tape, tuple, tuplen);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
stup->tuple = (void *) tuple;
/* set up first-column key value */
stup->datum1 = index_getattr(tuple,
1,
- RelationGetDescr(state->indexRel),
+ RelationGetDescr(arg->indexRel),
&stup->isnull1);
}
@@ -4414,20 +4512,21 @@ getdatum1_datum(Tuplesortstate *state, SortTuple *stup)
static int
comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
int compare;
compare = ApplySortComparator(a->datum1, a->isnull1,
b->datum1, b->isnull1,
- state->sortKeys);
+ ops->sortKeys);
if (compare != 0)
return compare;
/* if we have abbreviations, then "tuple" has the original value */
- if (state->sortKeys->abbrev_converter)
+ if (ops->sortKeys->abbrev_converter)
compare = ApplySortAbbrevFullComparator(PointerGetDatum(a->tuple), a->isnull1,
PointerGetDatum(b->tuple), b->isnull1,
- state->sortKeys);
+ ops->sortKeys);
return compare;
}
@@ -4435,6 +4534,8 @@ comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
static void
writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
+ TupleSortDatumArg *arg = (TupleSortDatumArg *) ops->arg;
void *waddr;
unsigned int tuplen;
unsigned int writtenlen;
@@ -4444,7 +4545,7 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
waddr = NULL;
tuplen = 0;
}
- else if (!state->tuples)
+ else if (!state->ops.tuples)
{
waddr = &stup->datum1;
tuplen = sizeof(Datum);
@@ -4452,7 +4553,7 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
else
{
waddr = stup->tuple;
- tuplen = datumGetSize(PointerGetDatum(stup->tuple), false, state->datumTypeLen);
+ tuplen = datumGetSize(PointerGetDatum(stup->tuple), false, arg->datumTypeLen);
Assert(tuplen != 0);
}
@@ -4460,7 +4561,7 @@ writetup_datum(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
LogicalTapeWrite(tape, waddr, tuplen);
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeWrite(tape, (void *) &writtenlen, sizeof(writtenlen));
}
@@ -4469,6 +4570,7 @@ static void
readtup_datum(Tuplesortstate *state, SortTuple *stup,
LogicalTape *tape, unsigned int len)
{
+ TuplesortOps *ops = TuplesortstateGetOps(state);
unsigned int tuplen = len - sizeof(unsigned int);
if (tuplen == 0)
@@ -4478,7 +4580,7 @@ readtup_datum(Tuplesortstate *state, SortTuple *stup,
stup->isnull1 = true;
stup->tuple = NULL;
}
- else if (!state->tuples)
+ else if (!state->ops.tuples)
{
Assert(tuplen == sizeof(Datum));
LogicalTapeReadExact(tape, &stup->datum1, tuplen);
@@ -4495,7 +4597,7 @@ readtup_datum(Tuplesortstate *state, SortTuple *stup,
stup->tuple = raddr;
}
- if (state->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
+ if (ops->sortopt & TUPLESORT_RANDOMACCESS) /* need trailing length
* word? */
LogicalTapeReadExact(tape, &tuplen, sizeof(tuplen));
}
--
2.30.2