aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2022-07-27 08:28:26 +0300
committerAlexander Korotkov <akorotkov@postgresql.org>2022-07-27 08:28:26 +0300
commitd0b193c0fad13cf35122b0d3dc805c76e323e8bf (patch)
tree3264a78a1e6b8d540ef808a2db1763ae6185f3fd /src/include
parentec92fe98356a8a36427fe9ef52873b50fe17852e (diff)
downloadpostgresql-d0b193c0fad13cf35122b0d3dc805c76e323e8bf.tar.gz
postgresql-d0b193c0fad13cf35122b0d3dc805c76e323e8bf.zip
Split tuplesortvariants.c from tuplesort.c
This commit puts the implementation of Tuple sort variants into the separate file tuplesortvariants.c. That gives better separation of the code and serves well as the demonstration that Tuple sort variant can be defined outside of tuplesort.c. 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
Diffstat (limited to 'src/include')
-rw-r--r--src/include/utils/tuplesort.h222
1 files changed, 188 insertions, 34 deletions
diff --git a/src/include/utils/tuplesort.h b/src/include/utils/tuplesort.h
index 364cf132fcb..e82b5a638d2 100644
--- a/src/include/utils/tuplesort.h
+++ b/src/include/utils/tuplesort.h
@@ -24,7 +24,9 @@
#include "access/itup.h"
#include "executor/tuptable.h"
#include "storage/dsm.h"
+#include "utils/logtape.h"
#include "utils/relcache.h"
+#include "utils/sortsupport.h"
/*
@@ -102,6 +104,148 @@ typedef struct TuplesortInstrumentation
int64 spaceUsed; /* space consumption, in kB */
} TuplesortInstrumentation;
+/*
+ * The objects we actually sort are SortTuple structs. These contain
+ * a pointer to the tuple proper (might be a MinimalTuple or IndexTuple),
+ * which is a separate palloc chunk --- we assume it is just one chunk and
+ * can be freed by a simple pfree() (except during merge, when we use a
+ * simple slab allocator). SortTuples also contain the tuple's first key
+ * column in Datum/nullflag format, and a source/input tape number that
+ * tracks which tape each heap element/slot belongs to during merging.
+ *
+ * Storing the first key column lets us save heap_getattr or index_getattr
+ * calls during tuple comparisons. We could extract and save all the key
+ * columns not just the first, but this would increase code complexity and
+ * overhead, and wouldn't actually save any comparison cycles in the common
+ * case where the first key determines the comparison result. Note that
+ * for a pass-by-reference datatype, datum1 points into the "tuple" storage.
+ *
+ * There is one special case: when the sort support infrastructure provides an
+ * "abbreviated key" representation, where the key is (typically) a pass by
+ * value proxy for a pass by reference type. In this case, the abbreviated key
+ * is stored in datum1 in place of the actual first key column.
+ *
+ * When sorting single Datums, the data value is represented directly by
+ * datum1/isnull1 for pass by value types (or null values). If the datatype is
+ * pass-by-reference and isnull1 is false, then "tuple" points to a separately
+ * palloc'd data value, otherwise "tuple" is NULL. The value of datum1 is then
+ * either the same pointer as "tuple", or is an abbreviated key value as
+ * described above. Accordingly, "tuple" is always used in preference to
+ * datum1 as the authoritative value for pass-by-reference cases.
+ */
+typedef struct
+{
+ void *tuple; /* the tuple itself */
+ Datum datum1; /* value of first key column */
+ bool isnull1; /* is first key column NULL? */
+ int srctape; /* source tape number */
+} SortTuple;
+
+typedef int (*SortTupleComparator) (const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
+
+/*
+ * The public part of a Tuple sort operation state. This data structure
+ * containsthe definition of sort-variant-specific interface methods and
+ * the part of Tuple sort operation state required by their implementations.
+ */
+typedef struct
+{
+ /*
+ * These function pointers decouple the routines that must know what kind
+ * of tuple we are sorting from the routines that don't need to know it.
+ * They are set up by the tuplesort_begin_xxx routines.
+ *
+ * Function to compare two tuples; result is per qsort() convention, ie:
+ * <0, 0, >0 according as a<b, a=b, a>b. The API must match
+ * qsort_arg_comparator.
+ */
+ SortTupleComparator comparetup;
+
+ /*
+ * Alter datum1 representation in the SortTuple's array back from the
+ * abbreviated key to the first column value.
+ */
+ void (*removeabbrev) (Tuplesortstate *state, SortTuple *stups,
+ int count);
+
+ /*
+ * 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.
+ */
+ void (*writetup) (Tuplesortstate *state, LogicalTape *tape,
+ SortTuple *stup);
+
+ /*
+ * Function to read a stored tuple from tape back into memory. 'len' is
+ * the already-read length of the stored tuple. The tuple is allocated
+ * from the slab memory arena, or is palloc'd, see
+ * tuplesort_readtup_alloc().
+ */
+ void (*readtup) (Tuplesortstate *state, SortTuple *stup,
+ LogicalTape *tape, unsigned int len);
+
+ /*
+ * Function to do some specific release of resources for the sort variant.
+ * In particular, this function should free everything stored in the "arg"
+ * field, which wouldn't be cleared on reset of the Tuple sort memory
+ * contextes. This can be NULL if nothing specific needs to be done.
+ */
+ void (*freestate) (Tuplesortstate *state);
+
+ /*
+ * The subsequent fields are used in the implementations of the functions
+ * above.
+ */
+ 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 */
+
+ /*
+ * 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; /* Specific information for the sort variant */
+} TuplesortPublic;
+
+/* Sort parallel code from state for sort__start probes */
+#define PARALLEL_SORT(coordinate) (coordinate == NULL || \
+ (coordinate)->sharedsort == NULL ? 0 : \
+ (coordinate)->isWorker ? 1 : 2)
+
+#define TuplesortstateGetPublic(state) ((TuplesortPublic *) state)
+
+/* When using this macro, beware of double evaluation of len */
+#define LogicalTapeReadExact(tape, ptr, len) \
+ do { \
+ if (LogicalTapeRead(tape, ptr, len) != (size_t) (len)) \
+ elog(ERROR, "unexpected end of data"); \
+ } while(0)
/*
* We provide multiple interfaces to what is essentially the same code,
@@ -205,6 +349,50 @@ typedef struct TuplesortInstrumentation
* generated (typically, caller uses a parallel heap scan).
*/
+
+extern Tuplesortstate *tuplesort_begin_common(int workMem,
+ SortCoordinate coordinate,
+ int sortopt);
+extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
+extern bool tuplesort_used_bound(Tuplesortstate *state);
+extern void tuplesort_puttuple_common(Tuplesortstate *state,
+ SortTuple *tuple, bool useAbbrev);
+extern void tuplesort_performsort(Tuplesortstate *state);
+extern bool tuplesort_gettuple_common(Tuplesortstate *state, bool forward,
+ SortTuple *stup);
+extern bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples,
+ bool forward);
+extern void tuplesort_end(Tuplesortstate *state);
+extern void tuplesort_reset(Tuplesortstate *state);
+
+extern void tuplesort_get_stats(Tuplesortstate *state,
+ TuplesortInstrumentation *stats);
+extern const char *tuplesort_method_name(TuplesortMethod m);
+extern const char *tuplesort_space_type_name(TuplesortSpaceType t);
+
+extern int tuplesort_merge_order(int64 allowedMem);
+
+extern Size tuplesort_estimate_shared(int nworkers);
+extern void tuplesort_initialize_shared(Sharedsort *shared, int nWorkers,
+ dsm_segment *seg);
+extern void tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg);
+
+/*
+ * These routines may only be called if randomAccess was specified 'true'.
+ * Likewise, backwards scan in gettuple/getdatum is only allowed if
+ * randomAccess was specified. Note that parallel sorts do not support
+ * randomAccess.
+ */
+
+extern void tuplesort_rescan(Tuplesortstate *state);
+extern void tuplesort_markpos(Tuplesortstate *state);
+extern void tuplesort_restorepos(Tuplesortstate *state);
+
+extern void *tuplesort_readtup_alloc(Tuplesortstate *state, Size tuplen);
+
+
+/* tuplesortvariants.c */
+
extern Tuplesortstate *tuplesort_begin_heap(TupleDesc tupDesc,
int nkeys, AttrNumber *attNums,
Oid *sortOperators, Oid *sortCollations,
@@ -238,9 +426,6 @@ extern Tuplesortstate *tuplesort_begin_datum(Oid datumType,
int workMem, SortCoordinate coordinate,
int sortopt);
-extern void tuplesort_set_bound(Tuplesortstate *state, int64 bound);
-extern bool tuplesort_used_bound(Tuplesortstate *state);
-
extern void tuplesort_puttupleslot(Tuplesortstate *state,
TupleTableSlot *slot);
extern void tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup);
@@ -250,8 +435,6 @@ extern void tuplesort_putindextuplevalues(Tuplesortstate *state,
extern void tuplesort_putdatum(Tuplesortstate *state, Datum val,
bool isNull);
-extern void tuplesort_performsort(Tuplesortstate *state);
-
extern bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward,
bool copy, TupleTableSlot *slot, Datum *abbrev);
extern HeapTuple tuplesort_getheaptuple(Tuplesortstate *state, bool forward);
@@ -259,34 +442,5 @@ extern IndexTuple tuplesort_getindextuple(Tuplesortstate *state, bool forward);
extern bool tuplesort_getdatum(Tuplesortstate *state, bool forward,
Datum *val, bool *isNull, Datum *abbrev);
-extern bool tuplesort_skiptuples(Tuplesortstate *state, int64 ntuples,
- bool forward);
-
-extern void tuplesort_end(Tuplesortstate *state);
-
-extern void tuplesort_reset(Tuplesortstate *state);
-
-extern void tuplesort_get_stats(Tuplesortstate *state,
- TuplesortInstrumentation *stats);
-extern const char *tuplesort_method_name(TuplesortMethod m);
-extern const char *tuplesort_space_type_name(TuplesortSpaceType t);
-
-extern int tuplesort_merge_order(int64 allowedMem);
-
-extern Size tuplesort_estimate_shared(int nworkers);
-extern void tuplesort_initialize_shared(Sharedsort *shared, int nWorkers,
- dsm_segment *seg);
-extern void tuplesort_attach_shared(Sharedsort *shared, dsm_segment *seg);
-
-/*
- * These routines may only be called if randomAccess was specified 'true'.
- * Likewise, backwards scan in gettuple/getdatum is only allowed if
- * randomAccess was specified. Note that parallel sorts do not support
- * randomAccess.
- */
-
-extern void tuplesort_rescan(Tuplesortstate *state);
-extern void tuplesort_markpos(Tuplesortstate *state);
-extern void tuplesort_restorepos(Tuplesortstate *state);
#endif /* TUPLESORT_H */