Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c9bfa40

Browse files
committed
Split out tiebreaker comparisons from comparetup_* functions
Previously, if a specialized comparator found equal datum1 keys, the "comparetup" function would repeat the comparison on the datum before proceeding with the unabbreviated first key and/or additional sort keys. Move comparing additional sort keys into "tiebreak" functions so that specialized comparators can call these directly if needed, avoiding duplicate work. Reviewed by David Rowley Discussion: https://postgr.es/m/CAFBsxsGaVfUrjTghpf%3DkDBYY%3DjWx1PN-fuusVe7Vw5s0XqGdGw%40mail.gmail.com
1 parent 89be0b8 commit c9bfa40

File tree

3 files changed

+108
-33
lines changed

3 files changed

+108
-33
lines changed

src/backend/utils/sort/tuplesort.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -485,9 +485,6 @@ static void tuplesort_updatemax(Tuplesortstate *state);
485485
* is to try to sort two tuples without having to follow the pointers to the
486486
* comparator or the tuple.
487487
*
488-
* XXX: For now, these fall back to comparator functions that will compare the
489-
* leading datum a second time.
490-
*
491488
* XXX: For now, there is no specialization for cases where datum1 is
492489
* authoritative and we don't even need to fall back to a callback at all (that
493490
* would be true for types like int4/int8/timestamp/date, but not true for
@@ -513,7 +510,7 @@ qsort_tuple_unsigned_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
513510
if (state->base.onlyKey != NULL)
514511
return 0;
515512

516-
return state->base.comparetup(a, b, state);
513+
return state->base.comparetup_tiebreak(a, b, state);
517514
}
518515

519516
#if SIZEOF_DATUM >= 8
@@ -537,7 +534,7 @@ qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
537534
if (state->base.onlyKey != NULL)
538535
return 0;
539536

540-
return state->base.comparetup(a, b, state);
537+
return state->base.comparetup_tiebreak(a, b, state);
541538
}
542539
#endif
543540

@@ -561,7 +558,7 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
561558
if (state->base.onlyKey != NULL)
562559
return 0;
563560

564-
return state->base.comparetup(a, b, state);
561+
return state->base.comparetup_tiebreak(a, b, state);
565562
}
566563

567564
/*

src/backend/utils/sort/tuplesortvariants.c

Lines changed: 98 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,36 @@ static void removeabbrev_datum(Tuplesortstate *state, SortTuple *stups,
4747
int count);
4848
static int comparetup_heap(const SortTuple *a, const SortTuple *b,
4949
Tuplesortstate *state);
50+
static int comparetup_heap_tiebreak(const SortTuple *a, const SortTuple *b,
51+
Tuplesortstate *state);
5052
static void writetup_heap(Tuplesortstate *state, LogicalTape *tape,
5153
SortTuple *stup);
5254
static void readtup_heap(Tuplesortstate *state, SortTuple *stup,
5355
LogicalTape *tape, unsigned int len);
5456
static int comparetup_cluster(const SortTuple *a, const SortTuple *b,
5557
Tuplesortstate *state);
58+
static int comparetup_cluster_tiebreak(const SortTuple *a, const SortTuple *b,
59+
Tuplesortstate *state);
5660
static void writetup_cluster(Tuplesortstate *state, LogicalTape *tape,
5761
SortTuple *stup);
5862
static void readtup_cluster(Tuplesortstate *state, SortTuple *stup,
5963
LogicalTape *tape, unsigned int tuplen);
6064
static int comparetup_index_btree(const SortTuple *a, const SortTuple *b,
6165
Tuplesortstate *state);
66+
static int comparetup_index_btree_tiebreak(const SortTuple *a, const SortTuple *b,
67+
Tuplesortstate *state);
6268
static int comparetup_index_hash(const SortTuple *a, const SortTuple *b,
6369
Tuplesortstate *state);
70+
static int comparetup_index_hash_tiebreak(const SortTuple *a, const SortTuple *b,
71+
Tuplesortstate *state);
6472
static void writetup_index(Tuplesortstate *state, LogicalTape *tape,
6573
SortTuple *stup);
6674
static void readtup_index(Tuplesortstate *state, SortTuple *stup,
6775
LogicalTape *tape, unsigned int len);
6876
static int comparetup_datum(const SortTuple *a, const SortTuple *b,
6977
Tuplesortstate *state);
78+
static int comparetup_datum_tiebreak(const SortTuple *a, const SortTuple *b,
79+
Tuplesortstate *state);
7080
static void writetup_datum(Tuplesortstate *state, LogicalTape *tape,
7181
SortTuple *stup);
7282
static void readtup_datum(Tuplesortstate *state, SortTuple *stup,
@@ -165,6 +175,7 @@ tuplesort_begin_heap(TupleDesc tupDesc,
165175

166176
base->removeabbrev = removeabbrev_heap;
167177
base->comparetup = comparetup_heap;
178+
base->comparetup_tiebreak = comparetup_heap_tiebreak;
168179
base->writetup = writetup_heap;
169180
base->readtup = readtup_heap;
170181
base->haveDatum1 = true;
@@ -242,6 +253,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
242253

243254
base->removeabbrev = removeabbrev_cluster;
244255
base->comparetup = comparetup_cluster;
256+
base->comparetup_tiebreak = comparetup_cluster_tiebreak;
245257
base->writetup = writetup_cluster;
246258
base->readtup = readtup_cluster;
247259
base->freestate = freestate_cluster;
@@ -351,6 +363,7 @@ tuplesort_begin_index_btree(Relation heapRel,
351363

352364
base->removeabbrev = removeabbrev_index;
353365
base->comparetup = comparetup_index_btree;
366+
base->comparetup_tiebreak = comparetup_index_btree_tiebreak;
354367
base->writetup = writetup_index;
355368
base->readtup = readtup_index;
356369
base->haveDatum1 = true;
@@ -431,6 +444,7 @@ tuplesort_begin_index_hash(Relation heapRel,
431444

432445
base->removeabbrev = removeabbrev_index;
433446
base->comparetup = comparetup_index_hash;
447+
base->comparetup_tiebreak = comparetup_index_hash_tiebreak;
434448
base->writetup = writetup_index;
435449
base->readtup = readtup_index;
436450
base->haveDatum1 = true;
@@ -476,6 +490,7 @@ tuplesort_begin_index_gist(Relation heapRel,
476490

477491
base->removeabbrev = removeabbrev_index;
478492
base->comparetup = comparetup_index_btree;
493+
base->comparetup_tiebreak = comparetup_index_btree_tiebreak;
479494
base->writetup = writetup_index;
480495
base->readtup = readtup_index;
481496
base->haveDatum1 = true;
@@ -546,6 +561,7 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
546561

547562
base->removeabbrev = removeabbrev_datum;
548563
base->comparetup = comparetup_datum;
564+
base->comparetup_tiebreak = comparetup_datum_tiebreak;
549565
base->writetup = writetup_datum;
550566
base->readtup = readtup_datum;
551567
base->haveDatum1 = true;
@@ -931,16 +947,7 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
931947
{
932948
TuplesortPublic *base = TuplesortstateGetPublic(state);
933949
SortSupport sortKey = base->sortKeys;
934-
HeapTupleData ltup;
935-
HeapTupleData rtup;
936-
TupleDesc tupDesc;
937-
int nkey;
938950
int32 compare;
939-
AttrNumber attno;
940-
Datum datum1,
941-
datum2;
942-
bool isnull1,
943-
isnull2;
944951

945952

946953
/* Compare the leading sort key */
@@ -951,6 +958,25 @@ comparetup_heap(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
951958
return compare;
952959

953960
/* Compare additional sort keys */
961+
return comparetup_heap_tiebreak(a, b, state);
962+
}
963+
964+
static int
965+
comparetup_heap_tiebreak(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
966+
{
967+
TuplesortPublic *base = TuplesortstateGetPublic(state);
968+
SortSupport sortKey = base->sortKeys;
969+
HeapTupleData ltup;
970+
HeapTupleData rtup;
971+
TupleDesc tupDesc;
972+
int nkey;
973+
int32 compare;
974+
AttrNumber attno;
975+
Datum datum1,
976+
datum2;
977+
bool isnull1,
978+
isnull2;
979+
954980
ltup.t_len = ((MinimalTuple) a->tuple)->t_len + MINIMAL_TUPLE_OFFSET;
955981
ltup.t_data = (HeapTupleHeader) ((char *) a->tuple - MINIMAL_TUPLE_OFFSET);
956982
rtup.t_len = ((MinimalTuple) b->tuple)->t_len + MINIMAL_TUPLE_OFFSET;
@@ -1061,6 +1087,27 @@ removeabbrev_cluster(Tuplesortstate *state, SortTuple *stups, int count)
10611087
static int
10621088
comparetup_cluster(const SortTuple *a, const SortTuple *b,
10631089
Tuplesortstate *state)
1090+
{
1091+
TuplesortPublic *base = TuplesortstateGetPublic(state);
1092+
SortSupport sortKey = base->sortKeys;
1093+
int32 compare;
1094+
1095+
/* Compare the leading sort key, if it's simple */
1096+
if (base->haveDatum1)
1097+
{
1098+
compare = ApplySortComparator(a->datum1, a->isnull1,
1099+
b->datum1, b->isnull1,
1100+
sortKey);
1101+
if (compare != 0)
1102+
return compare;
1103+
}
1104+
1105+
return comparetup_cluster_tiebreak(a, b, state);
1106+
}
1107+
1108+
static int
1109+
comparetup_cluster_tiebreak(const SortTuple *a, const SortTuple *b,
1110+
Tuplesortstate *state)
10641111
{
10651112
TuplesortPublic *base = TuplesortstateGetPublic(state);
10661113
TuplesortClusterArg *arg = (TuplesortClusterArg *) base->arg;
@@ -1069,26 +1116,19 @@ comparetup_cluster(const SortTuple *a, const SortTuple *b,
10691116
HeapTuple rtup;
10701117
TupleDesc tupDesc;
10711118
int nkey;
1072-
int32 compare;
1119+
int32 compare = 0;
10731120
Datum datum1,
10741121
datum2;
10751122
bool isnull1,
10761123
isnull2;
10771124

1078-
/* Be prepared to compare additional sort keys */
10791125
ltup = (HeapTuple) a->tuple;
10801126
rtup = (HeapTuple) b->tuple;
10811127
tupDesc = arg->tupDesc;
10821128

10831129
/* Compare the leading sort key, if it's simple */
10841130
if (base->haveDatum1)
10851131
{
1086-
compare = ApplySortComparator(a->datum1, a->isnull1,
1087-
b->datum1, b->isnull1,
1088-
sortKey);
1089-
if (compare != 0)
1090-
return compare;
1091-
10921132
if (sortKey->abbrev_converter)
10931133
{
10941134
AttrNumber leading = arg->indexInfo->ii_IndexAttrNumbers[0];
@@ -1269,6 +1309,25 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
12691309
* treatment for equal keys at the end.
12701310
*/
12711311
TuplesortPublic *base = TuplesortstateGetPublic(state);
1312+
SortSupport sortKey = base->sortKeys;
1313+
int32 compare;
1314+
1315+
/* Compare the leading sort key */
1316+
compare = ApplySortComparator(a->datum1, a->isnull1,
1317+
b->datum1, b->isnull1,
1318+
sortKey);
1319+
if (compare != 0)
1320+
return compare;
1321+
1322+
/* Compare additional sort keys */
1323+
return comparetup_index_btree_tiebreak(a, b, state);
1324+
}
1325+
1326+
static int
1327+
comparetup_index_btree_tiebreak(const SortTuple *a, const SortTuple *b,
1328+
Tuplesortstate *state)
1329+
{
1330+
TuplesortPublic *base = TuplesortstateGetPublic(state);
12721331
TuplesortIndexBTreeArg *arg = (TuplesortIndexBTreeArg *) base->arg;
12731332
SortSupport sortKey = base->sortKeys;
12741333
IndexTuple tuple1;
@@ -1283,15 +1342,6 @@ comparetup_index_btree(const SortTuple *a, const SortTuple *b,
12831342
bool isnull1,
12841343
isnull2;
12851344

1286-
1287-
/* Compare the leading sort key */
1288-
compare = ApplySortComparator(a->datum1, a->isnull1,
1289-
b->datum1, b->isnull1,
1290-
sortKey);
1291-
if (compare != 0)
1292-
return compare;
1293-
1294-
/* Compare additional sort keys */
12951345
tuple1 = (IndexTuple) a->tuple;
12961346
tuple2 = (IndexTuple) b->tuple;
12971347
keysz = base->nKeys;
@@ -1467,6 +1517,19 @@ comparetup_index_hash(const SortTuple *a, const SortTuple *b,
14671517
return 0;
14681518
}
14691519

1520+
/*
1521+
* Sorting for hash indexes only uses one sort key, so this shouldn't ever be
1522+
* called. It's only here for consistency.
1523+
*/
1524+
static int
1525+
comparetup_index_hash_tiebreak(const SortTuple *a, const SortTuple *b,
1526+
Tuplesortstate *state)
1527+
{
1528+
Assert(false);
1529+
1530+
return 0;
1531+
}
1532+
14701533
static void
14711534
writetup_index(Tuplesortstate *state, LogicalTape *tape, SortTuple *stup)
14721535
{
@@ -1526,8 +1589,16 @@ comparetup_datum(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
15261589
if (compare != 0)
15271590
return compare;
15281591

1529-
/* if we have abbreviations, then "tuple" has the original value */
1592+
return comparetup_datum_tiebreak(a, b, state);
1593+
}
15301594

1595+
static int
1596+
comparetup_datum_tiebreak(const SortTuple *a, const SortTuple *b, Tuplesortstate *state)
1597+
{
1598+
TuplesortPublic *base = TuplesortstateGetPublic(state);
1599+
int32 compare = 0;
1600+
1601+
/* if we have abbreviations, then "tuple" has the original value */
15311602
if (base->sortKeys->abbrev_converter)
15321603
compare = ApplySortAbbrevFullComparator(PointerGetDatum(a->tuple), a->isnull1,
15331604
PointerGetDatum(b->tuple), b->isnull1,

src/include/utils/tuplesort.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,13 @@ typedef struct
162162
*/
163163
SortTupleComparator comparetup;
164164

165+
/*
166+
* Fall back to the full tuple for comparison, but only compare the first
167+
* sortkey if it was abbreviated. Otherwise, only compare second and later
168+
* sortkeys.
169+
*/
170+
SortTupleComparator comparetup_tiebreak;
171+
165172
/*
166173
* Alter datum1 representation in the SortTuple's array back from the
167174
* abbreviated key to the first column value.

0 commit comments

Comments
 (0)