[teiid-commits] teiid SVN: r2906 - in trunk/engine/src: main/java/org/teiid/query/optimizer/relational/rules and 3 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon Feb 14 15:34:03 EST 2011


Author: shawkins
Date: 2011-02-14 15:34:03 -0500 (Mon, 14 Feb 2011)
New Revision: 2906

Modified:
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java
   trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1471 reusing the assign element logic to filter elements prior to optional join removal and merge virtual

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -437,6 +437,10 @@
         if (hints.hasJoin && hints.hasOptionalJoin) {
             rules.push(RuleConstants.REMOVE_OPTIONAL_JOINS);
         }
+        if (hints.hasVirtualGroups || (hints.hasJoin && hints.hasOptionalJoin)) {
+        	//do initial filtering to make merging and optional join logic easier
+            rules.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        }
         rules.push(RuleConstants.PLACE_ACCESS);
         return rules;
     }

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -123,15 +123,6 @@
 
 	    int nodeType = root.getType();
         
-        //fix no output elements if possible
-        if(outputElements.isEmpty() && (nodeType == NodeConstants.Types.ACCESS || nodeType == NodeConstants.Types.SOURCE)) {
-            PlanNode groupSource = FrameUtil.findJoinSourceNode(root);
-            ElementSymbol symbol = selectOutputElement(groupSource.getGroups(), metadata);
-            if (symbol != null) {//can be null for procedures
-                outputElements.add(symbol);
-            }
-        }
-        
 		// Update this node's output columns based on parent's columns
 		root.setProperty(NodeConstants.Info.OUTPUT_COLS, outputElements);
         
@@ -153,11 +144,21 @@
 		    		//add missing sort columns
 			    	OrderBy elements = (OrderBy) root.getProperty(NodeConstants.Info.SORT_ORDER);
 			    	outputElements = new ArrayList<SingleElementSymbol>(outputElements);
+			    	boolean hasUnrelated = false;
 			    	for (OrderByItem item : elements.getOrderByItems()) {
-						if (!outputElements.contains(item.getSymbol())) {
-							outputElements.add(item.getSymbol());
+			    		if (item.getExpressionPosition() == -1) {
+			    			int index = outputElements.indexOf(item.getSymbol());
+			    			if (index != -1) {
+			    				item.setExpressionPosition(index);
+			    			} else {
+			    				hasUnrelated = true;
+			    				outputElements.add(item.getSymbol());
+			    			}
 						}
 					}
+			    	if (!hasUnrelated) {
+			    		root.setProperty(NodeConstants.Info.UNRELATED_SORT, false);
+			    	}
 		    	}
 		        assignOutputElements(root.getLastChild(), outputElements, metadata, capFinder, rules, analysisRecord, context);
 		        break;
@@ -165,24 +166,6 @@
 		        outputElements = (List<SingleElementSymbol>)determineSourceOutput(root, outputElements, metadata, capFinder);
 	            root.setProperty(NodeConstants.Info.OUTPUT_COLS, outputElements);
 	            List<SingleElementSymbol> childElements = filterVirtualElements(root, outputElements, metadata);
-	            SymbolMap symbolMap = (SymbolMap)root.getProperty(NodeConstants.Info.SYMBOL_MAP);
-	            int size = symbolMap.asMap().size();
-	            symbolMap.asUpdatableMap().keySet().retainAll(outputElements);
-	            //if we have removed projected symbols, then we need to update the sort columns
-	            if (size > outputElements.size()) {
-	            	PlanNode sortNode = NodeEditor.findNodePreOrder(root, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
-	            	if (sortNode != null && !sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
-		            	List<Expression> symbolOrder = symbolMap.getValues();
-	            		OrderBy elements = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
-	            		for (OrderByItem item : elements.getOrderByItems()) {
-							int position = symbolOrder.indexOf(SymbolMap.getExpression(item.getSymbol()));
-							item.setExpressionPosition(position);
-							if (position == -1) {
-								sortNode.setProperty(NodeConstants.Info.UNRELATED_SORT, true);
-							}
-						}
-	            	}
-	            }
 	            assignOutputElements(root.getFirstChild(), childElements, metadata, capFinder, rules, analysisRecord, context);
 		        break;
 		    }
@@ -202,7 +185,29 @@
 		                execute(intoRoot.getFirstChild(), metadata, capFinder, rules, analysisRecord, context);
 		                return;
 		            }
-	            	root.setProperty(NodeConstants.Info.PROJECT_COLS, outputElements);
+	            	List<SingleElementSymbol> projectCols = outputElements;
+	            	boolean modifiedProject = false;
+	            	PlanNode sortNode = NodeEditor.findParent(root, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
+	            	if (sortNode != null && sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
+	            		//if this is the initial rule run, remove unrelated order before changing the project cols
+			            if (rules.contains(RuleConstants.ASSIGN_OUTPUT_ELEMENTS)) {
+		            		OrderBy elements = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
+		            		projectCols = new ArrayList<SingleElementSymbol>(projectCols);
+		            		for (OrderByItem item : elements.getOrderByItems()) {
+		            			if (item.getExpressionPosition() == -1) {
+		            				projectCols.remove(item.getSymbol());
+		            			}
+		            		}
+	            		} else {
+	            			modifiedProject = true;
+	            		}
+		            }
+		            root.setProperty(NodeConstants.Info.PROJECT_COLS, projectCols);
+	            	if (modifiedProject) {
+		            	root.getGroups().clear();
+		            	root.addGroups(GroupsUsedByElementsVisitor.getGroups(projectCols));
+		            	root.addGroups(GroupsUsedByElementsVisitor.getGroups(root.getCorrelatedReferenceElements()));
+	            	}
 		    	}
 	            
 	            List<SingleElementSymbol> requiredInput = collectRequiredInputSymbols(root);
@@ -292,33 +297,6 @@
     }
     
     /**
-     * Find a selectable element in the specified groups.  This is a helper for fixing
-     * the "no elements" case.
-     *
-     * @param groups Bunch of groups
-     * @param metadata Metadata implementation
-     * @throws QueryPlannerException
-     */
-    private ElementSymbol selectOutputElement(Collection<GroupSymbol> groups, QueryMetadataInterface metadata)
-        throws QueryMetadataException, TeiidComponentException {
-
-        // Find a group with selectable elements and pick the first one
-        for (GroupSymbol group : groups) {
-            List<ElementSymbol> elements = (List<ElementSymbol>)ResolverUtil.resolveElementsInGroup(group, metadata);
-            
-            for (ElementSymbol element : elements) {
-                if(metadata.elementSupports(element.getMetadataID(), SupportConstants.Element.SELECT)) {
-                    element = (ElementSymbol)element.clone();
-                    element.setGroupSymbol(group);
-                    return element;
-                }
-            }
-        }
-        
-        return null;
-    }
-
-    /**
      * <p>This method looks at a source node, which defines a virtual group, and filters the
      * virtual elements defined by the group down into just the output elements needed
      * by that source node.  This means, for instance, that the PROJECT node at the top
@@ -347,13 +325,29 @@
         Arrays.fill(filteredIndex, -1);
         
         SymbolMap symbolMap = (SymbolMap)sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
-        List originalOrder = symbolMap.getKeys();
         
+        List<ElementSymbol> originalOrder = symbolMap.getKeys();
+        
+        boolean updateGroups = outputColumns.size() != originalOrder.size();
+        boolean[] seenIndex = new boolean[outputColumns.size()];
+        
         for (int i = 0; i < outputColumns.size(); i++) {
             Expression expr = outputColumns.get(i);
             filteredIndex[i] = originalOrder.indexOf(expr);
+            if (!updateGroups) {
+            	seenIndex[filteredIndex[i]] = true;
+            }
         }
         
+        if (!updateGroups) {
+        	for (boolean b : seenIndex) {
+				if (!b) {
+					updateGroups = true;
+					break;
+				}
+			}
+        }
+        
         List<SingleElementSymbol> newCols = null;
         for(int i=allProjects.size()-1; i>=0; i--) {
             PlanNode projectNode = allProjects.get(i);
@@ -365,8 +359,51 @@
             }
             
             projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, newCols);
+            if (updateGroups) {
+	            projectNode.getGroups().clear();
+	            projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(newCols));
+	            projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(projectNode.getCorrelatedReferenceElements()));
+            }
         }
+        
+        if (!updateGroups) {
+        	for (int i : filteredIndex) {
+				if (i != filteredIndex[i]) {
+					updateGroups = true;
+					break;
+				}
+			}
+        }
+        
+        if (updateGroups) {
+        	SymbolMap newMap = new SymbolMap();
+            List<Expression> originalExpressionOrder = symbolMap.getValues();
 
+        	for (int i = 0; i < filteredIndex.length; i++) {
+        		newMap.addMapping(originalOrder.get(filteredIndex[i]), originalExpressionOrder.get(filteredIndex[i]));
+			}
+            PlanNode sortNode = NodeEditor.findNodePreOrder(sourceNode, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
+        	if (sortNode != null) {
+        		OrderBy elements = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
+        		for (OrderByItem item : elements.getOrderByItems()) {
+        			if (item.getExpressionPosition() == -1) {
+        				continue;
+        			}
+        			item.setExpressionPosition(-1);
+        			for (int i = 0; i < filteredIndex.length; i++) {
+        				if (item.getExpressionPosition() == filteredIndex[i]) {
+        					item.setExpressionPosition(i);
+        					break;
+        				}
+        			}
+					if (item.getExpressionPosition() == -1) {
+						sortNode.setProperty(NodeConstants.Info.UNRELATED_SORT, true);
+					}
+				}
+        	}
+        	sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, newMap);
+        }
+
 		// Create output columns for virtual group project
 		return newCols;
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -23,6 +23,7 @@
 package org.teiid.query.optimizer.relational.rules;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -33,6 +34,7 @@
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.SupportConstants;
 import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
 import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
 import org.teiid.query.optimizer.relational.OptimizerRule;
@@ -68,7 +70,10 @@
 import org.teiid.query.sql.lang.UnaryFromClause;
 import org.teiid.query.sql.lang.SetQuery.Operation;
 import org.teiid.query.sql.navigator.DeepPostOrderNavigator;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.sql.util.SymbolMap;
@@ -234,9 +239,45 @@
 		if (!CapabilitiesUtil.useAnsiJoin(RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata), metadata, capFinder)) {
 			simplifyFromClause(query);
         }
+		if (columns.isEmpty()) {
+        	if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata), metadata, capFinder)) {
+        		select.addSymbol(new ExpressionSymbol("dummy", new Constant(1))); //$NON-NLS-1$
+        	} else {
+        		//TODO: need to ensure the type is consistent  
+        		//- should be rare as the source would typically support select expression if it supports union
+        		select.addSymbol(selectOutputElement(query.getFrom().getGroups(), metadata));
+        	}
+        }
 		return query;
 	}		
+	
+    /**
+     * Find a selectable element in the specified groups.  This is a helper for fixing
+     * the "no elements" case.
+     *
+     * @param groups Bunch of groups
+     * @param metadata Metadata implementation
+     * @throws QueryPlannerException
+     */
+    private ElementSymbol selectOutputElement(Collection<GroupSymbol> groups, QueryMetadataInterface metadata)
+        throws QueryMetadataException, TeiidComponentException {
 
+        // Find a group with selectable elements and pick the first one
+        for (GroupSymbol group : groups) {
+            List<ElementSymbol> elements = (List<ElementSymbol>)ResolverUtil.resolveElementsInGroup(group, metadata);
+            
+            for (ElementSymbol element : elements) {
+                if(metadata.elementSupports(element.getMetadataID(), SupportConstants.Element.SELECT)) {
+                    element = (ElementSymbol)element.clone();
+                    element.setGroupSymbol(group);
+                    return element;
+                }
+            }
+        }
+        
+        return null;
+    }
+
     void buildQuery(PlanNode accessRoot, PlanNode node, Query query, QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
         
     	//visit source and join nodes as they appear

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -341,7 +341,6 @@
             }
         }
 
-        //TODO: in each of the cases below, check to see if the offending projected symbol is actually used in the upper frame
         List<ElementSymbol> virtualElements = symbolMap.getKeys();
         for (int i = 0; i < selectSymbols.size(); i++) {
         	SingleElementSymbol symbol = selectSymbols.get(i);

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -407,7 +407,9 @@
 
         List<SingleElementSymbol> projectedViewSymbols = Util.deepClone(symbolMap.getKeys(), SingleElementSymbol.class);
 
-        SymbolMap viewMapping = SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedViewSymbols, metadata);
+        PlanNode parent = NodeEditor.findParent(unionSource, NodeConstants.Types.SOURCE);
+        SymbolMap parentMap = (SymbolMap) parent.getProperty(NodeConstants.Info.SYMBOL_MAP);
+        SymbolMap viewMapping = SymbolMap.createSymbolMap(parentMap.getKeys(), projectedViewSymbols);
         for (AggregateSymbol agg : aggregates) {
         	agg = (AggregateSymbol)agg.clone();
         	ExpressionMappingVisitor.mapExpressions(agg, viewMapping.asMap());

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -23,16 +23,15 @@
 package org.teiid.query.optimizer.relational.rules;
 
 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 org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryPlannerException;
-import org.teiid.api.exception.query.QueryResolverException;
 import org.teiid.core.TeiidComponentException;
-import org.teiid.core.util.Assertion;
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -42,16 +41,14 @@
 import org.teiid.query.optimizer.relational.plantree.NodeEditor;
 import org.teiid.query.optimizer.relational.plantree.PlanNode;
 import org.teiid.query.resolver.util.ResolverUtil;
-import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.lang.JoinType;
-import org.teiid.query.sql.lang.OrderBy;
 import org.teiid.query.sql.symbol.AggregateSymbol;
 import org.teiid.query.sql.symbol.Constant;
 import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.util.SymbolMap;
-import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
 import org.teiid.query.util.CommandContext;
 
 
@@ -71,155 +68,42 @@
                                                    QueryMetadataException,
                                                    TeiidComponentException {
 
-        try {
-            removeOptionalJoinNodes(plan, metadata, capFinder, null);
-        } catch (QueryResolverException e) {
-            throw new TeiidComponentException(e);
-        }
+    	List<PlanNode> joinNodes = NodeEditor.findAllNodes(plan, NodeConstants.Types.JOIN);
+    	HashSet<PlanNode> removedNodes = new HashSet<PlanNode>();
+    	for (PlanNode planNode : joinNodes) {
+    		if (removedNodes.contains(planNode)) {
+    			continue;
+    		}
+    		Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups((Collection<? extends LanguageObject>)planNode.getProperty(NodeConstants.Info.OUTPUT_COLS));
+    		List<PlanNode> removed = removeJoin(groups, planNode, planNode.getFirstChild(), metadata);
+    		if (removed != null) {
+    			removedNodes.addAll(removed);
+    			continue;
+    		}
+    		removed = removeJoin(groups, planNode, planNode.getLastChild(), metadata);
+    		if (removed != null) {
+    			removedNodes.addAll(removed);
+    		}
+		}
         return plan;
     }
     
     /**
-     * remove optional from top to bottom
-     * @throws QueryResolverException 
-     */ 
-    private boolean removeOptionalJoinNodes(PlanNode node,
-                                            QueryMetadataInterface metadata,
-                                            CapabilitiesFinder capFinder, Set<ElementSymbol> elements) throws QueryPlannerException,
-                                                                         QueryMetadataException,
-                                                                         TeiidComponentException, QueryResolverException {
-        if (node.getChildCount() == 0) {
-            return false;
-        }
-        
-        boolean isRoot = false;
-        
-        switch (node.getType()) {
-        
-        	case NodeConstants.Types.JOIN:
-        	{
-        		if (removedJoin(node, node.getFirstChild(), elements, metadata)) {
-        			return true;
-        		}
-        		if (removedJoin(node, node.getLastChild(), elements, metadata)) {
-        			return true;
-        		}
-                List crits = (List)node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
-                ElementCollectorVisitor.getElements(crits, elements);
-                elements.addAll(node.getCorrelatedReferenceElements());
-                break;
-        	}
-            case NodeConstants.Types.PROJECT:
-            {
-            	//skip to the child project
-                if (node.getProperty(NodeConstants.Info.INTO_GROUP) != null) {
-                	elements = null;
-                	node = NodeEditor.findNodePreOrder(node.getFirstChild(), NodeConstants.Types.PROJECT);
-                }
-                	
-                if (elements == null) {
-                    isRoot = true;
-                    elements = new HashSet<ElementSymbol>();
-                }
-                
-                //if it is a grouping scenario just make it a root
-                if (!isRoot && NodeEditor.findNodePreOrder(node.getFirstChild(), NodeConstants.Types.GROUP, NodeConstants.Types.PROJECT) != null) {
-                    isRoot = true;
-                }
-                
-                if (isRoot) {
-                    List columns = (List)node.getProperty(NodeConstants.Info.PROJECT_COLS);
-                    ElementCollectorVisitor.getElements(columns, elements);
-                    elements.addAll(node.getCorrelatedReferenceElements());
-                }
-                
-                break;
-            }
-            case NodeConstants.Types.SOURCE:
-            {
-                if (elements == null) {
-                    break;
-                }
-                SymbolMap symbolMap = (SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP);
-                Set convertedElements = new HashSet();
-                for (ElementSymbol element : elements) {
-                    Expression convertedExpression = symbolMap.getMappedExpression(element);
-                    if (convertedExpression != null) {
-                        ElementCollectorVisitor.getElements(convertedExpression, convertedElements);
-                    }
-                }
-                elements = convertedElements;
-                isRoot = true;
-                break;
-            }
-            case NodeConstants.Types.SELECT: //covers having as well
-            {
-                if (elements != null) {
-                    Criteria crit = (Criteria)node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
-                    ElementCollectorVisitor.getElements(crit, elements);
-                    elements.addAll(node.getCorrelatedReferenceElements());
-                }
-                break;
-            }
-            case NodeConstants.Types.SORT:
-            {
-                if (elements != null) {
-                    OrderBy sortOrder = (OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
-                    ElementCollectorVisitor.getElements(sortOrder, elements);
-                }
-                break;
-            }
-            case NodeConstants.Types.SET_OP:
-            case NodeConstants.Types.DUP_REMOVE:
-            {
-                //allow project nodes to be seen as roots
-                elements = null;
-                break;
-            }
-        }
-        
-        //if this is a root then keep removing optional nodes until none can be removed
-        if (isRoot) {
-            boolean optionalRemoved = false;
-            do {
-                optionalRemoved = removeOptionalJoinNodes(node.getFirstChild(), metadata, capFinder, elements);
-            } while (optionalRemoved);
-            return false;
-        }
-
-        //otherwise recurse through the children
-        Iterator iter = node.getChildren().iterator();
-
-        while (node.getChildCount() >= 1 && iter.hasNext()) {
-            if (removeOptionalJoinNodes((PlanNode)iter.next(), metadata, capFinder, elements)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
      * remove the optional node if possible
      * @throws QueryPlannerException 
+     * @throws TeiidComponentException 
+     * @throws QueryMetadataException 
      */ 
-    private boolean removedJoin(PlanNode joinNode, PlanNode optionalNode,
-                                           Set elements, QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
-        Set groups = optionalNode.getGroups();
-        
-        Assertion.isNotNull(elements);
-        
-        for (Iterator i = elements.iterator(); i.hasNext();) {
-            ElementSymbol symbol = (ElementSymbol)i.next();
-            if (groups.contains(symbol.getGroupSymbol())) {
-                return false;  //groups contain an output symbol, don't remove
-            }
+    private List<PlanNode> removeJoin(Set<GroupSymbol> groups, PlanNode joinNode, PlanNode optionalNode, QueryMetadataInterface metadata) throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
+        if (!Collections.disjoint(optionalNode.getGroups(), groups)) {
+        	return null;
         }
-        
+    	
         JoinType jt = (JoinType)joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
         
         if (!optionalNode.hasBooleanProperty(NodeConstants.Info.IS_OPTIONAL) && 
         		(jt != JoinType.JOIN_LEFT_OUTER || optionalNode != joinNode.getLastChild() || useNonDistinctRows(joinNode.getParent()))) {
-        	return false;
+        	return null;
         }
     	// remove the parent node and move the sibling node upward
 		PlanNode parentNode = joinNode.getParent();
@@ -227,16 +111,16 @@
 		NodeEditor.removeChildNode(parentNode, joinNode);
 
 		// correct the parent nodes that may be using optional elements
-		for (GroupSymbol optionalGroup : optionalNode.getGroups()) {
+		/*for (GroupSymbol optionalGroup : optionalNode.getGroups()) {
 			List<ElementSymbol> optionalElements = ResolverUtil.resolveElementsInGroup(optionalGroup, metadata);
 			List<Constant> replacements = new ArrayList<Constant>(optionalElements.size());
 			for (ElementSymbol elementSymbol : optionalElements) {
 				replacements.add(new Constant(null, elementSymbol.getType()));
 			}
 			FrameUtil.convertFrame(parentNode, optionalGroup, null, SymbolMap.createSymbolMap(optionalElements, replacements).asMap(), metadata);
-		}
+		}*/
 
-		return true;
+		return NodeEditor.findAllNodes(optionalNode, NodeConstants.Types.JOIN);
     }
     
     /**

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -48,7 +48,7 @@
  */
 public class FunctionCollectorVisitor extends LanguageVisitor {
 
-    private Collection functions;
+    private Collection<Function> functions;
     
     private String functionName;
 
@@ -58,7 +58,7 @@
      * @param elements Collection to use for elements
      * @throws IllegalArgumentException If elements is null
      */
-	public FunctionCollectorVisitor(Collection functions) {
+	public FunctionCollectorVisitor(Collection<Function> functions) {
         this(functions, null);
 	}
 
@@ -68,7 +68,7 @@
      * @param elements Collection to use for elements
      * @throws IllegalArgumentException If elements is null
      */
-    public FunctionCollectorVisitor(Collection functions, String functionName) {
+    public FunctionCollectorVisitor(Collection<Function> functions, String functionName) {
         if(functions == null) {
             throw new IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0022")); //$NON-NLS-1$
         }
@@ -81,7 +81,7 @@
      * after the visitor has been run on the language object tree.
      * @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
      */
-    public Collection getFunctions() {
+    public Collection<Function> getFunctions() {
         return this.functions;
     }
 
@@ -101,7 +101,7 @@
      * @param obj Language object
      * @param elements Collection to collect elements in
      */
-    public static final void getFunctions(LanguageObject obj, Collection functions) {
+    public static final void getFunctions(LanguageObject obj, Collection<Function> functions) {
         getFunctions(obj, functions, false);
     }
     
@@ -110,7 +110,7 @@
      * @param obj Language object
      * @param elements Collection to collect elements in
      */
-    public static final void getFunctions(LanguageObject obj, Collection functions, boolean deep) {
+    public static final void getFunctions(LanguageObject obj, Collection<Function> functions, boolean deep) {
         FunctionCollectorVisitor visitor = new FunctionCollectorVisitor(functions);
         if (!deep) {
             PreOrderNavigator.doVisit(obj, visitor);
@@ -127,16 +127,16 @@
      * @param removeDuplicates True to remove duplicates
      * @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
      */
-    public static final Collection getFunctions(LanguageObject obj, boolean removeDuplicates) {
+    public static final Collection<Function> getFunctions(LanguageObject obj, boolean removeDuplicates) {
         return getFunctions(obj, removeDuplicates, false);
     }
 
-    public static final Collection getFunctions(LanguageObject obj, boolean removeDuplicates, boolean deep) {
-        Collection functions = null;
+    public static final Collection<Function> getFunctions(LanguageObject obj, boolean removeDuplicates, boolean deep) {
+        Collection<Function> functions = null;
         if(removeDuplicates) {
-            functions = new HashSet();
+            functions = new HashSet<Function>();
         } else {
-            functions = new ArrayList();
+            functions = new ArrayList<Function>();
         }
         getFunctions(obj, functions, deep);
         return functions;

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -213,7 +213,7 @@
 
     @Test public void testPushingCriteriaThroughFrameAccessPattern0() {
         TestOptimizer.helpPlan("select * from vm1.g9 where vm1.g9.e1='abc'", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
-            new String[] { "SELECT pm4.g1.e1 FROM pm4.g1 WHERE pm4.g1.e1 = 'abc'", //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm4.g1 WHERE pm4.g1.e1 = 'abc'", //$NON-NLS-1$
                             "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'" } ); //$NON-NLS-1$
     }
 
@@ -232,7 +232,7 @@
 
     @Test public void testPushingCriteriaThroughFrameAccessPattern3() {
         TestOptimizer.helpPlan("select * from vm1.g1, vm1.g9 where vm1.g1.e1='abc' and vm1.g1.e1=vm1.g9.e1", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
-            new String[] {"SELECT pm4.g1.e1 FROM pm4.g1 WHERE pm4.g1.e1 = 'abc'", //$NON-NLS-1$
+            new String[] {"SELECT 1 FROM pm4.g1 WHERE pm4.g1.e1 = 'abc'", //$NON-NLS-1$
                           "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'", //$NON-NLS-1$
                           "SELECT g1__1.e1, g1__1.e2, g1__1.e3, g1__1.e4 FROM pm1.g1 AS g1__1 WHERE g1__1.e1 = 'abc'"} ); //$NON-NLS-1$
     }

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -22,6 +22,7 @@
 
 package org.teiid.query.optimizer;
 
+import org.junit.Test;
 import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
 import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
 import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
@@ -29,18 +30,16 @@
 import org.teiid.query.processor.ProcessorPlan;
 import org.teiid.query.unittest.FakeMetadataFactory;
 
-import junit.framework.TestCase;
 
-
 /**
  * expressions in group use lacks robust support in MySQL, PostGres, and Derby Expressions and it's nothing more than syntactic sugar for an inline view,
  * a new approach was taken to use inline views rather than a non ANSI group by construct.
  * 
  * Later we can add a connector binding property to support non-select expressions in group by.
  */
-public class TestExpressionsInGroupBy extends TestCase {
+public class TestExpressionsInGroupBy {
 
-    public void testCase1565() throws Exception {
+    @Test public void testCase1565() throws Exception {
         // Create query
         String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date) AS x FROM bqt1.smalla) as y GROUP BY x"; //$NON-NLS-1$
 
@@ -64,7 +63,7 @@
     }   
     
     // Merge across multiple virtual groups - should be same outcome as testCase1565
-    public void testCase1565_2() throws Exception {
+    @Test public void testCase1565_2() throws Exception {
         // Create query
         String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date) AS x FROM (SELECT TimestampValue from bqt1.smalla) as z) as y GROUP BY x"; //$NON-NLS-1$
 
@@ -88,7 +87,7 @@
     }   
     
     // Merge across multiple virtual groups above the physical
-    public void testCase1565_3() throws Exception {
+    @Test public void testCase1565_3() throws Exception {
         String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date) AS x FROM (SELECT TimestampValue from bqt1.smalla) as z) as y GROUP BY x"; //$NON-NLS-1$
 
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), 
@@ -115,7 +114,7 @@
     }           
 
     // Test what happens when not all the functions in the virtual SELECT can be pushed
-    public void testCase1565_4() throws Exception {
+    @Test public void testCase1565_4() throws Exception {
         // Create query
         String sql = "SELECT x, y FROM (SELECT convert(TimestampValue, date) as x, length(stringkey) as y from bqt1.smalla) as z GROUP BY x, y"; //$NON-NLS-1$
 
@@ -153,7 +152,7 @@
     }       
     
     // Test nested functions
-    public void testCase1565_5() throws Exception {
+    @Test public void testCase1565_5() throws Exception {
         // Create query
         String sql = "SELECT x, COUNT(*) FROM (SELECT convert(intkey + 5, string) AS x FROM bqt1.smalla) as y GROUP BY x"; //$NON-NLS-1$
 
@@ -191,7 +190,7 @@
     }     
     
     // SELECT SUM(x) FROM (SELECT IntKey+1 AS x FROM BQT1.SmallA) AS g
-    public void testAggregateNoGroupByWithNestedFunction() {
+    @Test public void testAggregateNoGroupByWithNestedFunction() {
         ProcessorPlan plan = TestOptimizer.helpPlan("SELECT SUM(x) FROM (SELECT IntKey+1 AS x FROM BQT1.SmallA) AS g", FakeMetadataFactory.exampleBQTCached(), //$NON-NLS-1$
             new String[] { "SELECT IntKey FROM BQT1.SmallA"  }); //$NON-NLS-1$
 
@@ -216,7 +215,7 @@
     /**
      * Without inline view support the agg is not pushed down
      */
-    public void testFunctionInGroupBy() {
+    @Test public void testFunctionInGroupBy() {
         String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000 +' else '0-999' end " + //$NON-NLS-1$
             "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000 +' else '0-999' end"; //$NON-NLS-1$
 
@@ -261,7 +260,7 @@
      * 
      * @since 4.2
      */
-    public void testFunctionInGroupByCantPush() {
+    @Test public void testFunctionInGroupByCantPush() {
         String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000 +' else '0-999' end " + //$NON-NLS-1$
             "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000 +' else '0-999' end"; //$NON-NLS-1$
 
@@ -305,7 +304,7 @@
      * 
      * @since 4.2
      */
-    public void testFunctionInGroupByHavingCantPush() {
+    @Test public void testFunctionInGroupByHavingCantPush() {
         String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000 +' else '0-999' end " + //$NON-NLS-1$
             "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000 +' else '0-999' end " + //$NON-NLS-1$
             "HAVING case when IntKey>=5000 then '5000 +' else '0-999' end = '5000 +'"; //$NON-NLS-1$
@@ -349,7 +348,7 @@
      * 
      * @since 4.2
      */
-    public void testFunctionInGroupByCantPushRewritten() {
+    @Test public void testFunctionInGroupByCantPushRewritten() {
         String sql = "SELECT SUM(IntKey), c FROM (SELECT IntKey, case when IntKey>=5000 then '5000 +' else '0-999' end AS c FROM BQT1.SmallA) AS temp GROUP BY c"; //$NON-NLS-1$
 
         // Plan query
@@ -386,7 +385,7 @@
                                     });        
     }
     
-    public void testFunctionOfAggregateCantPush2() {
+    @Test public void testFunctionOfAggregateCantPush2() {
         String sql = "SELECT SUM(length(StringKey || 'x')) + 1 AS x FROM BQT1.SmallA GROUP BY StringKey || 'x' HAVING space(MAX(length((StringKey || 'x') || 'y'))) = '   '"; //$NON-NLS-1$
 
         // Plan query
@@ -419,7 +418,7 @@
     }
     
     
-    public void testDontPushGroupByUnsupportedFunction() throws Exception {
+    @Test public void testDontPushGroupByUnsupportedFunction() throws Exception {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = new BasicSourceCapabilities();
         caps.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -154,7 +154,7 @@
                                                     metadata, 
                                                     null, 
                                                     capFinder, 
-                                                    new String[] {"SELECT bqt1.smalla.intkey FROM bqt1.smalla", "SELECT BQT2.SmallA.IntKey FROM bqt2.smalla"}, true ); //$NON-NLS-1$  //$NON-NLS-2$
+                                                    new String[] {"SELECT bqt1.smalla.intkey FROM bqt1.smalla", "SELECT 1 FROM bqt2.smalla"}, true ); //$NON-NLS-1$  //$NON-NLS-2$
         
         TestOptimizer.checkNodeTypes(plan, new int[] {
             2,      // Access
@@ -266,7 +266,7 @@
         String sql = "select bqt1.smalla.intkey from bqt1.smalla inner join (select bqt3.smalla.intkey from bqt2.smalla left outer join bqt3.smalla on bqt2.smalla.intkey = bqt3.smalla.intkey and bqt3.smalla.intkey = 1) foo on bqt1.smalla.intkey = foo.intkey"; //$NON-NLS-1$
 
         // Plan query
-        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.intkey FROM bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT g_0.IntKey FROM bqt2.smalla AS g_0", "SELECT g_0.intkey AS c_0 FROM bqt1.smalla AS g_0 ORDER BY c_0"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.intkey FROM bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT 1 FROM bqt2.smalla AS g_0", "SELECT g_0.intkey AS c_0 FROM bqt1.smalla AS g_0 ORDER BY c_0"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
         TestOptimizer.checkNodeTypes(plan, new int[] {
             3,      // Access
@@ -293,7 +293,7 @@
         String sql = "select bqt1.smalla.intkey from bqt1.smalla left outer join (select bqt3.smalla.intkey from bqt3.smalla where bqt3.smalla.intkey = 1) foo on bqt1.smalla.intkey = foo.intkey"; //$NON-NLS-1$
 
         // Plan query
-        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.IntKey FROM bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT g_0.intkey FROM bqt1.smalla AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$ 
+        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT 1 FROM bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT g_0.intkey FROM bqt1.smalla AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$ 
 
         TestOptimizer.checkNodeTypes(plan, new int[] {
             2,      // Access

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -130,8 +130,8 @@
 		String leftQuery = "SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4, RAND() AS RandomLeft " //$NON-NLS-1$
 				+ "FROM pm1.g1"; //$NON-NLS-1$
 		// source query for other side of a JOIN
-		String rightQuery = "SELECT pm2.g2.e1 as ID, pm2.g2.e2, pm2.g2.e3, pm2.g2.e4 " //$NON-NLS-1$
-				+ "FROM pm2.g2"; //$NON-NLS-1$
+		String rightQuery = "SELECT pm1.g2.e1 as ID, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4 " //$NON-NLS-1$
+				+ "FROM pm1.g2"; //$NON-NLS-1$
 
 		// User Command
 		/*
@@ -147,7 +147,7 @@
 		// The user command should result in two atomic commands
 		String[] expected = new String[] {
 				"SELECT g_0.e1, g_0.e2, g_0.e3, g_0.e4 FROM pm1.g1 AS g_0",  //$NON-NLS-1$
-				"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm2.g2 AS g_0 ORDER BY c_0",  //$NON-NLS-1$
+				"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g2 AS g_0 ORDER BY c_0",  //$NON-NLS-1$
 		};
 
 		// create a plan and assert our atomic queries
@@ -169,7 +169,40 @@
 				0 // UnionAll
 		});
 	}
+	
+	/**
+	 * Note that we detect the lower rand is not used 
+	 */
+	public void testNonDeterministicPreJoin1() throws Exception {
+		// source query for one side of a JOIN
+		String leftQuery = "SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4, RAND() AS RandomLeft " //$NON-NLS-1$
+				+ "FROM pm1.g1"; //$NON-NLS-1$
+		// source query for other side of a JOIN
+		String rightQuery = "SELECT pm1.g2.e1 as ID, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4 " //$NON-NLS-1$
+				+ "FROM pm1.g2"; //$NON-NLS-1$
 
+		// User Command
+		/*
+		 * Return everything from the JOIN. TopRandom is the use of RAND() on
+		 * the user command while RandomLeft is the use of RAND() within a
+		 * source node.
+		 */
+		String sql = "SELECT l.ID, l.e2, l.e3, l.e4, r.ID, r.e2, r.e3, r.e4 " + //$NON-NLS-1$
+				"FROM (" + leftQuery + ") AS l, " + //$NON-NLS-1$ //$NON-NLS-2$
+				"(" + rightQuery + ") AS r " + //$NON-NLS-1$ //$NON-NLS-2$
+				"WHERE l.ID = r.ID"; //$NON-NLS-1$
+
+		// The user command should result in two atomic commands
+		String[] expected = new String[] {
+				"SELECT g_0.e1, g_0.e2, g_0.e3, g_0.e4, g_1.e1, g_1.e2, g_1.e3, g_1.e4 FROM pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE g_0.e1 = g_1.e1",  //$NON-NLS-1$
+		};
+
+		// create a plan and assert our atomic queries
+        ProcessorPlan plan = TestOptimizer.helpPlan(sql, TestOptimizer.example1(), expected, 
+        		ComparisonMode.EXACT_COMMAND_STRING);
+		TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
+	}
+
 	/**
 	 * <p>Test the use of a non-deterministic function on the sub-command of a user
 	 * command and the user command itself, which performs a JOIN of two sources.</p>

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -949,8 +949,8 @@
     /** defect #4997 */
     @Test public void testCountStarNoRows() { 
         ProcessorPlan plan = helpPlan("select count(*) from vm1.u4", example1(), //$NON-NLS-1$
-            new String[] { "SELECT e1 FROM pm1.g2",  //$NON-NLS-1$
-                            "SELECT e1 FROM pm1.g1" } ); //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm1.g2",  //$NON-NLS-1$
+                            "SELECT 1 FROM pm1.g1" } ); //$NON-NLS-1$
         checkNodeTypes(plan, new int[] {
             2,      // Access
             0,      // DependentAccess
@@ -962,7 +962,7 @@
             0,      // MergeJoinStrategy
             0,      // Null
             0,      // PlanExecution
-            2,      // Project
+            1,      // Project
             0,      // Select
             0,      // Sort
             1       // UnionAll
@@ -971,7 +971,7 @@
 
     @Test public void testPushingCriteriaWithCopy() { 
     	ProcessorPlan plan = helpPlan("select vm1.u1.e1 from vm1.u1, pm1.g1 where vm1.u1.e1='abc' and vm1.u1.e1=pm1.g1.e1", example1(), //$NON-NLS-1$
-			new String[] { "SELECT pm1.g1.e1 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'", //$NON-NLS-1$
+			new String[] { "SELECT 1 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'", //$NON-NLS-1$
                             "SELECT pm1.g3.e1, pm1.g3.e2, pm1.g3.e3, pm1.g3.e4 FROM pm1.g3 WHERE pm1.g3.e1 = 'abc'", //$NON-NLS-1$
 							"SELECT pm1.g2.e1, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4 FROM pm1.g2 WHERE pm1.g2.e1 = 'abc'", //$NON-NLS-1$
 							"SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'" } ); //$NON-NLS-1$
@@ -1057,17 +1057,17 @@
 
     @Test public void testDefect5282_1() {
         helpPlan("select * FROM vm1.a4 WHERE vm1.a4.count > 0", example1(), //$NON-NLS-1$
-            new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );     //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm1.g1" } );     //$NON-NLS-1$
     }
 
     @Test public void testDefect5282_2() {
         helpPlan("select count(*) FROM vm1.a4", example1(), //$NON-NLS-1$
-            new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );     //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm1.g1" } );     //$NON-NLS-1$
     }
 
     @Test public void testDefect5282_3() {
         helpPlan("select * FROM vm1.a5 WHERE vm1.a5.count > 0", example1(), //$NON-NLS-1$
-            new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );     //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm1.g1" } );     //$NON-NLS-1$
     }
     
     @Test public void testDepJoinHintBaseline() throws Exception {
@@ -1100,8 +1100,8 @@
 
     @Test public void testDefect6425_2() {
         helpPlan("select count(*) from vm1.u9", example1(), //$NON-NLS-1$
-            new String[] { "SELECT e1 FROM pm1.g1", //$NON-NLS-1$
-                            "SELECT e1 FROM pm1.g2" } );     //$NON-NLS-1$
+            new String[] { "SELECT 1 FROM pm1.g1", //$NON-NLS-1$
+                            "SELECT 1 FROM pm1.g2" } );     //$NON-NLS-1$
     }
     
     @Test public void testPushMatchCritWithReference() {
@@ -2714,7 +2714,7 @@
      */
     @Test public void testCrossJoinNoElementCriteriaOptimization2() {
         ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y where {b'true'} = {b'true'}", example1(),  //$NON-NLS-1$
-            new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
+            new String[]{"SELECT 1 FROM pm1.g1 AS g1__1", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
         checkNodeTypes(plan, new int[] {
             2,      // Access
             0,      // DependentAccess
@@ -2738,7 +2738,7 @@
      */
     @Test public void testCrossJoinNoElementCriteriaOptimization3() {
         ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y where {b'true'} in (select e3 FROM vm1.g1)", example1(),  //$NON-NLS-1$
-            new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
+            new String[]{"SELECT 1 FROM pm1.g1 AS g1__1", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
         checkNodeTypes(plan, new int[] {
             2,      // Access
             0,      // DependentAccess
@@ -2768,7 +2768,7 @@
         capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
         
         ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y where {b'true'} in (select e3 FROM vm1.g1)", example1(), null, capFinder,  //$NON-NLS-1$
-            new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1 WHERE TRUE IN (SELECT pm1.g1.e3 FROM pm1.g1)", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, true); //$NON-NLS-1$ //$NON-NLS-2$
+            new String[]{"SELECT 1 FROM pm1.g1 AS g1__1 WHERE TRUE IN (SELECT pm1.g1.e3 FROM pm1.g1)", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, true); //$NON-NLS-1$ //$NON-NLS-2$
         checkNodeTypes(plan, new int[] {
             2,      // Access
             0,      // DependentAccess
@@ -4488,7 +4488,7 @@
         ProcessorPlan plan = helpPlan(sql,  
                                       FakeMetadataFactory.exampleBQTCached(),
                                       null, capFinder,
-                                      new String[] {"SELECT '' AS y FROM BQT1.SmallA AS a UNION ALL SELECT '' FROM bqt1.smallb AS b"}, //$NON-NLS-1$ 
+                                      new String[] {"SELECT 1 AS c_0 FROM BQT1.SmallA AS a UNION ALL SELECT 1 AS c_0 FROM bqt1.smallb AS b"}, //$NON-NLS-1$ 
                                       SHOULD_SUCCEED );
 
         checkNodeTypes(plan, new int[] {
@@ -6409,7 +6409,7 @@
         capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
         
         helpPlan("select pm2.g1.e1 FROM pm2.g1 CROSS JOIN pm2.g2", example1(), null, capFinder, //$NON-NLS-1$
-            new String[] { "SELECT pm2.g1.e1 FROM pm2.g1", "SELECT pm2.g2.e1 FROM pm2.g2"}, true ); //$NON-NLS-1$ //$NON-NLS-2$
+            new String[] { "SELECT pm2.g1.e1 FROM pm2.g1", "SELECT 1 FROM pm2.g2"}, true ); //$NON-NLS-1$ //$NON-NLS-2$
                
     }
     
@@ -6430,7 +6430,7 @@
         String sql = "select count(*) from (select intkey from bqt1.smalla union all select intkey from bqt1.smallb) as a"; //$NON-NLS-1$
         
         ProcessorPlan plan = helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null, capFinder, 
-                                      new String[] {"SELECT COUNT(*) FROM (SELECT intkey FROM bqt1.smalla UNION ALL SELECT intkey FROM bqt1.smallb) AS a"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$ 
+                                      new String[] {"SELECT COUNT(*) FROM (SELECT 1 FROM bqt1.smalla UNION ALL SELECT 1 FROM bqt1.smallb) AS a"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$ 
         
         checkNodeTypes(plan, FULL_PUSHDOWN); 
     }

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -22,8 +22,11 @@
 
 package org.teiid.query.optimizer;
 
+import static org.junit.Assert.*;
+
 import java.util.Arrays;
 
+import org.junit.Test;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
 import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
@@ -33,11 +36,7 @@
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.unittest.FakeMetadataFactory;
 
-import junit.framework.TestCase;
-
-
-
-public class TestRuleRaiseNull extends TestCase {
+public class TestRuleRaiseNull {
     
     public static final int[] FULLY_NULL = new int[] {
                 0,      // Access
@@ -64,7 +63,7 @@
      * never equals anything).  Expected behavior is that a NullNode is inserted in place of the
      * unnecessary access node. 
      */
-    public void testUnionCriteriaOptimization() {
+    @Test public void testUnionCriteriaOptimization() {
 
         String sql = "select * from ( select intkey as cola, null as colb, intnum as colc from bqt1.smalla union all select null, intkey, intnum from bqt2.smalla) as X where X.cola = 1";  //$NON-NLS-1$
         
@@ -75,7 +74,7 @@
         
     }
     
-    public void testRaiseNullWithInnerJoin() {
+    @Test public void testRaiseNullWithInnerJoin() {
         String sql = "select b.intkey from (select intkey from bqt1.smalla where 1 = 0) a inner join (select intkey from bqt1.smallb) b on (a.intkey = b.intkey)"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -83,7 +82,7 @@
         TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
     }
     
-    public void testRaiseNullWithFullOuterJoin() {
+    @Test public void testRaiseNullWithFullOuterJoin() {
         String sql = "select b.intkey from (select intkey from bqt1.smalla) a full outer join (select intkey from bqt1.smallb where 1 = 0) b on (a.intkey = b.intkey)"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -91,7 +90,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithOuterJoin() {
+    @Test public void testRaiseNullWithOuterJoin() {
         String sql = "select b.intkey from (select intkey from bqt1.smalla) a left outer join (select intkey from bqt1.smallb where 1 = 0) b on (a.intkey = b.intkey)"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -99,7 +98,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithOuterJoin1() {
+    @Test public void testRaiseNullWithOuterJoin1() {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
         caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
@@ -112,7 +111,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithUnion() {
+    @Test public void testRaiseNullWithUnion() {
         String sql = "select b.x from (select intkey as x from bqt1.smalla where 1 = 0 union all select intnum as y from bqt1.smalla) b"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -122,7 +121,7 @@
         assertEquals(Arrays.asList(new Object[] {new ElementSymbol("b.x")}), plan.getOutputElements()); //$NON-NLS-1$
     }    
 
-    public void testRaiseNullWithUnion1() {
+    @Test public void testRaiseNullWithUnion1() {
         String sql = "select b.intkey from (select intkey from bqt1.smalla union all select intnum from bqt1.smalla where 1 = 0) b"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -130,7 +129,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }    
     
-    public void testRaiseNullWithUnion2() {
+    @Test public void testRaiseNullWithUnion2() {
         String sql = "select b.intkey, b.x from (select intkey, intnum as x from bqt1.smalla where 1 = 0 union all select intnum as a, null from bqt1.smalla union all select 1 as z, intkey as b from bqt1.smallb) b"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -153,7 +152,7 @@
         });
     }    
     
-    public void testRaiseNullWithUnion3() {
+    @Test public void testRaiseNullWithUnion3() {
         String sql = "select intkey, intnum as x from bqt1.smalla where 1 = 0 union all select intnum, intkey as z from bqt1.smalla where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -161,7 +160,7 @@
         TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
     } 
 
-    public void testRaiseNullWithUnion4() throws Exception {
+    @Test public void testRaiseNullWithUnion4() throws Exception {
         String sql = "select b.intkey, b.x from (select intkey, intnum as x from bqt1.smalla where 1 = 0 union all select 1 as z, intkey as b from bqt1.smallb) b inner join bqt1.smalla on b.intkey = bqt1.smalla.intkey"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -169,7 +168,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithUnion5() {
+    @Test public void testRaiseNullWithUnion5() {
         String sql = "select intkey from bqt1.smalla union all select intkey from bqt2.smalla where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -177,7 +176,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithUnion6() {
+    @Test public void testRaiseNullWithUnion6() {
         String sql = "select intkey from bqt1.smalla union all select intkey from bqt2.smalla union all select intkey from bqt2.smalla where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -200,17 +199,17 @@
         });
     }
     
-    public void testPushCriteriaThroughUnion9() {
+    @Test public void testPushCriteriaThroughUnion9() {
         TestOptimizer.helpPlan("select * from vm1.u8 where const = 's1'", TestOptimizer.example1(), //$NON-NLS-1$
             new String[] { "SELECT 's1', e1 FROM pm1.g1" } );     //$NON-NLS-1$
     }
 
-    public void testPushCriteriaThroughUnion10() {
+    @Test public void testPushCriteriaThroughUnion10() {
         TestOptimizer.helpPlan("select * from vm1.u8 where const = 's3'", TestOptimizer.example1(), //$NON-NLS-1$
             new String[] { "SELECT 's3', e1 FROM pm1.g3" } );     //$NON-NLS-1$
     }
     
-    public void testRaiseNullWithOuterJoinAndHaving() {
+    @Test public void testRaiseNullWithOuterJoinAndHaving() {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
         caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
@@ -242,7 +241,7 @@
      * Ensures proper handling of the removal of the first branch and
      * duplicate symbol names in the next branch
      */
-    public void testRaiseNullWithUnion7() throws Exception {
+    @Test public void testRaiseNullWithUnion7() throws Exception {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
         caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -260,7 +259,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithUnionOrderBy() {
+    @Test public void testRaiseNullWithUnionOrderBy() {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
         caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -276,7 +275,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithGroupBy() {
+    @Test public void testRaiseNullWithGroupBy() {
         String sql = "select max(e2), e1 from pm1.g1 where 1 = 0 group by e1"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[]{});
@@ -284,7 +283,7 @@
         TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
     }
 
-    public void testRaiseNullWithGroupBy1() {
+    @Test public void testRaiseNullWithGroupBy1() {
         String sql = "select max(e2) from pm1.g1 where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[]{});
@@ -307,7 +306,7 @@
         });
     }
     
-    public void testRaiseNullWithExcept() {
+    @Test public void testRaiseNullWithExcept() {
         String sql = "select e1 from pm1.g1 except select e2 from pm1.g2 where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[]{"SELECT DISTINCT g_0.e1 FROM pm1.g1 AS g_0"}); //$NON-NLS-1$
@@ -315,7 +314,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
 
-    public void testRaiseNullWithIntersect() {
+    @Test public void testRaiseNullWithIntersect() {
         String sql = "select max(e2) from pm1.g1 intersect select e2 from pm1.g2 where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[]{});
@@ -328,19 +327,19 @@
      * but instead is cleaned up properly later
      * See defect 9865
      */
-    public void testCrossJoinNoElementCriteriaOptimization() {
+    @Test public void testCrossJoinNoElementCriteriaOptimization() {
         ProcessorPlan plan = TestOptimizer.helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y where {b'true'} = {b'false'}", TestOptimizer.example1(),  //$NON-NLS-1$
             new String[0]);
         TestOptimizer.checkNodeTypes(plan, FULLY_NULL); 
     }
     
-    public void testSelectLiteralFalseCriteria() {
+    @Test public void testSelectLiteralFalseCriteria() {
         ProcessorPlan plan = TestOptimizer.helpPlan("Select 'x' from pm1.g1 where 1=0", TestOptimizer.example1(),  //$NON-NLS-1$
             new String[] { });
         TestOptimizer.checkNodeTypes(plan, FULLY_NULL); 
     }
     
-    public void testRaiseNullWithUnionNotAll() {
+    @Test public void testRaiseNullWithUnionNotAll() {
         String sql = "select intkey from bqt2.smalla union select intkey from bqt2.smalla where 1 = 0"; //$NON-NLS-1$
         
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(),  
@@ -348,7 +347,7 @@
         TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
     }
     
-    public void testRaiseNullWithUnionAndAliases() {
+    @Test public void testRaiseNullWithUnionAndAliases() {
         String sql = "select pm1.g1.e1 from pm1.g1, (select e1 from pm1.g1 where (1 = 0) union all select e1 as x from pm1.g2) x where pm1.g1.e1 <> x.e1"; //$NON-NLS-1$
         
         RelationalPlan plan = (RelationalPlan)TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(),  

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2011-02-14 20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2011-02-14 20:34:03 UTC (rev 2906)
@@ -6213,8 +6213,8 @@
 
         // Construct data manager with data 
         HardcodedDataManager dataManager = new HardcodedDataManager(); 
-        dataManager.addData("SELECT g_0.a FROM p1.t AS g_0",  //$NON-NLS-1$
-                            new List[] { Arrays.asList(new Object[] { new Integer(1) })});
+        dataManager.addData("SELECT 1 AS c_0 FROM p1.t AS g_1 UNION ALL SELECT 1 AS c_0 FROM p1.t AS g_0",  //$NON-NLS-1$
+                            new List[] { Arrays.asList(1), Arrays.asList(1)});
         helpProcess(plan, dataManager, expected); 
     }
     



More information about the teiid-commits mailing list