Index: java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj	(revision 153639)
+++ java/engine/org/apache/derby/impl/sql/compile/sqlgrammar.jj	(working copy)
@@ -1534,6 +1534,190 @@
 		throw StandardException.newException(SQLState.LANG_IDENTIFIER_TOO_LONG, identifier, String.valueOf(identifier_length_limit));
     }
 
+    private boolean judgedAsSimpleColumnByName()
+	{
+
+	int tokenIndex = 1;
+	
+		for(int i = 0;i < 3; i ++){
+
+			if(getToken(tokenIndex).kind != DELIMITED_IDENTIFIER && 
+	       	getToken(tokenIndex).kind != IDENTIFIER &&
+	       	! isNonReservedKeyword(getToken(tokenIndex).kind)){
+				return false;
+
+			}
+
+			tokenIndex ++;
+			boolean ascDescExist = false;
+
+			if(getToken(tokenIndex).kind == ASC ||
+           		getToken(tokenIndex).kind == DESC){
+				tokenIndex ++;
+				ascDescExist = true;
+			}
+
+	   		if(getToken(tokenIndex).kind == EOF || 
+	  	   		getToken(tokenIndex).kind == COMMA){
+				return true;
+			}
+			
+			if(ascDescExist){
+				return false;
+			}
+
+			if(i == 2){
+				return false;
+			}
+
+			if(getToken(tokenIndex).kind != PERIOD){
+				return false;
+			}
+			tokenIndex ++;		
+
+		}
+
+		return false;
+
+    }
+
+	private boolean isNonReservedKeyword(int kind){
+		return 
+			kind == ABS || 
+			kind == ABSVAL ||
+			kind == ACTION ||
+			kind == AFTER ||
+			kind == ALWAYS ||
+			kind == BEFORE ||
+			kind == BINARY ||
+			kind == BLOB ||
+			kind == C ||
+			kind == CALLED ||
+			kind == CLASS ||
+			kind == CLOB || 
+			kind == COALESCE ||
+			kind == COBOL ||
+			kind == COMMITTED ||
+			kind == COMPRESS ||
+			kind == CONCAT ||
+			kind == CONTAINS ||
+			kind == CS ||
+			kind == CURDATE ||
+			kind == CURTIME ||
+			kind == D ||
+			kind == DATA ||
+			kind == DATE ||
+			kind == DAY ||
+			kind == DIRTY ||
+			kind == DYNAMIC ||
+			kind == DATABASE ||
+			kind == DB2SQL ||
+			kind == EACH ||
+			kind == EXCLUSIVE ||
+			kind == FN ||
+			kind == FORTRAN ||
+			kind == GENERATED ||
+			kind == IDENTITY_VAL_LOCAL ||
+			kind == INCREMENT ||
+			kind == INDEX ||
+			kind == INITIAL ||
+			kind == INTERVAL ||
+			kind == JAVA ||
+			kind == LANGUAGE ||
+			kind == LARGE ||
+			kind == LCASE ||
+			kind == LENGTH ||
+			kind == LEVEL ||
+			kind == LOCATE ||
+			kind == LOCK ||
+			kind == LOCKS ||
+			kind == LOCKSIZE ||
+			kind == LOGGED ||
+			kind == LONG ||
+			kind == MESSAGE_LOCALE ||
+			kind == METHOD ||
+			kind == MOD ||
+			kind == MODE ||
+			kind == MODIFIES ||
+			kind == MODIFY ||
+			kind == MODULE ||
+			kind == MONTH ||
+			kind == _MORE ||
+			kind == MUMPS ||
+			kind == NAME ||
+			kind == NCLOB ||
+			kind == NEW ||
+			kind == NEW_TABLE ||
+			kind == NULLABLE ||
+			kind == NUMBER ||
+			kind == OBJECT ||
+			kind == OFF ||
+			kind == OLD ||
+			kind == OLD_TABLE ||
+			kind == OJ ||
+			kind == PASCAL ||
+			kind == PLI ||
+			kind == PRECISION ||
+			kind == READS ||
+			kind == RELEASE ||
+			kind == RENAME ||
+			kind == REPEATABLE ||
+			kind == REFERENCING ||
+			kind == RESET ||
+			kind == RESULT ||
+			kind == RETAIN ||
+			kind == RETURNS ||
+			kind == ROW ||
+			kind == RR ||
+			kind == RS ||
+			kind == SCALE ||
+			kind == SAVEPOINT ||
+			kind == SEQUENTIAL ||
+			kind == SERIALIZABLE ||
+			kind == SETS ||
+			kind == SHARE ||
+			kind == SPECIFIC ||
+			kind == SQLID ||
+			kind == SQRT ||
+			kind == STABILITY ||
+			kind == START ||
+			kind == STATEMENT ||
+			kind == STYLE ||
+			kind == T ||
+			kind == THEN ||
+			kind == TIME ||
+			kind == TIMESTAMP ||
+			kind == TRIGGER ||
+			kind == TRUNCATE ||
+			kind == TS ||
+			kind == TYPE ||
+			kind == UCASE ||
+			kind == UNCOMMITTED ||
+			kind == UR ||
+			kind == USAGE ||
+			kind == VALUE ||
+			kind == VARBINARY ||
+			kind == PARAMETER ||
+			kind == WHEN;
+	}
+
+    private boolean judgedAsSimpleColumnByNum(){
+
+	if(getToken(1).kind != EXACT_NUMERIC){
+		return false;
+	}
+
+	if(getToken(2).kind == EOF || 
+	   getToken(2).kind == ASC ||
+           getToken(2).kind == DESC ||
+	   getToken(2).kind == COMMA){
+			return true;
+
+	}
+
+	return false;
+
+    }
 }
 
 PARSER_END(SQLParser)
@@ -6584,7 +6768,7 @@
 	orderCol = sortKey() /* [ collateClause() ] */ [ orderingSpecification(orderCol) ]
 	{
 		orderCols.addOrderByColumn(orderCol);
-	}
+	} 
 }
 
 OrderByColumn
@@ -6597,8 +6781,10 @@
 	String correlationName = null;
 	String schemaName = null;
 	int columnPosition;
+	ValueNode columnExpression;
 } 
 {
+	LOOKAHEAD({judgedAsSimpleColumnByName()})
 	firstName = identifier(DB2Limit.DB2_MAX_IDENTIFIER_LENGTH128, false)
 	[
 		<PERIOD> secondName = identifier(DB2Limit.DB2_MAX_IDENTIFIER_LENGTH128, false)
@@ -6644,6 +6830,7 @@
 								getContextManager());
 	}
 |
+	LOOKAHEAD({judgedAsSimpleColumnByNum()})
 	columnPosition = uint_value()
 	{
 		return (OrderByColumn) nodeFactory.getNode(
@@ -6651,6 +6838,15 @@
 								ReuseFactory.getInteger(columnPosition),
 								getContextManager());
 	}
+|
+	columnExpression = additiveExpression(null,0,true)
+	{
+		return (OrderByColumn) nodeFactory.getNode(
+								C_NodeTypes.ORDER_BY_COLUMN,
+								columnExpression,
+								null,
+								getContextManager());
+	}
 }
 
 
Index: java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java
===================================================================
--- java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java	(revision 153639)
+++ java/engine/org/apache/derby/impl/sql/compile/OrderByColumn.java	(working copy)
@@ -46,7 +46,9 @@
 	private	String			correlationName;
 	private String	schemaName;
 	private boolean			ascending = true;
+	private ValueNode expression;
 
+
 	/**
 	 * Initializer.
 	 *
@@ -63,13 +65,25 @@
 		this.schemaName = (String) schemaName;
 	}
 
-	/**
+    	/**
 	 * Initializer.
 	 *
+	 * @param expression            Expression of this column
+	 * @param dummy                 Dummy to distinguish from init with one parameter
+	 */
+	public void init(Object expression,
+			 Object dummy)
+	{
+		this.expression = (ValueNode)expression;
+	}
+	
+	/**
+	 *I nitializer.
+	 *
 	 * @param columnPosition	The position of the column being referenced
 	 */
 	public void init(Object columnPosition) {
-		this.columnPosition = ((Integer) columnPosition).intValue();
+	    this.columnPosition = ((Integer) columnPosition).intValue();
 	}
 
 	/**
@@ -236,8 +250,26 @@
 				throw StandardException.newException(SQLState.LANG_ORDER_BY_COLUMN_NOT_FOUND, errString);
 			}
 			columnPosition = resultCol.getColumnPosition();
-		}
-		else {
+		}else if(expression != null){
+		    
+		    ResultColumn col = null;
+		    int i = 0;
+		    
+		    for(i = 0;
+			i < targetCols.size();
+			i  ++){
+			col = targetCols.getOrderByColumn(i);
+			if(col != null && 
+			   col.getExpression() == expression){
+			    
+			    break;
+			}
+		    }
+		    
+		    resultCol = col;
+		    columnPosition = i;
+		    
+		}else {
 			resultCol = targetCols.getOrderByColumn(columnPosition);
 			if (resultCol == null) {
 				throw StandardException.newException(SQLState.LANG_COLUMN_OUT_OF_RANGE, String.valueOf(columnPosition));
@@ -295,6 +327,15 @@
 				targetCols.addResultColumn(resultCol);
 				targetCols.incOrderBySelect();
 			}
+
+		}else if(expression != null){
+			ResultColumnList	targetCols = target.getResultColumns();
+			resultCol = (ResultColumn) getNodeFactory().getNode(C_NodeTypes.RESULT_COLUMN,
+									    null,
+									    expression,
+									    getContextManager());
+			targetCols.addResultColumn(resultCol);
+			targetCols.incOrderBySelect();
 		}
 	}
 
Index: java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql	(revision 153639)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/lang/orderby.sql	(working copy)
@@ -133,7 +133,7 @@
 -- . order by on column not in select, in table (error)
 select i from obt order by v;
 
--- . order by on expression (not allowed)
+-- . order by on expression (allowed)
 select i from obt order by i+1;
 
 -- . order by on qualified column name, incorrect correlation name (not allowed)
@@ -350,6 +350,44 @@
 select a, b, c from t order by b, c;
 select b, c from t order by app.t.a;
 
+
+--Test addtive expression in order clause
+
+create table test_word(value varchar(32));
+insert into test_word(value) values('anaconda');
+insert into test_word(value) values('America');
+insert into test_word(value) values('camel');
+insert into test_word(value) values('Canada');
+
+select * from test_word order by value;
+select * from test_word order by upper(value);
+
+drop table test_word;
+
+create table test_number(value integer);
+insert into test_number(value) values(-1);
+insert into test_number(value) values(0);
+insert into test_number(value) values(1);
+insert into test_number(value) values(2);
+insert into test_number(value) values(3);
+insert into test_number(value) values(100);
+insert into test_number(value) values(1000);
+select * from test_number order by value;
+select * from test_number order by value + 1;
+select * from test_number order by value - 1;
+select * from test_number order by value * 1;
+select * from test_number order by value / 1;
+select * from test_number order by 1 + value;
+select * from test_number order by 1 - value;
+select * from test_number order by 1 * value;
+select * from test_number where value <> 0 order by 1 / value;
+select * from test_number order by -1 + value;
+select * from test_number order by -1 - value;
+select * from test_number order by - 1 * value;
+select * from test_number where value <> 0 order by - 1 / value;
+select * from test_number order by abs(value);
+drop table test_number;
+
 -- error case
 select * from t order by d;
 select t.* from t order by d;
Index: java/testing/org/apache/derbyTesting/functionTests/master/orderby.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/orderby.out	(revision 153639)
+++ java/testing/org/apache/derbyTesting/functionTests/master/orderby.out	(working copy)
@@ -345,9 +345,15 @@
 2          
 1          
 NULL       
-ij> -- . order by on expression (not allowed)
+ij> -- . order by on expression (allowed)
 select i from obt order by i+1;
-ERROR 42X01: Syntax error: Encountered "+" at line 2, column 29.
+I          
+-----------
+1          
+1          
+2          
+3          
+NULL       
 ij> -- . order by on qualified column name, incorrect correlation name (not allowed)
 select i from obt t order by obt.i;
 ERROR 42X04: Column 'OBT.I' is not in any table in the FROM list or it appears within a join specification and is outside the scope of the join specification or it appears in a HAVING clause and is not in the GROUP BY list.  If this is a CREATE or ALTER TABLE statement then 'OBT.I' is not a column in the target table.
@@ -863,6 +869,189 @@
 2          |NULL       
 3          |NULL       
 0          |NULL       
+ij> --Test addtive expression in order clause
+create table test_word(value varchar(32));
+0 rows inserted/updated/deleted
+ij> insert into test_word(value) values('anaconda');
+1 row inserted/updated/deleted
+ij> insert into test_word(value) values('America');
+1 row inserted/updated/deleted
+ij> insert into test_word(value) values('camel');
+1 row inserted/updated/deleted
+ij> insert into test_word(value) values('Canada');
+1 row inserted/updated/deleted
+ij> select * from test_word order by value;
+VALUE                           
+--------------------------------
+America                         
+Canada                          
+anaconda                        
+camel                           
+ij> select * from test_word order by upper(value);
+VALUE                           
+--------------------------------
+America                         
+anaconda                        
+camel                           
+Canada                          
+ij> drop table test_word;
+0 rows inserted/updated/deleted
+ij> create table test_number(value integer);
+0 rows inserted/updated/deleted
+ij> insert into test_number(value) values(-1);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(0);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(1);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(2);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(3);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(100);
+1 row inserted/updated/deleted
+ij> insert into test_number(value) values(1000);
+1 row inserted/updated/deleted
+ij> select * from test_number order by value;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by value + 1;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by value - 1;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by value * 1;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by value / 1;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by 1 + value;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by 1 - value;
+VALUE      
+-----------
+1000       
+100        
+3          
+2          
+1          
+0          
+-1         
+ij> select * from test_number order by 1 * value;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number where value <> 0 order by 1 / value;
+VALUE      
+-----------
+-1         
+1000       
+100        
+3          
+2          
+1          
+ij> select * from test_number order by -1 + value;
+VALUE      
+-----------
+-1         
+0          
+1          
+2          
+3          
+100        
+1000       
+ij> select * from test_number order by -1 - value;
+VALUE      
+-----------
+1000       
+100        
+3          
+2          
+1          
+0          
+-1         
+ij> select * from test_number order by - 1 * value;
+VALUE      
+-----------
+1000       
+100        
+3          
+2          
+1          
+0          
+-1         
+ij> select * from test_number where value <> 0 order by - 1 / value;
+VALUE      
+-----------
+1          
+1000       
+100        
+3          
+2          
+-1         
+ij> select * from test_number order by abs(value);
+VALUE      
+-----------
+0          
+1          
+-1         
+2          
+3          
+100        
+1000       
+ij> drop table test_number;
+0 rows inserted/updated/deleted
 ij> -- error case
 select * from t order by d;
 ERROR 42X04: Column 'D' is not in any table in the FROM list or it appears within a join specification and is outside the scope of the join specification or it appears in a HAVING clause and is not in the GROUP BY list.  If this is a CREATE or ALTER TABLE statement then 'D' is not a column in the target table.
