[teiid-commits] teiid SVN: r3594 - in trunk/engine/src: main/java/org/teiid/query/optimizer/relational and 6 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Oct 28 16:43:18 EDT 2011


Author: shawkins
Date: 2011-10-28 16:43:18 -0400 (Fri, 28 Oct 2011)
New Revision: 3594

Added:
   trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java
Modified:
   trunk/engine/src/main/java/org/teiid/query/analysis/AnalysisRecord.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/NestedTableJoinStrategy.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/relational/TestRuleStack.java
Log:
TEIID-964 adding support for pushing must pushdown functions in the select clause

Modified: trunk/engine/src/main/java/org/teiid/query/analysis/AnalysisRecord.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/analysis/AnalysisRecord.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/analysis/AnalysisRecord.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -23,7 +23,6 @@
 package org.teiid.query.analysis;
 
 import java.io.PrintWriter;
-import java.io.Serializable;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -209,7 +208,7 @@
 	 * @param projectedSymbols The list of SingleElementSymbol projected from a plan or node
 	 * @return List of output columns for sending to the client as part of the plan
 	 */                
-	public static List<String> getOutputColumnProperties(List<SingleElementSymbol> projectedSymbols) {
+	public static List<String> getOutputColumnProperties(List<? extends SingleElementSymbol> projectedSymbols) {
 	    if(projectedSymbols != null) {
 	        List<String> outputCols = new ArrayList<String>(projectedSymbols.size());
 	        for(int i=0; i<projectedSymbols.size() ; i++) {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -64,6 +64,7 @@
 import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
 import org.teiid.query.optimizer.relational.rules.CapabilitiesUtil;
 import org.teiid.query.optimizer.relational.rules.CriteriaCapabilityValidatorVisitor;
+import org.teiid.query.optimizer.relational.rules.RuleAssignOutputElements;
 import org.teiid.query.optimizer.relational.rules.RuleCollapseSource;
 import org.teiid.query.optimizer.relational.rules.RuleConstants;
 import org.teiid.query.optimizer.relational.rules.RuleMergeCriteria;
@@ -406,7 +407,7 @@
         
         rules.push(RuleConstants.CALCULATE_COST);
         
-        rules.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        rules.push(new RuleAssignOutputElements(true));
         
         if (hints.hasLimit) {
             rules.push(RuleConstants.PUSH_LIMIT);
@@ -454,7 +455,7 @@
         }
         if (hints.hasVirtualGroups || (hints.hasJoin && hints.hasOptionalJoin)) {
         	//do initial filtering to make merging and optional join logic easier
-            rules.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+            rules.push(new RuleAssignOutputElements(false));
         }
         rules.push(RuleConstants.PLACE_ACCESS);
         return rules;

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -35,6 +35,8 @@
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryPlannerException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.metadata.FunctionMethod.PushDown;
+import org.teiid.query.QueryPlugin;
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -58,12 +60,16 @@
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.ExpressionSymbol;
+import org.teiid.query.sql.symbol.Function;
 import org.teiid.query.sql.symbol.GroupSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.sql.symbol.WindowFunction;
 import org.teiid.query.sql.util.SymbolMap;
 import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
 import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.EvaluatableVisitor;
+import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
+import org.teiid.query.sql.visitor.FunctionCollectorVisitor;
 import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
 import org.teiid.query.util.CommandContext;
 
@@ -76,6 +82,13 @@
  * from the children nodes.  </p>
  */
 public final class RuleAssignOutputElements implements OptimizerRule {
+	
+	private boolean finalRun;
+	private boolean checkSymbols;
+	
+	public RuleAssignOutputElements(boolean finalRun) {
+		this.finalRun = finalRun;
+	}
 
     /**
      * Execute the rule.  This rule is executed exactly once during every planning
@@ -141,6 +154,13 @@
 	            if (command instanceof StoredProcedure) {
 	                //if the access node represents a stored procedure, then we can't actually change the output symbols
 	                root.setProperty(NodeConstants.Info.OUTPUT_COLS, command.getProjectedSymbols());
+	            } else if (checkSymbols) {
+	            	Object modelId = RuleRaiseAccess.getModelIDFromAccess(root, metadata);
+	            	for (SingleElementSymbol symbol : outputElements) {
+	                    if(!RuleRaiseAccess.canPushSymbol(symbol, true, modelId, metadata, capFinder, analysisRecord)) {
+	                    	throw new QueryPlannerException(QueryPlugin.Util.getString("RuleAssignOutputElements.couldnt_push_expression", symbol, modelId)); //$NON-NLS-1$
+	                    } 
+					}
 	            }
 		    case NodeConstants.Types.TUPLE_LIMIT:
 		    case NodeConstants.Types.DUP_REMOVE:
@@ -195,7 +215,7 @@
 	            	PlanNode sortNode = NodeEditor.findParent(root, NodeConstants.Types.SORT, NodeConstants.Types.SOURCE);
 	            	if (sortNode != null && sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
 	            		//if this is the initial rule run, remove unrelated order before changing the project cols
-			            if (rules.contains(RuleConstants.ASSIGN_OUTPUT_ELEMENTS)) {
+			            if (!finalRun) {
 		            		OrderBy elements = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
 		            		projectCols = new ArrayList<SingleElementSymbol>(projectCols);
 		            		for (OrderByItem item : elements.getOrderByItems()) {
@@ -298,16 +318,21 @@
      * virtual elements - so just reset it and proceed as before
      * @throws TeiidComponentException 
      * @throws QueryMetadataException 
+     * @throws QueryPlannerException 
      */
     static List<? extends SingleElementSymbol> determineSourceOutput(PlanNode root,
                                            List<SingleElementSymbol> outputElements,
                                            QueryMetadataInterface metadata,
-                                           CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException {
+                                           CapabilitiesFinder capFinder) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
         PlanNode virtualRoot = root.getLastChild();
         
         if(hasDupRemoval(virtualRoot)) {
             // Reset the outputColumns for this source node to be all columns for the virtual group
             SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
+            if (!symbolMap.asMap().keySet().containsAll(outputElements)) {
+            	outputElements.removeAll(symbolMap.asMap().keySet());
+            	throw new QueryPlannerException(QueryPlugin.Util.getString("RuleAssignOutputElements.cannot_introduce_expressions", outputElements)); //$NON-NLS-1$
+            }
             return symbolMap.getKeys();
         } 
         PlanNode limit = NodeEditor.findNodePreOrder(root, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.PROJECT);
@@ -359,8 +384,9 @@
      * @param sourceNode Node to filter
      * @param metadata Metadata implementation
      * @return The filtered list of columns for this node (used in recursing tree)
+     * @throws QueryPlannerException 
      */
-	static List<SingleElementSymbol> filterVirtualElements(PlanNode sourceNode, List<SingleElementSymbol> outputColumns, QueryMetadataInterface metadata) {
+	static List<SingleElementSymbol> filterVirtualElements(PlanNode sourceNode, List<SingleElementSymbol> outputColumns, QueryMetadataInterface metadata) throws QueryPlannerException {
 
 		PlanNode virtualRoot = sourceNode.getLastChild();
 
@@ -379,10 +405,16 @@
         
         boolean updateGroups = outputColumns.size() != originalOrder.size();
         boolean[] seenIndex = new boolean[outputColumns.size()];
+        boolean newSymbols = false;
         
         for (int i = 0; i < outputColumns.size(); i++) {
             Expression expr = outputColumns.get(i);
             filteredIndex[i] = originalOrder.indexOf(expr);
+            if (filteredIndex[i] == -1) {
+            	updateGroups = true;
+            	//we're adding this symbol, which needs to be updated against respective symbol maps
+            	newSymbols = true;
+            }
             if (!updateGroups) {
             	seenIndex[filteredIndex[i]] = true;
             }
@@ -402,8 +434,21 @@
             PlanNode projectNode = allProjects.get(i);
             List<SingleElementSymbol> projectCols = (List<SingleElementSymbol>) projectNode.getProperty(NodeConstants.Info.PROJECT_COLS);
 
-            newCols = RelationalNode.projectTuple(filteredIndex, projectCols);
+            newCols = RelationalNode.projectTuple(filteredIndex, projectCols, true);
             
+            if (newSymbols) {
+				SymbolMap childMap = SymbolMap.createSymbolMap(symbolMap.getKeys(), (List) projectNode.getProperty(NodeConstants.Info.PROJECT_COLS));
+            	for (int j = 0; j < filteredIndex.length; j++) {
+					if (filteredIndex[j] != -1) {
+						continue;
+					}
+					SingleElementSymbol ex = (SingleElementSymbol) outputColumns.get(j).clone();
+					ExpressionMappingVisitor.mapExpressions(ex, childMap.asMap());
+					newCols.set(j, ex);
+					filteredIndex[j] = j;
+				}
+            }
+            
             projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, newCols);
             if (updateGroups) {
 	            projectNode.getGroups().clear();
@@ -428,25 +473,6 @@
         	for (int i = 0; i < filteredIndex.length; i++) {
         		newMap.addMapping(originalOrder.get(filteredIndex[i]), originalExpressionOrder.get(filteredIndex[i]));
 			}
-            PlanNode sortNode = NodeEditor.findNodePreOrder(sourceNode, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
-        	if (sortNode != null) {
-        		OrderBy elements = (OrderBy) sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
-        		for (OrderByItem item : elements.getOrderByItems()) {
-        			if (item.getExpressionPosition() == -1) {
-        				continue;
-        			}
-        			item.setExpressionPosition(-1);
-        			for (int i = 0; i < filteredIndex.length; i++) {
-        				if (item.getExpressionPosition() == filteredIndex[i]) {
-        					item.setExpressionPosition(i);
-        					break;
-        				}
-        			}
-					if (item.getExpressionPosition() == -1) {
-						sortNode.setProperty(NodeConstants.Info.UNRELATED_SORT, true);
-					}
-				}
-        	}
         	sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, newMap);
         }
 
@@ -501,7 +527,23 @@
                     if (ss instanceof WindowFunction || (ss instanceof ExpressionSymbol && !(ss instanceof AggregateSymbol))) {
                         createdSymbols.add(ss);
                     }
-                    ElementCollectorVisitor.getElements(ss, requiredSymbols);
+                    boolean symbolRequired = false;
+                    if (finalRun && !(ss instanceof ElementSymbol) && NodeEditor.findParent(node, NodeConstants.Types.ACCESS) == null) {
+                    	Collection<Function> functions = FunctionCollectorVisitor.getFunctions(ss, false);
+                    	for (Function function : functions) {
+							if (function.getFunctionDescriptor().getPushdown() != PushDown.MUST_PUSHDOWN || EvaluatableVisitor.willBecomeConstant(function)) {
+								continue;
+							}
+							//assume we need the whole thing
+							requiredSymbols.add(ss);
+							symbolRequired = true;
+							checkSymbols = true;
+							break;
+						}
+                    }
+                    if (!symbolRequired) {
+                    	ElementCollectorVisitor.getElements(ss, requiredSymbols);
+                    }
                 }
 				break;
             }

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -36,7 +36,6 @@
 	public static final OptimizerRule RAISE_ACCESS = new RuleRaiseAccess();
     public static final OptimizerRule CHOOSE_DEPENDENT = new RuleChooseDependent();
 	public static final OptimizerRule COLLAPSE_SOURCE = new RuleCollapseSource();
-	public static final OptimizerRule ASSIGN_OUTPUT_ELEMENTS = new RuleAssignOutputElements();
     public static final OptimizerRule COPY_CRITERIA = new RuleCopyCriteria();
     public static final OptimizerRule CLEAN_CRITERIA = new RuleCleanCriteria();    
     public static final OptimizerRule VALIDATE_WHERE_ALL = new RuleValidateWhereAll();    

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -202,11 +202,12 @@
      * Removes source layers that only do a simple projection of the elements below.
      * @throws TeiidComponentException 
      * @throws QueryMetadataException 
+     * @throws QueryPlannerException 
      */
     private static PlanNode checkForSimpleProjection(PlanNode frame,
                                                      PlanNode root,
                                                      PlanNode parentProject,
-                                                     QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException {
+                                                     QueryMetadataInterface metadata) throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
         // check that the parent only performs projection
         PlanNode nodeToCheck = parentProject.getFirstChild();
         while (nodeToCheck != frame) {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -452,7 +452,7 @@
      * @throws QueryMetadataException
      * @since 4.1.2
      */
-    private static boolean canPushSymbol(Expression symbol, boolean inSelectClause, Object modelID, 
+    static boolean canPushSymbol(Expression symbol, boolean inSelectClause, Object modelID, 
     		QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord record) 
     throws TeiidComponentException, QueryMetadataException {
 

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -167,7 +167,7 @@
 		}
 		
         // Incoming elements and lookup map for evaluating expressions
-        List<SingleElementSymbol> sourceElements = this.getChildren()[0].getElements();
+        List<? extends SingleElementSymbol> sourceElements = this.getChildren()[0].getElements();
         this.elementMap = createLookupMap(sourceElements);
 
     	// List should contain all grouping columns / expressions as we need those for sorting

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/NestedTableJoinStrategy.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/NestedTableJoinStrategy.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/NestedTableJoinStrategy.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -164,7 +164,7 @@
 	}
 
 	private void updateContext(List<?> tuple,
-			List<SingleElementSymbol> elements) {
+			List<? extends SingleElementSymbol> elements) {
 		for (int i = 0; i < elements.size(); i++) {
 			SingleElementSymbol element = elements.get(i);
 			if (element instanceof ElementSymbol) {

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalNode.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -46,6 +46,7 @@
 import org.teiid.query.processor.BatchCollector.BatchProducer;
 import org.teiid.query.sql.symbol.AliasSymbol;
 import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.util.CommandContext;
 
 
@@ -53,7 +54,7 @@
 	
 	static class NodeData {
 		int nodeID;
-		List elements;
+		List<? extends SingleElementSymbol> elements;
 		Number estimateNodeCardinality;
 		Number setSizeEstimate;
 		Number depAccessEstimate;
@@ -165,16 +166,16 @@
         }
     }
 
-	public void setElements(List elements) {
+	public void setElements(List<? extends SingleElementSymbol> elements) {
 		this.data.elements = elements;
 	}
 	
 	@Override
-	public List getOutputElements() {
+	public List<? extends SingleElementSymbol> getOutputElements() {
 		return getElements();
 	}
 
-	public List getElements() {
+	public List<? extends SingleElementSymbol> getElements() {
 		return this.data.elements;
 	}
     	
@@ -373,13 +374,21 @@
 
 		return result;
 	}
-	
+
 	public static <T> List<T> projectTuple(int[] indexes, List<T> tupleValues) {
+		return projectTuple(indexes, tupleValues, false);
+	}
 	
+	public static <T> List<T> projectTuple(int[] indexes, List<T> tupleValues, boolean omitMissing) {
+	
 		List<T> projectedTuple = new ArrayList<T>(indexes.length);
 	
 		for (int index : indexes) {
-			projectedTuple.add(tupleValues.get(index));
+			if (omitMissing && index == -1) {
+				projectedTuple.add(null);
+			} else {
+				projectedTuple.add(tupleValues.get(index));
+			}
 		}
 	
 		return projectedTuple;

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2011-10-28 20:43:18 UTC (rev 3594)
@@ -941,4 +941,7 @@
 DdlPlan.event_already_exists={0} already has an INSTEAD OF trigger defined for {1}.
 error_refresh=error occurred during refreshing the materialized view entries for view {0}
 
-support_required=Without required support property {0}, pushdown will not be enabled for {1} on translator {2}.
\ No newline at end of file
+support_required=Without required support property {0}, pushdown will not be enabled for {1} on translator {2}.
+
+RuleAssignOutputElements.couldnt_push_expression=Expression(s) {0} cannot be pushed to source.
+RuleAssignOutputElements.cannot_introduce_expressions=Cannot introduce new expressions {1} in duplicate removal.
\ No newline at end of file

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -6471,77 +6471,9 @@
 
     /**
      * Test the query optimizer's ability to properly plan and optimize a query 
-     * that uses ambiguous alias names in the top level query and its sub-query.
-     * <p>
-     * No source table is being used.  For example, <code>SELECT A.e2 FROM 
-     * (SELECT e2 FROM (SELECT 1 AS e2) AS A) AS A</code>
-     * <p>
-     * The test is to ensure that A.e2 from the top level is not confused with 
-     * e2 in the second level.
-     * <p>
-     * Related Defects: JBEDSP-1137
-     */
-    @Test public void testAmbiguousAliasInSubQueryNoSource() {
-        // Create query
-    	String sql = "SELECT A.e2 AS e2 FROM (" + //$NON-NLS-1$
-    	"	SELECT e2 AS e2 FROM (" + //$NON-NLS-1$
-    	"		SELECT 5 AS e2" + //$NON-NLS-1$
-    	"	) AS A" + //$NON-NLS-1$
-    	") AS A"; //$NON-NLS-1$
-
-        helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] {});
-    }
-         
-    /**
-     * Test the query optimizer's ability to properly plan and optimize a query 
      * that uses ambiguous alias names in the top level query and its sub-query
      * and uses columns belonging to the alias as a parameter to a function.
      * <p>
-     * No source table is being used.  For example, <code>SELECT CONVERT(A.e2, 
-     * biginteger) AS e2 FROM (SELECT CONVERT(e2, long) AS e2 FROM (SELECT 1 AS 
-     * e2) AS A) AS A</code>
-     * <p>
-     * The test is to ensure that A.e2 from the top level is not confused with 
-     * e2 in the second level.
-     * <p>
-     * Related Defects: JBEDSP-1137
-     */
-    @Test public void testAmbiguousAliasFunctionInSubQueryNoSource() {
-        // Create query
-    	String sql = "SELECT CONVERT(A.e2, biginteger) AS e2 FROM (" + //$NON-NLS-1$
-    	"	SELECT CONVERT(e2, long) AS e2 FROM (" + //$NON-NLS-1$
-    	"		SELECT 5 AS e2" + //$NON-NLS-1$
-    	"	) AS A" + //$NON-NLS-1$
-    	") AS A"; //$NON-NLS-1$
-
-    	helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] {});
-    }
-
-    /**
-     * Test the query optimizer's ability to properly plan and optimize a query 
-     * that uses ambiguous alias names in the top level query and its sub-query.
-     * <p>
-     * For example, <code>SELECT A.e2 FROM (SELECT e12FROM pm1.g1 AS A) AS A</code>
-     * <p>
-     * The test is to ensure that A.e2 from the top level is not confused with 
-     * e2 in the second level.
-     * <p>
-     * Related Defects: JBEDSP-1137
-     */
-    @Test public void testAmbiguousAliasInSubQuerySource() {
-        // Create query
-    	String sql = "SELECT A.e2 AS e2 FROM (" + //$NON-NLS-1$
-    	"   SELECT e2 AS e2 FROM pm1.g1 AS A" + //$NON-NLS-1$
-    	") AS A"; //$NON-NLS-1$
-
-        helpPlan(sql, RealMetadataFactory.example1Cached(), new String[] {"SELECT e2 FROM pm1.g1 AS A"}); //$NON-NLS-1$
-    }
-         
-    /**
-     * Test the query optimizer's ability to properly plan and optimize a query 
-     * that uses ambiguous alias names in the top level query and its sub-query
-     * and uses columns belonging to the alias as a parameter to a function.
-     * <p>
      * For example, <code>SELECT CONVERT(A.e2, biginteger) AS e2 FROM (SELECT 
      * CONVERT(e2, long) AS e2 FROM pm1.g1 AS A) AS A</code>
      * <p>

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/relational/TestRuleStack.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/relational/TestRuleStack.java	2011-10-27 19:31:00 UTC (rev 3593)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/relational/TestRuleStack.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -22,14 +22,12 @@
 
 package org.teiid.query.optimizer.relational;
 
-import org.teiid.query.optimizer.relational.OptimizerRule;
-import org.teiid.query.optimizer.relational.RuleStack;
+import junit.framework.TestCase;
+
 import org.teiid.query.optimizer.relational.rules.RuleConstants;
 import org.teiid.query.optimizer.relational.rules.RulePushSelectCriteria;
 
-import junit.framework.TestCase;
 
-
 /**
  */
 public class TestRuleStack extends TestCase {
@@ -76,12 +74,12 @@
     public void testRemove() {
         // Set up
         RuleStack stack = new RuleStack();
-        stack.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        stack.push(RuleConstants.ACCESS_PATTERN_VALIDATION);
         stack.push(RuleConstants.COLLAPSE_SOURCE);
-        stack.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        stack.push(RuleConstants.ACCESS_PATTERN_VALIDATION);
         
         // Remove all instances of ASSIGN_OUTPUT_ELEMENTS
-        stack.remove(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        stack.remove(RuleConstants.ACCESS_PATTERN_VALIDATION);
         
         // Verify size and pop'ed values
         assertEquals(1, stack.size());
@@ -92,10 +90,10 @@
     public void testContains() {
         // Set up
         RuleStack stack = new RuleStack();
-        stack.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+        stack.push(RuleConstants.ACCESS_PATTERN_VALIDATION);
         stack.push(RuleConstants.COLLAPSE_SOURCE);
         
-        assertEquals(true, stack.contains(RuleConstants.ASSIGN_OUTPUT_ELEMENTS));
+        assertEquals(true, stack.contains(RuleConstants.ACCESS_PATTERN_VALIDATION));
         assertEquals(false, stack.contains(RuleConstants.PLACE_ACCESS));
     }
 

Added: trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java	                        (rev 0)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java	2011-10-28 20:43:18 UTC (rev 3594)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.processor;
+
+import static org.teiid.query.optimizer.TestOptimizer.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.teiid.query.function.FunctionTree;
+import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.optimizer.FakeFunctionMetadataSource;
+import org.teiid.query.optimizer.TestOptimizer;
+import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
+import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
+import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
+import org.teiid.query.unittest.RealMetadataFactory;
+
+ at SuppressWarnings({"nls", "unchecked"})
+public class TestFunctionPushdown {
+
+	@Test public void testMustPushdownOverMultipleSourcesWithoutSupport() throws Exception {
+		QueryMetadataInterface metadata = RealMetadataFactory.createTransformationMetadata(RealMetadataFactory.example1Cached().getMetadataStore(), "example1", new FunctionTree("foo", new FakeFunctionMetadataSource()));
+		
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+        
+        String sql = "select func(x.e1) from pm1.g1 as x, pm2.g1 as y where x.e2 = y.e2"; //$NON-NLS-1$
+        
+        helpPlan(sql, metadata, null, capFinder, 
+                                      new String[] {}, ComparisonMode.FAILED_PLANNING); //$NON-NLS-1$ 
+	}
+
+	@Test public void testMustPushdownOverMultipleSources() throws Exception {
+		QueryMetadataInterface metadata = RealMetadataFactory.createTransformationMetadata(RealMetadataFactory.example1Cached().getMetadataStore(), "example1", new FunctionTree("foo", new FakeFunctionMetadataSource()));
+		
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+        caps.setFunctionSupport("misc.namespace.func", true);
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+        
+        String sql = "select func(x.e1) from pm1.g1 as x, pm2.g1 as y where x.e2 = y.e2"; //$NON-NLS-1$
+        
+        ProcessorPlan plan = helpPlan(sql, metadata, null, capFinder, 
+                                      new String[] {"SELECT g_0.e2 AS c_0, func(g_0.e1) AS c_1 FROM pm1.g1 AS g_0 ORDER BY c_0", "SELECT g_0.e2 AS c_0 FROM pm2.g1 AS g_0 ORDER BY c_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ 
+        
+        HardcodedDataManager dataManager = new HardcodedDataManager();
+        dataManager.addData("SELECT g_0.e2 AS c_0, func(g_0.e1) AS c_1 FROM pm1.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList(1, "a")});
+        dataManager.addData("SELECT g_0.e2 AS c_0 FROM pm2.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList(1), Arrays.asList(2)});
+        
+        TestProcessor.helpProcess(plan, dataManager, new List[] {Arrays.asList("a")});
+	}
+
+	@Test public void testMustPushdownOverMultipleSourcesWithView() throws Exception {
+		QueryMetadataInterface metadata = RealMetadataFactory.createTransformationMetadata(RealMetadataFactory.example1Cached().getMetadataStore(), "example1", new FunctionTree("foo", new FakeFunctionMetadataSource()));
+		
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+        caps.setFunctionSupport("misc.namespace.func", true);
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+        
+        String sql = "select func(x.e1) from (select x.* from pm1.g1 as x, pm2.g1 as y where x.e2 = y.e2 order by e1 limit 10) as x"; //$NON-NLS-1$
+        
+        ProcessorPlan plan = helpPlan(sql, metadata, null, capFinder, 
+                                      new String[] {"SELECT g_0.e2 AS c_0 FROM pm2.g1 AS g_0 ORDER BY c_0", "SELECT g_0.e2 AS c_0, func(g_0.e1) AS c_1, g_0.e1 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ 
+        
+        HardcodedDataManager dataManager = new HardcodedDataManager();
+        dataManager.addData("SELECT g_0.e2 AS c_0 FROM pm2.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList(1)});
+        dataManager.addData("SELECT g_0.e2 AS c_0, func(g_0.e1) AS c_1, g_0.e1 AS c_2 FROM pm1.g1 AS g_0 ORDER BY c_0", new List[] {Arrays.asList(1, "aa", "a"), Arrays.asList(2, "bb", "b")});
+        
+        TestProcessor.helpProcess(plan, dataManager, new List[] {Arrays.asList("aa")});
+	}
+	
+	@Test public void testMustPushdownOverMultipleSourcesWithViewDupRemoval() throws Exception {
+		QueryMetadataInterface metadata = RealMetadataFactory.createTransformationMetadata(RealMetadataFactory.example1Cached().getMetadataStore(), "example1", new FunctionTree("foo", new FakeFunctionMetadataSource()));
+		
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
+        caps.setFunctionSupport("misc.namespace.func", true);
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+        
+        String sql = "select func(x.e1) from (select distinct x.* from pm1.g1 as x, pm2.g1 as y where x.e2 = y.e2 order by e1 limit 10) as x"; //$NON-NLS-1$
+        
+        helpPlan(sql, metadata, null, capFinder, 
+                                      new String[] {}, ComparisonMode.FAILED_PLANNING); //$NON-NLS-1$ 
+	}
+	
+}


Property changes on: trunk/engine/src/test/java/org/teiid/query/processor/TestFunctionPushdown.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain



More information about the teiid-commits mailing list