@@ -616,7 +616,8 @@ static Tuplesortstate *tuplesort_begin_common(int workMem,
616616SortCoordinate coordinate ,
617617int sortopt );
618618static void tuplesort_begin_batch (Tuplesortstate * state );
619- static void puttuple_common (Tuplesortstate * state ,SortTuple * tuple );
619+ static void puttuple_common (Tuplesortstate * state ,SortTuple * tuple ,
620+ bool useAbbrev );
620621static bool consider_abort_common (Tuplesortstate * state );
621622static void inittapes (Tuplesortstate * state ,bool mergeruns );
622623static void inittapestate (Tuplesortstate * state ,int maxTapes );
@@ -1841,7 +1842,6 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18411842{
18421843MemoryContext oldcontext = MemoryContextSwitchTo (state -> tuplecontext );
18431844SortTuple stup ;
1844- Datum original ;
18451845MinimalTuple tuple ;
18461846HeapTupleData htup ;
18471847
@@ -1852,49 +1852,15 @@ tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
18521852/* set up first-column key value */
18531853htup .t_len = tuple -> t_len + MINIMAL_TUPLE_OFFSET ;
18541854htup .t_data = (HeapTupleHeader ) ((char * )tuple - MINIMAL_TUPLE_OFFSET );
1855- original = heap_getattr (& htup ,
1856- state -> sortKeys [0 ].ssup_attno ,
1857- state -> tupDesc ,
1858- & stup .isnull1 );
1855+ stup . datum1 = heap_getattr (& htup ,
1856+ state -> sortKeys [0 ].ssup_attno ,
1857+ state -> tupDesc ,
1858+ & stup .isnull1 );
18591859
18601860MemoryContextSwitchTo (state -> sortcontext );
18611861
1862- if (!state -> sortKeys -> abbrev_converter || stup .isnull1 )
1863- {
1864- /*
1865- * Store ordinary Datum representation, or NULL value. If there is a
1866- * converter it won't expect NULL values, and cost model is not
1867- * required to account for NULL, so in that case we avoid calling
1868- * converter and just set datum1 to zeroed representation (to be
1869- * consistent, and to support cheap inequality tests for NULL
1870- * abbreviated keys).
1871- */
1872- stup .datum1 = original ;
1873- }
1874- else if (!consider_abort_common (state ))
1875- {
1876- /* Store abbreviated key representation */
1877- stup .datum1 = state -> sortKeys -> abbrev_converter (original ,
1878- state -> sortKeys );
1879- }
1880- else
1881- {
1882- /* Abort abbreviation */
1883- stup .datum1 = original ;
1884-
1885- /*
1886- * Set state to be consistent with never trying abbreviation.
1887- *
1888- * Alter datum1 representation in already-copied tuples, so as to
1889- * ensure a consistent representation (current tuple was just
1890- * handled). It does not matter if some dumped tuples are already
1891- * sorted on tape, since serialized tuples lack abbreviated keys
1892- * (TSS_BUILDRUNS state prevents control reaching here in any case).
1893- */
1894- REMOVEABBREV (state ,state -> memtuples ,state -> memtupcount );
1895- }
1896-
1897- puttuple_common (state ,& stup );
1862+ puttuple_common (state ,& stup ,
1863+ state -> sortKeys -> abbrev_converter && !stup .isnull1 );
18981864
18991865MemoryContextSwitchTo (oldcontext );
19001866}
@@ -1908,7 +1874,6 @@ void
19081874tuplesort_putheaptuple (Tuplesortstate * state ,HeapTuple tup )
19091875{
19101876SortTuple stup ;
1911- Datum original ;
19121877MemoryContext oldcontext = MemoryContextSwitchTo (state -> tuplecontext );
19131878
19141879/* copy the tuple into sort storage */
@@ -1924,49 +1889,14 @@ tuplesort_putheaptuple(Tuplesortstate *state, HeapTuple tup)
19241889 */
19251890if (state -> haveDatum1 )
19261891{
1927- original = heap_getattr (tup ,
1928- state -> indexInfo -> ii_IndexAttrNumbers [0 ],
1929- state -> tupDesc ,
1930- & stup .isnull1 );
1931-
1932- if (!state -> sortKeys -> abbrev_converter || stup .isnull1 )
1933- {
1934- /*
1935- * Store ordinary Datum representation, or NULL value. If there
1936- * is a converter it won't expect NULL values, and cost model is
1937- * not required to account for NULL, so in that case we avoid
1938- * calling converter and just set datum1 to zeroed representation
1939- * (to be consistent, and to support cheap inequality tests for
1940- * NULL abbreviated keys).
1941- */
1942- stup .datum1 = original ;
1943- }
1944- else if (!consider_abort_common (state ))
1945- {
1946- /* Store abbreviated key representation */
1947- stup .datum1 = state -> sortKeys -> abbrev_converter (original ,
1948- state -> sortKeys );
1949- }
1950- else
1951- {
1952- /* Abort abbreviation */
1953- stup .datum1 = original ;
1954-
1955- /*
1956- * Set state to be consistent with never trying abbreviation.
1957- *
1958- * Alter datum1 representation in already-copied tuples, so as to
1959- * ensure a consistent representation (current tuple was just
1960- * handled). It does not matter if some dumped tuples are already
1961- * sorted on tape, since serialized tuples lack abbreviated keys
1962- * (TSS_BUILDRUNS state prevents control reaching here in any
1963- * case).
1964- */
1965- REMOVEABBREV (state ,state -> memtuples ,state -> memtupcount );
1966- }
1892+ stup .datum1 = heap_getattr (tup ,
1893+ state -> indexInfo -> ii_IndexAttrNumbers [0 ],
1894+ state -> tupDesc ,
1895+ & stup .isnull1 );
19671896}
19681897
1969- puttuple_common (state ,& stup );
1898+ puttuple_common (state ,& stup ,
1899+ state -> haveDatum1 && state -> sortKeys -> abbrev_converter && !stup .isnull1 );
19701900
19711901MemoryContextSwitchTo (oldcontext );
19721902}
@@ -1982,7 +1912,6 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
19821912{
19831913MemoryContext oldcontext ;
19841914SortTuple stup ;
1985- Datum original ;
19861915IndexTuple tuple ;
19871916
19881917stup .tuple = index_form_tuple_context (RelationGetDescr (rel ),values ,
@@ -1991,49 +1920,15 @@ tuplesort_putindextuplevalues(Tuplesortstate *state, Relation rel,
19911920tuple -> t_tid = * self ;
19921921USEMEM (state ,GetMemoryChunkSpace (stup .tuple ));
19931922/* set up first-column key value */
1994- original = index_getattr (tuple ,
1995- 1 ,
1996- RelationGetDescr (state -> indexRel ),
1997- & stup .isnull1 );
1923+ stup . datum1 = index_getattr (tuple ,
1924+ 1 ,
1925+ RelationGetDescr (state -> indexRel ),
1926+ & stup .isnull1 );
19981927
19991928oldcontext = MemoryContextSwitchTo (state -> sortcontext );
20001929
2001- if (!state -> sortKeys || !state -> sortKeys -> abbrev_converter || stup .isnull1 )
2002- {
2003- /*
2004- * Store ordinary Datum representation, or NULL value. If there is a
2005- * converter it won't expect NULL values, and cost model is not
2006- * required to account for NULL, so in that case we avoid calling
2007- * converter and just set datum1 to zeroed representation (to be
2008- * consistent, and to support cheap inequality tests for NULL
2009- * abbreviated keys).
2010- */
2011- stup .datum1 = original ;
2012- }
2013- else if (!consider_abort_common (state ))
2014- {
2015- /* Store abbreviated key representation */
2016- stup .datum1 = state -> sortKeys -> abbrev_converter (original ,
2017- state -> sortKeys );
2018- }
2019- else
2020- {
2021- /* Abort abbreviation */
2022- stup .datum1 = original ;
2023-
2024- /*
2025- * Set state to be consistent with never trying abbreviation.
2026- *
2027- * Alter datum1 representation in already-copied tuples, so as to
2028- * ensure a consistent representation (current tuple was just
2029- * handled). It does not matter if some dumped tuples are already
2030- * sorted on tape, since serialized tuples lack abbreviated keys
2031- * (TSS_BUILDRUNS state prevents control reaching here in any case).
2032- */
2033- REMOVEABBREV (state ,state -> memtuples ,state -> memtupcount );
2034- }
2035-
2036- puttuple_common (state ,& stup );
1930+ puttuple_common (state ,& stup ,
1931+ state -> sortKeys && state -> sortKeys -> abbrev_converter && !stup .isnull1 );
20371932
20381933MemoryContextSwitchTo (oldcontext );
20391934}
@@ -2074,43 +1969,15 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
20741969}
20751970else
20761971{
2077- Datum original = datumCopy (val , false,state -> datumTypeLen );
2078-
20791972stup .isnull1 = false;
2080- stup .tuple = DatumGetPointer (original );
1973+ stup .datum1 = datumCopy (val , false,state -> datumTypeLen );
1974+ stup .tuple = DatumGetPointer (stup .datum1 );
20811975USEMEM (state ,GetMemoryChunkSpace (stup .tuple ));
20821976MemoryContextSwitchTo (state -> sortcontext );
2083-
2084- if (!state -> sortKeys -> abbrev_converter )
2085- {
2086- stup .datum1 = original ;
2087- }
2088- else if (!consider_abort_common (state ))
2089- {
2090- /* Store abbreviated key representation */
2091- stup .datum1 = state -> sortKeys -> abbrev_converter (original ,
2092- state -> sortKeys );
2093- }
2094- else
2095- {
2096- /* Abort abbreviation */
2097- stup .datum1 = original ;
2098-
2099- /*
2100- * Set state to be consistent with never trying abbreviation.
2101- *
2102- * Alter datum1 representation in already-copied tuples, so as to
2103- * ensure a consistent representation (current tuple was just
2104- * handled). It does not matter if some dumped tuples are already
2105- * sorted on tape, since serialized tuples lack abbreviated keys
2106- * (TSS_BUILDRUNS state prevents control reaching here in any
2107- * case).
2108- */
2109- REMOVEABBREV (state ,state -> memtuples ,state -> memtupcount );
2110- }
21111977}
21121978
2113- puttuple_common (state ,& stup );
1979+ puttuple_common (state ,& stup ,
1980+ state -> tuples && !isNull && state -> sortKeys -> abbrev_converter );
21141981
21151982MemoryContextSwitchTo (oldcontext );
21161983}
@@ -2119,10 +1986,41 @@ tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
21191986 * Shared code for tuple and datum cases.
21201987 */
21211988static void
2122- puttuple_common (Tuplesortstate * state ,SortTuple * tuple )
1989+ puttuple_common (Tuplesortstate * state ,SortTuple * tuple , bool useAbbrev )
21231990{
21241991Assert (!LEADER (state ));
21251992
1993+ if (!useAbbrev )
1994+ {
1995+ /*
1996+ * Leave ordinary Datum representation, or NULL value. If there is a
1997+ * converter it won't expect NULL values, and cost model is not
1998+ * required to account for NULL, so in that case we avoid calling
1999+ * converter and just set datum1 to zeroed representation (to be
2000+ * consistent, and to support cheap inequality tests for NULL
2001+ * abbreviated keys).
2002+ */
2003+ }
2004+ else if (!consider_abort_common (state ))
2005+ {
2006+ /* Store abbreviated key representation */
2007+ tuple -> datum1 = state -> sortKeys -> abbrev_converter (tuple -> datum1 ,
2008+ state -> sortKeys );
2009+ }
2010+ else
2011+ {
2012+ /*
2013+ * Set state to be consistent with never trying abbreviation.
2014+ *
2015+ * Alter datum1 representation in already-copied tuples, so as to
2016+ * ensure a consistent representation (current tuple was just
2017+ * handled). It does not matter if some dumped tuples are already
2018+ * sorted on tape, since serialized tuples lack abbreviated keys
2019+ * (TSS_BUILDRUNS state prevents control reaching here in any case).
2020+ */
2021+ REMOVEABBREV (state ,state -> memtuples ,state -> memtupcount );
2022+ }
2023+
21262024switch (state -> status )
21272025{
21282026case TSS_INITIAL :