Author: shawkins
Date: 2012-01-07 11:10:27 -0500 (Sat, 07 Jan 2012)
New Revision: 3781
Modified:
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCleanCriteria.java
branches/7.6.x/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java
Log:
TEIID-1893 fix for invalid output columns
Modified:
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
---
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2012-01-06
20:53:01 UTC (rev 3780)
+++
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2012-01-07
16:10:27 UTC (rev 3781)
@@ -408,7 +408,7 @@
rules.push(RuleConstants.PLAN_SORTS);
- //TODO: update plan sorts to take advantage or semi-join ordering
+ //TODO: update plan sorts to take advantage of semi-join ordering
if (hints.hasJoin || hints.hasCriteria) {
rules.push(new RuleMergeCriteria(idGenerator, capFinder, analysisRecord,
context, metadata));
}
@@ -431,9 +431,7 @@
rules.push(new RulePushAggregates(idGenerator));
}
if(hints.hasJoin) {
- rules.push(RuleConstants.CHOOSE_DEPENDENT);
- }
- if(hints.hasJoin) {
+ rules.push(RuleConstants.CHOOSE_DEPENDENT);
rules.push(RuleConstants.CHOOSE_JOIN_STRATEGY);
rules.push(RuleConstants.RAISE_ACCESS);
//after planning the joins, let the criteria be pushed back into place
@@ -444,8 +442,9 @@
if (hints.hasSetQuery) {
rules.push(RuleConstants.PLAN_UNIONS);
}
- if(hints.hasCriteria || hints.hasJoin) {
+ if(hints.hasCriteria || hints.hasJoin || hints.hasVirtualGroups) {
//after copy criteria, it is no longer necessary to have phantom criteria
nodes, so do some cleaning
+ //also remove possible erroneous output elements
rules.push(RuleConstants.CLEAN_CRITERIA);
}
if(hints.hasJoin) {
Modified:
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
---
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2012-01-06
20:53:01 UTC (rev 3780)
+++
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2012-01-07
16:10:27 UTC (rev 3781)
@@ -310,10 +310,14 @@
QueryMetadataInterface metadata, float cost)
throws QueryMetadataException, TeiidComponentException {
PlanNode projectNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.PROJECT);
+ float result = cost;
if (projectNode != null) {
- cost = getNDVEstimate(node.getParent(), metadata, cost,
(List)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS), false);
+ result = getNDVEstimate(node.getParent(), metadata, cost,
(List)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS), false);
+ if (result == UNKNOWN_VALUE) {
+ return cost;
+ }
}
- return cost;
+ return result;
}
private static void setCardinalityEstimate(PlanNode node, Float bestEstimate, boolean
setColEstimates, QueryMetadataInterface metadata) throws QueryMetadataException,
TeiidComponentException {
Modified:
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCleanCriteria.java
===================================================================
---
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCleanCriteria.java 2012-01-06
20:53:01 UTC (rev 3780)
+++
branches/7.6.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCleanCriteria.java 2012-01-07
16:10:27 UTC (rev 3781)
@@ -35,6 +35,7 @@
import org.teiid.query.optimizer.relational.plantree.NodeConstants;
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.util.CommandContext;
@@ -53,40 +54,7 @@
boolean pushRaiseNull = false;
- for (PlanNode critNode : NodeEditor.findAllNodes(plan,
NodeConstants.Types.SELECT)) {
-
- if (critNode.hasBooleanProperty(NodeConstants.Info.IS_PHANTOM)) {
- NodeEditor.removeChildNode(critNode.getParent(), critNode);
- continue;
- }
-
- //TODO: remove dependent set criteria that has not been meaningfully pushed
from its parent join
-
- if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING) ||
critNode.getGroups().size() != 0) {
- continue;
- }
-
- Criteria crit =
(Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
- //if not evaluatable, just move on to the next criteria
- if (!EvaluatableVisitor.isFullyEvaluatable(crit, true)) {
- continue;
- }
- //if evaluatable
- try {
- boolean eval = Evaluator.evaluate(crit);
- if(eval) {
- NodeEditor.removeChildNode(critNode.getParent(), critNode);
- } else {
- FrameUtil.replaceWithNullNode(critNode);
- pushRaiseNull = true;
- }
- //none of the following exceptions should ever occur
- } catch(BlockedException e) {
- throw new TeiidComponentException(e);
- } catch (ExpressionEvaluationException e) {
- throw new TeiidComponentException(e);
- }
- }
+ pushRaiseNull = clean(plan);
if (pushRaiseNull) {
rules.push(RuleConstants.RAISE_NULL);
@@ -94,7 +62,55 @@
return plan;
}
+
+ private boolean clean(PlanNode plan)
+ throws TeiidComponentException {
+ boolean pushRaiseNull = false;
+ plan.setProperty(Info.OUTPUT_COLS, null);
+ for (PlanNode node : plan.getChildren()) {
+ pushRaiseNull |= clean(node);
+ }
+ if (plan.getType() == NodeConstants.Types.SELECT) {
+ pushRaiseNull = cleanCriteria(plan);
+ }
+ return pushRaiseNull;
+ }
+ boolean cleanCriteria(PlanNode critNode) throws TeiidComponentException {
+ if (critNode.hasBooleanProperty(NodeConstants.Info.IS_PHANTOM)) {
+ NodeEditor.removeChildNode(critNode.getParent(), critNode);
+ return false;
+ }
+
+ //TODO: remove dependent set criteria that has not been meaningfully pushed from
its parent join
+
+ if (critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING) ||
critNode.getGroups().size() != 0) {
+ return false;
+ }
+
+ Criteria crit =
(Criteria)critNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
+ //if not evaluatable, just move on to the next criteria
+ if (!EvaluatableVisitor.isFullyEvaluatable(crit, true)) {
+ return false;
+ }
+ //if evaluatable
+ try {
+ boolean eval = Evaluator.evaluate(crit);
+ if(eval) {
+ NodeEditor.removeChildNode(critNode.getParent(), critNode);
+ } else {
+ FrameUtil.replaceWithNullNode(critNode);
+ return true;
+ }
+ //none of the following exceptions should ever occur
+ } catch(BlockedException e) {
+ throw new TeiidComponentException(e);
+ } catch (ExpressionEvaluationException e) {
+ throw new TeiidComponentException(e);
+ }
+ return false;
+ }
+
public String toString() {
return "CleanCriteria"; //$NON-NLS-1$
}
Modified:
branches/7.6.x/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java
===================================================================
---
branches/7.6.x/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java 2012-01-06
20:53:01 UTC (rev 3780)
+++
branches/7.6.x/engine/src/test/java/org/teiid/query/optimizer/TestUnionPlanning.java 2012-01-07
16:10:27 UTC (rev 3781)
@@ -23,8 +23,10 @@
package org.teiid.query.optimizer;
import org.junit.Test;
+import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
+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.ProcessorPlan;
@@ -254,5 +256,36 @@
0, // Sort
2 // UnionAll
});
- }
+ }
+
+ @Test public void testUnionCosting() throws Exception {
+ TransformationMetadata metadata = RealMetadataFactory.example1();
+ RealMetadataFactory.setCardinality("pm1.g1", 100, metadata);
+ RealMetadataFactory.setCardinality("pm1.g2", 100, metadata);
+ RealMetadataFactory.setCardinality("pm1.g3", 100, metadata);
+ RealMetadataFactory.setCardinality("pm1.g4", 100, metadata);
+ BasicSourceCapabilities bac = new BasicSourceCapabilities();
+ bac.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
+ bac.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
+ ProcessorPlan plan = TestOptimizer.helpPlan("SELECT T.e1 AS e1, T.e2 AS e2,
T.e3 AS e3 FROM (SELECT e1, 'a' AS e2, e3 FROM pm1.g1 UNION SELECT e1, 'b'
AS e2, e3 FROM pm1.g2 UNION SELECT e1, 'c' AS e2, e3 FROM pm1.g3) AS T, vm1.g1 AS
L WHERE (T.e1 = L.e1) AND (T.e3 = TRUE)", metadata, null, new
DefaultCapabilitiesFinder(bac),//$NON-NLS-1$
+ new String[] { "SELECT pm1.g1.e1 FROM pm1.g1", "SELECT
pm1.g1.e1, pm1.g1.e3 FROM pm1.g1 WHERE pm1.g1.e3 = TRUE", "SELECT pm1.g3.e1,
pm1.g3.e3 FROM pm1.g3 WHERE pm1.g3.e3 = TRUE", "SELECT pm1.g2.e1, pm1.g2.e3 FROM
pm1.g2 WHERE pm1.g2.e3 = TRUE" }, ComparisonMode.EXACT_COMMAND_STRING);
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 4, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 2 // UnionAll
+ });
+ }
+
}