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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy