[teiid-commits] teiid SVN: r3230 - in branches/7.1.1.CP2/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 Jun 7 17:36:51 EDT 2011


Author: mdrillin
Date: 2011-06-07 17:36:50 -0400 (Tue, 07 Jun 2011)
New Revision: 3230

Modified:
   branches/7.1.1.CP2/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
   branches/7.1.1.CP2/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.1.CP2/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- branches/7.1.1.CP2/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2011-06-07 21:19:41 UTC (rev 3229)
+++ branches/7.1.1.CP2/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java	2011-06-07 21:36:50 UTC (rev 3230)
@@ -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.1.CP2/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java
===================================================================
--- branches/7.1.1.CP2/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java	2011-06-07 21:19:41 UTC (rev 3229)
+++ branches/7.1.1.CP2/engine/src/test/java/org/teiid/query/optimizer/TestOptionalJoins.java	2011-06-07 21:36:50 UTC (rev 3230)
@@ -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