[teiid-commits] teiid SVN: r4632 - in branches/7.7.x/engine/src: test/java/org/teiid/query/optimizer and 1 other directory.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Mon Apr 21 16:33:54 EDT 2014


Author: jolee
Date: 2014-04-21 16:33:53 -0400 (Mon, 21 Apr 2014)
New Revision: 4632

Modified:
   branches/7.7.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
   branches/7.7.x/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java
Log:
TEIID-2921: Allow the projection raising (or order pushing) logic to work with non-simple ordering expressions

Modified: branches/7.7.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
--- branches/7.7.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java	2014-04-16 18:26:12 UTC (rev 4631)
+++ branches/7.7.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java	2014-04-21 20:33:53 UTC (rev 4632)
@@ -23,6 +23,7 @@
 package org.teiid.query.optimizer.relational.rules;
 
 import java.util.ArrayList;
+import java.util.LinkedHashSet;
 import java.util.List;
 
 import org.teiid.api.exception.query.QueryMetadataException;
@@ -34,9 +35,10 @@
 import org.teiid.query.optimizer.relational.OptimizerRule;
 import org.teiid.query.optimizer.relational.RuleStack;
 import org.teiid.query.optimizer.relational.plantree.NodeConstants;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
 import org.teiid.query.optimizer.relational.plantree.NodeEditor;
+import org.teiid.query.optimizer.relational.plantree.NodeFactory;
 import org.teiid.query.optimizer.relational.plantree.PlanNode;
-import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
 import org.teiid.query.processor.relational.JoinNode.JoinStrategyType;
 import org.teiid.query.processor.relational.MergeJoinStrategy.SortOption;
 import org.teiid.query.sql.lang.OrderBy;
@@ -236,17 +238,34 @@
 		List<SingleElementSymbol> childOutputCols = (List<SingleElementSymbol>) projectNode.getFirstChild().getProperty(Info.OUTPUT_COLS);
 		OrderBy orderBy = (OrderBy) node.getProperty(Info.SORT_ORDER);
 		List<SingleElementSymbol> orderByKeys = orderBy.getSortKeys();
+		LinkedHashSet<SingleElementSymbol> toProject = new LinkedHashSet<SingleElementSymbol>();
 		for (SingleElementSymbol ss : orderByKeys) {
+			SingleElementSymbol original = ss;
 			if(ss instanceof AliasSymbol) {
                 ss = ((AliasSymbol)ss).getSymbol();
             }
             if (ss instanceof ExpressionSymbol && !(ss instanceof AggregateSymbol)) {
-                return root; //TODO: insert a new project node to handle this case
+            	if (!raiseAccess) {
+            		return root; //TODO: insert a new project node to handle this case
+            	}
             }
 			if (!childOutputCols.contains(ss)) {
-				return root;
+				if (!raiseAccess) {
+					return root;
+				}
+				toProject.add(original);
 			}
 		}
+		PlanNode toRepair = projectNode.getParent();
+		if (!toProject.isEmpty()) {
+			PlanNode intermediateProject = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
+			toProject.addAll(childOutputCols);
+			List<SingleElementSymbol> projectCols = new ArrayList<SingleElementSymbol>(toProject);
+			childOutputCols = projectCols;
+			intermediateProject.setProperty(NodeConstants.Info.PROJECT_COLS, projectCols);
+			intermediateProject.setProperty(NodeConstants.Info.OUTPUT_COLS, new ArrayList<Expression>(projectCols));
+			toRepair.getFirstChild().addAsParent(intermediateProject);
+		}
 		NodeEditor.removeChildNode(projectNode.getParent(), projectNode);
 		if (parent != null && parent.getType() == NodeConstants.Types.TUPLE_LIMIT && parent.getParent() != null) {
 			parent.addAsParent(projectNode);
@@ -270,14 +289,16 @@
 			unrelated = true;
 		}
 		for (OrderByItem item : orderBy.getOrderByItems()) {
-			if (unrelated) {
+			if (unrelated || !toProject.isEmpty()) {
 			    //update sort order
 				int index = childOutputCols.indexOf(item.getSymbol());
 				item.setExpressionPosition(index);
 			}
-			//strip alias as project was raised
-			if (item.getSymbol() instanceof AliasSymbol) {
-				item.setSymbol(((AliasSymbol)item.getSymbol()).getSymbol());
+			if (toProject.isEmpty()) {
+				//strip alias as project was raised
+				if (item.getSymbol() instanceof AliasSymbol) {
+					item.setSymbol(((AliasSymbol)item.getSymbol()).getSymbol());
+				}
 			}
 		}
 		projectNode.setProperty(Info.OUTPUT_COLS, orderByOutputSymbols);
@@ -287,17 +308,25 @@
 			parent.setProperty(Info.OUTPUT_COLS, childOutputCols);
 		}
 		if (raiseAccess) {
-			PlanNode accessNode = node.getFirstChild();
+			PlanNode accessNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.ACCESS);
+			
 			//instead of just calling ruleraiseaccess, we're more selective
 			//we do not want to raise the access node over a project that is handling an unrelated sort
 			PlanNode newRoot = RuleRaiseAccess.raiseAccessNode(root, accessNode, metadata, capFinder, true, record);
 			if (newRoot != null) {
+				accessNode.setProperty(NodeConstants.Info.OUTPUT_COLS, childOutputCols);
 				root = newRoot;
-				if (accessNode.getParent().getType() == NodeConstants.Types.TUPLE_LIMIT) {
-					newRoot = RulePushLimit.raiseAccessOverLimit(root, accessNode, metadata, capFinder, accessNode.getParent(), record);
+				if (!toProject.isEmpty()) {
+					newRoot = RuleRaiseAccess.raiseAccessNode(root, accessNode, metadata, capFinder, true, record);
 				}
 				if (newRoot != null) {
 					root = newRoot;
+					if (accessNode.getParent().getType() == NodeConstants.Types.TUPLE_LIMIT) {
+						newRoot = RulePushLimit.raiseAccessOverLimit(root, accessNode, metadata, capFinder, accessNode.getParent(), record);
+					}
+					if (newRoot != null) {
+						root = newRoot;
+					}
 				}
 			}
 		}

Modified: branches/7.7.x/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java
===================================================================
--- branches/7.7.x/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java	2014-04-16 18:26:12 UTC (rev 4631)
+++ branches/7.7.x/engine/src/test/java/org/teiid/query/optimizer/TestSortOptimization.java	2014-04-21 20:33:53 UTC (rev 4632)
@@ -25,18 +25,25 @@
 import static org.junit.Assert.*;
 import static org.teiid.query.optimizer.TestOptimizer.*;
 
+import java.util.Arrays;
+import java.util.List;
+
 import org.junit.Test;
 import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
 import org.teiid.query.optimizer.TestOptimizer.DupRemoveSortNode;
 import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
+import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
 import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
 import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
 import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
+import org.teiid.query.processor.HardcodedDataManager;
 import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.processor.TestProcessor;
 import org.teiid.query.processor.relational.LimitNode;
 import org.teiid.query.processor.relational.ProjectNode;
 import org.teiid.query.processor.relational.RelationalPlan;
 import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.translator.SourceSystemFunctions;
 
 
 public class TestSortOptimization {
@@ -300,6 +307,33 @@
                                       new String[] {"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm1.g1 AS g_0 ORDER BY c_0 LIMIT 1"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
     }
     
+    @Test public void testProjectionRaisingWithComplexOrdering() { 
+        String sql = "select e1 || 1, e2 / 2 from pm1.g1 as x order by e1 || 1 limit 2"; //$NON-NLS-1$
+        BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
+        bsc.setFunctionSupport(SourceSystemFunctions.CONCAT, true);
+        bsc.setCapabilitySupport(Capability.ROW_LIMIT, true);
+        CapabilitiesFinder finder = new DefaultCapabilitiesFinder(bsc);
+        RelationalPlan plan = (RelationalPlan)helpPlan(sql, RealMetadataFactory.example1Cached(), null, finder, 
+                                      new String[] {"SELECT concat(g_0.e1, '1') AS c_0, g_0.e1 AS c_1, g_0.e2 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0 LIMIT 2"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
+        
+        assertTrue(plan.getRootNode() instanceof ProjectNode);
+    }
+    
+    @Test public void testProjectionRaisingWithComplexOrdering1() { 
+        String sql = "select e1 || 1 as a, e2 / 2 from pm1.g1 as x order by a, e2 limit 2"; //$NON-NLS-1$
+        BasicSourceCapabilities bsc = TestOptimizer.getTypicalCapabilities();
+        bsc.setFunctionSupport(SourceSystemFunctions.CONCAT, true);
+        bsc.setCapabilitySupport(Capability.ROW_LIMIT, true);
+        CapabilitiesFinder finder = new DefaultCapabilitiesFinder(bsc);
+        RelationalPlan plan = (RelationalPlan)helpPlan(sql, RealMetadataFactory.example1Cached(), null, finder, 
+                                      new String[] {"SELECT concat(g_0.e1, '1') AS c_0, g_0.e1 AS c_1, g_0.e2 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0, c_2 LIMIT 2"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
+        
+        assertTrue(plan.getRootNode() instanceof ProjectNode);
+        HardcodedDataManager hdm = new HardcodedDataManager();
+        hdm.addData("SELECT concat(g_0.e1, '1') AS c_0, g_0.e1 AS c_1, g_0.e2 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0, c_2 LIMIT 2", new List<?>[] {Arrays.asList("c1", "c", 2), Arrays.asList("d1", "d", 3)});
+        TestProcessor.helpProcess(plan, hdm, new List<?>[] {Arrays.asList("c1", 1), Arrays.asList("d1", 1)});
+    }
+    
     //TODO this should trigger another view removal and thus the combination of the grouping/dup operation
     @Test public void testGroupDupCombination1Pushdown() { 
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();



More information about the teiid-commits mailing list