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;
}