multi-key.patch
application/octet-stream
Filename: multi-key.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/utils/sort/gen_qsort_tuple.pl | 19 | 0 |
| src/backend/utils/sort/tuplesort.c | 54 | 0 |
| src/include/c.h | 14 | 0 |
commit 4a4fb12548eb2533f8804a691daad4bfb53302f4
Author: Robert Haas <rhaas@postgresql.org>
Date: Tue Feb 14 23:45:06 2012 -0500
Revert "Revert "Multi-key specializations.""
This reverts commit 6319911c04ab827449aab0c68cb7d5966825746e.
diff --git a/src/backend/utils/sort/gen_qsort_tuple.pl b/src/backend/utils/sort/gen_qsort_tuple.pl
index 40d5548..a31a3e2 100755
--- a/src/backend/utils/sort/gen_qsort_tuple.pl
+++ b/src/backend/utils/sort/gen_qsort_tuple.pl
@@ -49,6 +49,25 @@ print <<'EOM';
EOM
emit_qsort_implementation();
+$SUFFIX = 'heap';
+$EXTRAARGS = ', Tuplesortstate *state';
+$EXTRAPARAMS = ', state';
+$CMPPARAMS = ', state';
+print <<'EOM';
+static pg_always_inline int
+cmp_heap(SortTuple *a, SortTuple *b, Tuplesortstate *state)
+{
+ int compare;
+
+ compare = ApplySortComparator(a->datum1, a->isnull1,
+ b->datum1, b->isnull1, state->sortKeys);
+ if (compare == 0)
+ compare = state->comparetup_rest(a, b, state);
+ return compare;
+}
+EOM
+emit_qsort_implementation();
+
sub emit_qsort_boilerplate
{
print <<'EOM';
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 10b19c0..cdaa230 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -229,6 +229,12 @@ struct Tuplesortstate
SortTupleComparator comparetup;
/*
+ * Function to compare the non-leading columns of two tuples, as per
+ * above.
+ */
+ SortTupleComparator comparetup_rest;
+
+ /*
* 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
@@ -462,6 +468,8 @@ static unsigned int getlen(Tuplesortstate *state, int tapenum, bool eofOK);
static void markrunend(Tuplesortstate *state, int tapenum);
static int comparetup_heap(const SortTuple *a, const SortTuple *b,
Tuplesortstate *state);
+static int comparetup_heap_rest(const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state);
static void copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup);
static void writetup_heap(Tuplesortstate *state, int tapenum,
SortTuple *stup);
@@ -615,6 +623,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
randomAccess);
state->comparetup = comparetup_heap;
+ state->comparetup_rest = comparetup_heap_rest;
state->copytup = copytup_heap;
state->writetup = writetup_heap;
state->readtup = readtup_heap;
@@ -1238,6 +1247,8 @@ tuplesort_performsort(Tuplesortstate *state)
if (state->onlyKey != NULL)
qsort_ssup(state->memtuples, state->memtupcount,
state->onlyKey);
+ else if (state->comparetup_rest != NULL)
+ qsort_heap(state->memtuples, state->memtupcount, state);
else
qsort_tuple(state->memtuples,
state->memtupcount,
@@ -2712,6 +2723,49 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
return 0;
}
+static int
+comparetup_heap_rest(const SortTuple *a, const SortTuple *b,
+ Tuplesortstate *state)
+{
+ SortSupport sortKey = state->sortKeys;
+ HeapTupleData ltup;
+ HeapTupleData rtup;
+ TupleDesc tupDesc;
+ int nkey;
+ int32 compare = 0;
+
+ /*
+ * We don't have to compare the leading sort key, because qsort_heap will
+ * have already done that. Our join is to compare the remaining sort keys
+ * to break ties.
+ */
+ ltup.t_len = ((MinimalTuple) a->tuple)->t_len + MINIMAL_TUPLE_OFFSET;
+ 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;
+ sortKey++;
+ for (nkey = 1; nkey < state->nKeys; nkey++, sortKey++)
+ {
+ AttrNumber attno = sortKey->ssup_attno;
+ Datum datum1,
+ datum2;
+ bool isnull1,
+ isnull2;
+
+ datum1 = heap_getattr(<up, attno, tupDesc, &isnull1);
+ datum2 = heap_getattr(&rtup, attno, tupDesc, &isnull2);
+
+ compare = ApplySortComparator(datum1, isnull1,
+ datum2, isnull2,
+ sortKey);
+ if (compare != 0)
+ return compare;
+ }
+
+ return 0;
+}
+
static void
copytup_heap(Tuplesortstate *state, SortTuple *stup, void *tup)
{
diff --git a/src/include/c.h b/src/include/c.h
index 7396adb..ecb1a60 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -850,4 +850,18 @@ extern int fdatasync(int fildes);
/* /port compatibility functions */
#include "port.h"
+/*
+ * Define a cross-platform "always-inline" macro. This is a very sharp tool that
+ * should be used judiciously.
+ */
+#ifdef __always_inline
+#define pg_always_inline __always_inline
+#elif defined(__force_inline)
+#define pg_always_inline __force_inline
+#elif __GNUC__
+#define pg_always_inline inline __attribute__((always_inline))
+#else
+#define pg_always_inline inline
+#endif
+
#endif /* C_H */