[teiid-commits] teiid SVN: r2676 - in branches/7.1.x/engine/src: test/java/org/teiid/query/optimizer and 1 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Oct 22 17:40:33 EDT 2010


Author: shawkins
Date: 2010-10-22 17:40:32 -0400 (Fri, 22 Oct 2010)
New Revision: 2676

Modified:
   branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
   branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java
   branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java
   branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1317 ensuring that limit expressions get evaluated prior to pushdown

Modified: branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2010-10-22 16:24:31 UTC (rev 2675)
+++ branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2010-10-22 21:40:32 UTC (rev 2676)
@@ -39,6 +39,7 @@
 import org.teiid.query.optimizer.relational.RuleStack;
 import org.teiid.query.optimizer.relational.plantree.NodeConstants;
 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.ProcessorPlan;
@@ -378,24 +379,20 @@
 
     private void processLimit(PlanNode node,
                               QueryCommand query, QueryMetadataInterface metadata) {
+    	
         Expression limit = (Expression)node.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT);
-        if (limit != null) {
-            if (query.getLimit() != null) {
-                Expression oldlimit = query.getLimit().getRowLimit();
-                query.getLimit().setRowLimit(RulePushLimit.getMinValue(limit, oldlimit)); 
-            } else {
-                query.setLimit(new Limit(null, limit));
-            }
-        }
         Expression offset = (Expression)node.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT);
-        if (offset != null) {
-            if (query.getLimit() != null) {
-                Expression oldoffset = query.getLimit().getOffset();
-                query.getLimit().setOffset(RulePushLimit.getSum(offset, oldoffset, metadata.getFunctionLibrary())); 
-            } else {
-                query.setLimit(new Limit(offset, null));
-            }
+        
+        PlanNode limitNode = NodeFactory.getNewNode(NodeConstants.Types.TUPLE_LIMIT);
+        Expression childLimit = null;
+        Expression childOffset = null;
+        if (query.getLimit() != null) {
+        	childLimit = query.getLimit().getRowLimit();
+        	childOffset = query.getLimit().getOffset();
         }
+        RulePushLimit.combineLimits(limitNode, metadata, limit, offset, childLimit, childOffset);
+        
+        query.setLimit(new Limit((Expression)limitNode.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT), (Expression)limitNode.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT)));
     }
 
     /** 

Modified: branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java	2010-10-22 16:24:31 UTC (rev 2675)
+++ branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushLimit.java	2010-10-22 21:40:32 UTC (rev 2676)
@@ -26,11 +26,16 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.teiid.api.exception.query.ExpressionEvaluationException;
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryPlannerException;
+import org.teiid.common.buffer.BlockedException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidRuntimeException;
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.query.analysis.AnalysisRecord;
+import org.teiid.query.eval.Evaluator;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -47,7 +52,9 @@
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.Function;
 import org.teiid.query.sql.symbol.SearchedCaseExpression;
+import org.teiid.query.sql.visitor.EvaluatableVisitor;
 import org.teiid.query.util.CommandContext;
+import org.teiid.translator.SourceSystemFunctions;
 
 
 /** 
@@ -116,18 +123,19 @@
             return false;
         }
         
-        switch (child.getType()) {
+        Expression parentLimit = (Expression)limitNode.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT);
+		Expression parentOffset = (Expression)limitNode.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT);
+		switch (child.getType()) {
             case NodeConstants.Types.TUPLE_LIMIT:
             {
+            	
                 //combine the limits
-                Expression minLimit = getMinValue((Expression)limitNode.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT), (Expression)child.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT)); 
-                Expression offSet = getSum((Expression)limitNode.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT), (Expression)child.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT), metadata.getFunctionLibrary()); 
+                Expression childLimit = (Expression)child.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT);
+				Expression childOffset = (Expression)child.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT);
+				
+				combineLimits(limitNode, metadata, parentLimit, parentOffset, childLimit, childOffset);
                 
                 NodeEditor.removeChildNode(limitNode, child);
-                
-                limitNode.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, minLimit);
-                limitNode.setProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT, offSet);
-                
                 limitNodes.remove(child);
                 
                 return canPushLimit(rootNode, limitNode, limitNodes, metadata, capFinder);
@@ -141,9 +149,7 @@
                 List<PlanNode> grandChildren = new LinkedList<PlanNode>(child.getChildren());
                 for (PlanNode grandChild : grandChildren) {
                     PlanNode newLimit = NodeFactory.getNewNode(NodeConstants.Types.TUPLE_LIMIT);
-                    Expression limit = (Expression)limitNode.getProperty(NodeConstants.Info.MAX_TUPLE_LIMIT);
-                    Expression offset = (Expression)limitNode.getProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT);
-                    newLimit.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, getSum(limit, offset, metadata.getFunctionLibrary()));
+                    newLimit.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, op(SourceSystemFunctions.ADD_OP, parentLimit, parentOffset, metadata.getFunctionLibrary()));
                     grandChild.addAsParent(newLimit);
                     limitNodes.add(newLimit);
                 }
@@ -171,6 +177,28 @@
             }
         }
     }
+
+	static void combineLimits(PlanNode limitNode,
+			QueryMetadataInterface metadata, Expression parentLimit,
+			Expression parentOffset, Expression childLimit,
+			Expression childOffset) {
+		Expression minLimit = null;
+		Expression offSet = null;
+		
+		if (childLimit == null) {
+			minLimit = parentLimit;
+			offSet = op(SourceSystemFunctions.ADD_OP, childOffset, parentOffset, metadata.getFunctionLibrary());
+		} else {
+			minLimit = getMinValue(parentLimit, op(SourceSystemFunctions.SUBTRACT_OP, childLimit, parentOffset, metadata.getFunctionLibrary())); 
+		    offSet = childOffset;
+		    if (offSet == null) {
+		    	offSet = parentOffset;
+		    }
+		}
+		
+		limitNode.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, minLimit);
+		limitNode.setProperty(NodeConstants.Info.OFFSET_TUPLE_COUNT, offSet);
+	}
     
     static PlanNode raiseAccessOverLimit(PlanNode rootNode,
                                           PlanNode accessNode,
@@ -206,7 +234,7 @@
                 
                 // since we're pushing underneath the offset, we want enough rows to satisfy both the limit and the row offset
                 
-                pushedLimit.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, getSum(limit, offset, metadata.getFunctionLibrary())); 
+                pushedLimit.setProperty(NodeConstants.Info.MAX_TUPLE_LIMIT, op(SourceSystemFunctions.ADD_OP, limit, offset, metadata.getFunctionLibrary())); 
                 
                 if (accessNode.getChildCount() == 0) {
                     accessNode.addFirstChild(pushedLimit);
@@ -221,11 +249,7 @@
         return RuleRaiseAccess.performRaise(rootNode, accessNode, parentNode);
     }
 
-    /**
-     * @param limitNode
-     * @param child
-     */
-    static Expression getSum(Expression expr1, Expression expr2, FunctionLibrary functionLibrary) {
+    static Expression op(String op, Expression expr1, Expression expr2, FunctionLibrary functionLibrary) {
         if (expr1 == null) {
             return expr2;
         }
@@ -233,15 +257,29 @@
             return expr1;
         }
         
-        Function newExpr = new Function("+", new Expression[] {expr1, expr2}); //$NON-NLS-1$
-        newExpr.setFunctionDescriptor(functionLibrary.findFunction("+", new Class[] {DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER})); //$NON-NLS-1$
+        Function newExpr = new Function(op, new Expression[] {expr1, expr2});
+        newExpr.setFunctionDescriptor(functionLibrary.findFunction(op, new Class[] {DataTypeManager.DefaultDataClasses.INTEGER, DataTypeManager.DefaultDataClasses.INTEGER}));
         newExpr.setType(newExpr.getFunctionDescriptor().getReturnType());
+        return evaluateIfPossible(newExpr);
+    }
+
+	private static Expression evaluateIfPossible(Expression newExpr) {
+		if (EvaluatableVisitor.isFullyEvaluatable(newExpr, true)) {
+        	try {
+				return new Constant(Evaluator.evaluate(newExpr), newExpr.getType());
+			} catch (TeiidException e) {
+				throw new TeiidRuntimeException(e, "Unexpected Exception"); //$NON-NLS-1$
+			}
+        }
         return newExpr;
-    }
+	}
     
     /**
      * @param limitNode
      * @param child
+     * @throws TeiidComponentException 
+     * @throws BlockedException 
+     * @throws ExpressionEvaluationException 
      */
     static Expression getMinValue(Expression expr1, Expression expr2) {
         if (expr1 == null) {
@@ -254,7 +292,8 @@
         Criteria crit = new CompareCriteria(expr1, CompareCriteria.LT, expr2);
         SearchedCaseExpression sce = new SearchedCaseExpression(Arrays.asList(new Object[] {crit}), Arrays.asList(new Object[] {expr1}));
         sce.setElseExpression(expr2);
-        return sce;
+        sce.setType(expr1.getType());
+        return evaluateIfPossible(sce);
     }
     
     /**

Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java	2010-10-22 16:24:31 UTC (rev 2675)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java	2010-10-22 21:40:32 UTC (rev 2676)
@@ -268,7 +268,7 @@
 
         String sql = "SELECT * FROM pm1.g1 limit 50, 100";//$NON-NLS-1$
         String[] expectedSql = new String[] {
-            "SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1 LIMIT (100 + 50)" //$NON-NLS-1$
+            "SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1 LIMIT 150" //$NON-NLS-1$
             };
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), 
                                                     null, capFinder, expectedSql, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);  
@@ -535,7 +535,7 @@
 
         String sql = "SELECT * FROM pm1.g1 UNION SELECT * FROM PM1.g2 LIMIT 50, 100";//$NON-NLS-1$
         String[] expectedSql = new String[] {
-            "SELECT PM1.g2.e1 AS c_0, PM1.g2.e2 AS c_1, PM1.g2.e3 AS c_2, PM1.g2.e4 AS c_3 FROM PM1.g2 LIMIT (100 + 50)", "SELECT pm1.g1.e1 AS c_0, pm1.g1.e2 AS c_1, pm1.g1.e3 AS c_2, pm1.g1.e4 AS c_3 FROM pm1.g1 LIMIT (100 + 50)" //$NON-NLS-1$ //$NON-NLS-2$
+            "SELECT PM1.g2.e1 AS c_0, PM1.g2.e2 AS c_1, PM1.g2.e3 AS c_2, PM1.g2.e4 AS c_3 FROM PM1.g2 LIMIT 150", "SELECT pm1.g1.e1 AS c_0, pm1.g1.e2 AS c_1, pm1.g1.e3 AS c_2, pm1.g1.e4 AS c_3 FROM pm1.g1 LIMIT 150" //$NON-NLS-1$ //$NON-NLS-2$
             };
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), 
                                                     null, capFinder, expectedSql, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);  
@@ -603,7 +603,7 @@
 
         String sql = "SELECT * from (SELECT pm1.g1.e1 FROM pm1.g1 LIMIT 10, 100) x LIMIT 20, 75";//$NON-NLS-1$
         String[] expectedSql = new String[] {
-            "SELECT pm1.g1.e1 AS c_0 FROM pm1.g1 LIMIT CASE WHEN (75 + (20 + 10)) < (100 + 10) THEN (75 + (20 + 10)) ELSE (100 + 10) END" //$NON-NLS-1$
+            "SELECT pm1.g1.e1 AS c_0 FROM pm1.g1 LIMIT 105" //$NON-NLS-1$
             };
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), 
                                                     null, capFinder, expectedSql, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);  
@@ -636,9 +636,9 @@
         // pm1 model supports order by
         capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
 
-        String sql = "SELECT * from (SELECT pm1.g1.e1 FROM pm1.g1 LIMIT 10, 100) x LIMIT 20, 75";//$NON-NLS-1$
+        String sql = "SELECT * from (SELECT pm1.g1.e1 FROM pm1.g1 LIMIT 10, 100) x LIMIT 40, 75";//$NON-NLS-1$
         String[] expectedSql = new String[] {
-            "SELECT pm1.g1.e1 AS c_0 FROM pm1.g1 LIMIT (20 + 10), CASE WHEN 75 < 100 THEN 75 ELSE 100 END" //$NON-NLS-1$
+            "SELECT pm1.g1.e1 AS c_0 FROM pm1.g1 LIMIT 10, 60" //$NON-NLS-1$
             };
         ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), 
                                                     null, capFinder, expectedSql, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);  

Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2010-10-22 16:24:31 UTC (rev 2675)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2010-10-22 21:40:32 UTC (rev 2676)
@@ -68,7 +68,6 @@
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.function.FunctionTree;
-import org.teiid.query.function.SystemFunctionManager;
 import org.teiid.query.function.UDFSource;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.metadata.QueryMetadataInterface;
@@ -7338,7 +7337,7 @@
         FakeDataManager dataManager = new FakeDataManager();
         sampleData2(dataManager);
         
-        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), null, capFinder, new String[] {"SELECT pm1.g1.e1 FROM pm1.g1 LIMIT (5 + 1)"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+        ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), null, capFinder, new String[] {"SELECT pm1.g1.e1 FROM pm1.g1 LIMIT 6"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
         helpProcess(plan, dataManager, expected);          
     }
     



More information about the teiid-commits mailing list