[teiid-commits] teiid SVN: r1880 - in branches/JCA: connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase and 21 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Sat Feb 27 08:43:13 EST 2010


Author: shawkins
Date: 2010-02-27 08:43:10 -0500 (Sat, 27 Feb 2010)
New Revision: 1880

Added:
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java
Modified:
   branches/JCA/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java
   branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java
   branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java
   branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java
   branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java
   branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java
   branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java
   branches/JCA/documentation/reference/src/main/docbook/en-US/content/datatypes.xml
   branches/JCA/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
   branches/JCA/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
   branches/JCA/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java
   branches/JCA/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java
   branches/JCA/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java
Log:
TEIID-833 merging from truck (except for console) -r 1840:1878

Modified: branches/JCA/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java
===================================================================
--- branches/JCA/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connector-api/src/main/java/org/teiid/connector/visitor/util/SQLStringVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -685,6 +685,10 @@
         if (obj.isDistinct()) {
             buffer.append(SQLReservedWords.DISTINCT).append(SQLReservedWords.SPACE);
         }
+        if (useSelectLimit() && obj.getLimit() != null) {
+            append(obj.getLimit());
+            buffer.append(SQLReservedWords.SPACE);
+        }
         append(obj.getDerivedColumns());
         if (obj.getFrom() != null) {
         	buffer.append(SQLReservedWords.SPACE).append(SQLReservedWords.FROM).append(SQLReservedWords.SPACE);      
@@ -710,7 +714,7 @@
             buffer.append(SQLReservedWords.SPACE);
             append(obj.getOrderBy());
         }
-        if (obj.getLimit() != null) {
+        if (!useSelectLimit() && obj.getLimit() != null) {
             buffer.append(SQLReservedWords.SPACE);
             append(obj.getLimit());
         }
@@ -893,4 +897,8 @@
     protected boolean useParensForJoins() {
     	return false;
     }
+    
+    protected boolean useSelectLimit() {
+    	return false;
+    }
 }

Modified: branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/sybase/SybaseSQLTranslator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -43,7 +43,7 @@
 import org.teiid.connector.language.Function;
 import org.teiid.connector.language.Limit;
 import org.teiid.connector.language.OrderBy;
-import org.teiid.connector.language.QueryExpression;
+import org.teiid.connector.language.SetQuery;
 
 
 /**
@@ -166,12 +166,15 @@
     	return 3;
     }
     
+    /**
+     * SetQueries don't have a concept of TOP, an inline view is needed.
+     */
     @Override
     public List<?> translateCommand(Command command, ExecutionContext context) {
-    	if (!(command instanceof QueryExpression)) {
+    	if (!(command instanceof SetQuery)) {
     		return null;
     	}
-		QueryExpression queryCommand = (QueryExpression)command;
+    	SetQuery queryCommand = (SetQuery)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(Limit 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: branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/SQLConversionVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -364,4 +364,8 @@
     	return translator.useParensForJoins();
     }
 	
+	protected boolean useSelectLimit() {
+		return translator.useSelectLimit();
+	}
+	
 }

Modified: branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/main/java/org/teiid/connector/jdbc/translator/Translator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -808,4 +808,12 @@
     	return false;
     }
     
+    /**
+     * 
+     * @return true if the limit clause is part of the select
+     */
+    public boolean useSelectLimit() {
+    	return false;
+    }
+    
 }

Modified: branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/access/TestAccessSQLTranslator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -65,7 +65,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, 
@@ -75,7 +75,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: branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/mysql/TestMySQLTranslator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -332,8 +332,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: branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java
===================================================================
--- branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/connectors/connector-jdbc/src/test/java/org/teiid/connector/jdbc/sqlserver/TestSqlServerConversionVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -99,7 +99,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, 
@@ -116,6 +116,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: branches/JCA/documentation/reference/src/main/docbook/en-US/content/datatypes.xml
===================================================================
--- branches/JCA/documentation/reference/src/main/docbook/en-US/content/datatypes.xml	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/documentation/reference/src/main/docbook/en-US/content/datatypes.xml	2010-02-27 13:43:10 UTC (rev 1880)
@@ -245,6 +245,15 @@
           Allowed explicit conversions may still fail during processing
           if the runtime values are not actually convertable.</para>
       </listitem>
+      <listitem>
+         <warning>
+	         <para>The Teiid conversions of float/double/bigdecimal/timestamp to string rely on the JDBC/Java defined
+	         output formats.  Pushdown behavior attempts to mimic these results, but may vary depending upon the actual
+	         source type and conversion logic.  Care should be taken to not assume the string form in criteria or other
+	         places where a variation may cause different results.
+	         </para>
+         </warning>
+      </listitem>
     </itemizedlist>
     <para>
     </para>

Modified: branches/JCA/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
===================================================================
--- branches/JCA/documentation/reference/src/main/docbook/en-US/content/sql_support.xml	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/documentation/reference/src/main/docbook/en-US/content/sql_support.xml	2010-02-27 13:43:10 UTC (rev 1880)
@@ -793,7 +793,7 @@
         <para>Syntax Rules:
         </para>
         <listitem>
-          <para>Sort columns may be specified positionally by a 1 based
+          <para>Sort columns may be specified positionally by a 1-based positional
 	        integer, by SELECT clause alias name, by SELECT clause expression, or by an unrelated expression.</para>
         </listitem>
         <listitem>
@@ -806,7 +806,8 @@
         </listitem>
         <listitem>
           <para>Unrelated expressions, expressions not appearing as an aliased expression in the select clause, 
-          are allowed in the order by clause of a non-set QUERY.  The columns referenced in the expression must also follow the prior rule.
+          are allowed in the order by clause of a non-set QUERY.  The columns referenced in the expression must come from the
+          from clause table references.  The column references cannot be to alias names or positional.
           </para>
         </listitem>
         <listitem>

Modified: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/AliasGenerator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanHints.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/RelationalPlanner.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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(), SingleElementSymbol.class);
 
         // 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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/plantree/NodeConstants.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/FrameUtil.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/JoinRegion.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleCollapseSource.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleImplementJoinStrategy.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanSorts.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePushAggregates.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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, SingleElementSymbol.class);
 
         SymbolMap viewMapping = SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedSymbols, metadata);
         for (AggregateSymbol agg : aggregates) {

Modified: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseAccess.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRaiseNull.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/optimizer/xml/XMLPlanner.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/processor/proc/AbstractAssignmentInstruction.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/command/SetQueryResolver.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -138,7 +138,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: branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/resolver/util/ResolverUtil.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -346,15 +346,12 @@
         for (int i = 0; i < orderBy.getVariableCount(); i++) {
         	SingleElementSymbol sortKey = orderBy.getVariable(i);
         	if (sortKey instanceof ElementSymbol) {
-        		int index = resolveSortKey(orderBy, fromClauseGroups, knownElements, metadata,
-    					isSimpleQuery, knownShortNames, (ElementSymbol)sortKey);
+        		int index = resolveSortKey(fromClauseGroups, knownElements, metadata, isSimpleQuery,
+    					knownShortNames, (ElementSymbol)sortKey);
                 if (index == -1) {
                 	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
@@ -367,6 +364,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        	
@@ -374,24 +372,18 @@
     			throw new QueryResolverException(QueryPlugin.Util.getString("ResolverUtil.setquery_order_expression", sortKey)); //$NON-NLS-1$	 
     		}
         	for (ElementSymbol symbol : ElementCollectorVisitor.getElements(sortKey, false)) {
-                resolveSortKey(orderBy, fromClauseGroups, knownElements, metadata,
-    					isSimpleQuery, knownShortNames, symbol); 
+                resolveSortKey(fromClauseGroups, null, metadata, isSimpleQuery, null, 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);
         }
     }
     
-    private static int resolveSortKey(OrderBy orderBy, List fromClauseGroups,
-			List knownElements, QueryMetadataInterface metadata,
-			boolean isSimpleQuery, String[] knownShortNames,
-			ElementSymbol symbol) throws MetaMatrixComponentException,
+    private static int resolveSortKey(List fromClauseGroups, List knownElements,
+			QueryMetadataInterface metadata, boolean isSimpleQuery,
+			String[] knownShortNames, ElementSymbol symbol) throws MetaMatrixComponentException,
 			QueryMetadataException, QueryResolverException {
 		SingleElementSymbol matchedSymbol = null;
 		String symbolName = symbol.getName();
@@ -403,38 +395,40 @@
 		    throw new QueryResolverException(ErrorMessageKeys.RESOLVER_0043, QueryPlugin.Util.getString(ErrorMessageKeys.RESOLVER_0043, symbolName));
 		}
 
-		// walk the SELECT col short names, looking for a match on the current ORDER BY 'short name'
-		for(int i=0; i<knownShortNames.length; i++) {
-			if( shortName.equalsIgnoreCase( knownShortNames[i] )) {
-		        if (groupPart != null) {
-		            Object knownSymbol = knownElements.get(i);
-		            if(knownSymbol instanceof ElementSymbol) {
-		                ElementSymbol knownElement = (ElementSymbol) knownSymbol;
-		                GroupSymbol group = knownElement.getGroupSymbol();
-		                
-		                // skip this one if the two short names are not from the same group
-		                if (!nameMatchesGroup(groupPart.toUpperCase(), group.getCanonicalName())) {
-		                    continue;
-		                }
-		            }
-		        }
-		        
-		        // if we already have a matched symbol, matching again here means it is duplicate/ambiguous
-		        if(matchedSymbol != null) {
-		            throw new QueryResolverException(ErrorMessageKeys.RESOLVER_0042, QueryPlugin.Util.getString(ErrorMessageKeys.RESOLVER_0042, symbolName));
-		        }
-		        matchedSymbol = (SingleElementSymbol)knownElements.get(i);
-		    }
+		if (knownShortNames != null) {
+			// walk the SELECT col short names, looking for a match on the current ORDER BY 'short name'
+			for(int i=0; i<knownShortNames.length; i++) {
+				if( shortName.equalsIgnoreCase( knownShortNames[i] )) {
+			        if (groupPart != null) {
+			            Object knownSymbol = knownElements.get(i);
+			            if(knownSymbol instanceof ElementSymbol) {
+			                ElementSymbol knownElement = (ElementSymbol) knownSymbol;
+			                GroupSymbol group = knownElement.getGroupSymbol();
+			                
+			                // skip this one if the two short names are not from the same group
+			                if (!nameMatchesGroup(groupPart.toUpperCase(), group.getCanonicalName())) {
+			                    continue;
+			                }
+			            }
+			        }
+			        
+			        // if we already have a matched symbol, matching again here means it is duplicate/ambiguous
+			        if(matchedSymbol != null) {
+			            throw new QueryResolverException(ErrorMessageKeys.RESOLVER_0042, QueryPlugin.Util.getString(ErrorMessageKeys.RESOLVER_0042, symbolName));
+			        }
+			        matchedSymbol = (SingleElementSymbol)knownElements.get(i);
+			    }
+			}
+			if (matchedSymbol != null) {
+			    TempMetadataID tempMetadataID = new TempMetadataID(symbol.getName(), matchedSymbol.getType());
+			    int position = knownElements.indexOf(matchedSymbol);
+			    tempMetadataID.setPosition(position);
+			    symbol.setMetadataID(tempMetadataID);
+			    symbol.setType(matchedSymbol.getType());
+			    return position;
+			}
 		}
 		            		           
-		if (matchedSymbol != null) {
-		    TempMetadataID tempMetadataID = new TempMetadataID(symbol.getName(), matchedSymbol.getType());
-		    int position = knownElements.indexOf(matchedSymbol);
-		    tempMetadataID.setPosition(position);
-		    symbol.setMetadataID(tempMetadataID);
-		    symbol.setType(matchedSymbol.getType());
-		    return position;
-		}
 		if (!isSimpleQuery) {
 	        throw new QueryResolverException(QueryPlugin.Util.getString("ResolverUtil.invalid_unrelated", symbol.getName())); //$NON-NLS-1$
 	    }

Modified: branches/JCA/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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;
@@ -71,6 +72,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;
@@ -93,6 +95,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;
@@ -135,7 +138,6 @@
 import com.metamatrix.query.sql.symbol.Reference;
 import com.metamatrix.query.sql.symbol.ScalarSubquery;
 import com.metamatrix.query.sql.symbol.SearchedCaseExpression;
-import com.metamatrix.query.sql.symbol.SelectSymbol;
 import com.metamatrix.query.sql.symbol.SingleElementSymbol;
 import com.metamatrix.query.sql.util.SymbolMap;
 import com.metamatrix.query.sql.util.ValueIterator;
@@ -794,19 +796,21 @@
         
         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
+        	  	continue; // must be unrelated
         	}
         	querySymbol = (SingleElementSymbol)projectedSymbols.get(index);
         	Expression expr = SymbolMap.getExpression(querySymbol);
         	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());
         	}
         }
         
@@ -822,7 +826,9 @@
         int originalSymbolCount = select.getProjectedSymbols().size();
 
         //add unrelated to select
-        select.addSymbols(orderBy.getUnrelated());
+        for (OrderByItem orderByItem : unrelatedItems) {
+            select.addSymbol(orderByItem.getSymbol());				
+		}
         makeSelectUnique(select, false);
         
         Query query = queryCommand.getProjectedQuery();
@@ -836,8 +842,8 @@
         Query top = null;
         
         try {
-        	Query intermediate = createInlineViewQuery(new GroupSymbol("X"), query, metadata, select.getProjectedSymbols()); //$NON-NLS-1$
-			Iterator iter = intermediate.getSelect().getProjectedSymbols().iterator();
+        	top = createInlineViewQuery(new GroupSymbol("X"), query, metadata, select.getProjectedSymbols()); //$NON-NLS-1$
+			Iterator iter = top.getSelect().getProjectedSymbols().iterator();
 		    HashMap<Expression, SingleElementSymbol> expressionMap = new HashMap<Expression, SingleElementSymbol>();
 		    for (SingleElementSymbol symbol : (List<SingleElementSymbol>)select.getProjectedSymbols()) {
 		    	SingleElementSymbol ses = (SingleElementSymbol)iter.next();
@@ -845,22 +851,6 @@
 		        expressionMap.put(new ElementSymbol(symbol.getName()), ses);
 		    }
 		    ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap);
-		    for (int i = 0; i < orderBy.getVariableCount(); i++) {
-		    	int index = orderBy.getExpressionPosition(i);
-		    	SingleElementSymbol ss = orderBy.getVariable(i);
-		    	if (index == -1 && !(ss instanceof ElementSymbol)) {
-		    		intermediate.getSelect().addSymbol((SelectSymbol)ss.clone());
-		    	}
-			}
-		    makeSelectUnique(intermediate.getSelect(), true);
-		    
-        	top = createInlineViewQuery(new GroupSymbol("Y"), intermediate, metadata, intermediate.getSelect().getProjectedSymbols()); //$NON-NLS-1$
-			iter = top.getSelect().getProjectedSymbols().iterator();
-		    expressionMap = new HashMap<Expression, SingleElementSymbol>();
-		    for (SingleElementSymbol symbol : (List<SingleElementSymbol>)intermediate.getSelect().getProjectedSymbols()) {
-		        expressionMap.put(SymbolMap.getExpression(symbol), (SingleElementSymbol)iter.next());
-		    }
-		    ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap);
 		    //now the order by should only contain element symbols
 		} catch (QueryResolverException e) {
 			throw new QueryValidatorException(e, e.getMessage());
@@ -869,12 +859,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);
@@ -892,7 +877,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), ElementSymbol.class);
             Insert insert = new Insert(into.getGroup(), allIntoElements, Collections.emptyList());
             query.setInto(null);
             insert.setQueryExpression(query);
@@ -2401,14 +2386,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: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageObject.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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,17 @@
 	 * @return Deep clone of this object
 	 */
     Object clone();
+    
+    public static class Util {
+
+		public static <S extends LanguageObject, T extends S> ArrayList<S> deepClone(List<T> collection, Class<S> type) {
+			ArrayList<S> result = new ArrayList<S>(collection.size());
+			for (LanguageObject obj : collection) {
+				result.add(type.cast(obj.clone()));
+			}
+			return result;
+		}
+    	
+    }
     	 
 }

Modified: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/LanguageVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderBy.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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, OrderByItem.class);
+        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;
+    }
+    
 }

Copied: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java (from rev 1879, trunk/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java)
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java	                        (rev 0)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/lang/OrderByItem.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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);
+	}
+	
+}

Modified: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/navigator/PreOrPostOrderNavigator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/sql/visitor/SQLStringVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java
===================================================================
--- branches/JCA/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/com/metamatrix/query/validator/ValidationVisitor.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java
===================================================================
--- branches/JCA/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/main/java/org/teiid/dqp/internal/datamgr/language/LanguageBridgeFactory.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -85,6 +85,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;
@@ -416,15 +417,12 @@
         if(orderBy == null){
             return null;
         }
-        List items = orderBy.getVariables();
-        List types = orderBy.getTypes();
+        List<OrderByItem> items = orderBy.getOrderByItems();
         List<SortSpecification> translatedItems = new ArrayList<SortSpecification>();
         for (int i = 0; i < items.size(); i++) {
-            SingleElementSymbol symbol = (SingleElementSymbol)items.get(i);
-            Ordering direction = (((Boolean)types.get(i)).booleanValue() == OrderBy.DESC)
-                                ? Ordering.DESC
-                                : Ordering.ASC;
-                                
+            SingleElementSymbol symbol = items.get(i).getSymbol();
+            Ordering direction = items.get(i).isAscending() ? Ordering.ASC: Ordering.DESC;
+            
             SortSpecification orderByItem = null;                                
             if(symbol instanceof AliasSymbol || (symbol.getOutputName() != null && symbol.getOutputName().indexOf(ElementSymbol.SEPARATOR) == -1)){
             	orderByItem = new SortSpecification(direction, new ColumnReference(null, symbol.getOutputName(), null, symbol.getType()));
@@ -509,7 +507,6 @@
     ColumnReference translate(ElementSymbol symbol) throws MetaMatrixComponentException {
         ColumnReference element = null;
         element = new ColumnReference(translate(symbol.getGroupSymbol()), symbol.getOutputName(), null, symbol.getType());
-        
         if (element.getTable().getMetadataObject() == null) {
             return element;
         }

Modified: branches/JCA/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java
===================================================================
--- branches/JCA/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/test/java/com/metamatrix/query/optimizer/relational/TestAliasGenerator.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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: branches/JCA/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java
===================================================================
--- branches/JCA/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java	2010-02-27 12:48:26 UTC (rev 1879)
+++ branches/JCA/engine/src/test/java/com/metamatrix/query/rewriter/TestOrderByRewrite.java	2010-02-27 13:43:10 UTC (rev 1880)
@@ -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$                        		
@@ -309,8 +309,8 @@
     } 
     
     @Test public void testOrderByExpression() throws Exception {
-    	Query resolvedQuery = (Query) getCommand("SELECT 0 AS SOMEINT, pm1.g1.e2 as y FROM pm1.g1 ORDER BY y + SOMEINT, e3"); //$NON-NLS-1$
-        assertEquals("SELECT Y_1.SOMEINT, Y_1.Y FROM (SELECT X_1.SOMEINT, X_1.Y, X_1.E3, (X_1.Y + X_1.SOMEINT) AS EXPR1 FROM (SELECT 0 AS SOMEINT, pm1.g1.e2 AS y, e3 FROM pm1.g1) AS X_1) AS Y_1 ORDER BY Y_1.EXPR1, Y_1.E3", resolvedQuery.toString()); //$NON-NLS-1$
+    	Query resolvedQuery = (Query) getCommand("SELECT 0 AS SOMEINT, pm1.g1.e2 as y FROM pm1.g1 ORDER BY e2 || e1, e3"); //$NON-NLS-1$
+        assertEquals("SELECT X_1.SOMEINT, X_1.Y FROM (SELECT 0 AS SOMEINT, pm1.g1.e2 AS y, (e2 || e1) AS EXPR1, e3 FROM pm1.g1) AS X_1 ORDER BY X_1.EXPR1, X_1.E3", resolvedQuery.toString()); //$NON-NLS-1$
     }
     
     @Test public void testRewiteOrderBy() {



More information about the teiid-commits mailing list