From 1137fd62ea2a3e43ca9b9221d4e700c970fd883e Mon Sep 17 00:00:00 2001
From: mtimm_01 <mtimm_01@uni-muenster.de>
Date: Mon, 5 Jan 2015 15:04:16 +0100
Subject: [PATCH 1/3] Sortorder added.

---
 src/backend/commands/explain.c        | 90 +++++++++++++++++++++++++++++++++++
 src/test/regress/expected/inherit.out |  9 ++--
 src/test/regress/parallel_schedule    |  2 +-
 src/test/regress/serial_schedule      |  1 +
 4 files changed, 98 insertions(+), 4 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 064f880..611886b 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -14,6 +14,9 @@
 #include "postgres.h"
 
 #include "access/xact.h"
+#include "access/htup_details.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_operator.h"
 #include "catalog/pg_type.h"
 #include "commands/createas.h"
 #include "commands/defrem.h"
@@ -30,7 +33,9 @@
 #include "utils/rel.h"
 #include "utils/ruleutils.h"
 #include "utils/snapmgr.h"
+#include "utils/syscache.h"
 #include "utils/tuplesort.h"
+#include "utils/typcache.h"
 #include "utils/xml.h"
 
 
@@ -84,6 +89,7 @@ static void show_group_keys(GroupState *gstate, List *ancestors,
 static void show_sort_group_keys(PlanState *planstate, const char *qlabel,
 					 int nkeys, AttrNumber *keycols,
 					 List *ancestors, ExplainState *es);
+static void show_sort_order(SortState *sortstate, ExplainState *es);
 static void show_sort_info(SortState *sortstate, ExplainState *es);
 static void show_hash_info(HashState *hashstate, ExplainState *es);
 static void show_tidbitmap_info(BitmapHeapScanState *planstate,
@@ -1435,6 +1441,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			break;
 		case T_Sort:
 			show_sort_keys((SortState *) planstate, ancestors, es);
+			if (es->verbose)
+				show_sort_order((SortState *)planstate, es);
 			show_sort_info((SortState *) planstate, es);
 			break;
 		case T_MergeAppend:
@@ -1880,6 +1888,88 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
 }
 
 /*
+ * In verbose mode, additional information about the collation, sort order
+ * and NULLS FIRST/LAST is printed
+ */
+static void
+show_sort_order(SortState *sortstate, ExplainState *es)
+{
+	Sort *plan = (Sort *) sortstate->ss.ps.plan;
+	Plan *planstatePlan = (Plan *) sortstate->ss.ps.plan;
+
+	int nkeys = plan->numCols;
+	AttrNumber *keycols = plan->sortColIdx;
+	int keyno;
+
+	Oid sortcoltype;
+	TypeCacheEntry *typentry;
+
+	HeapTuple opertup;
+	Form_pg_operator operform;
+	char *oprname;
+	List *elements = NIL;
+	int maxItemLength = 200;
+	char sort_order_values[nkeys][maxItemLength + 1];
+
+	if (nkeys <= 0)
+		return;
+
+	for (keyno = 0; keyno < nkeys; keyno++)
+	{
+		strcpy(sort_order_values[keyno], "");
+		Oid			 collId		= plan->collations[keyno];
+		Oid			 operId		= plan->sortOperators[keyno];
+		AttrNumber	 keyresno	= keycols[keyno];
+		TargetEntry	*target		= get_tle_by_resno(planstatePlan->targetlist,
+												   keyresno);
+
+		sortcoltype	 = exprType(target->expr);
+		typentry	 = lookup_type_cache(sortcoltype,
+										 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
+
+		if (OidIsValid(collId) && collId != DEFAULT_COLLATION_OID)
+		{
+			char	*collname	= get_collation_name(collId);
+			char	*localeptr	= setlocale(LC_COLLATE, NULL);
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "COLLATE '%s' ", collname);
+			/* for those who use COLLATE although their default is already
+			 * the wanted */
+			if (strcmp(collname, localeptr) == 0)
+			{
+				snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " (%s is LC_COLLATE) ", collname);
+			}
+		}
+		/* print verbose information, also defaults like ASC NULLS LAST*/
+		if (operId == typentry->lt_opr)
+		{
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "%s", "ASC");
+		}
+		else if (operId == typentry->gt_opr)
+		{
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "%s", "DESC");
+		}
+		else
+		{
+			opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operId));
+			operform = (Form_pg_operator) GETSTRUCT (opertup);
+			oprname = NameStr(operform->oprname);
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "USING %s", oprname);
+			ReleaseSysCache(opertup);
+		}
+		if (plan->nullsFirst[keyno])
+		{
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " NULLS FIRST");
+		}
+		else
+		{
+			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " NULLS LAST");
+		}
+		elements = lappend(elements, sort_order_values[keyno]);
+	}
+	ExplainPropertyList("Sort Order", elements, es);
+}
+
+/*
  * If it's EXPLAIN ANALYZE, show tuplesort stats for a sort node
  */
 static void
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index 56e2c99..9492066 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1187,6 +1187,7 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
  Sort
    Output: matest0.id, matest0.name, ((1 - matest0.id))
    Sort Key: ((1 - matest0.id))
+   Sort Order: ASC NULLS LAST
    ->  Result
          Output: matest0.id, matest0.name, (1 - matest0.id)
          ->  Append
@@ -1198,7 +1199,7 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
                      Output: matest2.id, matest2.name
                ->  Seq Scan on public.matest3
                      Output: matest3.id, matest3.name
-(14 rows)
+(15 rows)
 
 select * from matest0 order by 1-id;
  id |  name  
@@ -1247,11 +1248,12 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
    ->  Sort
          Output: matest2.id, matest2.name, ((1 - matest2.id))
          Sort Key: ((1 - matest2.id))
+         Sort Order: ASC NULLS LAST
          ->  Seq Scan on public.matest2
                Output: matest2.id, matest2.name, (1 - matest2.id)
    ->  Index Scan using matest3i on public.matest3
          Output: matest3.id, matest3.name, (1 - matest3.id)
-(13 rows)
+(14 rows)
 
 select * from matest0 order by 1-id;
  id |  name  
@@ -1285,6 +1287,7 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Sort
                              Output: matest2.id, ((1 - matest2.id))
                              Sort Key: ((1 - matest2.id))
+                             Sort Order: ASC NULLS LAST
                              ->  Bitmap Heap Scan on public.matest2
                                    Output: matest2.id, (1 - matest2.id)
                                    Filter: ((1 - matest2.id) IS NOT NULL)
@@ -1292,7 +1295,7 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Index Scan using matest3i on public.matest3
                              Output: matest3.id, (1 - matest3.id)
                              Index Cond: ((1 - matest3.id) IS NOT NULL)
-(25 rows)
+(26 rows)
 
 select min(1-id) from matest0;
  min 
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 62ef6ec..3cf63ff 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -59,7 +59,7 @@ test: create_index create_view
 # ----------
 # Another group of parallel tests
 # ----------
-test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views
+test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views explain_sortorder
 
 # ----------
 # sanity_check does a vacuum, affecting the sort order of SELECT *
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index b491b97..dc242f1 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -71,6 +71,7 @@ test: typed_table
 test: vacuum
 test: drop_if_exists
 test: updatable_views
+test: explain_sortorder
 test: sanity_check
 test: errors
 test: select
-- 
1.9.1


From 3cd1fd75654f948ff69c34df222e362cf3b59dfa Mon Sep 17 00:00:00 2001
From: mtimm_01 <mtimm_01@uni-muenster.de>
Date: Mon, 5 Jan 2015 15:41:39 +0100
Subject: [PATCH 2/3] added files for make check

---
 src/test/regress/expected/explain_sortorder.out | 19 +++++++++++++++++++
 src/test/regress/sql/explain_sortorder.sql      | 12 ++++++++++++
 2 files changed, 31 insertions(+)
 create mode 100644 src/test/regress/expected/explain_sortorder.out
 create mode 100644 src/test/regress/sql/explain_sortorder.sql

diff --git a/src/test/regress/expected/explain_sortorder.out b/src/test/regress/expected/explain_sortorder.out
new file mode 100644
index 0000000..8450924
--- /dev/null
+++ b/src/test/regress/expected/explain_sortorder.out
@@ -0,0 +1,19 @@
+--
+-- Test explain feature: sort order
+--
+CREATE TABLE sortordertest (n1 char(1), n2 int4);
+-- Insert values by which should be ordered
+INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4);
+-- Display sort order when explain analyze and verbose are true.
+EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
+                         QUERY PLAN                         
+------------------------------------------------------------
+ Sort
+   Output: n1, n2, ((n1)::character(1))
+   Sort Key: sortordertest.n1, sortordertest.n2
+   Sort Order: COLLATE 'C' DESC NULLS FIRST, ASC NULLS LAST
+   ->  Seq Scan on public.sortordertest
+         Output: n1, n2, n1
+(6 rows)
+
+DROP TABLE sortordertest;
diff --git a/src/test/regress/sql/explain_sortorder.sql b/src/test/regress/sql/explain_sortorder.sql
new file mode 100644
index 0000000..3d8ace8
--- /dev/null
+++ b/src/test/regress/sql/explain_sortorder.sql
@@ -0,0 +1,12 @@
+--
+-- Test explain feature: sort order
+--
+CREATE TABLE sortordertest (n1 char(1), n2 int4);
+
+-- Insert values by which should be ordered
+INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4);
+
+-- Display sort order when explain analyze and verbose are true.
+EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
+
+DROP TABLE sortordertest;
\ No newline at end of file
-- 
1.9.1


From 2bb617934df2de8830e305f39d6fc976e0e64b25 Mon Sep 17 00:00:00 2001
From: mtimm_01 <mtimm_01@uni-muenster.de>
Date: Tue, 13 Jan 2015 11:10:59 +0100
Subject: [PATCH 3/3] replaced malloc() with StringInfo, removed comment,
 declaration and initialisation in one line

---
 src/backend/commands/explain.c                  | 165 +++++++++++-------------
 src/test/regress/expected/aggregates.out        |   2 +-
 src/test/regress/expected/equivclass.out        |   4 +-
 src/test/regress/expected/explain_sortorder.out |  15 +--
 src/test/regress/expected/inherit.out           |   9 +-
 src/test/regress/sql/explain_sortorder.sql      |   4 +-
 6 files changed, 91 insertions(+), 108 deletions(-)

diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 611886b..6f6cb6c 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -37,6 +37,7 @@
 #include "utils/tuplesort.h"
 #include "utils/typcache.h"
 #include "utils/xml.h"
+#include "nodes/nodeFuncs.h"
 
 
 /* Hook for plugins to get control in ExplainOneQuery() */
@@ -89,7 +90,7 @@ static void show_group_keys(GroupState *gstate, List *ancestors,
 static void show_sort_group_keys(PlanState *planstate, const char *qlabel,
 					 int nkeys, AttrNumber *keycols,
 					 List *ancestors, ExplainState *es);
-static void show_sort_order(SortState *sortstate, ExplainState *es);
+static char *get_sortorder_by_keyno(SortState *sortstate, ExplainState *es, int keyno);
 static void show_sort_info(SortState *sortstate, ExplainState *es);
 static void show_hash_info(HashState *hashstate, ExplainState *es);
 static void show_tidbitmap_info(BitmapHeapScanState *planstate,
@@ -122,7 +123,6 @@ static void ExplainYAMLLineStarting(ExplainState *es);
 static void escape_yaml(StringInfo buf, const char *str);
 
 
-
 /*
  * ExplainQuery -
  *	  execute an EXPLAIN command
@@ -1441,8 +1441,6 @@ ExplainNode(PlanState *planstate, List *ancestors,
 			break;
 		case T_Sort:
 			show_sort_keys((SortState *) planstate, ancestors, es);
-			if (es->verbose)
-				show_sort_order((SortState *)planstate, es);
 			show_sort_info((SortState *) planstate, es);
 			break;
 		case T_MergeAppend:
@@ -1852,12 +1850,12 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
 					 int nkeys, AttrNumber *keycols,
 					 List *ancestors, ExplainState *es)
 {
-	Plan	   *plan = planstate->plan;
-	List	   *context;
-	List	   *result = NIL;
-	bool		useprefix;
-	int			keyno;
-	char	   *exprstr;
+	Plan		*plan = planstate->plan;
+	List		*context;
+	List		*result = NIL;
+	bool		 useprefix;
+	int			 keyno;
+	char		*exprstr;
 
 	if (nkeys <= 0)
 		return;
@@ -1871,17 +1869,25 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
 
 	for (keyno = 0; keyno < nkeys; keyno++)
 	{
-		/* find key expression in tlist */
-		AttrNumber	keyresno = keycols[keyno];
-		TargetEntry *target = get_tle_by_resno(plan->targetlist,
-											   keyresno);
-
+		/* find key ekeynoxpression in tlist */
+		AttrNumber	 keyresno = keycols[keyno];
+		TargetEntry	*target = get_tle_by_resno(plan->targetlist, keyresno);
+		char		*sortorder;
+		StringInfo	element_concat_sortorder;
+
+		if (nodeTag(plan) == T_Sort) {
+			sortorder	= get_sortorder_by_keyno((SortState *) planstate, es, keyno);
+		} else {
+			sortorder	= "";
+		}
 		if (!target)
 			elog(ERROR, "no tlist entry for key %d", keyresno);
 		/* Deparse the expression, showing any top-level cast */
-		exprstr = deparse_expression((Node *) target->expr, context,
-									 useprefix, true);
-		result = lappend(result, exprstr);
+		exprstr = deparse_expression((Node *) target->expr, context, useprefix, true);
+		element_concat_sortorder = makeStringInfo();
+		appendStringInfoString(element_concat_sortorder, exprstr);
+		appendStringInfoString(element_concat_sortorder, sortorder);
+		result = lappend(result, element_concat_sortorder->data);
 	}
 
 	ExplainPropertyList(qlabel, result, es);
@@ -1891,82 +1897,65 @@ show_sort_group_keys(PlanState *planstate, const char *qlabel,
  * In verbose mode, additional information about the collation, sort order
  * and NULLS FIRST/LAST is printed
  */
-static void
-show_sort_order(SortState *sortstate, ExplainState *es)
+static char *
+get_sortorder_by_keyno(SortState *sortstate, ExplainState *es, int keyno)
 {
-	Sort *plan = (Sort *) sortstate->ss.ps.plan;
-	Plan *planstatePlan = (Plan *) sortstate->ss.ps.plan;
-
-	int nkeys = plan->numCols;
-	AttrNumber *keycols = plan->sortColIdx;
-	int keyno;
-
-	Oid sortcoltype;
-	TypeCacheEntry *typentry;
+	Sort				*plan;
+	Plan				*planstatePlan;
+	Oid					 sortcoltype;
+	TypeCacheEntry		*typentry;
+	HeapTuple			 opertup;
+	Form_pg_operator	 operform;
+	char				*oprname;
+	StringInfo			 sortorderInformation;
+	Oid					 collId;
+	Oid					 operId;
+	AttrNumber			 keyresno;
+	TargetEntry			*target;
+
+	plan				= (Sort *) sortstate->ss.ps.plan;
+	planstatePlan		= (Plan *) sortstate->ss.ps.plan;
+	collId				= plan->collations[keyno];
+	operId				= plan->sortOperators[keyno];
+	keyresno			= plan->sortColIdx[keyno];
+	target				= get_tle_by_resno(planstatePlan->targetlist, keyresno);
+	sortcoltype			= exprType((const Node *) target->expr);
+	typentry			= lookup_type_cache(sortcoltype, TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
+	sortorderInformation = makeStringInfo();
+
+	if (OidIsValid(collId) && collId != DEFAULT_COLLATION_OID)
+	{
+		char	*collname;
+		char	*localeptr;
 
-	HeapTuple opertup;
-	Form_pg_operator operform;
-	char *oprname;
-	List *elements = NIL;
-	int maxItemLength = 200;
-	char sort_order_values[nkeys][maxItemLength + 1];
+		collname = get_collation_name(collId);
+		localeptr = setlocale(LC_COLLATE, NULL);
 
-	if (nkeys <= 0)
-		return;
-
-	for (keyno = 0; keyno < nkeys; keyno++)
-	{
-		strcpy(sort_order_values[keyno], "");
-		Oid			 collId		= plan->collations[keyno];
-		Oid			 operId		= plan->sortOperators[keyno];
-		AttrNumber	 keyresno	= keycols[keyno];
-		TargetEntry	*target		= get_tle_by_resno(planstatePlan->targetlist,
-												   keyresno);
-
-		sortcoltype	 = exprType(target->expr);
-		typentry	 = lookup_type_cache(sortcoltype,
-										 TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
-
-		if (OidIsValid(collId) && collId != DEFAULT_COLLATION_OID)
-		{
-			char	*collname	= get_collation_name(collId);
-			char	*localeptr	= setlocale(LC_COLLATE, NULL);
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "COLLATE '%s' ", collname);
-			/* for those who use COLLATE although their default is already
-			 * the wanted */
-			if (strcmp(collname, localeptr) == 0)
-			{
-				snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " (%s is LC_COLLATE) ", collname);
-			}
-		}
-		/* print verbose information, also defaults like ASC NULLS LAST*/
-		if (operId == typentry->lt_opr)
-		{
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "%s", "ASC");
-		}
-		else if (operId == typentry->gt_opr)
-		{
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "%s", "DESC");
-		}
-		else
-		{
-			opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operId));
-			operform = (Form_pg_operator) GETSTRUCT (opertup);
-			oprname = NameStr(operform->oprname);
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), "USING %s", oprname);
-			ReleaseSysCache(opertup);
-		}
-		if (plan->nullsFirst[keyno])
+		appendStringInfo(sortorderInformation, " COLLATE '%s'", collname);
+		/* for those who use COLLATE although their default is already the wanted */
+		if (strcmp(collname, localeptr) == 0)
 		{
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " NULLS FIRST");
+			appendStringInfo(sortorderInformation, " (%s is LC_COLLATE)", collname);
 		}
-		else
-		{
-			snprintf(sort_order_values[keyno] + strlen(sort_order_values[keyno]), maxItemLength - strlen(sort_order_values[keyno]), " NULLS LAST");
-		}
-		elements = lappend(elements, sort_order_values[keyno]);
 	}
-	ExplainPropertyList("Sort Order", elements, es);
+	if (operId == typentry->gt_opr)
+	{
+		appendStringInfoString(sortorderInformation, " DESC");
+	}
+	else if (operId != typentry->lt_opr)
+	{
+		opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operId));
+		operform = (Form_pg_operator) GETSTRUCT (opertup);
+		oprname = NameStr(operform->oprname);
+		appendStringInfo(sortorderInformation, " USING %s", oprname);
+		ReleaseSysCache(opertup);
+	}
+	if (plan->nullsFirst[keyno])
+	{
+		//snprintf(sort_order_values + strlen(sort_order_values), maxItemLength - strlen(sort_order_values), " NULLS FIRST");
+		appendStringInfoString(sortorderInformation, " NULLS FIRST");
+	}
+	return sortorderInformation->data;
 }
 
 /*
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 40f5398..ca8aec8 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -735,7 +735,7 @@ explain (costs off)
                              QUERY PLAN                              
 ---------------------------------------------------------------------
  Sort
-   Sort Key: (generate_series(1, 3))
+   Sort Key: (generate_series(1, 3)) DESC NULLS FIRST
    InitPlan 1 (returns $0)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out
index b312292..dfae84e 100644
--- a/src/test/regress/expected/equivclass.out
+++ b/src/test/regress/expected/equivclass.out
@@ -319,7 +319,7 @@ explain (costs off)
                      ->  Index Scan using ec1_expr4 on ec1 ec1_3
                ->  Materialize
                      ->  Sort
-                           Sort Key: ec1.f1
+                           Sort Key: ec1.f1 USING <
                            ->  Index Scan using ec1_pkey on ec1
                                  Index Cond: (ff = 42::bigint)
 (20 rows)
@@ -376,7 +376,7 @@ explain (costs off)
          ->  Index Scan using ec1_expr4 on ec1 ec1_3
    ->  Materialize
          ->  Sort
-               Sort Key: ec1.f1
+               Sort Key: ec1.f1 USING <
                ->  Index Scan using ec1_pkey on ec1
                      Index Cond: (ff = 42::bigint)
 (14 rows)
diff --git a/src/test/regress/expected/explain_sortorder.out b/src/test/regress/expected/explain_sortorder.out
index 8450924..abd8130 100644
--- a/src/test/regress/expected/explain_sortorder.out
+++ b/src/test/regress/expected/explain_sortorder.out
@@ -5,15 +5,12 @@ CREATE TABLE sortordertest (n1 char(1), n2 int4);
 -- Insert values by which should be ordered
 INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4);
 -- Display sort order when explain analyze and verbose are true.
-EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
-                         QUERY PLAN                         
-------------------------------------------------------------
+EXPLAIN (COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
+                   QUERY PLAN                    
+-------------------------------------------------
  Sort
-   Output: n1, n2, ((n1)::character(1))
-   Sort Key: sortordertest.n1, sortordertest.n2
-   Sort Order: COLLATE 'C' DESC NULLS FIRST, ASC NULLS LAST
-   ->  Seq Scan on public.sortordertest
-         Output: n1, n2, n1
-(6 rows)
+   Sort Key: n1 COLLATE 'C' DESC NULLS FIRST, n2
+   ->  Seq Scan on sortordertest
+(3 rows)
 
 DROP TABLE sortordertest;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index 9492066..56e2c99 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1187,7 +1187,6 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
  Sort
    Output: matest0.id, matest0.name, ((1 - matest0.id))
    Sort Key: ((1 - matest0.id))
-   Sort Order: ASC NULLS LAST
    ->  Result
          Output: matest0.id, matest0.name, (1 - matest0.id)
          ->  Append
@@ -1199,7 +1198,7 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
                      Output: matest2.id, matest2.name
                ->  Seq Scan on public.matest3
                      Output: matest3.id, matest3.name
-(15 rows)
+(14 rows)
 
 select * from matest0 order by 1-id;
  id |  name  
@@ -1248,12 +1247,11 @@ explain (verbose, costs off) select * from matest0 order by 1-id;
    ->  Sort
          Output: matest2.id, matest2.name, ((1 - matest2.id))
          Sort Key: ((1 - matest2.id))
-         Sort Order: ASC NULLS LAST
          ->  Seq Scan on public.matest2
                Output: matest2.id, matest2.name, (1 - matest2.id)
    ->  Index Scan using matest3i on public.matest3
          Output: matest3.id, matest3.name, (1 - matest3.id)
-(14 rows)
+(13 rows)
 
 select * from matest0 order by 1-id;
  id |  name  
@@ -1287,7 +1285,6 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Sort
                              Output: matest2.id, ((1 - matest2.id))
                              Sort Key: ((1 - matest2.id))
-                             Sort Order: ASC NULLS LAST
                              ->  Bitmap Heap Scan on public.matest2
                                    Output: matest2.id, (1 - matest2.id)
                                    Filter: ((1 - matest2.id) IS NOT NULL)
@@ -1295,7 +1292,7 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Index Scan using matest3i on public.matest3
                              Output: matest3.id, (1 - matest3.id)
                              Index Cond: ((1 - matest3.id) IS NOT NULL)
-(26 rows)
+(25 rows)
 
 select min(1-id) from matest0;
  min 
diff --git a/src/test/regress/sql/explain_sortorder.sql b/src/test/regress/sql/explain_sortorder.sql
index 3d8ace8..555d22f 100644
--- a/src/test/regress/sql/explain_sortorder.sql
+++ b/src/test/regress/sql/explain_sortorder.sql
@@ -7,6 +7,6 @@ CREATE TABLE sortordertest (n1 char(1), n2 int4);
 INSERT INTO sortordertest(n1, n2) VALUES ('d', 5), ('b', 3), ('a', 1), ('e', 2), ('c', 4);
 
 -- Display sort order when explain analyze and verbose are true.
-EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
+EXPLAIN (COSTS OFF) SELECT * FROM sortordertest ORDER BY n1 COLLATE "C" DESC, n2;
 
-DROP TABLE sortordertest;
\ No newline at end of file
+DROP TABLE sortordertest;
-- 
1.9.1

