Index: java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java	(revision 634153)
+++ java/engine/org/apache/derby/impl/sql/compile/ResultColumn.java	(working copy)
@@ -208,6 +208,34 @@
 	}
 
 	/**
+	 * Return TRUE if this result column matches the provided column name.
+	 *
+	 * This function is used by ORDER BY column resolution. For the
+	 * ORDER BY clause, Derby will prefer to match on the column's
+	 * alias (exposedName), but will also successfully match on the
+	 * underlying column name. Thus the following statements are
+	 * treated equally:
+	 *  select name from person order by name;
+	 *  select name as person_name from person order by name;
+	 *  select name as person_name from person order by person_name;
+	 * See DERBY-2351 for more discussion.
+	 */
+	boolean columnNameMatches(String columnName)
+	{
+		if (columnName.equals(exposedName) || columnName.equals(name))
+			return true;
+		if (expression instanceof ColumnReference &&
+			columnName.equals(((ColumnReference)expression).getColumnName()))
+			return true;
+		return false;
+	}
+        String getSourceColumnName()
+        {
+		if (expression instanceof ColumnReference)
+                    return ((ColumnReference)expression).getColumnName();
+                return null;
+        }
+	/**
 	 * The following methods implement the ResultColumnDescriptor
 	 * interface.  See the Language Module Interface for details.
 	 */
Index: java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java	(revision 634153)
+++ java/engine/org/apache/derby/impl/sql/compile/ResultColumnList.java	(working copy)
@@ -441,6 +441,7 @@
 			 *	o  The RC is not qualified, but its expression is a ColumnReference
 			 *	   from the same table (as determined by the tableNumbers).
 			 */
+                        boolean columnNameMatches;
 			if (tableName != null)
 			{
                 ValueNode rcExpr = resultColumn.getExpression();
@@ -450,8 +451,14 @@
                 ColumnReference cr = (ColumnReference) rcExpr;
                 if( (! tableName.equals( cr.getTableNameNode())) && tableNumber != cr.getTableNumber())
                     continue;
+				columnNameMatches =
+					columnName.equals( resultColumn.getSourceColumnName() );
 			}
+			else
+				columnNameMatches =
+					resultColumn.columnNameMatches(columnName);
 
+
 			/* We finally got past the qualifiers, now see if the column
 			 * names are equal. If they are, then we appear to have found
 			* our order by column. If we find our order by column multiple
@@ -469,7 +476,7 @@
 			* should be removed from the ResultColumnList and returned
 			* to the caller.
 			 */
-			if (columnName.equals( resultColumn.getName()) )
+			if (columnNameMatches)
 			{
 				if (retVal == null)
 				{
@@ -558,6 +565,7 @@
 			// exposedName will not be null and "*" will not have an expression
 			// or tablename.
 			// We may be checking on "ORDER BY T.A" against "SELECT T.B, T.A".
+                        boolean columnNameMatches;
 			if (tableName != null)
 			{
 				ValueNode rcExpr = resultColumn.getExpression();
@@ -568,12 +576,17 @@
 				ColumnReference cr = (ColumnReference) rcExpr;
                 if( ! tableName.equals( cr.getTableNameNode()))
                     continue;
+				columnNameMatches =
+					columnName.equals( resultColumn.getSourceColumnName() );
 			}
+			else
+				columnNameMatches =
+					resultColumn.columnNameMatches(columnName);
 
 			/* We finally got past the qualifiers, now see if the column
 			 * names are equal.
 			 */
-			if (columnName.equals( resultColumn.getName()) )
+			if (columnNameMatches)
 			{
 				if (retVal == null)
 				{
Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql	(revision 634153)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql	(working copy)
@@ -680,7 +680,36 @@
 SELECT DISTINCT name FROM person ORDER BY name;
 -- This query should return two rows, ordered by name descending:
 SELECT DISTINCT name FROM person ORDER BY name desc;
+-- Some test cases involving column aliasing:
+select distinct name as first_name from person order by name;
+select distinct name as first_name from person order by first_name;
+select distinct person.name from person order by name;
+select distinct name as first_name from person order by person.name;
+select distinct name as age from person order by age;
+select distinct name as age from person order by person.age;
+select distinct name, name from person order by name;
+select distinct name, name as first_name from person order by name;
+select distinct name, name as first_name from person order by 2;
+select distinct name from person order by lower(name);
+create table pets (name varchar(10), age int);
+insert into pets values ('Rover', 3), ('Fido', 5), ('Buster', 1);
+select distinct name from person union select distinct name from pets order by name;
+select distinct name from person, pets order by name;
+select distinct person.name as person_name, pets.name as pet_name from person,pets order by name;
+select distinct person.name as person_name, pets.name from person,pets order by name;
+select distinct person.name as person_name, pets.name from person,pets order by person.name;
+select distinct person.name as name, pets.name as pet_name from person,pets order by name;
+select distinct person.name as name, pets.name as pet_name from person,pets order by pets.name;
+-- Include some of the error cases from above without the DISTINCT
+-- specification to investigate how that affects the behavior:
+select name as age from person order by person.age;
+select name from person, pets order by name;
+select person.name as person_name, pets.name as pet_name from person,pets order by name;
+select person.name as person_name, pets.name from person,pets order by person.name;
+select person.name as person_name, pets.name from person,pets order by name;
+select person.name as name, pets.name as pet_name from person,pets order by name;
 drop table person;
+drop table pets;
 
 
 create table d2887_types(
Index: java/testing/org/apache/derbyTesting/functionTests/master/orderby.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/orderby.out	(revision 634153)
+++ java/testing/org/apache/derbyTesting/functionTests/master/orderby.out	(working copy)
@@ -1759,8 +1759,119 @@
 ----------
 Mary      
 John      
+ij> -- Some test cases involving column aliasing:
+select distinct name as first_name from person order by name;
+FIRST_NAME
+----------
+John      
+Mary      
+ij> select distinct name as first_name from person order by first_name;
+FIRST_NAME
+----------
+John      
+Mary      
+ij> select distinct person.name from person order by name;
+NAME      
+----------
+John      
+Mary      
+ij> select distinct name as first_name from person order by person.name;
+FIRST_NAME
+----------
+John      
+Mary      
+ij> select distinct name as age from person order by age;
+AGE       
+----------
+John      
+Mary      
+ij> select distinct name as age from person order by person.age;
+ERROR 42879: The ORDER BY clause may not contain column 'AGE', since the query specifies DISTINCT and that column does not appear in the query result.
+ij> select distinct name, name from person order by name;
+NAME      |NAME      
+---------------------
+John      |John      
+Mary      |Mary      
+ij> select distinct name, name as first_name from person order by name;
+NAME      |FIRST_NAME
+---------------------
+John      |John      
+Mary      |Mary      
+ij> select distinct name, name as first_name from person order by 2;
+NAME      |FIRST_NAME
+---------------------
+John      |John      
+Mary      |Mary      
+ij> create table pets (name varchar(10), age int);
+0 rows inserted/updated/deleted
+ij> insert into pets values ('Rover', 3), ('Fido', 5), ('Buster', 1);
+3 rows inserted/updated/deleted
+ij> select distinct name from person union select distinct name from pets order by name;
+NAME      
+----------
+Buster    
+Fido      
+John      
+Mary      
+Rover     
+ij> select distinct name from person, pets order by name;
+ERROR 42X03: Column name 'NAME' is in more than one table in the FROM list.
+ij> select distinct person.name as person_name, pets.name as pet_name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
+ij> select distinct person.name as person_name, pets.name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
+ij> select distinct person.name as person_name, pets.name from person,pets order by person.name;
+PERSON_NA&|NAME      
+---------------------
+John      |Buster    
+John      |Fido      
+John      |Rover     
+Mary      |Buster    
+Mary      |Fido      
+Mary      |Rover     
+ij> select distinct person.name as name, pets.name as pet_name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
+ij> select distinct person.name as name, pets.name as pet_name from person,pets order by pets.name;
+NAME      |PET_NAME  
+---------------------
+John      |Buster    
+Mary      |Buster    
+John      |Fido      
+Mary      |Fido      
+John      |Rover     
+Mary      |Rover     
+ij> -- Include some of the error cases from above without the DISTINCT
+-- specification to investigate how that affects the behavior:
+select name as age from person order by person.age;
+AGE       
+----------
+John      
+Mary      
+John      
+ij> select name from person, pets order by name;
+ERROR 42X03: Column name 'NAME' is in more than one table in the FROM list.
+ij> select person.name as person_name, pets.name as pet_name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
+ij> select person.name as person_name, pets.name from person,pets order by person.name;
+PERSON_NA&|NAME      
+---------------------
+John      |Buster    
+John      |Fido      
+John      |Rover     
+John      |Buster    
+John      |Fido      
+John      |Rover     
+Mary      |Buster    
+Mary      |Fido      
+Mary      |Rover     
+ij> select person.name as person_name, pets.name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
+ij> select person.name as name, pets.name as pet_name from person,pets order by name;
+ERROR 42X79: Column name 'NAME' appears more than once in the result of the query expression.
 ij> drop table person;
 0 rows inserted/updated/deleted
+ij> drop table pets;
+0 rows inserted/updated/deleted
 ij> create table d2887_types(
    id             int,
    c1_smallint    smallint,
@@ -2049,4 +2160,4 @@
 ERROR 42X77: Column position '2' is out of range for the query expression.
 ij> drop table d3303;
 0 rows inserted/updated/deleted
-ij> 
+ij> 
\ No newline at end of file
Index: java/testing/org/apache/derbyTesting/functionTests/master/synonym.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/synonym.out	(revision 634153)
+++ java/testing/org/apache/derbyTesting/functionTests/master/synonym.out	(working copy)
@@ -523,9 +523,7 @@
 -----------------------------------------
 1                   |1                   
 ij> select t1.id as idcolumn1, t1.id as idcolumn2 from t1 order by t1.idcolumn1, t1.idcolumn2;
-IDCOLUMN1           |IDCOLUMN2           
------------------------------------------
-1                   |1                   
+ERROR 42X04: Column 'T1.IDCOLUMN1' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE  statement then 'T1.IDCOLUMN1' is not a column in the target table.
 ij> select t1.id from (select t1.id from t1) t1 order by t1.id;
 ID                  
 --------------------
