@@ -147,13 +147,18 @@ bool optimize_bounded_sort = true;
147
147
* case where the first key determines the comparison result. Note that
148
148
* for a pass-by-reference datatype, datum1 points into the "tuple" storage.
149
149
*
150
+ * There is one special case: when the sort support infrastructure provides an
151
+ * "abbreviated key" representation, where the key is (typically) a pass by
152
+ * value proxy for a pass by reference type. In this case, the abbreviated key
153
+ * is stored in datum1 in place of the actual first key column.
154
+ *
150
155
* When sorting single Datums, the data value is represented directly by
151
- * datum1/isnull1. If the datatype is pass-by-reference and isnull1 is false,
152
- * then datum1 points to a separately palloc'd data value that is also pointed
153
- * to by the "tuple" pointer; otherwise "tuple" is NULL. There is one special
154
- * case: when the sort support infrastructure provides an " abbreviated key"
155
- * representation, where the key is (typically) a pass by value proxy for a
156
- * pass by reference type .
156
+ * datum1/isnull1 for pass by value types (or null values). If the datatype is
157
+ * pass-by-reference and isnull1 is false, then "tuple" points to a separately
158
+ * palloc'd data value, otherwise "tuple" is NULL. The value of datum1 is then
159
+ * either the same pointer as "tuple", or is an abbreviated key value as
160
+ * described above. Accordingly, "tuple" is always used in preference to
161
+ * datum1 as the authoritative value for pass-by- reference cases .
157
162
*
158
163
* While building initial runs, tupindex holds the tuple's run number. During
159
164
* merge passes, we re-use it to hold the input tape number that each tuple in
@@ -901,30 +906,36 @@ tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation,
901
906
state -> copytup = copytup_datum ;
902
907
state -> writetup = writetup_datum ;
903
908
state -> readtup = readtup_datum ;
909
+ state -> abbrevNext = 10 ;
904
910
905
911
state -> datumType = datumType ;
906
912
907
- /* Prepare SortSupport data */
908
- state -> onlyKey = (SortSupport ) palloc0 (sizeof (SortSupportData ));
909
-
910
- state -> onlyKey -> ssup_cxt = CurrentMemoryContext ;
911
- state -> onlyKey -> ssup_collation = sortCollation ;
912
- state -> onlyKey -> ssup_nulls_first = nullsFirstFlag ;
913
- /*
914
- * Conversion to abbreviated representation infeasible in the Datum case.
915
- * It must be possible to subsequently fetch original datum values within
916
- * tuplesort_getdatum(), which would require special-case preservation of
917
- * original values.
918
- */
919
- state -> onlyKey -> abbreviate = false;
920
-
921
- PrepareSortSupportFromOrderingOp (sortOperator , state -> onlyKey );
922
-
923
913
/* lookup necessary attributes of the datum type */
924
914
get_typlenbyval (datumType , & typlen , & typbyval );
925
915
state -> datumTypeLen = typlen ;
926
916
state -> datumTypeByVal = typbyval ;
927
917
918
+ /* Prepare SortSupport data */
919
+ state -> sortKeys = (SortSupport ) palloc0 (sizeof (SortSupportData ));
920
+
921
+ state -> sortKeys -> ssup_cxt = CurrentMemoryContext ;
922
+ state -> sortKeys -> ssup_collation = sortCollation ;
923
+ state -> sortKeys -> ssup_nulls_first = nullsFirstFlag ;
924
+
925
+ /* abbreviation is possible here only for by-reference types */
926
+ state -> sortKeys -> abbreviate = !typbyval ;
927
+
928
+ PrepareSortSupportFromOrderingOp (sortOperator , state -> sortKeys );
929
+
930
+ /*
931
+ * The "onlyKey" optimization cannot be used with abbreviated keys, since
932
+ * tie-breaker comparisons may be required. Typically, the optimization is
933
+ * only of value to pass-by-value types anyway, whereas abbreviated keys
934
+ * are typically only of value to pass-by-reference types.
935
+ */
936
+ if (!state -> sortKeys -> abbrev_converter )
937
+ state -> onlyKey = state -> sortKeys ;
938
+
928
939
MemoryContextSwitchTo (oldcontext );
929
940
930
941
return state ;
@@ -1307,9 +1318,17 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
1307
1318
SortTuple stup ;
1308
1319
1309
1320
/*
1310
- * If it's a pass-by-reference value, copy it into memory we control, and
1311
- * decrease availMem. Then call the common code.
1321
+ * Pass-by-value types or null values are just stored directly in
1322
+ * stup.datum1 (and stup.tuple is not used and set to NULL).
1323
+ *
1324
+ * Non-null pass-by-reference values need to be copied into memory we
1325
+ * control, and possibly abbreviated. The copied value is pointed to by
1326
+ * stup.tuple and is treated as the canonical copy (e.g. to return via
1327
+ * tuplesort_getdatum or when writing to tape); stup.datum1 gets the
1328
+ * abbreviated value if abbreviation is happening, otherwise it's identical
1329
+ * to stup.tuple.
1312
1330
*/
1331
+
1313
1332
if (isNull || state -> datumTypeByVal )
1314
1333
{
1315
1334
stup .datum1 = val ;
@@ -1318,10 +1337,44 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
1318
1337
}
1319
1338
else
1320
1339
{
1321
- stup .datum1 = datumCopy (val , false, state -> datumTypeLen );
1340
+ Datum original = datumCopy (val , false, state -> datumTypeLen );
1341
+
1322
1342
stup .isnull1 = false;
1323
- stup .tuple = DatumGetPointer (stup . datum1 );
1343
+ stup .tuple = DatumGetPointer (original );
1324
1344
USEMEM (state , GetMemoryChunkSpace (stup .tuple ));
1345
+
1346
+ if (!state -> sortKeys -> abbrev_converter )
1347
+ {
1348
+ stup .datum1 = original ;
1349
+ }
1350
+ else if (!consider_abort_common (state ))
1351
+ {
1352
+ /* Store abbreviated key representation */
1353
+ stup .datum1 = state -> sortKeys -> abbrev_converter (original ,
1354
+ state -> sortKeys );
1355
+ }
1356
+ else
1357
+ {
1358
+ /* Abort abbreviation */
1359
+ int i ;
1360
+
1361
+ stup .datum1 = original ;
1362
+
1363
+ /*
1364
+ * Set state to be consistent with never trying abbreviation.
1365
+ *
1366
+ * Alter datum1 representation in already-copied tuples, so as to
1367
+ * ensure a consistent representation (current tuple was just handled).
1368
+ * Note that we rely on all tuples copied so far actually being
1369
+ * contained within memtuples array.
1370
+ */
1371
+ for (i = 0 ; i < state -> memtupcount ; i ++ )
1372
+ {
1373
+ SortTuple * mtup = & state -> memtuples [i ];
1374
+
1375
+ mtup -> datum1 = PointerGetDatum (mtup -> tuple );
1376
+ }
1377
+ }
1325
1378
}
1326
1379
1327
1380
puttuple_common (state , & stup );
@@ -1886,10 +1939,12 @@ tuplesort_getdatum(Tuplesortstate *state, bool forward,
1886
1939
}
1887
1940
else
1888
1941
{
1942
+ /* use stup.tuple because stup.datum1 may be an abbreviation */
1943
+
1889
1944
if (should_free )
1890
- * val = stup .datum1 ;
1945
+ * val = PointerGetDatum ( stup .tuple ) ;
1891
1946
else
1892
- * val = datumCopy (stup .datum1 , false, state -> datumTypeLen );
1947
+ * val = datumCopy (PointerGetDatum ( stup .tuple ) , false, state -> datumTypeLen );
1893
1948
* isNull = false;
1894
1949
}
1895
1950
@@ -3715,9 +3770,22 @@ readtup_index(Tuplesortstate *state, SortTuple *stup,
3715
3770
static int
3716
3771
comparetup_datum (const SortTuple * a , const SortTuple * b , Tuplesortstate * state )
3717
3772
{
3718
- return ApplySortComparator (a -> datum1 , a -> isnull1 ,
3719
- b -> datum1 , b -> isnull1 ,
3720
- state -> onlyKey );
3773
+ int compare ;
3774
+
3775
+ compare = ApplySortComparator (a -> datum1 , a -> isnull1 ,
3776
+ b -> datum1 , b -> isnull1 ,
3777
+ state -> sortKeys );
3778
+ if (compare != 0 )
3779
+ return compare ;
3780
+
3781
+ /* if we have abbreviations, then "tuple" has the original value */
3782
+
3783
+ if (state -> sortKeys -> abbrev_converter )
3784
+ compare = ApplySortAbbrevFullComparator (PointerGetDatum (a -> tuple ), a -> isnull1 ,
3785
+ PointerGetDatum (b -> tuple ), b -> isnull1 ,
3786
+ state -> sortKeys );
3787
+
3788
+ return compare ;
3721
3789
}
3722
3790
3723
3791
static void
@@ -3746,8 +3814,8 @@ writetup_datum(Tuplesortstate *state, int tapenum, SortTuple *stup)
3746
3814
}
3747
3815
else
3748
3816
{
3749
- waddr = DatumGetPointer ( stup -> datum1 ) ;
3750
- tuplen = datumGetSize (stup -> datum1 , false, state -> datumTypeLen );
3817
+ waddr = stup -> tuple ;
3818
+ tuplen = datumGetSize (PointerGetDatum ( stup -> tuple ) , false, state -> datumTypeLen );
3751
3819
Assert (tuplen != 0 );
3752
3820
}
3753
3821
0 commit comments