2828#include "rum.h" /* RumItem */
2929
3030#if PG_VERSION_NUM >=160000
31- #include "tuplesort16.c"
32- #undef TRACE_SORT
31+ /*
32+ * After allocating a public interface for Tuplesortstate, no need to include
33+ * source code from pg-core.
34+ */
3335#elif PG_VERSION_NUM >=150000
3436#include "tuplesort15.c"
3537#elif PG_VERSION_NUM >=140000
4648#include "tuplesort96.c"
4749#endif
4850
51+ /*
52+ * In case of using custom compare function we should store function pointer in
53+ * sort stare in order to use it later.
54+ */
55+
56+ #if PG_VERSION_NUM >=160000
57+ /*
58+ * After allocating a public interface for Tuplesortstate we may use
59+ * TuplesortPublic->arg filed to store pointer to the compare function.
60+ */
61+
62+ /* GUC variables */
63+ #ifdef TRACE_SORT
64+ extern PGDLLIMPORT bool trace_sort ;
65+ #endif
66+
67+ /* All memory management should be inside Tuplesortstate module. */
68+ #define USEMEM (state ,amt )do {} while(0)
69+
70+ #else /* PG_VERSION_NUM >= 160000 */
4971/*
5072 * We need extra field in a state structure but we should not modify struct
5173 * RumTuplesortstate which is inherited from Tuplesortstate core function.
@@ -55,6 +77,7 @@ typedef struct RumTuplesortstateExt
5577RumTuplesortstate ts ;
5678FmgrInfo * cmp ;
5779}RumTuplesortstateExt ;
80+ #endif /* PG_VERSION_NUM < 160000 */
5881
5982static int comparetup_rum (const SortTuple * a ,const SortTuple * b ,
6083RumTuplesortstate * state ,bool compareItemPointer );
@@ -70,12 +93,18 @@ static void copytup_rumitem(RumTuplesortstate *state, SortTuple *stup,
7093static void * rum_tuplesort_getrum_internal (RumTuplesortstate * state ,
7194bool forward ,bool * should_free );
7295
96+ /*
97+ * Tuplesortstate handling should be done through this macro.
98+ */
7399#if PG_VERSION_NUM >=160000
74100#define TSS_GET (state )TuplesortstateGetPublic((state))
75101#else
76102#define TSS_GET (state )(state)
77103#endif
78104
105+ /*
106+ * Logical tape handling should be done through this macro.
107+ */
79108#if PG_VERSION_NUM >=150000
80109#define LT_TYPE LogicalTape *
81110#define LT_ARG tape
@@ -86,6 +115,25 @@ static void *rum_tuplesort_getrum_internal(RumTuplesortstate *state,
86115#define TAPE (state ,LT_ARG ) state->tapeset, LT_ARG
87116#endif
88117
118+ /*
119+ * Just for convenience and uniformity.
120+ */
121+ #if PG_VERSION_NUM >=110000
122+ #define tuplesort_begin_common (x ,y ) tuplesort_begin_common((x), NULL, (y))
123+ #endif
124+
125+ /*
126+ * Trace log wrapper.
127+ */
128+ #ifdef TRACE_SORT
129+ #define LOG_SORT (...)\
130+ if (trace_sort)\
131+ ereport(LOG, errmsg_internal(__VA_ARGS__))
132+ #else
133+ #define LOG_SORT (...)\
134+ {}
135+ #endif
136+
89137static inline int
90138compare_rum_itempointer (ItemPointerData p1 ,ItemPointerData p2 )
91139{
@@ -156,19 +204,29 @@ comparetup_rum_false(const SortTuple *a, const SortTuple *b,
156204return comparetup_rum (a ,b ,state , false);
157205}
158206
207+ static inline FmgrInfo *
208+ comparetup_rumitem_custom_fun (RumTuplesortstate * state )
209+ {
210+ #if PG_VERSION_NUM >=160000
211+ return (FmgrInfo * )TSS_GET (state )-> arg ;
212+ #else
213+ return ((RumTuplesortstateExt * )state )-> cmp ;
214+ #endif
215+ }
216+
159217static int
160218comparetup_rumitem (const SortTuple * a ,const SortTuple * b ,
161219RumTuplesortstate * state )
162220{
163- RumItem * i1 ,
164- * i2 ;
165- FmgrInfo * cmp ;
221+ RumItem * i1 ,
222+ * i2 ;
223+ FmgrInfo * cmp ;
166224
167225/* Extract RumItem from RumScanItem */
168226i1 = (RumItem * )a -> tuple ;
169227i2 = (RumItem * )b -> tuple ;
170228
171- cmp = (( RumTuplesortstateExt * ) state )-> cmp ;
229+ cmp = comparetup_rumitem_custom_fun ( state );
172230if (cmp != NULL )
173231{
174232if (i1 -> addInfoIsNull || i2 -> addInfoIsNull )
@@ -242,17 +300,21 @@ writetup_rum_internal(RumTuplesortstate *state, LT_TYPE LT_ARG,
242300void * item = stup -> tuple ;
243301size_t size = rum_item_size (state );
244302unsignedint writtenlen = size + sizeof (unsignedint );
303+ bool randomAccess ;
245304
246305LogicalTapeWrite (TAPE (state ,LT_ARG ),
247306 (void * )& writtenlen ,sizeof (writtenlen ));
248307LogicalTapeWrite (TAPE (state ,LT_ARG ),
249308 (void * )item ,size );
250- #if PG_VERSION_NUM >=150000
251- if (TSS_GET (state )-> sortopt & TUPLESORT_RANDOMACCESS )/* need trailing
252- * length word? */
253- #else
254- if (TSS_GET (state )-> randomAccess )/* need trailing length word? */
255- #endif
309+
310+ randomAccess =
311+ #if PG_VERSION_NUM >=150000
312+ (TSS_GET (state )-> sortopt & TUPLESORT_RANDOMACCESS )!= 0 ;
313+ #else
314+ TSS_GET (state )-> randomAccess ;
315+ #endif
316+
317+ if (randomAccess )
256318LogicalTapeWrite (TAPE (TSS_GET (state ),LT_ARG ), (void * )& writtenlen ,
257319sizeof (writtenlen ));
258320}
@@ -280,6 +342,7 @@ readtup_rum_internal(RumTuplesortstate *state, SortTuple *stup,
280342Assert (tuplen == size );
281343
282344USEMEM (state ,GetMemoryChunkSpace (item ));
345+
283346#if PG_VERSION_NUM >=150000
284347LogicalTapeReadExact (LT_ARG ,item ,size );
285348#else
@@ -316,10 +379,6 @@ readtup_rumitem(RumTuplesortstate *state, SortTuple *stup, LT_TYPE LT_ARG,
316379readtup_rum_internal (state ,stup ,LT_ARG ,len , true);
317380}
318381
319- #if PG_VERSION_NUM >=110000
320- #define tuplesort_begin_common (x ,y ) tuplesort_begin_common((x), NULL, (y))
321- #endif
322-
323382RumTuplesortstate *
324383rum_tuplesort_begin_rum (int workMem ,int nKeys ,bool randomAccess ,
325384bool compareItemPointer )
@@ -336,12 +395,8 @@ rum_tuplesort_begin_rum(int workMem, int nKeys, bool randomAccess,
336395
337396oldcontext = MemoryContextSwitchTo (TSS_GET (state )-> sortcontext );
338397
339- #ifdef TRACE_SORT
340- if (trace_sort )
341- elog (LOG ,
342- "begin rum sort: nKeys = %d, workMem = %d, randomAccess = %c" ,
398+ LOG_SORT ("begin rum sort: nKeys = %d, workMem = %d, randomAccess = %c" ,
343399nKeys ,workMem ,randomAccess ?'t' :'f' );
344- #endif
345400
346401TSS_GET (state )-> nKeys = nKeys ;
347402TSS_GET (state )-> comparetup = compareItemPointer ?comparetup_rum_true :
@@ -357,6 +412,23 @@ rum_tuplesort_begin_rum(int workMem, int nKeys, bool randomAccess,
357412RumTuplesortstate *
358413rum_tuplesort_begin_rumitem (int workMem ,FmgrInfo * cmp )
359414{
415+ #if PG_VERSION_NUM >=160000
416+ RumTuplesortstate * state = tuplesort_begin_common (workMem , false);
417+ MemoryContext oldcontext ;
418+
419+ oldcontext = MemoryContextSwitchTo (TSS_GET (state )-> sortcontext );
420+
421+ LOG_SORT ("begin rumitem sort: workMem = %d" ,workMem );
422+
423+ TSS_GET (state )-> comparetup = comparetup_rumitem ;
424+ TSS_GET (state )-> writetup = writetup_rumitem ;
425+ TSS_GET (state )-> readtup = readtup_rumitem ;
426+ TSS_GET (state )-> arg = cmp ;
427+
428+ MemoryContextSwitchTo (oldcontext );
429+
430+ return state ;
431+ #else
360432RumTuplesortstate * state = tuplesort_begin_common (workMem , false);
361433RumTuplesortstateExt * rs ;
362434MemoryContext oldcontext ;
@@ -366,11 +438,7 @@ rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp)
366438/* Allocate extended state in the same context as state */
367439rs = palloc (sizeof (* rs ));
368440
369- #ifdef TRACE_SORT
370- if (trace_sort )
371- elog (LOG ,
372- "begin rumitem sort: workMem = %d" ,workMem );
373- #endif
441+ LOG_SORT ("begin rumitem sort: workMem = %d" ,workMem );
374442
375443rs -> cmp = cmp ;
376444TSS_GET (state )-> comparetup = comparetup_rumitem ;
@@ -383,6 +451,7 @@ rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp)
383451MemoryContextSwitchTo (oldcontext );
384452
385453return (RumTuplesortstate * )rs ;
454+ #endif
386455}
387456
388457/*
@@ -397,7 +466,7 @@ rum_tuplesort_begin_rumitem(int workMem, FmgrInfo *cmp)
397466void
398467rum_tuplesort_end (RumTuplesortstate * state )
399468{
400- #if PG_VERSION_NUM >=130000
469+ #if PG_VERSION_NUM < 160000 && PG_VERSION_NUM >=130000
401470tuplesort_free (state );
402471#else
403472tuplesort_end (state );