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

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Fri Aug 6 01:08:26 EDT 2010


Author: shawkins
Date: 2010-08-06 01:08:25 -0400 (Fri, 06 Aug 2010)
New Revision: 2423

Modified:
   trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataStore.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCopyCriteria.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/BatchedUpdateNode.java
   trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
   trunk/engine/src/main/java/org/teiid/query/resolver/command/SetQueryResolver.java
   trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
   trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestGroupRecontext.java
   trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-536 allowing for the evaluation of uncorrelated scalarsubqueries prior to pushdown if they cannot be pushed to the source.

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -41,28 +41,35 @@
     
 	private static final int LOCAL_CACHE_SIZE = 8;
 	
+	public enum Type {
+		VIRTUAL,
+		TEMP,
+		SCALAR
+	}
+	
     private String ID;      // never null, upper cased fully-qualified string
-    private int selectPosition = -1; //used for order by symbol resolving.  refers to the position in the select clause
-    private int position;
-    private Class<?> type;     // type of this element, only for element
+    private Type metadataType = Type.VIRTUAL;
+    
+    //Table metadata
+    private Collection<TempMetadataID> accessPatterns;
     private List<TempMetadataID> elements;  // of TempMetadataID, only for group
-    private Object originalMetadataID;
-    private boolean isVirtual = true;   // virtual by default
-    private boolean isTempTable;
-    private Collection<TempMetadataID> accessPatterns;
     private int cardinality = QueryMetadataInterface.UNKNOWN_CARDINALITY;
-    private LRUCache<Object, Object> localCache;
-    private boolean scalarGroup;
     private List<TempMetadataID> primaryKey;
     private QueryNode queryNode;
+    private transient LRUCache<Object, Object> localCache;
     
+    //Column metadata
+    private Object originalMetadataID;
+    private int position;
+    private Class<?> type;     // type of this element, only for element
+    
     /**
      * Constructor for group form of metadata ID.
      * @param ID Fully-qualified, upper-case name of ID
      * @param elements List of TempMetadataID representing elements
      */
     public TempMetadataID(String ID, List<TempMetadataID> elements) {
-        this(ID, elements, true, false);
+        this(ID, elements, Type.VIRTUAL);
     }
     
     /**
@@ -71,15 +78,14 @@
      * @param elements List of TempMetadataID representing elements
      * @param isVirtual whether or not the group is a virtual group
      */
-    public TempMetadataID(String ID, List<TempMetadataID> elements, boolean isVirtual, boolean isTempTable) {
+    public TempMetadataID(String ID, List<TempMetadataID> elements, Type type) {
         this.ID = ID;
         this.elements = elements;
         int pos = 1;
         for (TempMetadataID tempMetadataID : elements) {
 			tempMetadataID.setPosition(pos++);
 		}
-        this.isVirtual = isVirtual;
-        this.isTempTable = isTempTable;
+        this.metadataType = type;
     }
     
     /**
@@ -147,7 +153,7 @@
      * @return True if virtual
      */
     public boolean isVirtual() {
-        return this.isVirtual;    
+        return metadataType == Type.VIRTUAL;    
     }
     
     /**
@@ -156,7 +162,7 @@
      * @since 5.5
      */
     public boolean isTempTable() {
-        return this.isTempTable;
+        return this.metadataType == Type.TEMP;
     }
     
     /**
@@ -222,17 +228,13 @@
     }
 
     public void setTempTable(boolean isTempTable) {
-        this.isTempTable = isTempTable;
+        if (isTempTable) {
+        	this.metadataType = Type.TEMP;
+        } else {
+        	this.metadataType = Type.VIRTUAL;
+        }
     }
 
-    public int getSelectPosition() {
-        return this.selectPosition;
-    }
-
-    public void setSelectPosition(int position) {
-        this.selectPosition = position;
-    }  
-    
     Object getProperty(Object key) {
     	if (this.localCache != null) {
     		return this.localCache.get(key);
@@ -248,11 +250,11 @@
     }
 
 	public boolean isScalarGroup() {
-		return scalarGroup;
+		return this.metadataType == Type.SCALAR;
 	}
 
-	public void setScalarGroup(boolean scalarGroup) {
-		this.scalarGroup = scalarGroup;
+	public void setScalarGroup() {
+		this.metadataType = Type.SCALAR;
 	}
 
 	public List<TempMetadataID> getPrimaryKey() {

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataStore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataStore.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataStore.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -29,6 +29,7 @@
 import java.util.List;
 import java.util.Map;
 
+import org.teiid.query.metadata.TempMetadataID.Type;
 import org.teiid.query.sql.symbol.AggregateSymbol;
 import org.teiid.query.sql.symbol.AliasSymbol;
 import org.teiid.query.sql.symbol.ElementSymbol;
@@ -115,7 +116,7 @@
         }
 
         // Create group ID
-        TempMetadataID groupID = new TempMetadataID(tempName, elementIDs, isVirtual, isTempTable);
+        TempMetadataID groupID = new TempMetadataID(tempName, elementIDs, isVirtual?Type.VIRTUAL:Type.TEMP);
         this.tempGroups.put(tempName, groupID);
         return groupID;
     }

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -367,14 +367,14 @@
     @Override
     public void visit(ScalarSubquery obj) {
     	try {    
-            // Check if compares are allowed
-            if(! this.caps.supportsCapability(Capability.QUERY_SUBQUERIES_SCALAR)) {
-                markInvalid();
-                return;
+            if(!this.caps.supportsCapability(Capability.QUERY_SUBQUERIES_SCALAR) 
+            		|| validateSubqueryPushdown(obj, modelID, metadata, capFinder) == null) {
+            	if (obj.getCommand().getCorrelatedReferences() == null) {
+            		obj.setShouldEvaluate(true);
+            	} else {
+            		markInvalid();
+            	}
             }
-            if (validateSubqueryPushdown(obj, modelID, metadata, capFinder) == null) {
-            	markInvalid();
-            }
         } catch(QueryMetadataException e) {
             handleException(new TeiidComponentException(e));
         } catch(TeiidComponentException e) {

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -23,6 +23,7 @@
 package org.teiid.query.optimizer.relational.rules;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -78,10 +79,22 @@
         
         PlanNode endNode = NodeEditor.findParent(startNode.getType()==NodeConstants.Types.SOURCE?startNode.getParent():startNode, NodeConstants.Types.SOURCE);
         
+        boolean rewrite = false;
+        if (newGroups != null && newGroups.size() == 1) {
+        	for (Expression expression : (Collection<Expression>)symbolMap.values()) {
+				if (!(expression instanceof ElementSymbol)) {
+					rewrite = true;
+					break;
+				}
+			}
+        } else {
+        	rewrite = true;
+        }
+        
         while(current != endNode) { 
             
             // Make translations as defined in node in each current node
-            convertNode(current, oldGroup, newGroups, symbolMap, metadata);
+            convertNode(current, oldGroup, newGroups, symbolMap, metadata, rewrite);
             
             PlanNode parent = current.getParent(); 
             
@@ -162,7 +175,7 @@
     // symbols.  In that case, some additional work can be done because we can assume 
     // that an oldElement isn't being replaced by an expression using elements from 
     // multiple new groups.  
-    static void convertNode(PlanNode node, GroupSymbol oldGroup, Set<GroupSymbol> newGroups, Map symbolMap, QueryMetadataInterface metadata)
+    static void convertNode(PlanNode node, GroupSymbol oldGroup, Set<GroupSymbol> newGroups, Map symbolMap, QueryMetadataInterface metadata, boolean rewrite)
         throws QueryPlannerException {
 
         // Convert expressions from correlated subquery references;
@@ -203,7 +216,7 @@
         
         if(type == NodeConstants.Types.SELECT) { 
             Criteria crit = (Criteria) node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
-            crit = convertCriteria(crit, symbolMap, metadata);
+            crit = convertCriteria(crit, symbolMap, metadata, rewrite);
             node.setProperty(NodeConstants.Info.SELECT_CRITERIA, crit);
             
             if (!singleMapping) {
@@ -223,7 +236,7 @@
             List<Criteria> joinCrits = (List<Criteria>) node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
             if(joinCrits != null && !joinCrits.isEmpty()) {
             	Criteria crit = new CompoundCriteria(joinCrits);
-            	crit = convertCriteria(crit, symbolMap, metadata);
+            	crit = convertCriteria(crit, symbolMap, metadata, rewrite);
             	if (crit instanceof CompoundCriteria) {
             		node.setProperty(NodeConstants.Info.JOIN_CRITERIA, ((CompoundCriteria)crit).getCriteria());
             	} else {
@@ -275,11 +288,14 @@
         return expression;
     }   
         
-    static Criteria convertCriteria(Criteria criteria, final Map symbolMap, QueryMetadataInterface metadata)
+    static Criteria convertCriteria(Criteria criteria, final Map symbolMap, QueryMetadataInterface metadata, boolean rewrite)
         throws QueryPlannerException {
 
         ExpressionMappingVisitor.mapExpressions(criteria, symbolMap);
         
+        if (!rewrite) {
+        	return criteria;
+        }
         // Simplify criteria if possible
         try {
             return QueryRewriter.rewriteCriteria(criteria, null, null, metadata);

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -371,6 +371,7 @@
 		    	};
 		    	DeepPostOrderNavigator.doVisit(command, visitor);
 		    }
+		    command.setProcessorPlan(container.getCommand().getProcessorPlan());
 		    container.setCommand(command);
 		}
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCopyCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCopyCriteria.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCopyCriteria.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -131,7 +131,7 @@
         Criteria tgtCrit = (Criteria) crit.clone();
         
         try {
-            tgtCrit = FrameUtil.convertCriteria(tgtCrit, tgtMap, metadata);
+            tgtCrit = FrameUtil.convertCriteria(tgtCrit, tgtMap, metadata, true);
         } catch (QueryPlannerException err) {
             LogManager.logDetail(LogConstants.CTX_QUERY_PLANNER, err, "Could not remap target criteria in RuleCopyCriteria"); //$NON-NLS-1$
             return false;

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -756,7 +756,7 @@
     throws QueryPlannerException {
         
         while (node != null) {
-            FrameUtil.convertNode(node, null, null, exprMap, metadata);
+            FrameUtil.convertNode(node, null, null, exprMap, metadata, true);
             
             switch (node.getType()) {
                 case NodeConstants.Types.SOURCE:

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -562,7 +562,7 @@
             copyNode.setProperty(NodeConstants.Info.IS_HAVING, Boolean.TRUE);
         }
 
-        FrameUtil.convertNode(copyNode, sourceGroup, null, symbolMap.asMap(), metadata);  
+        FrameUtil.convertNode(copyNode, sourceGroup, null, symbolMap.asMap(), metadata, true);  
         PlanNode intermediateParent = NodeEditor.findParent(projectNode, NodeConstants.Types.ACCESS, NodeConstants.Types.SOURCE | NodeConstants.Types.SET_OP);
         if (intermediateParent != null) {
             intermediateParent.addAsParent(copyNode);

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -25,6 +25,7 @@
 import static org.teiid.query.analysis.AnalysisRecord.*;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import org.teiid.api.exception.query.ExpressionEvaluationException;
@@ -35,6 +36,7 @@
 import org.teiid.common.buffer.TupleSource;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.eval.Evaluator;
 import org.teiid.query.execution.QueryExecPlugin;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.rewriter.QueryRewriter;
@@ -42,7 +44,7 @@
 import org.teiid.query.util.CommandContext;
 
 
-public class AccessNode extends RelationalNode {
+public class AccessNode extends SubqueryAwareRelationalNode {
 
     // Initialization state
     private Command command;
@@ -110,15 +112,15 @@
 	}
 
     protected boolean prepareNextCommand(Command atomicCommand) throws TeiidComponentException, TeiidProcessingException {
-    	return prepareCommand(atomicCommand, this, this.getContext(), this.getContext().getMetadata());
+    	return prepareCommand(atomicCommand, getEvaluator(Collections.emptyMap()), this.getContext(), this.getContext().getMetadata());
     }
 
-	static boolean prepareCommand(Command atomicCommand, RelationalNode node, CommandContext context, QueryMetadataInterface metadata)
+	static boolean prepareCommand(Command atomicCommand, Evaluator eval, CommandContext context, QueryMetadataInterface metadata)
 			throws ExpressionEvaluationException, TeiidComponentException,
 			TeiidProcessingException {
         try {
             // Defect 16059 - Rewrite the command once the references have been replaced with values.
-            QueryRewriter.evaluateAndRewrite(atomicCommand, node.getDataManager(), context, metadata);
+            QueryRewriter.evaluateAndRewrite(atomicCommand, eval, context, metadata);
         } catch (QueryValidatorException e) {
             throw new TeiidProcessingException(e, QueryExecPlugin.Util.getString("AccessNode.rewrite_failed", atomicCommand)); //$NON-NLS-1$
         }
@@ -185,6 +187,7 @@
     }
     
 	public void closeDirect() {
+		super.closeDirect();
         closeSources();            
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/BatchedUpdateNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/BatchedUpdateNode.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/BatchedUpdateNode.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -24,6 +24,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -33,6 +34,7 @@
 import org.teiid.common.buffer.TupleSource;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.eval.Evaluator;
 import org.teiid.query.execution.QueryExecPlugin;
 import org.teiid.query.sql.lang.BatchedUpdateCommand;
 import org.teiid.query.sql.lang.Command;
@@ -45,7 +47,7 @@
  * Node that batches commands sent to the DataManager.
  * @since 4.2
  */
-public class BatchedUpdateNode extends RelationalNode {
+public class BatchedUpdateNode extends SubqueryAwareRelationalNode {
     
     private static final List<Integer> ZERO_COUNT_TUPLE = Arrays.asList(Integer.valueOf(0));
 
@@ -98,7 +100,9 @@
             boolean needProcessing = false;
             if(shouldEvaluate != null && shouldEvaluate.get(i)) {
                 updateCommand = (Command) updateCommand.clone();
-                needProcessing = AccessNode.prepareCommand(updateCommand, this, context, context.getMetadata());
+                Evaluator eval = getEvaluator(Collections.emptyMap());
+                eval.initialize(context, getDataManager());
+                needProcessing = AccessNode.prepareCommand(updateCommand, eval, context, context.getMetadata());
             } else {
                 needProcessing = RelationalNodeUtil.shouldExecute(updateCommand, true);
             }
@@ -146,6 +150,7 @@
      * @since 4.2
      */
     public void closeDirect() {
+    	super.closeDirect();
         if (tupleSource != null) {
         	tupleSource.closeSource();
         	tupleSource = null;

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -229,7 +229,7 @@
 		GroupSymbol variables = new GroupSymbol(name);
 	    externalGroups.addGroup(variables);
 	    TempMetadataID tid = metadata.addTempGroup(name, symbols);
-	    tid.setScalarGroup(true);
+	    tid.setScalarGroup();
 	    variables.setMetadataID(tid);
 	    return variables;
 	}

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/SetQueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/SetQueryResolver.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/SetQueryResolver.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -36,15 +36,14 @@
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.metadata.TempMetadataID;
 import org.teiid.query.resolver.CommandResolver;
 import org.teiid.query.resolver.QueryResolver;
 import org.teiid.query.resolver.util.ResolverUtil;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.OrderByItem;
 import org.teiid.query.sql.lang.QueryCommand;
 import org.teiid.query.sql.lang.SetQuery;
-import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.SingleElementSymbol;
 import org.teiid.query.util.ErrorMessageKeys;
 
@@ -139,12 +138,11 @@
      * @return True if the ORDER BY contains the element
      */
     public static boolean orderByContainsVariable(OrderBy orderBy, SingleElementSymbol ses, int position) {
-        for (final Iterator iterator = orderBy.getSortKeys().iterator(); iterator.hasNext();) {
-            final ElementSymbol element = (ElementSymbol)iterator.next();
-            if (position == ((TempMetadataID)element.getMetadataID()).getSelectPosition()) {
-                return true;
-            }
-        } 
+    	for (OrderByItem item : orderBy.getOrderByItems()) {
+			if (item.getExpressionPosition() == position) {
+				return true;
+			}
+		}
         return false;
     }
     

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -427,7 +427,6 @@
 			if (matchedSymbol != null) {
 			    TempMetadataID tempMetadataID = new TempMetadataID(symbol.getName(), matchedSymbol.getType());
 			    int position = knownElements.indexOf(matchedSymbol);
-			    tempMetadataID.setSelectPosition(position);
 			    symbol.setMetadataID(tempMetadataID);
 			    symbol.setType(matchedSymbol.getType());
 			    return position;

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -62,7 +62,6 @@
 import org.teiid.query.metadata.QueryMetadataInterface;
 import org.teiid.query.metadata.TempMetadataAdapter;
 import org.teiid.query.metadata.TempMetadataStore;
-import org.teiid.query.processor.ProcessorDataManager;
 import org.teiid.query.processor.relational.DependentValueSource;
 import org.teiid.query.resolver.QueryResolver;
 import org.teiid.query.resolver.util.ResolverUtil;
@@ -180,7 +179,8 @@
     private CreateUpdateProcedureCommand procCommand;
     
     private boolean rewriteSubcommands;
-    private ProcessorDataManager dataMgr;
+    private boolean processing;
+    private Evaluator evaluator;
     private Map variables; //constant propagation
     private int commandType;
     
@@ -189,12 +189,14 @@
 		this.metadata = metadata;
 		this.context = context;
 		this.procCommand = procCommand;
+		this.evaluator = new Evaluator(Collections.emptyMap(), null, context);
 	}
     
-    public static Command evaluateAndRewrite(Command command, ProcessorDataManager dataMgr, CommandContext context, QueryMetadataInterface metadata) throws TeiidProcessingException, TeiidComponentException {
+    public static Command evaluateAndRewrite(Command command, Evaluator eval, CommandContext context, QueryMetadataInterface metadata) throws TeiidProcessingException, TeiidComponentException {
     	QueryRewriter queryRewriter = new QueryRewriter(metadata, context, null);
-    	queryRewriter.dataMgr = dataMgr;
+    	queryRewriter.evaluator = eval;
     	queryRewriter.rewriteSubcommands = true;
+    	queryRewriter.processing = true;
 		return queryRewriter.rewriteCommand(command, false);
     }
 
@@ -1049,7 +1051,7 @@
 
 	private Criteria rewriteDependentSetCriteria(DependentSetCriteria dsc)
 			throws TeiidComponentException, TeiidProcessingException{
-		if (dataMgr == null) {
+		if (!processing) {
 			return rewriteCriteria(dsc);
 		}
 		SetCriteria setCrit = new SetCriteria();
@@ -1147,9 +1149,9 @@
 	}
     
     private Criteria evaluateCriteria(Criteria crit) throws TeiidComponentException, TeiidProcessingException{
-        if(EvaluatableVisitor.isFullyEvaluatable(crit, true)) {
+        if(EvaluatableVisitor.isFullyEvaluatable(crit, !processing)) {
             try {
-            	Boolean eval = new Evaluator(Collections.emptyMap(), this.dataMgr, context).evaluateTVL(crit, Collections.emptyList());
+            	Boolean eval = evaluator.evaluateTVL(crit, Collections.emptyList());
                 
                 if (eval == null) {
                     return UNKNOWN_CRITERIA;
@@ -1807,7 +1809,7 @@
 	private Criteria getSimpliedCriteria(Criteria crit, Expression a, boolean outcome, boolean nullPossible) {
 		if (nullPossible) {
 			if (outcome) {
-				if (this.dataMgr != null) {
+				if (processing) {
 					return crit;
 				}
 				IsNullCriteria inc = new IsNullCriteria(a);
@@ -1885,7 +1887,7 @@
     	if (expression instanceof ElementSymbol) {
     		ElementSymbol es = (ElementSymbol)expression;
     		Class<?> type  = es.getType();
-            if (dataMgr == null && es.isExternalReference()) {
+            if (!processing && es.isExternalReference()) {
                 String grpName = es.getGroupSymbol().getCanonicalName();
                 
                 if (variables == null) {
@@ -1922,7 +1924,11 @@
         } else if (expression instanceof SearchedCaseExpression) {
         	expression = rewriteCaseExpression((SearchedCaseExpression)expression);
         } else if (expression instanceof ScalarSubquery) {
-            rewriteSubqueryContainer((ScalarSubquery)expression, true);
+        	ScalarSubquery subquery = (ScalarSubquery)expression;
+        	if (subquery.shouldEvaluate() && processing) {
+        		return new Constant(evaluator.evaluate(subquery, null), subquery.getType());
+        	}
+            rewriteSubqueryContainer(subquery, true);
             return expression;
         } else if (expression instanceof ExpressionSymbol) {
         	if (expression instanceof AggregateSymbol) {
@@ -1936,7 +1942,7 @@
         	rewriteExpressions(expression);
         } 
     	
-        if(dataMgr == null) {
+        if(!processing) {
         	if (!EvaluatableVisitor.isFullyEvaluatable(expression, true)) {
         		return expression;
         	}
@@ -1944,7 +1950,7 @@
 			return expression;
 		}
     	
-		Object value = new Evaluator(Collections.emptyMap(), dataMgr, context).evaluate(expression, Collections.emptyList());
+		Object value = evaluator.evaluate(expression, Collections.emptyList());
         if (value instanceof Constant) {
         	return (Constant)value; //multi valued substitution
         }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ScalarSubquery.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -43,9 +43,10 @@
 	private static AtomicInteger ID = new AtomicInteger();
 	
     private Command command;
-    private Class type;
+    private Class<?> type;
     private int hashCode;
     private String id = "$sc/id" + ID.getAndIncrement(); //$NON-NLS-1$
+    private boolean shouldEvaluate;
 
     /**
      * Default constructor
@@ -58,6 +59,14 @@
         this.setCommand(subqueryCommand);
     }
     
+    public boolean shouldEvaluate() {
+    	return shouldEvaluate;
+    }
+    
+    public void setShouldEvaluate(boolean shouldEvaluate) {
+		this.shouldEvaluate = shouldEvaluate;
+	}
+    
     @Override
     public String getContextSymbol() {
     	return id;
@@ -150,6 +159,7 @@
         ScalarSubquery clone = new ScalarSubquery(copyCommand);
         //Don't invoke the lazy-loading getType()
         clone.setType(this.type);
+        clone.shouldEvaluate = this.shouldEvaluate;
         return clone;
     }
 

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/EvaluatableVisitor.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -130,7 +130,11 @@
     }
     
     public void visit(ScalarSubquery obj){
-		evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
+    	if (obj.shouldEvaluate()) {
+    		evaluationNotPossible(EvaluationLevel.PROCESSING);
+    	} else {
+    		evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
+    	}
     }
     
     public void visit(DependentSetCriteria obj) {

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -1349,27 +1349,6 @@
         }); 
     }
 
-    @Test public void testCompareSubquery4() {
-        ProcessorPlan plan = helpPlan("Select e1 from pm1.g1 where e1 > (select e1 FROM pm2.g1 where e2 = 13)", example1(),  //$NON-NLS-1$
-            new String[] { "SELECT e1 FROM pm1.g1" }); //$NON-NLS-1$
-        checkNodeTypes(plan, new int[] {
-            1,      // Access
-            0,      // DependentAccess
-            1,      // DependentSelect
-            0,      // DependentProject
-            0,      // DupRemove
-            0,      // Grouping
-            0,      // NestedLoopJoinStrategy
-            0,      // MergeJoinStrategy
-            0,      // Null
-            0,      // PlanExecution
-            1,      // Project
-            0,      // Select
-            0,      // Sort
-            0       // UnionAll
-        }); 
-    }
-
     @Test public void testExistsSubquery1() {
         ProcessorPlan plan = helpPlan("Select e1 from pm1.g1 where exists (select e1 FROM pm2.g1)", example1(),  //$NON-NLS-1$
             new String[] { "SELECT e1 FROM pm1.g1" }); //$NON-NLS-1$
@@ -1391,48 +1370,6 @@
         }); 
     }
     
-    @Test public void testScalarSubquery1() {
-        ProcessorPlan plan = helpPlan("Select e1, (select e1 FROM pm2.g1 where e1 = 'x') from pm1.g1", example1(),  //$NON-NLS-1$
-            new String[] { "SELECT e1 FROM pm1.g1" }); //$NON-NLS-1$
-        checkNodeTypes(plan, new int[] {
-            1,      // Access
-            0,      // DependentAccess
-            0,      // DependentSelect
-            1,      // DependentProject
-            0,      // DupRemove
-            0,      // Grouping
-            0,      // NestedLoopJoinStrategy
-            0,      // MergeJoinStrategy
-            0,      // Null
-            0,      // PlanExecution
-            0,      // Project
-            0,      // Select
-            0,      // Sort
-            0       // UnionAll
-        }); 
-    }    
-
-    @Test public void testScalarSubquery2() {
-        ProcessorPlan plan = helpPlan("Select e1, (select e1 FROM pm2.g1 where e1 = 'x') as X from pm1.g1", example1(),  //$NON-NLS-1$
-            new String[] { "SELECT e1 FROM pm1.g1" }); //$NON-NLS-1$
-        checkNodeTypes(plan, new int[] {
-            1,      // Access
-            0,      // DependentAccess
-            0,      // DependentSelect
-            1,      // DependentProject
-            0,      // DupRemove
-            0,      // Grouping
-            0,      // NestedLoopJoinStrategy
-            0,      // MergeJoinStrategy
-            0,      // Null
-            0,      // PlanExecution
-            0,      // Project
-            0,      // Select
-            0,      // Sort
-            0       // UnionAll
-        }); 
-    } 
-    
     @Test public void testTempGroup() {
         ProcessorPlan plan = helpPlan("select e1 from tm1.g1 where e1 = 'x'", FakeMetadataFactory.example1Cached(),  //$NON-NLS-1$
             new String[] { "SELECT e1 FROM tm1.g1" }); //$NON-NLS-1$
@@ -5747,14 +5684,14 @@
         caps.setFunctionSupport("convert", true); //$NON-NLS-1$ 
         capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$ 
          
-        String sql = "select e1 from pm1.g1 where e1 = convert((exec pm1.sq11(1, 2)), integer)"; //$NON-NLS-1$ 
+        String sql = "select pm1.g1.e1, pm1.g1.e2 from pm1.g1 where e1 = convert((exec pm1.sq11(e2, 2)), integer)"; //$NON-NLS-1$ 
          
         helpPlan(sql, 
                  FakeMetadataFactory.example1Cached(), 
                  null, 
                  capFinder, 
                  new String[] { 
-                     "SELECT e1 FROM pm1.g1"}, //$NON-NLS-1$ 
+                     "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, //$NON-NLS-1$ 
                  SHOULD_SUCCEED); 
              
     }

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -217,7 +217,7 @@
     /**
      * Check that scalar subquery in select is pushed 
      */
-    public void DEFER_testPushSubqueryInSelectClause1() {
+    public void testPushSubqueryInSelectClause1() {
         FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
         BasicSourceCapabilities caps = new BasicSourceCapabilities();
         caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
@@ -710,6 +710,41 @@
             new String[] { "SELECT g_0.e1, (convert((SELECT MAX(g_1.e1) FROM pm1.g1 AS g_1), integer) + 1) FROM pm1.g1 AS g_0" }, SHOULD_SUCCEED); //$NON-NLS-1$
         checkNodeTypes(plan, FULL_PUSHDOWN); 
     }
-
-
+    
+    @Test public void testScalarSubquery2() {
+        ProcessorPlan plan = helpPlan("Select e1, (select e1 FROM pm2.g1 where pm1.g1.e1 = 'x') as X from pm1.g1", example1(),  //$NON-NLS-1$
+            new String[] { "SELECT e1 FROM pm1.g1" }); //$NON-NLS-1$
+        checkNodeTypes(plan, new int[] {
+            1,      // Access
+            0,      // DependentAccess
+            0,      // DependentSelect
+            1,      // DependentProject
+            0,      // DupRemove
+            0,      // Grouping
+            0,      // NestedLoopJoinStrategy
+            0,      // MergeJoinStrategy
+            0,      // Null
+            0,      // PlanExecution
+            0,      // Project
+            0,      // Select
+            0,      // Sort
+            0       // UnionAll
+        }); 
+    } 
+    
+    /**
+     * Technically this is not a full push-down, but the subquery will be evaluated prior to pushdown
+     */
+    @Test public void testCompareSubquery4() {
+        ProcessorPlan plan = helpPlan("Select e1 from pm1.g1 where e1 > (select e1 FROM pm2.g1 where e2 = 13)", example1(),  //$NON-NLS-1$
+            new String[] { "SELECT g_0.e1 FROM pm1.g1 AS g_0 WHERE g_0.e1 > (SELECT g_1.e1 FROM pm2.g1 AS g_1 WHERE g_1.e2 = 13)" }); //$NON-NLS-1$
+        checkNodeTypes(plan, FULL_PUSHDOWN); 
+    }
+    
+    @Test public void testScalarSubquery1() {
+        ProcessorPlan plan = helpPlan("Select e1, (select e1 FROM pm2.g1 where e1 = 'x') from pm1.g1", example1(),  //$NON-NLS-1$
+            new String[] { "SELECT g_0.e1, (SELECT g_1.e1 FROM pm2.g1 AS g_1 WHERE g_1.e1 = 'x') FROM pm1.g1 AS g_0" }); //$NON-NLS-1$
+        checkNodeTypes(plan, FULL_PUSHDOWN); 
+    }   
+    
 }

Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestGroupRecontext.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestGroupRecontext.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/relational/rules/TestGroupRecontext.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -122,7 +122,7 @@
         SubqueryCompareCriteria crit = new SubqueryCompareCriteria(e1, query, SubqueryCompareCriteria.EQ, SubqueryCompareCriteria.ALL);
         SubqueryCompareCriteria expected = new SubqueryCompareCriteria(x1, query, SubqueryCompareCriteria.EQ, SubqueryCompareCriteria.ALL);
 
-        FrameUtil.convertCriteria(crit, symbolMap, null);  
+        FrameUtil.convertCriteria(crit, symbolMap, null, true);  
         
         assertEquals(crit, expected);
     }

Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2010-08-06 05:00:38 UTC (rev 2422)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java	2010-08-06 05:08:25 UTC (rev 2423)
@@ -23,6 +23,7 @@
 package org.teiid.query.processor;
 
 import static org.junit.Assert.*;
+import static org.teiid.query.optimizer.TestOptimizer.*;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -7483,6 +7484,32 @@
         
         helpProcess(plan, dataManager, expected);
     }
+    
+    @Test public void testUncorrelatedScalarSubqueryPushdown() throws Exception {
+        FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+        FakeMetadataFacade metadata = example1();
+        
+        BasicSourceCapabilities caps = getTypicalCapabilities();
+        caps.setCapabilitySupport(Capability.QUERY_SUBQUERIES_SCALAR, false);
+        caps.setCapabilitySupport(Capability.QUERY_AGGREGATES, true);
+        caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_MAX, true);
+        capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+        
+        ProcessorPlan plan = helpPlan("select pm1.g1.e1 from pm1.g1 where e1 < (select max(vm1.g1.e1) from vm1.g1)", metadata,  //$NON-NLS-1$
+                                      null, capFinder,
+            new String[] { "SELECT g_0.e1 FROM pm1.g1 AS g_0 WHERE g_0.e1 < (SELECT MAX(g_1.e1) FROM pm1.g1 AS g_1)" }, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+        checkNodeTypes(plan, FULL_PUSHDOWN);
+        
+        HardcodedDataManager hdm = new HardcodedDataManager();
+        hdm.addData("SELECT MAX(g_0.e1) FROM pm1.g1 AS g_0", new List[] {Arrays.asList("c")});
+        hdm.addData("SELECT g_0.e1 FROM pm1.g1 AS g_0 WHERE g_0.e1 < 'c'", new List[] {Arrays.asList("a")});
+        
+        List[] expected = new List[] {
+        		Arrays.asList("a"),
+        };    
+
+        helpProcess(plan, hdm, expected);
+    }
        
     private static final boolean DEBUG = false;
 }



More information about the teiid-commits mailing list