[teiid-commits] teiid SVN: r3471 - in branches/7.1.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
Tue Sep 13 18:57:21 EDT 2011
Author: loleary
Date: 2011-09-13 18:57:20 -0400 (Tue, 13 Sep 2011)
New Revision: 3471
Modified:
branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
Log:
TEIID-1622 - Fixes issue with optimization of optional JOIN when used with UNION ALL
Modified: branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-09-13 22:57:03 UTC (rev 3470)
+++ branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-09-13 22:57:20 UTC (rev 3471)
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -50,6 +51,7 @@
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.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.util.CommandContext;
@@ -72,7 +74,7 @@
TeiidComponentException {
try {
- removeOptionalJoinNodes(plan, metadata, capFinder, null);
+ removeOptionalJoinNodes(plan, metadata, capFinder, null, null);
} catch (QueryResolverException e) {
throw new TeiidComponentException(e);
}
@@ -85,13 +87,22 @@
*/
private boolean removeOptionalJoinNodes(PlanNode node,
QueryMetadataInterface metadata,
- CapabilitiesFinder capFinder, Set<ElementSymbol> elements) throws QueryPlannerException,
+ CapabilitiesFinder capFinder, Set<ElementSymbol> elements, List<Integer> indexes) throws QueryPlannerException,
QueryMetadataException,
TeiidComponentException, QueryResolverException {
if (node.getChildCount() == 0) {
return false;
}
+ if (indexes != null && node.getParent() != null && node.getParent().getType() == NodeConstants.Types.SET_OP && node.getParent().getFirstChild() != node) {
+ elements = new HashSet<ElementSymbol>();
+ List columns = (List)node.getProperty(NodeConstants.Info.PROJECT_COLS);
+ for (int i : indexes) {
+ SingleElementSymbol column = (SingleElementSymbol) columns.get(i);
+ ElementCollectorVisitor.getElements(column, elements);
+ }
+ }
+
boolean isRoot = false;
switch (node.getType()) {
@@ -138,15 +149,21 @@
case NodeConstants.Types.SOURCE:
{
if (elements == null) {
+ indexes = null;
break;
}
SymbolMap symbolMap = (SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP);
Set convertedElements = new HashSet();
+ indexes = new LinkedList<Integer>();
+ List<ElementSymbol> keys = symbolMap.getKeys();
+ List<Expression> values = symbolMap.getValues();
for (ElementSymbol element : elements) {
- Expression convertedExpression = symbolMap.getMappedExpression(element);
- if (convertedExpression != null) {
+ int index = keys.indexOf(element);
+ if (index >= 0) {
+ Expression convertedExpression = values.get(index);
+ indexes.add(index);
ElementCollectorVisitor.getElements(convertedExpression, convertedElements);
- }
+ }
}
elements = convertedElements;
isRoot = true;
@@ -170,6 +187,14 @@
break;
}
case NodeConstants.Types.SET_OP:
+ {
+ if (!node.hasBooleanProperty(NodeConstants.Info.USE_ALL)) {
+ //allow project nodes to be seen as roots
+ elements = null;
+ indexes = null;
+ }
+ break;
+ }
case NodeConstants.Types.DUP_REMOVE:
{
//allow project nodes to be seen as roots
@@ -182,7 +207,7 @@
if (isRoot) {
boolean optionalRemoved = false;
do {
- optionalRemoved = removeOptionalJoinNodes(node.getFirstChild(), metadata, capFinder, elements);
+ optionalRemoved = removeOptionalJoinNodes(node.getFirstChild(), metadata, capFinder, elements, indexes);
} while (optionalRemoved);
return false;
}
@@ -191,7 +216,7 @@
Iterator iter = node.getChildren().iterator();
while (node.getChildCount() >= 1 && iter.hasNext()) {
- if (removeOptionalJoinNodes((PlanNode)iter.next(), metadata, capFinder, elements)) {
+ if (removeOptionalJoinNodes((PlanNode)iter.next(), metadata, capFinder, elements, indexes)) {
return true;
}
}
Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2011-09-13 22:57:03 UTC (rev 3470)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java 2011-09-13 22:57:20 UTC (rev 3471)
@@ -311,7 +311,7 @@
}
/**
- * Union should prevent the removal from happening
+ * Union all should not prevent the removal from happening
*/
@Test public void testOptionalJoinWithUnion() {
ProcessorPlan plan = TestOptimizer.helpPlan("select pm1.g2.e4 from /* optional */ pm1.g1 inner join pm1.g2 on pm1.g1.e1 = pm1.g2.e1 union all select convert(pm1.g2.e2, double) from /* optional */ pm1.g1 inner join pm1.g2 on pm1.g1.e1 = pm1.g2.e1", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
@@ -335,6 +335,31 @@
});
}
+ /**
+ * The first branch should have the join removed, but not the second branch
+ */
+ @Test public void testOptionalJoinWithUnion1() {
+ ProcessorPlan plan = TestOptimizer.helpPlan("select e4 from (select e4, e2 from (select pm1.g2.e4, pm1.g1.e2 from /* optional */ pm1.g1 inner join pm1.g2 on pm1.g1.e1 = pm1.g2.e1) as x union all select e4, e2 from (select convert(pm2.g1.e2, double) as e4, pm2.g2.e2 from /* optional */ pm2.g1 inner join pm2.g2 on pm2.g1.e1 = pm2.g2.e1) as x) as y", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
+ new String[] {"SELECT pm1.g2.e4 FROM pm1.g2", "SELECT g_0.e2 FROM pm2.g1 AS g_0, pm2.g2 AS g_1 WHERE g_0.e1 = g_1.e1"} ); //$NON-NLS-1$ //$NON-NLS-2$
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // Join
+ 0, // MergeJoin
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+
@Test public void testOptionalJoinWithCompoundCriteria() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT length(z) FROM /* optional */ pm1.g1 inner join (select e2 as y, e3 || 'x' as z from pm1.g1 ORDER BY z) AS x on pm1.g1.e2=x.y and concat(x.y, x.z) = '1'", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
new String[] {"SELECT e3 FROM pm1.g1"} ); //$NON-NLS-1$
More information about the teiid-commits
mailing list