[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