[teiid-commits] teiid SVN: r1841 - in trunk: connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase and 20 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Feb 18 15:12:15 EST 2010


Author: shawkins
Date: 2010-02-18 15:12:13 -0500 (Thu, 18 Feb 2010)
New Revision: 1841

Added:
   trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java
Modified:
   trunk/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java
   trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java
   trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
   trunk/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java
   trunk/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java
   trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java
   trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
   trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java
   trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java
   trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java
Log:
TEIID-989 cleaning up the handling of unrelated order by items.  also introduced an order by item class into the engine.

Modified: trunk/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java
===================================================================
--- trunk/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -821,7 +821,7 @@
             buffer.append(SQLReservedWords.SPACE);
             append(obj.getOrderBy());
         }
-        if (obj.getLimit() != null) {
+        if (!useSelectLimit() && obj.getLimit() != null) {
             buffer.append(SQLReservedWords.SPACE);
             append(obj.getLimit());
         }
@@ -860,12 +860,16 @@
     	visitSelect(obj, null);
     }
 
-	private void visitSelect(ISelect obj, ICommand command) {
+	private void visitSelect(ISelect obj, IQuery command) {
 		buffer.append(SQLReservedWords.SELECT).append(SQLReservedWords.SPACE);
         buffer.append(getSourceComment(command));
         if (obj.isDistinct()) {
             buffer.append(SQLReservedWords.DISTINCT).append(SQLReservedWords.SPACE);
         }
+        if (useSelectLimit() && command.getLimit() != null) {
+            append(command.getLimit());
+            buffer.append(SQLReservedWords.SPACE);
+        }
         append(obj.getSelectSymbols());
 	}
 
@@ -1038,4 +1042,8 @@
     protected boolean useParensForJoins() {
     	return false;
     }
+    
+    protected boolean useSelectLimit() {
+    	return false;
+    }
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -43,7 +43,7 @@
 import org.teiid.connector.language.IFunction;
 import org.teiid.connector.language.ILimit;
 import org.teiid.connector.language.IOrderBy;
-import org.teiid.connector.language.IQueryCommand;
+import org.teiid.connector.language.ISetQuery;
 
 
 /**
@@ -166,12 +166,15 @@
     	return 3;
     }
     
+    /**
+     * SetQueries don't have a concept of TOP, an inline view is needed.
+     */
     @Override
     public List<?> translateCommand(ICommand command, ExecutionContext context) {
-    	if (!(command instanceof IQueryCommand)) {
+    	if (!(command instanceof ISetQuery)) {
     		return null;
     	}
-		IQueryCommand queryCommand = (IQueryCommand)command;
+    	ISetQuery queryCommand = (ISetQuery)command;
 		if (queryCommand.getLimit() == null) {
 			return null;
     	}
@@ -180,8 +183,8 @@
 		queryCommand.setLimit(null);
 		queryCommand.setOrderBy(null);
 		List<Object> parts = new ArrayList<Object>(6);
-		parts.add("SELECT TOP "); //$NON-NLS-1$
-		parts.add(limit.getRowLimit());
+		parts.add("SELECT "); //$NON-NLS-1$
+		parts.addAll(translateLimit(limit, context));
 		parts.add(" * FROM ("); //$NON-NLS-1$
 		parts.add(queryCommand);
 		parts.add(") AS X"); //$NON-NLS-1$
@@ -192,7 +195,18 @@
 		return parts;
     }
     
+    @SuppressWarnings("unchecked")
+	@Override
+    public List<?> translateLimit(ILimit limit, ExecutionContext context) {
+    	return Arrays.asList("TOP ", limit.getRowLimit()); //$NON-NLS-1$
+    }
+    
     @Override
+    public boolean useSelectLimit() {
+    	return true;
+    }
+    
+    @Override
     public Class<? extends ConnectorCapabilities> getDefaultCapabilities() {
     	return SybaseCapabilities.class;
     }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -374,4 +374,8 @@
     	return translator.useParensForJoins();
     }
 	
+	protected boolean useSelectLimit() {
+		return translator.useSelectLimit();
+	}
+	
 }

Modified: trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -839,4 +839,12 @@
     	return false;
     }
     
+    /**
+     * 
+     * @return true if the limit clause is part of the select
+     */
+    public boolean useSelectLimit() {
+    	return false;
+    }
+    
 }

Modified: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -66,7 +66,7 @@
 
     public void testRowLimit() throws Exception {
         String input = "select intkey from bqt1.smalla limit 100"; //$NON-NLS-1$
-        String output = "SELECT TOP 100 * FROM (SELECT SmallA.IntKey FROM SmallA) AS X";  //$NON-NLS-1$
+        String output = "SELECT TOP 100 SmallA.IntKey FROM SmallA";  //$NON-NLS-1$
 
         helpTestVisitor(
             input, 
@@ -76,7 +76,7 @@
     
     public void testRowLimit1() throws Exception {
         String input = "select distinct intkey from bqt1.smalla limit 100"; //$NON-NLS-1$
-        String output = "SELECT TOP 100 * FROM (SELECT DISTINCT SmallA.IntKey FROM SmallA) AS X";  //$NON-NLS-1$
+        String output = "SELECT DISTINCT TOP 100 SmallA.IntKey FROM SmallA";  //$NON-NLS-1$
 
         helpTestVisitor(
             input, 

Modified: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -335,8 +335,8 @@
     }
     
     @Test public void testBooleanToString() throws Exception {
-    	String input = "SELECT convert(INTKEY, boolean) FROM BQT1.SmallA ORDER BY INTKEY"; //$NON-NLS-1$
-        String output = "SELECT CASE WHEN SmallA.IntKey = 0 THEN 0 WHEN SmallA.IntKey IS NOT NULL THEN 1 END FROM SmallA ORDER BY INTKEY"; //$NON-NLS-1$
+    	String input = "SELECT convert(INTKEY, boolean) FROM BQT1.SmallA"; //$NON-NLS-1$
+        String output = "SELECT CASE WHEN SmallA.IntKey = 0 THEN 0 WHEN SmallA.IntKey IS NOT NULL THEN 1 END FROM SmallA"; //$NON-NLS-1$
           
         TranslationHelper.helpTestVisitor(TranslationHelper.BQT_VDB,
             input, 

Modified: trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java
===================================================================
--- trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -96,7 +96,7 @@
     @Test
     public void testRowLimit() throws Exception {
         String input = "select intkey from bqt1.smalla limit 100"; //$NON-NLS-1$
-        String output = "SELECT TOP 100 * FROM (SELECT SmallA.IntKey FROM SmallA) AS X"; //$NON-NLS-1$
+        String output = "SELECT TOP 100 SmallA.IntKey FROM SmallA"; //$NON-NLS-1$
                
         helpTestVisitor(getBQTVDB(),
             input, 
@@ -113,6 +113,15 @@
             output);        
     }
     
+    @Test public void testLimitWithOrderByUnrelated() throws Exception {
+        String input = "select intkey from bqt1.smalla order by intnum limit 100"; //$NON-NLS-1$
+        String output = "SELECT TOP 100 SmallA.IntKey FROM SmallA ORDER BY SmallA.IntNum"; //$NON-NLS-1$
+               
+        helpTestVisitor(getBQTVDB(),
+            input, 
+            output);        
+    }
+    
     @Test
     public void testDateFunctions() throws Exception {
         String input = "select dayName(timestampValue), dayOfWeek(timestampValue), quarter(timestampValue) from bqt1.smalla"; //$NON-NLS-1$

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -343,7 +343,7 @@
 	                        
 	            if (needsAlias) {
 	                element = new AliasSymbol(element.getShortName(), (SingleElementSymbol)expr);
-	                obj.getVariables().set(i, element);
+	                obj.getOrderByItems().get(i).setSymbol(element);
 	            }
 	            element.setOutputName(name);
             }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -34,9 +34,6 @@
     // This flag indicates that the plan has a virtual group somewhere
     public boolean hasVirtualGroups = false;
     
-    // This flag indicates that the plan has a sort somewhere
-    public boolean hasSort = false;
-    
     // flag indicates that the plan has a union somewhere
     public boolean hasSetQuery = false;
     

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -74,6 +74,7 @@
 import com.metamatrix.query.sql.lang.Criteria;
 import com.metamatrix.query.sql.lang.Insert;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.StoredProcedure;
 import com.metamatrix.query.sql.lang.SetQuery.Operation;
@@ -321,11 +322,10 @@
 			case NodeConstants.Types.SORT:
 			case NodeConstants.Types.DUP_REMOVE:
                 SortNode sortNode = new SortNode(getID());
-                
-				List elements = (List) node.getProperty(NodeConstants.Info.SORT_ORDER);
-				List sortTypes = (List) node.getProperty(NodeConstants.Info.ORDER_TYPES);
-				
-				sortNode.setSortElements(elements, sortTypes);
+                OrderBy orderBy = (OrderBy) node.getProperty(NodeConstants.Info.SORT_ORDER);
+				if (orderBy != null) {
+					sortNode.setSortElements(orderBy.getSortKeys(), orderBy.getTypes());
+				}
 				if (node.getType() == NodeConstants.Types.DUP_REMOVE) {
 					sortNode.setMode(Mode.DUP_REMOVE);
 				} else if (node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL)) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -65,6 +65,7 @@
 import com.metamatrix.query.resolver.QueryResolver;
 import com.metamatrix.query.resolver.util.BindVariableVisitor;
 import com.metamatrix.query.rewriter.QueryRewriter;
+import com.metamatrix.query.sql.LanguageObject.Util;
 import com.metamatrix.query.sql.lang.Command;
 import com.metamatrix.query.sql.lang.Criteria;
 import com.metamatrix.query.sql.lang.From;
@@ -156,7 +157,7 @@
 		connectSubqueryContainers(plan); //TODO: merge with node creation
         
         // Set top column information on top node
-        List<SingleElementSymbol> topCols = QueryRewriter.deepClone(command.getProjectedSymbols(), SingleElementSymbol.class);
+        List<SingleElementSymbol> topCols = Util.deepClone(command.getProjectedSymbols());
 
         // Build rule set based on hints
         RuleStack rules = RelationalPlanner.buildRules(hints);
@@ -530,7 +531,6 @@
         
 		if(command.getOrderBy() != null) {
 			node = attachSorting(node, command.getOrderBy());
-            hints.hasSort = true;
 		}
 
         if (command.getLimit() != null) {
@@ -786,8 +786,7 @@
 	private static PlanNode attachSorting(PlanNode plan, OrderBy orderBy) {
 		PlanNode sortNode = NodeFactory.getNewNode(NodeConstants.Types.SORT);
 		
-		sortNode.setProperty(NodeConstants.Info.SORT_ORDER, orderBy.getVariables());
-		sortNode.setProperty(NodeConstants.Info.ORDER_TYPES, orderBy.getTypes());
+		sortNode.setProperty(NodeConstants.Info.SORT_ORDER, orderBy);
 		if (orderBy.hasUnrelated()) {
 			sortNode.setProperty(Info.UNRELATED_SORT, true);
 		}

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -108,8 +108,7 @@
         IS_DEPENDENT_SET, // Boolean - only used with dependent joins
 
         // Sort node properties
-        ORDER_TYPES,        // List <Boolean>
-        SORT_ORDER,         // List <SingleElementSymbol>
+        SORT_ORDER,         // OrderBy
         UNRELATED_SORT,     // Boolean
         IS_DUP_REMOVAL,		// Boolean
 

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -235,10 +235,8 @@
             convertAccessPatterns(symbolMap, node);
         
         } else if(type == NodeConstants.Types.SORT) { 
-        	List<SingleElementSymbol> sortCols = (List<SingleElementSymbol>)node.getProperty(NodeConstants.Info.SORT_ORDER);
-            OrderBy orderBy = new OrderBy(sortCols);
+        	OrderBy orderBy = (OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
             ExpressionMappingVisitor.mapExpressions(orderBy, symbolMap);
-            node.setProperty(NodeConstants.Info.SORT_ORDER, orderBy.getVariables());
             if (!singleMapping) {
                 GroupsUsedByElementsVisitor.getGroups(orderBy, groups);
             }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -52,7 +52,7 @@
 import com.metamatrix.query.sql.visitor.GroupsUsedByElementsVisitor;
 
 /**
- *  A join region is a set of cross and inner joins whose ordering is completely interchangable.
+ *  A join region is a set of cross and inner joins whose ordering is completely interchangeable.
  *  
  *  It can be conceptually thought of as:
  *     Criteria node some combination of groups A, B, C
@@ -73,30 +73,30 @@
     
     public static final int UNKNOWN_TUPLE_EST = 100000;
     
-    private LinkedHashMap dependentJoinSourceNodes = new LinkedHashMap();
-    private LinkedHashMap joinSourceNodes = new LinkedHashMap();
+    private LinkedHashMap<PlanNode, PlanNode> dependentJoinSourceNodes = new LinkedHashMap<PlanNode, PlanNode>();
+    private LinkedHashMap<PlanNode, PlanNode> joinSourceNodes = new LinkedHashMap<PlanNode, PlanNode>();
         
-    private List dependentCritieraNodes = new ArrayList();
-    private List criteriaNodes = new ArrayList();
+    private List<PlanNode> dependentCritieraNodes = new ArrayList<PlanNode>();
+    private List<PlanNode> criteriaNodes = new ArrayList<PlanNode>();
     
-    private List unsatisfiedAccessPatterns = new LinkedList();
+    private List<Collection<AccessPattern>> unsatisfiedAccessPatterns = new LinkedList<Collection<AccessPattern>>();
     
     private Map<ElementSymbol, Set<Collection<GroupSymbol>>> dependentCriteriaElements;
-    private Map critieriaToSourceMap;
+    private Map<PlanNode, Set<PlanNode>> critieriaToSourceMap;
     
     public PlanNode getJoinRoot() {
         return joinRoot;
     }
     
-    public List getUnsatisfiedAccessPatterns() {
+    public List<Collection<AccessPattern>> getUnsatisfiedAccessPatterns() {
         return unsatisfiedAccessPatterns;
     }
     
-    public Map getJoinSourceNodes() {
+    public Map<PlanNode, PlanNode> getJoinSourceNodes() {
         return joinSourceNodes;
     }
 
-    public Map getDependentJoinSourceNodes() {
+    public Map<PlanNode, PlanNode> getDependentJoinSourceNodes() {
         return dependentJoinSourceNodes;
     }
     
@@ -104,7 +104,7 @@
         return criteriaNodes;
     }
     
-    public List getDependentCriteriaNodes() {
+    public List<PlanNode> getDependentCriteriaNodes() {
         return dependentCritieraNodes;
     }
     
@@ -112,7 +112,7 @@
         return this.dependentCriteriaElements;
     }
 
-    public Map getCritieriaToSourceMap() {
+    public Map<PlanNode, Set<PlanNode>> getCritieriaToSourceMap() {
         return this.critieriaToSourceMap;
     }
 
@@ -122,7 +122,7 @@
             root = root.getParent();
         }
         if (sourceNode.hasCollectionProperty(NodeConstants.Info.ACCESS_PATTERNS)) {
-            Collection aps = (Collection)sourceNode.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
+            Collection<AccessPattern> aps = (Collection<AccessPattern>)sourceNode.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
             unsatisfiedAccessPatterns.add(aps);
             dependentJoinSourceNodes.put(sourceNode, root);
         } else {
@@ -146,12 +146,11 @@
         }
     }
                     
-    public void addJoinCriteriaList(List joinCriteria) {
+    public void addJoinCriteriaList(List<? extends Criteria> joinCriteria) {
         if (joinCriteria == null || joinCriteria.isEmpty()) {
             return;
         }
-        for (Iterator i = joinCriteria.iterator(); i.hasNext();) {
-            Criteria crit = (Criteria)i.next();
+        for (Criteria crit : joinCriteria) {
             criteriaNodes.add(RelationalPlanner.createSelectNode(crit, false));
         }
     }
@@ -167,20 +166,19 @@
      * 
      */
     public void reconstructJoinRegoin() {
-        LinkedHashMap combined = new LinkedHashMap(joinSourceNodes);
+        LinkedHashMap<PlanNode, PlanNode> combined = new LinkedHashMap<PlanNode, PlanNode>(joinSourceNodes);
         combined.putAll(dependentJoinSourceNodes);
         
         PlanNode root = null;
         
         if (combined.size() < 2) {
-            root = (PlanNode)combined.values().iterator().next();
+            root = combined.values().iterator().next();
             root.removeProperty(NodeConstants.Info.EST_CARDINALITY);
         } else {
             root = RulePlanJoins.createJoinNode();
         
-            for (Iterator i = combined.entrySet().iterator(); i.hasNext();) {
-                Map.Entry entry = (Map.Entry)i.next();
-                PlanNode joinSourceRoot = (PlanNode)entry.getValue();
+            for (Map.Entry<PlanNode, PlanNode> entry : combined.entrySet()) {
+                PlanNode joinSourceRoot = entry.getValue();
                 joinSourceRoot.removeProperty(NodeConstants.Info.EST_CARDINALITY);
                 if (root.getChildCount() == 2) {
                     PlanNode parentJoin = RulePlanJoins.createJoinNode();
@@ -189,10 +187,10 @@
                     root = parentJoin;
                 }
                 root.addLastChild(joinSourceRoot);
-                root.addGroups(((PlanNode)entry.getKey()).getGroups());
+                root.addGroups(entry.getKey().getGroups());
             }
         }
-        LinkedList criteria = new LinkedList(dependentCritieraNodes);
+        LinkedList<PlanNode> criteria = new LinkedList<PlanNode>(dependentCritieraNodes);
         criteria.addAll(criteriaNodes);
 
         PlanNode parent = this.joinRoot.getParent();
@@ -201,9 +199,7 @@
 
         parent.removeChild(joinRoot);
         
-        for (Iterator i = criteria.iterator(); i.hasNext();) {
-            PlanNode critNode = (PlanNode)i.next();
-            
+        for (PlanNode critNode : criteria) {
             critNode.removeFromParent();
             critNode.removeAllChildren();
             critNode.addFirstChild(root);
@@ -229,24 +225,24 @@
      * @return
      */
     public double scoreRegion(Object[] joinOrder, QueryMetadataInterface metadata) {
-        List joinSourceEntries = new ArrayList(joinSourceNodes.entrySet());
+        List<Map.Entry<PlanNode, PlanNode>> joinSourceEntries = new ArrayList<Map.Entry<PlanNode, PlanNode>>(joinSourceNodes.entrySet());
         double totalIntermediatCost = 0;
         double cost = 1;
         
-        HashSet criteria = new HashSet(this.criteriaNodes);
-        HashSet groups = new HashSet(this.joinSourceNodes.size());
+        HashSet<PlanNode> criteria = new HashSet<PlanNode>(this.criteriaNodes);
+        HashSet<GroupSymbol> groups = new HashSet<GroupSymbol>(this.joinSourceNodes.size());
         
         for (int i = 0; i < joinOrder.length; i++) {
             Integer source = (Integer)joinOrder[i];
             
-            Map.Entry entry = (Map.Entry)joinSourceEntries.get(source.intValue());
-            PlanNode joinSourceRoot = (PlanNode)entry.getValue();
+            Map.Entry<PlanNode, PlanNode> entry = joinSourceEntries.get(source.intValue());
+            PlanNode joinSourceRoot = entry.getValue();
             
             //check to make sure that this group ordering satisfies the access patterns
             if (!this.unsatisfiedAccessPatterns.isEmpty()) {
-                PlanNode joinSource = (PlanNode)entry.getKey();
+                PlanNode joinSource = entry.getKey();
                 
-                Collection requiredGroups = (Collection)joinSource.getProperty(NodeConstants.Info.REQUIRED_ACCESS_PATTERN_GROUPS);
+                Collection<GroupSymbol> requiredGroups = (Collection<GroupSymbol>)joinSource.getProperty(NodeConstants.Info.REQUIRED_ACCESS_PATTERN_GROUPS);
                 
                 if (requiredGroups != null && !groups.containsAll(requiredGroups)) {
                     return Double.MAX_VALUE;
@@ -266,11 +262,9 @@
             cost *= sourceCost;
             
             if (!criteria.isEmpty() && i > 0) {
-                List applicableCriteria = getJoinCriteriaForGroups(groups, criteria);
+                List<PlanNode> applicableCriteria = getJoinCriteriaForGroups(groups, criteria);
                 
-                for (Iterator j = applicableCriteria.iterator(); j.hasNext();) {
-                    PlanNode criteriaNode = (PlanNode)j.next();
-                    
+                for (PlanNode criteriaNode : applicableCriteria) {
                     float filter = ((Float)criteriaNode.getProperty(NodeConstants.Info.EST_SELECTIVITY)).floatValue();
                     
                     cost *= filter;
@@ -290,15 +284,9 @@
      *  This does not necessarily mean that a join tree will be successfully created
      */
     public boolean isSatisfiable() {
-        if (getUnsatisfiedAccessPatterns().isEmpty()) {
-            return true;
-        }
-        
-        for (Iterator i = getUnsatisfiedAccessPatterns().iterator(); i.hasNext();) {
-            Collection accessPatterns = (Collection)i.next();
+    	for (Collection<AccessPattern> accessPatterns : getUnsatisfiedAccessPatterns()) {
             boolean matchedAll = false;
-            for (Iterator j = accessPatterns.iterator(); j.hasNext();) {
-                AccessPattern ap = (AccessPattern)j.next();
+            for (AccessPattern ap : accessPatterns) {
                 if (dependentCriteriaElements.keySet().containsAll(ap.getUnsatisfied())) {
                     matchedAll = true;
                     break;
@@ -313,8 +301,7 @@
     }
 
     public void initializeCostingInformation(QueryMetadataInterface metadata) throws QueryMetadataException, MetaMatrixComponentException {
-        for (Iterator i = joinSourceNodes.values().iterator(); i.hasNext();) {
-            PlanNode node = (PlanNode)i.next();
+    	for (PlanNode node : joinSourceNodes.values()) {
             NewCalculateCostUtil.computeCostForTree(node, metadata);
         }
         
@@ -328,9 +315,7 @@
      */
     private void estimateCriteriaSelectivity(QueryMetadataInterface metadata) throws QueryMetadataException,
                                                                              MetaMatrixComponentException {
-        for (Iterator i = criteriaNodes.iterator(); i.hasNext();) {
-            PlanNode node = (PlanNode)i.next();
-            
+        for (PlanNode node : criteriaNodes) {
             Criteria crit = (Criteria)node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
             
             float[] baseCosts = new float[] {100, 10000, 1000000};
@@ -355,28 +340,21 @@
      *  TODO: assumptions are made here about how dependent criteria must look that are a little restrictive
      */
     public void initializeJoinInformation() {
-        critieriaToSourceMap = new HashMap();
+        critieriaToSourceMap = new HashMap<PlanNode, Set<PlanNode>>();
                 
-        LinkedList crits = new LinkedList(criteriaNodes);
+        LinkedList<PlanNode> crits = new LinkedList<PlanNode>(criteriaNodes);
         crits.addAll(dependentCritieraNodes);
         
-        LinkedHashMap source = new LinkedHashMap(joinSourceNodes);
+        LinkedHashMap<PlanNode, PlanNode> source = new LinkedHashMap<PlanNode, PlanNode>(joinSourceNodes);
         source.putAll(dependentJoinSourceNodes);
         
-        for (Iterator j = crits.iterator(); j.hasNext();) {
-            PlanNode critNode = (PlanNode)j.next();
-            
-            for (Iterator k = critNode.getGroups().iterator(); k.hasNext();) {
-
-                GroupSymbol group = (GroupSymbol)k.next();
-                
-                for (Iterator i = source.keySet().iterator(); i.hasNext();) {
-                    PlanNode node = (PlanNode)i.next();
-                    
+        for (PlanNode critNode : crits) {
+        	for (GroupSymbol group : critNode.getGroups()) {
+        		for (PlanNode node : source.keySet()) {
                     if (node.getGroups().contains(group)) {
-                        Set sources = (Set)critieriaToSourceMap.get(critNode);
+                        Set<PlanNode> sources = critieriaToSourceMap.get(critNode);
                         if (sources == null) {
-                            sources = new HashSet();
+                            sources = new HashSet<PlanNode>();
                             critieriaToSourceMap.put(critNode, sources);
                         }
                         sources.add(node);
@@ -390,22 +368,18 @@
             return;
         }
         
-        Map dependentGroupToSourceMap = new HashMap();
+        Map<GroupSymbol, PlanNode> dependentGroupToSourceMap = new HashMap<GroupSymbol, PlanNode>();
         
-        for (Iterator i = dependentJoinSourceNodes.keySet().iterator(); i.hasNext();) {
-            PlanNode node = (PlanNode)i.next();
-            
-            for (Iterator j = node.getGroups().iterator(); j.hasNext();) {
-                GroupSymbol symbol = (GroupSymbol)j.next();
+        for (PlanNode node : dependentJoinSourceNodes.keySet()) {
+        	for (GroupSymbol symbol : node.getGroups()) {
                 dependentGroupToSourceMap.put(symbol, node);
             }
         }
         
-        for (Iterator i = getCriteriaNodes().iterator(); i.hasNext();) {
-            PlanNode node = (PlanNode)i.next();
+        for (Iterator<PlanNode> i = getCriteriaNodes().iterator(); i.hasNext();) {
+            PlanNode node = i.next();
             
-            for (Iterator j = node.getGroups().iterator(); j.hasNext();) {
-                GroupSymbol symbol = (GroupSymbol)j.next();
+            for (GroupSymbol symbol : node.getGroups()) {
                 if (dependentGroupToSourceMap.containsKey(symbol)) {
                     i.remove();
                     dependentCritieraNodes.add(node);
@@ -416,8 +390,7 @@
         
         dependentCriteriaElements = new HashMap<ElementSymbol, Set<Collection<GroupSymbol>>>();
         
-        for (Iterator i = dependentCritieraNodes.iterator(); i.hasNext();) {
-            PlanNode critNode = (PlanNode)i.next();
+        for (PlanNode critNode : dependentCritieraNodes) {
             Criteria crit = (Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
             if(!(crit instanceof CompareCriteria)) {
                 continue;
@@ -479,17 +452,15 @@
         return false;
     }
     
-    public List getJoinCriteriaForGroups(Set groups) {
+    public List<PlanNode> getJoinCriteriaForGroups(Set<GroupSymbol> groups) {
         return getJoinCriteriaForGroups(groups, getCriteriaNodes());
     }
     
     //TODO: this should be better than a linear search
-    protected List getJoinCriteriaForGroups(Set groups, Collection nodes) {
-        List result = new LinkedList();
+    protected List<PlanNode> getJoinCriteriaForGroups(Set<GroupSymbol> groups, Collection<PlanNode> nodes) {
+        List<PlanNode> result = new LinkedList<PlanNode>();
         
-        for (Iterator i = nodes.iterator(); i.hasNext();) {
-            PlanNode critNode = (PlanNode)i.next();
-            
+        for (PlanNode critNode : nodes) {
             if (groups.containsAll(critNode.getGroups())) {
                 result.add(critNode);
             }
@@ -499,12 +470,12 @@
     }
     
     public void changeJoinOrder(Object[] joinOrder) {
-        List joinSourceEntries = new ArrayList(joinSourceNodes.entrySet());
+        List<Map.Entry<PlanNode, PlanNode>> joinSourceEntries = new ArrayList<Map.Entry<PlanNode, PlanNode>>(joinSourceNodes.entrySet());
         
         for (int i = 0; i < joinOrder.length; i++) {
             Integer source = (Integer)joinOrder[i];
             
-            Map.Entry entry = (Map.Entry)joinSourceEntries.get(source.intValue());
+            Map.Entry<PlanNode, PlanNode> entry = joinSourceEntries.get(source.intValue());
             
             this.joinSourceNodes.remove(entry.getKey());
             this.joinSourceNodes.put(entry.getKey(), entry.getValue());

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -46,6 +46,8 @@
 import com.metamatrix.query.resolver.util.ResolverUtil;
 import com.metamatrix.query.sql.lang.Command;
 import com.metamatrix.query.sql.lang.Criteria;
+import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.StoredProcedure;
 import com.metamatrix.query.sql.symbol.AggregateSymbol;
 import com.metamatrix.query.sql.symbol.AliasSymbol;
@@ -147,11 +149,11 @@
 		    case NodeConstants.Types.SORT:
 		    	if (root.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
 		    		//add missing sort columns
-			    	List<SingleElementSymbol> elements = (List<SingleElementSymbol>) root.getProperty(NodeConstants.Info.SORT_ORDER);
+			    	OrderBy elements = (OrderBy) root.getProperty(NodeConstants.Info.SORT_ORDER);
 			    	outputElements = new ArrayList<SingleElementSymbol>(outputElements);
-			    	for (SingleElementSymbol singleElementSymbol : elements) {
-						if (!outputElements.contains(singleElementSymbol)) {
-							outputElements.add(singleElementSymbol);
+			    	for (OrderByItem item : elements.getOrderByItems()) {
+						if (!outputElements.contains(item.getSymbol())) {
+							outputElements.add(item.getSymbol());
 						}
 					}
 		    	}
@@ -235,15 +237,15 @@
         if (sort == null) {
         	return outputElements;
         }
-        List sortOrder = (List)sort.getProperty(NodeConstants.Info.SORT_ORDER);
+        OrderBy sortOrder = (OrderBy)sort.getProperty(NodeConstants.Info.SORT_ORDER);
         List<SingleElementSymbol> topCols = FrameUtil.findTopCols(sort);
         
         SymbolMap symbolMap = (SymbolMap)root.getProperty(NodeConstants.Info.SYMBOL_MAP);
         
         List<ElementSymbol> symbolOrder = symbolMap.getKeys();
         
-        for (final Iterator iterator = sortOrder.iterator(); iterator.hasNext();) {
-            final Expression expr = (Expression)iterator.next();
+        for (OrderByItem item : sortOrder.getOrderByItems()) {
+            final Expression expr = item.getSymbol();
             int index = topCols.indexOf(expr);
             ElementSymbol symbol = symbolOrder.get(index);
             if (!outputElements.contains(symbol)) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -87,24 +87,21 @@
 
             if(nonRelationalPlan != null) {
                 accessNode.setProperty(NodeConstants.Info.PROCESSOR_PLAN, nonRelationalPlan);
-            } else { 
-                // Create command from access on down and save in access node
-                if(command == null) {
-                	PlanNode commandRoot = accessNode;
-                	GroupSymbol intoGroup = (GroupSymbol)accessNode.getFirstChild().getProperty(NodeConstants.Info.INTO_GROUP);
-                	if (intoGroup != null) {
-                		commandRoot = NodeEditor.findNodePreOrder(accessNode, NodeConstants.Types.SOURCE).getFirstChild();
-                	}
-                    plan = removeUnnecessaryInlineView(plan, commandRoot);
-                    QueryCommand queryCommand = createQuery(metadata, capFinder, accessNode, commandRoot);
-                	addDistinct(metadata, capFinder, accessNode, queryCommand);
-                    command = queryCommand;
-                    if (intoGroup != null) {
-                    	Insert insertCommand = new Insert(intoGroup, ResolverUtil.resolveElementsInGroup(intoGroup, metadata), null);
-                    	insertCommand.setQueryExpression(queryCommand);
-                    	command = insertCommand;
-                    }
-                } 
+            } else if(command == null) {
+            	PlanNode commandRoot = accessNode;
+            	GroupSymbol intoGroup = (GroupSymbol)accessNode.getFirstChild().getProperty(NodeConstants.Info.INTO_GROUP);
+            	if (intoGroup != null) {
+            		commandRoot = NodeEditor.findNodePreOrder(accessNode, NodeConstants.Types.SOURCE).getFirstChild();
+            	}
+                plan = removeUnnecessaryInlineView(plan, commandRoot);
+                QueryCommand queryCommand = createQuery(metadata, capFinder, accessNode, commandRoot);
+            	addDistinct(metadata, capFinder, accessNode, queryCommand);
+                command = queryCommand;
+                if (intoGroup != null) {
+                	Insert insertCommand = new Insert(intoGroup, ResolverUtil.resolveElementsInGroup(intoGroup, metadata), null);
+                	insertCommand.setQueryExpression(queryCommand);
+                	command = insertCommand;
+                }
             }
     		accessNode.setProperty(NodeConstants.Info.ATOMIC_REQUEST, command);
     		accessNode.removeAllChildren();
@@ -417,10 +414,7 @@
     }
     
 	private void processOrderBy(PlanNode node, QueryCommand query) {
-		List params = (List)node.getProperty(NodeConstants.Info.SORT_ORDER);
-		List types = (List)node.getProperty(NodeConstants.Info.ORDER_TYPES);
-		OrderBy orderBy = new OrderBy(params, types);
-		query.setOrderBy(orderBy);
+		query.setOrderBy((OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER));
 	}
 
    /**

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -24,7 +24,6 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
@@ -122,10 +121,8 @@
         
         boolean needsCorrection = outputSymbols.size() > oldSize;
                 
-        List<Boolean> directions = Collections.nCopies(orderSymbols.size(), OrderBy.ASC);
+        PlanNode sortNode = createSortNode(new ArrayList<SingleElementSymbol>(orderSymbols), outputSymbols);
         
-        PlanNode sortNode = createSortNode(orderSymbols, outputSymbols, directions);
-        
         if (sourceNode.getType() == NodeConstants.Types.ACCESS) {
         	if (NewCalculateCostUtil.usesKey(sourceNode, expressions, metadata)) {
                 joinNode.setProperty(joinNode.getFirstChild() == childNode ? NodeConstants.Info.IS_LEFT_DISTINCT : NodeConstants.Info.IS_RIGHT_DISTINCT, true);
@@ -151,13 +148,11 @@
         return false;
     }
 
-    private static PlanNode createSortNode(Collection orderSymbols,
-                                           Collection outputElements,
-                                           List directions) {
+    private static PlanNode createSortNode(List<SingleElementSymbol> orderSymbols,
+                                           Collection outputElements) {
         PlanNode sortNode = NodeFactory.getNewNode(NodeConstants.Types.SORT);
-        sortNode.setProperty(NodeConstants.Info.SORT_ORDER, new ArrayList(orderSymbols));
+        sortNode.setProperty(NodeConstants.Info.SORT_ORDER, new OrderBy(orderSymbols));
         sortNode.setProperty(NodeConstants.Info.OUTPUT_COLS, new ArrayList(outputElements));
-        sortNode.setProperty(NodeConstants.Info.ORDER_TYPES, directions);
         return sortNode;
     }
 

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -42,6 +42,8 @@
 import com.metamatrix.query.optimizer.relational.plantree.NodeEditor;
 import com.metamatrix.query.optimizer.relational.plantree.PlanNode;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.symbol.ElementSymbol;
 import com.metamatrix.query.sql.symbol.Expression;
 import com.metamatrix.query.sql.symbol.Function;
@@ -244,14 +246,12 @@
         PlanNode sort = NodeEditor.findParent(parentProject, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
         if (sort != null) { //special handling is needed since we are retaining the child aliases
         	List<SingleElementSymbol> childProject = (List<SingleElementSymbol>)NodeEditor.findNodePreOrder(frame, NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS);
-        	List<SingleElementSymbol> elements = (List<SingleElementSymbol>)sort.getProperty(NodeConstants.Info.SORT_ORDER);
-        	List<SingleElementSymbol> newElements = new ArrayList<SingleElementSymbol>(elements.size());
-        	for (SingleElementSymbol singleElementSymbol : elements) {
-				newElements.add(childProject.get(selectSymbols.indexOf(singleElementSymbol)));
+        	OrderBy elements = (OrderBy)sort.getProperty(NodeConstants.Info.SORT_ORDER);
+        	for (OrderByItem item : elements.getOrderByItems()) {
+				item.setSymbol(childProject.get(selectSymbols.indexOf(item.getSymbol())));
 			}
-            sort.setProperty(NodeConstants.Info.SORT_ORDER, newElements);
             sort.getGroups().clear();
-            sort.addGroups(GroupsUsedByElementsVisitor.getGroups(newElements));
+            sort.addGroups(GroupsUsedByElementsVisitor.getGroups(elements));
         }
         
         prepareFrame(frame);

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -38,7 +38,9 @@
 import com.metamatrix.query.optimizer.relational.plantree.NodeConstants.Info;
 import com.metamatrix.query.processor.relational.JoinNode.JoinStrategyType;
 import com.metamatrix.query.processor.relational.MergeJoinStrategy.SortOption;
+import com.metamatrix.query.sql.lang.OrderBy;
 import com.metamatrix.query.sql.lang.SetQuery;
+import com.metamatrix.query.sql.symbol.SingleElementSymbol;
 import com.metamatrix.query.util.CommandContext;
 
 /**
@@ -74,7 +76,7 @@
 			if (mergeSortWithDupRemoval(node)) {
 				node.setProperty(NodeConstants.Info.IS_DUP_REMOVAL, true);
 			}
-			List orderColumns = (List)node.getProperty(NodeConstants.Info.SORT_ORDER);
+			List<SingleElementSymbol> orderColumns = ((OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER)).getSortKeys();
 			PlanNode possibleSort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE | NodeConstants.Types.ACCESS);
 			if (possibleSort != null) {
 				List exprs = (List)possibleSort.getProperty(Info.GROUP_COLS);

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -58,10 +58,12 @@
 import com.metamatrix.query.resolver.util.ResolverVisitor;
 import com.metamatrix.query.rewriter.QueryRewriter;
 import com.metamatrix.query.sql.ReservedWords;
+import com.metamatrix.query.sql.LanguageObject.Util;
 import com.metamatrix.query.sql.lang.CompareCriteria;
 import com.metamatrix.query.sql.lang.Criteria;
 import com.metamatrix.query.sql.lang.IsNullCriteria;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
 import com.metamatrix.query.sql.lang.Select;
 import com.metamatrix.query.sql.lang.SetQuery.Operation;
 import com.metamatrix.query.sql.symbol.AggregateSymbol;
@@ -294,8 +296,10 @@
 		//branches other than the first need to have their projected column names updated
 		PlanNode sortNode = NodeEditor.findNodePreOrder(unionSource, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
 		List<SingleElementSymbol> sortOrder = null;
+		OrderBy orderBy = null;
 		if (sortNode != null) {
-			sortOrder = (List<SingleElementSymbol>)sortNode.getProperty(Info.SORT_ORDER);
+			orderBy = (OrderBy)sortNode.getProperty(Info.SORT_ORDER);
+			sortOrder = orderBy.getSortKeys();
 		}
 		List<SingleElementSymbol> projectCols = FrameUtil.findTopCols(unionSource);
 		for (int i = 0; i < virtualElements.size(); i++) {
@@ -306,6 +310,7 @@
 					int sortIndex = sortOrder.indexOf(projectedSymbol);
 					if (sortIndex > -1) {
 						updateSymbolName(sortOrder, sortIndex, virtualElem, sortOrder.get(sortIndex));
+						orderBy.getOrderByItems().get(sortIndex).setSymbol(sortOrder.get(sortIndex));
 					}
 				}
 				updateSymbolName(projectCols, i, virtualElem, projectedSymbol);
@@ -336,7 +341,7 @@
 			}
         }
 
-        List<SingleElementSymbol> projectedViewSymbols = QueryRewriter.deepClone(projectedSymbols, SingleElementSymbol.class);
+        List<SingleElementSymbol> projectedViewSymbols = Util.deepClone(projectedSymbols);
 
         SymbolMap viewMapping = SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedSymbols, metadata);
         for (AggregateSymbol agg : aggregates) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -47,6 +47,7 @@
 import com.metamatrix.query.sql.lang.CompareCriteria;
 import com.metamatrix.query.sql.lang.Criteria;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
 import com.metamatrix.query.sql.lang.SetQuery.Operation;
 import com.metamatrix.query.sql.symbol.AggregateSymbol;
 import com.metamatrix.query.sql.symbol.ElementSymbol;
@@ -255,9 +256,9 @@
             return false;
         } 
         
-        List sortCols = (List)parentNode.getProperty(NodeConstants.Info.SORT_ORDER);
-        for (int i = 0; i < sortCols.size(); i++) {
-            SingleElementSymbol symbol = (SingleElementSymbol)sortCols.get(i);
+        //TODO: this check shouldn't be necessary, since the order by is not introducing new expressions
+        List<SingleElementSymbol> sortCols = ((OrderBy)parentNode.getProperty(NodeConstants.Info.SORT_ORDER)).getSortKeys();
+        for (SingleElementSymbol symbol : sortCols) {
             if(! canPushSymbol(symbol, true, modelID, metadata, capFinder)) {
                 return false;
             }

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -40,6 +40,8 @@
 import com.metamatrix.query.optimizer.relational.plantree.NodeFactory;
 import com.metamatrix.query.optimizer.relational.plantree.PlanNode;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.SetQuery;
 import com.metamatrix.query.sql.symbol.AliasSymbol;
 import com.metamatrix.query.sql.symbol.ExpressionSymbol;
@@ -159,11 +161,11 @@
                     PlanNode sort = NodeEditor.findParent(firstProject, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
                     
                     if (sort != null) { //correct the sort to the new columns as well
-                        List<SingleElementSymbol> sortOrder = (List<SingleElementSymbol>)sort.getProperty(NodeConstants.Info.SORT_ORDER);
-                        for (int i = 0; i < sortOrder.size(); i++) {
-                            SingleElementSymbol sortElement = sortOrder.get(i);
+                        OrderBy sortOrder = (OrderBy)sort.getProperty(NodeConstants.Info.SORT_ORDER);
+                        for (OrderByItem item : sortOrder.getOrderByItems()) {
+                            SingleElementSymbol sortElement = item.getSymbol();
                             sortElement = newProjectSymbols.get(oldProjectSymbols.indexOf(sortElement));
-                            sortOrder.set(i, sortElement);
+                            item.setSymbol(sortElement);
                         }
                     }
                     

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -45,6 +45,7 @@
 import com.metamatrix.query.sql.ReservedWords;
 import com.metamatrix.query.sql.lang.Criteria;
 import com.metamatrix.query.sql.lang.JoinType;
+import com.metamatrix.query.sql.lang.OrderBy;
 import com.metamatrix.query.sql.symbol.AggregateSymbol;
 import com.metamatrix.query.sql.symbol.Constant;
 import com.metamatrix.query.sql.symbol.ElementSymbol;
@@ -163,7 +164,7 @@
             case NodeConstants.Types.SORT:
             {
                 if (elements != null) {
-                    List sortOrder = (List)node.getProperty(NodeConstants.Info.SORT_ORDER);
+                    OrderBy sortOrder = (OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
                     ElementCollectorVisitor.getElements(sortOrder, elements);
                 }
                 break;

Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -305,7 +305,7 @@
             return;
         }
         
-        List elements = orderBy.getVariables();
+        List elements = orderBy.getSortKeys();
 		List types = orderBy.getTypes();
 
 		for (int i = 0; i< elements.size(); i++) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -104,7 +104,7 @@
         clone.setVariable(this.variable);
         clone.setExpression(this.expression);
         if (processPlan != null) {
-            clone.setProcessPlan((ProcessorPlan)getProcessPlan().clone());
+            clone.setProcessPlan(getProcessPlan().clone());
         }
     }
 

Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -137,7 +137,7 @@
      * @return True if the ORDER BY contains the element
      */
     public static boolean orderByContainsVariable(OrderBy orderBy, SingleElementSymbol ses, int position) {
-        for (final Iterator iterator = orderBy.getVariables().iterator(); iterator.hasNext();) {
+        for (final Iterator iterator = orderBy.getSortKeys().iterator(); iterator.hasNext();) {
             final ElementSymbol element = (ElementSymbol)iterator.next();
             if (position == ((TempMetadataID)element.getMetadataID()).getPosition()) {
                 return true;

Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -354,9 +354,6 @@
                 	index = expressions.indexOf(SymbolMap.getExpression(sortKey));
                 }
                 orderBy.setExpressionPosition(i, index);
-                if (index == -1) {
-                	orderBy.addUnrelated((ElementSymbol)sortKey);
-                }
                 continue;
         	} else if (sortKey instanceof ExpressionSymbol) {
         		// check for legacy positional
@@ -369,6 +366,7 @@
             		    throw new QueryResolverException(QueryPlugin.Util.getString("SQLParser.non_position_constant", c)); //$NON-NLS-1$
         		    }
         		    orderBy.setExpressionPosition(i, elementOrder - 1);
+        		    continue;
         		}
         	}
         	//handle order by expressions        	
@@ -380,13 +378,9 @@
     					isSimpleQuery, knownShortNames, symbol); 
 			}
             ResolverVisitor.resolveLanguageObject(sortKey, metadata);
-            int index = expressions.indexOf(SymbolMap.getExpression(sortKey));
             
-            if (index != -1) {
-    			//the query is using an derived column, but not through an alias
-    			orderBy.setExpressionPosition(i, index);
-    		} 
-            //must be an unrelated sort expression
+            int index = expressions.indexOf(SymbolMap.getExpression(sortKey));
+        	orderBy.setExpressionPosition(i, index);
         }
     }
     

Modified: trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -35,6 +35,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -64,6 +65,7 @@
 import com.metamatrix.query.function.FunctionMethods;
 import com.metamatrix.query.metadata.QueryMetadataInterface;
 import com.metamatrix.query.metadata.TempMetadataAdapter;
+import com.metamatrix.query.metadata.TempMetadataID;
 import com.metamatrix.query.metadata.TempMetadataStore;
 import com.metamatrix.query.processor.ProcessorDataManager;
 import com.metamatrix.query.processor.relational.DependentValueSource;
@@ -73,6 +75,7 @@
 import com.metamatrix.query.sql.LanguageObject;
 import com.metamatrix.query.sql.ProcedureReservedWords;
 import com.metamatrix.query.sql.ReservedWords;
+import com.metamatrix.query.sql.LanguageObject.Util;
 import com.metamatrix.query.sql.lang.AbstractSetCriteria;
 import com.metamatrix.query.sql.lang.BatchedUpdateCommand;
 import com.metamatrix.query.sql.lang.BetweenCriteria;
@@ -95,6 +98,7 @@
 import com.metamatrix.query.sql.lang.MatchCriteria;
 import com.metamatrix.query.sql.lang.NotCriteria;
 import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.QueryCommand;
 import com.metamatrix.query.sql.lang.SPParameter;
@@ -796,10 +800,12 @@
         
         boolean hasUnrelatedExpression = false;
         
+        LinkedList<OrderByItem> unrelatedItems = new LinkedList<OrderByItem>();
         for (int i = 0; i < orderBy.getVariableCount(); i++) {
         	SingleElementSymbol querySymbol = orderBy.getVariable(i);
         	int index = orderBy.getExpressionPosition(i);
         	if (index == -1) {
+    			unrelatedItems.add(orderBy.getOrderByItems().get(i));
         		hasUnrelatedExpression |= (querySymbol instanceof ExpressionSymbol);
         	  	continue; // must be unrelated - but potentially contains references to the select clause
         	}
@@ -808,7 +814,7 @@
         	if (!previousExpressions.add(expr) || (queryCommand instanceof Query && EvaluatableVisitor.isFullyEvaluatable(expr, true))) {
                 orderBy.removeOrderByItem(i--);
         	} else {
-        		orderBy.getVariables().set(i, querySymbol.clone());
+        		orderBy.getOrderByItems().get(i).setSymbol((SingleElementSymbol)querySymbol.clone());
         	}
         }
         
@@ -824,7 +830,14 @@
         int originalSymbolCount = select.getProjectedSymbols().size();
 
         //add unrelated to select
-        select.addSymbols(orderBy.getUnrelated());
+        for (OrderByItem orderByItem : unrelatedItems) {
+        	Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(orderByItem.getSymbol(), true);
+        	for (ElementSymbol elementSymbol : elements) {
+        		if (!(elementSymbol.getMetadataID() instanceof TempMetadataID) || ((TempMetadataID)elementSymbol.getMetadataID()).getPosition() == -1) {
+                    select.addSymbol(elementSymbol);				
+        		}
+			}
+		}
         makeSelectUnique(select, false);
         
         Query query = queryCommand.getProjectedQuery();
@@ -871,12 +884,7 @@
 		} catch (MetaMatrixComponentException e) {
 			throw new QueryValidatorException(e, e.getMessage());
 		}
-		//filter back out the unrelated
-		orderBy.getUnrelated().clear();
 		List symbols = top.getSelect().getSymbols();
-		for (ElementSymbol symbol : (List<ElementSymbol>)symbols.subList(originalSymbolCount, symbols.size())) {
-			orderBy.addUnrelated(symbol);
-		}
 		top.getSelect().setSymbols(symbols.subList(0, originalSymbolCount));
 		top.setInto(into);
 		top.setLimit(limit);
@@ -894,7 +902,7 @@
     private Insert rewriteSelectInto(Query query) throws QueryValidatorException {
         Into into = query.getInto();
         try {
-            List<ElementSymbol> allIntoElements = deepClone(ResolverUtil.resolveElementsInGroup(into.getGroup(), metadata), ElementSymbol.class);
+            List<ElementSymbol> allIntoElements = Util.deepClone(ResolverUtil.resolveElementsInGroup(into.getGroup(), metadata));
             Insert insert = new Insert(into.getGroup(), allIntoElements, Collections.emptyList());
             query.setInto(null);
             insert.setQueryExpression(query);
@@ -2408,14 +2416,6 @@
         return query;
     }    
     
-    public static <S extends Expression, T extends S> List<S> deepClone(List<T> collection, Class<S> clazz) {
-    	ArrayList<S> result = new ArrayList<S>(collection.size());
-    	for (Expression expression : collection) {
-			result.add((S)expression.clone());
-		}
-    	return result;
-    }
-    
     public static void makeSelectUnique(Select select, boolean expressionSymbolsOnly) {
         
         select.setSymbols(select.getProjectedSymbols());

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -23,6 +23,8 @@
 package com.metamatrix.query.sql;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This is the primary interface for all language objects.  It extends a few 
@@ -43,5 +45,18 @@
 	 * @return Deep clone of this object
 	 */
     Object clone();
+    
+    public static class Util {
+
+		@SuppressWarnings("unchecked")
+		public static <S extends LanguageObject, T extends S> ArrayList<S> deepClone(List<T> collection) {
+			ArrayList<S> result = new ArrayList<S>(collection.size());
+			for (LanguageObject obj : collection) {
+				result.add((S)obj.clone());
+			}
+			return result;
+		}
+    	
+    }
     	 
 }

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -125,4 +125,5 @@
     public void visit(ProcedureContainer obj) {}
     public void visit(SetClauseList obj) {}
     public void visit(SetClause obj) {}
+    public void visit(OrderByItem obj) {}
 }

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -23,22 +23,15 @@
 package com.metamatrix.query.sql.lang;
 
 import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Set;
 
 import com.metamatrix.core.util.EquivalenceUtil;
 import com.metamatrix.core.util.HashCodeUtil;
-import com.metamatrix.query.QueryPlugin;
 import com.metamatrix.query.sql.LanguageObject;
 import com.metamatrix.query.sql.LanguageVisitor;
-import com.metamatrix.query.sql.symbol.ElementSymbol;
 import com.metamatrix.query.sql.symbol.SingleElementSymbol;
 import com.metamatrix.query.sql.visitor.SQLStringVisitor;
-import com.metamatrix.query.util.ErrorMessageKeys;
 
 /**
  * Represents the ORDER BY clause of a query.  The ORDER BY clause states
@@ -55,42 +48,34 @@
 	/** Constant for the descending value */
     public static final boolean DESC = false;
 
-	private List sortOrder;
-    private List orderTypes;
+    private List<OrderByItem> orderByItems = new ArrayList<OrderByItem>();
+    
     /**
-     * set by the resolver to contain element symbol references 
-     * outside of the select clause
-     */
-    private Set<ElementSymbol> unrelated; 
-    private List<Integer> expressionPositions;
-    /**
      * Constructs a default instance of this class.
      */
     public OrderBy() {
-    	sortOrder = new ArrayList();
-        orderTypes = new ArrayList();
     }
 
     /**
-     * Constructs an instance of this class from an ordered set of elements.
+     * Constructs an instance of this class from an ordered list of elements.
      * @param parameters The ordered list of SingleElementSymbol
      */
-    public OrderBy( List parameters ) {
-        sortOrder = new ArrayList( parameters );
-        orderTypes = new ArrayList(parameters.size());
-        for( int i=0; i< parameters.size(); i++) {
-        	orderTypes.add(Boolean.TRUE);
-        }
+    public OrderBy( List<? extends SingleElementSymbol> parameters ) {
+    	for (SingleElementSymbol singleElementSymbol : parameters) {
+			orderByItems.add(new OrderByItem(singleElementSymbol, ASC));
+		}
     }
-
+    
     /**
      * Constructs an instance of this class from an ordered set of elements.
      * @param parameters The ordered list of SingleElementSymbol
      * @param types The list of directions by which the results are ordered (Boolean, true=ascending)
      */
-    public OrderBy( List parameters, List types ) {
-        sortOrder = new ArrayList( parameters );
-        orderTypes = new ArrayList( types );
+    public OrderBy( List<? extends SingleElementSymbol> parameters, List<Boolean> types ) {
+    	Iterator<Boolean> typeIter = types.iterator();
+    	for (SingleElementSymbol singleElementSymbol : parameters) {
+			orderByItems.add(new OrderByItem(singleElementSymbol, typeIter.next()));
+		}
     }
 
     // =========================================================================
@@ -101,32 +86,20 @@
      * @return Number of variables in ORDER BY
      */
     public int getVariableCount() {
-        return sortOrder.size();
+        return orderByItems.size();
     }
-
-    /**
-     * Returns an ordered list of the symbols in ORDER BY
-     * @param List of SingleElementSymbol in ORDER BY
-     */
-    public List getVariables() {
-        return sortOrder;
+    
+    public List<OrderByItem> getOrderByItems() {
+    	return this.orderByItems;
     }
 
     /**
-     * Returns an ordered list of sort direction for each order.
-     * @param List of Boolean, Boolean.TRUE represents ascending
-     */
-    public List getTypes() {
-        return orderTypes;
-    }
-
-    /**
      * Returns the ORDER BY element at the specified index.
      * @param index Index to get
      * @return The element at the index
      */
     public SingleElementSymbol getVariable( int index ) {
-        return (SingleElementSymbol)sortOrder.get(index);
+        return orderByItems.get(index).getSymbol();
     }
 
     /**
@@ -135,7 +108,7 @@
      * @return The sort order at the index
      */
     public Boolean getOrderType( int index ) {
-        return (Boolean)orderTypes.get(index);
+        return orderByItems.get(index).isAscending();
     }
 
     /**
@@ -143,10 +116,7 @@
      * @param element Element to add
      */
     public void addVariable( SingleElementSymbol element ) {
-    	if(element != null) {
-	        sortOrder.add(element);
-            orderTypes.add(Boolean.valueOf(ASC));
-        }
+    	addVariable(element, ASC);
     }
 
     /**
@@ -157,28 +127,10 @@
      */
     public void addVariable( SingleElementSymbol element, boolean type ) {
     	if(element != null) {
-	        sortOrder.add(element);
-            orderTypes.add(Boolean.valueOf(type));
+            orderByItems.add(new OrderByItem(element, type));
         }
     }
     
-    /**
-     * Sets a new collection of variables to be used.  The replacement
-     * set must be of the same size as the previous set.
-     * @param elements Collection of SingleElementSymbol
-     * @throws IllegalArgumentException if element is null or size of elements != size of existing elements
-     */
-    public void replaceVariables( Collection elements ) {
-		if(elements == null) {
-            throw new IllegalArgumentException(QueryPlugin.Util.getString(ErrorMessageKeys.SQL_0004));
-		}
-		if(elements.size() != sortOrder.size()) {
-            throw new IllegalArgumentException(QueryPlugin.Util.getString(ErrorMessageKeys.SQL_0005));
-		}
-
-        sortOrder = new ArrayList(elements);
-    }
-
     public void acceptVisitor(LanguageVisitor visitor) {
         visitor.visit(this);
     }
@@ -190,26 +142,10 @@
     /**
      * Return deep copy of this ORDER BY clause.
      */
-    public Object clone() {
-	    List thisSymbols = getVariables();
-	    List copySymbols = new ArrayList(thisSymbols.size());
-	    Iterator iter = thisSymbols.iterator();
-	    while(iter.hasNext()) {
-	    	SingleElementSymbol ses = (SingleElementSymbol) iter.next();
-	    	copySymbols.add(ses.clone());
-	    }
-		OrderBy result = new OrderBy(copySymbols, getTypes());
-		if (this.unrelated != null) {
-			HashSet<ElementSymbol> copyUnrelated = new HashSet<ElementSymbol>();
-			for (ElementSymbol elementSymbol : this.unrelated) {
-				copyUnrelated.add((ElementSymbol)elementSymbol.clone());
-			}
-			result.unrelated = copyUnrelated;
-		}
-		if (this.expressionPositions != null) {
-			result.expressionPositions = new ArrayList<Integer>(expressionPositions);
-		}
-        return result;
+    public OrderBy clone() {
+    	OrderBy clone = new OrderBy();
+    	clone.orderByItems = LanguageObject.Util.deepClone(this.orderByItems);
+        return clone;
 	}
 
 	/**
@@ -228,8 +164,7 @@
 		}
 
 		OrderBy other = (OrderBy) obj;
-        return EquivalenceUtil.areEqual(getVariables(), other.getVariables()) &&
-               EquivalenceUtil.areEqual(getTypes(), other.getTypes());
+        return EquivalenceUtil.areEqual(orderByItems, other.orderByItems);
 	}
 
 	/**
@@ -240,10 +175,7 @@
 	 * @return Hash code
 	 */
 	public int hashCode() {
-        int hc = 0;
-		hc = HashCodeUtil.hashCode(0, getVariables());
-        hc = HashCodeUtil.hashCode(hc, getTypes());
-        return hc;
+        return HashCodeUtil.hashCode(0, orderByItems);
 	}
 
     /**
@@ -254,42 +186,45 @@
     	return SQLStringVisitor.getSQLString(this);
     }
 
-    public boolean hasUnrelated() {
-		return this.unrelated != null;
-	}
-    
-    public void addUnrelated(ElementSymbol symbol) {
-    	if (this.unrelated == null) {
-    		this.unrelated = new HashSet<ElementSymbol>();
-    	}
-    	this.unrelated.add(symbol);
-	}
-    
-    public Set<ElementSymbol> getUnrelated() {
-    	if (this.unrelated == null) {
-    		return Collections.emptySet();
-    	}
-		return unrelated;
-	}
-    
     public void setExpressionPosition(int orderIndex, int selectIndex) {
-    	if (this.expressionPositions == null) {
-    		this.expressionPositions = new ArrayList<Integer>(Collections.nCopies(sortOrder.size(), -1));
-    	}
-    	this.expressionPositions.set(orderIndex, selectIndex);
+    	this.orderByItems.get(orderIndex).setExpressionPosition(selectIndex);
     }
     
     public int getExpressionPosition(int orderIndex) {
-    	if (expressionPositions == null) {
-    		return -1;
-    	}
-		return expressionPositions.get(orderIndex);
+    	return this.orderByItems.get(orderIndex).getExpressionPosition();
 	}
     
     public void removeOrderByItem(int index) {
-        sortOrder.remove(index);
-        orderTypes.remove(index);
-        expressionPositions.remove(index);
+        this.orderByItems.remove(index);
     }
     
+    public boolean hasUnrelated() {
+    	for (OrderByItem item : orderByItems) {
+			if (item.isUnrelated()) {
+				return true;
+			}
+		}
+    	return false;
+    }
+    
+    /**
+     * Get the list or sort key symbols.  Modifications to this list will not add or remove {@link OrderByItem}s.
+     * @return
+     */
+    public List<SingleElementSymbol> getSortKeys() {
+    	ArrayList<SingleElementSymbol> result = new ArrayList<SingleElementSymbol>(orderByItems.size());
+    	for (OrderByItem item : orderByItems) {
+			result.add(item.getSymbol());
+		}
+    	return result;
+    }
+    
+    public List<Boolean> getTypes() {
+    	ArrayList<Boolean> result = new ArrayList<Boolean>(orderByItems.size());
+    	for (OrderByItem item : orderByItems) {
+			result.add(item.isAscending());
+		}
+    	return result;
+    }
+    
 }

Added: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java	                        (rev 0)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -0,0 +1,109 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package com.metamatrix.query.sql.lang;
+
+import com.metamatrix.query.sql.LanguageObject;
+import com.metamatrix.query.sql.LanguageVisitor;
+import com.metamatrix.query.sql.symbol.SingleElementSymbol;
+import com.metamatrix.query.sql.visitor.SQLStringVisitor;
+
+public class OrderByItem implements LanguageObject {
+	
+	private static final long serialVersionUID = 6937561370697819126L;
+	
+	private Integer expressionPosition; //set during resolving to the select clause position
+	private boolean ascending = true;
+	private SingleElementSymbol symbol;
+
+	public OrderByItem(SingleElementSymbol symbol, boolean ascending) {
+		this.symbol = symbol;
+		this.ascending = ascending;
+	}
+	
+	public int getExpressionPosition() {
+		return expressionPosition == null?-1:expressionPosition;
+	}
+
+	public void setExpressionPosition(int expressionPosition) {
+		this.expressionPosition = expressionPosition;
+	}
+
+	public boolean isAscending() {
+		return ascending;
+	}
+
+	public void setAscending(boolean ascending) {
+		this.ascending = ascending;
+	}
+
+	public SingleElementSymbol getSymbol() {
+		return symbol;
+	}
+
+	public void setSymbol(SingleElementSymbol symbol) {
+		this.symbol = symbol;
+	}
+
+	/**
+	 * 
+	 * @return true if the expression does not appear in the select clause
+	 */
+	public boolean isUnrelated() {
+		return expressionPosition != null && expressionPosition == -1;
+	}
+
+	@Override
+	public void acceptVisitor(LanguageVisitor visitor) {
+		visitor.visit(this);
+	}
+	
+	@Override
+	public OrderByItem clone() {
+		OrderByItem clone = new OrderByItem((SingleElementSymbol)this.symbol.clone(), ascending);
+		clone.expressionPosition = this.expressionPosition;
+		return clone;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (!(obj instanceof OrderByItem)) {
+			return false;
+		}
+		OrderByItem o = (OrderByItem)obj;
+		return o.symbol.equals(symbol) && o.ascending == this.ascending;
+	}
+	
+	@Override
+	public int hashCode() {
+		return symbol.hashCode();
+	}
+	
+	@Override
+	public String toString() {
+		return SQLStringVisitor.getSQLString(this);
+	}
+	
+}


Property changes on: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -49,6 +49,7 @@
 import com.metamatrix.query.sql.lang.NotCriteria;
 import com.metamatrix.query.sql.lang.Option;
 import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.SPParameter;
 import com.metamatrix.query.sql.lang.Select;
@@ -350,9 +351,15 @@
     }
     public void visit(OrderBy obj) {
         preVisitVisitor(obj);
-        visitNodes(obj.getVariables());
+        visitNodes(obj.getOrderByItems());
         postVisitVisitor(obj);
     }
+    @Override
+    public void visit(OrderByItem obj) {
+    	preVisitVisitor(obj);
+        visitNode(obj.getSymbol());
+        postVisitVisitor(obj);
+    }
     public void visit(Query obj) {
         preVisitVisitor(obj);
         visitNode(obj.getSelect());

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -41,7 +41,7 @@
 import com.metamatrix.query.sql.lang.IsNullCriteria;
 import com.metamatrix.query.sql.lang.Limit;
 import com.metamatrix.query.sql.lang.MatchCriteria;
-import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.SPParameter;
 import com.metamatrix.query.sql.lang.Select;
 import com.metamatrix.query.sql.lang.SetClause;
@@ -90,29 +90,35 @@
             
             if (symbol instanceof SingleElementSymbol) {
                 SingleElementSymbol ses = (SingleElementSymbol)symbol;
-                SingleElementSymbol replacmentSymbol = null; 
-
-                Expression expr = ses;
-                if (ses instanceof ExpressionSymbol && !(ses instanceof AggregateSymbol)) {
-                    expr = ((ExpressionSymbol)ses).getExpression();
-                }
+                SingleElementSymbol replacmentSymbol = replaceSymbol(ses, alias);
                 
-                Expression replacement = replaceExpression(expr);
-                
-                if (replacement instanceof SingleElementSymbol) {
-                    replacmentSymbol = (SingleElementSymbol)replacement;
-                } else {
-                    replacmentSymbol = new ExpressionSymbol(ses.getName(), replacement);
-                }
-                
-                if (alias && createAliases() && !replacmentSymbol.getShortCanonicalName().equals(ses.getShortCanonicalName())) {
-                    replacmentSymbol = new AliasSymbol(ses.getShortName(), replacmentSymbol);
-                }
-                
                 symbols.set(i, replacmentSymbol);
             }
         }
     }
+
+	private SingleElementSymbol replaceSymbol(SingleElementSymbol ses,
+			boolean alias) {
+		SingleElementSymbol replacmentSymbol = null; 
+
+		Expression expr = ses;
+		if (ses instanceof ExpressionSymbol && !(ses instanceof AggregateSymbol)) {
+		    expr = ((ExpressionSymbol)ses).getExpression();
+		}
+		
+		Expression replacement = replaceExpression(expr);
+		
+		if (replacement instanceof SingleElementSymbol) {
+		    replacmentSymbol = (SingleElementSymbol)replacement;
+		} else {
+		    replacmentSymbol = new ExpressionSymbol(ses.getName(), replacement);
+		}
+		
+		if (alias && createAliases() && !replacmentSymbol.getShortCanonicalName().equals(ses.getShortCanonicalName())) {
+		    replacmentSymbol = new AliasSymbol(ses.getShortName(), replacmentSymbol);
+		}
+		return replacmentSymbol;
+	}
     
     /** 
      * @see com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.symbol.AliasSymbol)
@@ -265,12 +271,9 @@
         replaceSymbols(obj.getSymbols(), false);
     }
     
-    /**
-     * Swap each SingleElementSymbol in OrderBy (other symbols are ignored).
-     * @param obj Object to remap
-     */
-    public void visit(OrderBy obj) {
-        replaceSymbols(obj.getVariables(), true);        
+    @Override
+    public void visit(OrderByItem obj) {
+    	obj.setSymbol(replaceSymbol(obj.getSymbol(), true));
     }
     
     public void visit(Limit obj) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -58,6 +58,7 @@
 import com.metamatrix.query.sql.lang.NotCriteria;
 import com.metamatrix.query.sql.lang.Option;
 import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.PredicateCriteria;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.QueryCommand;
@@ -697,29 +698,28 @@
         parts.add(SPACE);
         parts.add(ReservedWords.BY);
 		parts.add(SPACE);
-
-        List variables = obj.getVariables();
-        List types = obj.getTypes();
-        Iterator iter = variables.iterator();
-        Iterator typeIter = types.iterator();
-        while ( iter.hasNext() ) {
-		    SingleElementSymbol ses = (SingleElementSymbol)iter.next();
-		    if (ses instanceof AliasSymbol) {
-		    	AliasSymbol as = (AliasSymbol)ses;
-		    	outputDisplayName(as.getOutputName());
-		    } else {
-		    	parts.add(registerNode(ses));
-		    }
-            Boolean type = (Boolean) typeIter.next();
-            if( type.booleanValue() == OrderBy.DESC ) {
-                parts.add(SPACE);
-                parts.add(ReservedWords.DESC);
-            } // Don't print default "ASC"
-
-            if (iter.hasNext()) {
-                parts.add( ", " ); //$NON-NLS-1$
-            }
+		for (Iterator<OrderByItem> iterator = obj.getOrderByItems().iterator(); iterator.hasNext();) {
+			OrderByItem item = iterator.next();
+			parts.add(registerNode(item));
+			if (iterator.hasNext()) {
+				parts.add( ", " ); //$NON-NLS-1$				
+			}
+		}
+    }
+    
+    @Override
+    public void visit(OrderByItem obj) {
+    	SingleElementSymbol ses = obj.getSymbol();
+	    if (ses instanceof AliasSymbol) {
+	    	AliasSymbol as = (AliasSymbol)ses;
+	    	outputDisplayName(as.getOutputName());
+	    } else {
+	    	parts.add(registerNode(ses));
 	    }
+        if(!obj.isAscending()) {
+            parts.add(SPACE);
+            parts.add(ReservedWords.DESC);
+        } // Don't print default "ASC"
     }
     
     public void visit(DynamicCommand obj) {

Modified: trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -64,6 +64,7 @@
 import com.metamatrix.query.sql.lang.NotCriteria;
 import com.metamatrix.query.sql.lang.Option;
 import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.QueryCommand;
 import com.metamatrix.query.sql.lang.Select;
@@ -203,8 +204,9 @@
         validateInsert(obj);
     }
 
-    public void visit(OrderBy obj) {
-        validateSortable(obj.getVariables());
+    @Override
+    public void visit(OrderByItem obj) {
+    	validateSortable(obj.getSymbol());
     }
     
     public void visit(Query obj) {
@@ -605,12 +607,16 @@
         Iterator iter = symbols.iterator();
         while(iter.hasNext()) {
             SingleElementSymbol symbol = (SingleElementSymbol) iter.next();
-            if (isNonComparable(symbol)) {
-                handleValidationError(QueryPlugin.Util.getString(ErrorMessageKeys.VALIDATOR_0026, symbol), symbol);
-            }
+            validateSortable(symbol);
         }
     }
 
+	private void validateSortable(SingleElementSymbol symbol) {
+		if (isNonComparable(symbol)) {
+		    handleValidationError(QueryPlugin.Util.getString(ErrorMessageKeys.VALIDATOR_0026, symbol), symbol);
+		}
+	}
+
     public static boolean isNonComparable(Expression symbol) {
         return DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(symbol.getType()));
     }
@@ -647,11 +653,8 @@
         }
         if (obj.getOrderBy() != null) {
         	OrderBy orderBy = obj.getOrderBy();
-        	if (orderBy.hasUnrelated()) {
-        		handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.unrelated_orderby_xml"), obj); //$NON-NLS-1$
-        	}
-        	for (SingleElementSymbol ses : (List<SingleElementSymbol>)orderBy.getVariables()) {
-				if (!(ses instanceof ElementSymbol)) {
+        	for (OrderByItem item : orderBy.getOrderByItems()) {
+				if (!(item.getSymbol() instanceof ElementSymbol)) {
 					handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.orderby_expression_xml"), obj); //$NON-NLS-1$
 				}
 			}

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -97,6 +97,7 @@
 import com.metamatrix.query.sql.lang.MatchCriteria;
 import com.metamatrix.query.sql.lang.NotCriteria;
 import com.metamatrix.query.sql.lang.OrderBy;
+import com.metamatrix.query.sql.lang.OrderByItem;
 import com.metamatrix.query.sql.lang.Query;
 import com.metamatrix.query.sql.lang.QueryCommand;
 import com.metamatrix.query.sql.lang.SPParameter;
@@ -438,19 +439,15 @@
         if(orderBy == null){
             return null;
         }
-        List items = orderBy.getVariables();
-        List types = orderBy.getTypes();
-        List translatedItems = new ArrayList();
-        for (int i = 0; i < items.size(); i++) {
-            SingleElementSymbol symbol = (SingleElementSymbol)items.get(i);
-            boolean direction = (((Boolean)types.get(i)).booleanValue() == OrderBy.DESC)
-                                ? IOrderByItem.DESC
-                                : IOrderByItem.ASC;
+        List<OrderByItemImpl> translatedItems = new ArrayList<OrderByItemImpl>();
+        for (OrderByItem item : orderBy.getOrderByItems()) {
+            SingleElementSymbol symbol = item.getSymbol();
+            boolean direction = item.isAscending()?IOrderByItem.ASC:IOrderByItem.DESC;
                                 
             OrderByItemImpl orderByItem = null;                                
             if(symbol instanceof ElementSymbol){
                 IElement innerElement = translate((ElementSymbol)symbol);
-                if (symbol.getOutputName() != null && symbol.getOutputName().indexOf(ElementSymbol.SEPARATOR) != -1) {
+                if (item.isUnrelated() || (symbol.getOutputName() != null && symbol.getOutputName().indexOf(ElementSymbol.SEPARATOR) != -1)) {
                 	orderByItem = new OrderByItemImpl(null, direction, innerElement);
                 } else {
                 	orderByItem = new OrderByItemImpl(symbol.getOutputName(), direction, innerElement);
@@ -535,8 +532,7 @@
     }
 
     IElement translate(ElementSymbol symbol) throws MetaMatrixComponentException {
-        ElementImpl element = null;
-        element = new ElementImpl(translate(symbol.getGroupSymbol()), symbol.getOutputName(), null, symbol.getType());
+        ElementImpl element = new ElementImpl(translate(symbol.getGroupSymbol()), symbol.getOutputName(), null, symbol.getType());
         
         if (element.getGroup().getMetadataObject() == null) {
             return element;

Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -72,7 +72,7 @@
         String sql = "select e1 from pm1.g1 order by e1"; //$NON-NLS-1$
         String expected = "SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0"; //$NON-NLS-1$
         Query command = (Query)helpTest(sql, expected, true, FakeMetadataFactory.example1Cached());
-        assertEquals(((SingleElementSymbol)command.getOrderBy().getVariables().get(0)).getName(), "e1"); //$NON-NLS-1$
+        assertEquals(command.getOrderBy().getSortKeys().get(0).getName(), "e1"); //$NON-NLS-1$
         assertEquals(((SingleElementSymbol)command.getProjectedSymbols().get(0)).getShortName(), "e1"); //$NON-NLS-1$
     }
     

Modified: trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java	2010-02-18 16:21:36 UTC (rev 1840)
+++ trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java	2010-02-18 20:12:13 UTC (rev 1841)
@@ -65,7 +65,7 @@
                                    String[] elementNames,
                                    String[] elementIDs) {
         List elements = new ArrayList();
-        for (Iterator i = langObj.getVariables().iterator(); i.hasNext();) {
+        for (Iterator i = langObj.getSortKeys().iterator(); i.hasNext();) {
             ElementCollectorVisitor.getElements((LanguageObject)i.next(), elements);
         }
 
@@ -84,7 +84,7 @@
     private void helpCheckExpressionsSymbols(OrderBy langObj,
                                              String[] functionsNames) {
     	int expCount = 0;
-        for (Iterator i = langObj.getVariables().iterator(); i.hasNext();) {
+        for (Iterator i = langObj.getSortKeys().iterator(); i.hasNext();) {
         	SingleElementSymbol ses = (SingleElementSymbol)i.next();
             if (ses instanceof ExpressionSymbol) {
                 assertEquals("Expression Symbols does not match: ", functionsNames[expCount++], ses.toString()); //$NON-NLS-1$                        		



More information about the teiid-commits mailing list