[teiid-commits] teiid SVN: r3008 - in trunk: engine/src/main/java/org/teiid/query/eval and 11 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Fri Mar 18 14:50:33 EDT 2011
Author: shawkins
Date: 2011-03-18 14:50:32 -0400 (Fri, 18 Mar 2011)
New Revision: 3008
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.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/NewCalculateCostUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/JoinType.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestExistsCriteriaImpl.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.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/parser/TestOptionsAndHints.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java
Log:
TEIID-1497 adding a merge join hint to in/exists subqueries
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -349,8 +349,12 @@
return result;
}
- Exists translate(ExistsCriteria criteria) {
- return new Exists(translate(criteria.getCommand()));
+ Condition translate(ExistsCriteria criteria) {
+ Exists exists = new Exists(translate(criteria.getCommand()));
+ if (criteria.isNegated()) {
+ return new Not(exists);
+ }
+ return exists;
}
IsNull translate(IsNullCriteria criteria) {
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -588,9 +588,9 @@
throw new ExpressionEvaluationException(e, e.getMessage());
}
if(valueIter.hasNext()) {
- return true;
+ return !criteria.isNegated();
}
- return false;
+ return criteria.isNegated();
}
public Object evaluate(Expression expression, List<?> tuple)
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 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -327,6 +327,11 @@
return;
}
+ if (crit.isNegated() && !this.caps.supportsCapability(Capability.CRITERIA_NOT)) {
+ markInvalid(crit, "Negation is not supported by source"); //$NON-NLS-1$
+ return;
+ }
+
try {
if (validateSubqueryPushdown(crit, modelID, metadata, capFinder, analysisRecord) == null) {
if (crit.getCommand().getCorrelatedReferences() == null) {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -602,7 +602,7 @@
return;
}
- float cardinality = getNDVEstimate(node, metadata, childCost, expressions, false);
+ float cardinality = getNDVEstimate(node, metadata, childCost, expressions, true);
setCardinalityEstimate(node, cardinality, true, metadata);
}
@@ -1283,6 +1283,8 @@
ndv = cardinality;
} else if (useCardinalityIfUnknown) {
ndv = cardinality/2;
+ } else {
+ return UNKNOWN_VALUE;
}
}
return Math.max(1, ndv);
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -33,6 +33,8 @@
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
+import org.teiid.client.plan.Annotation;
+import org.teiid.client.plan.Annotation.Priority;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.id.IDGenerator;
import org.teiid.query.analysis.AnalysisRecord;
@@ -119,6 +121,7 @@
public List<Criteria> nonEquiJoinCriteria = new LinkedList<Criteria>();
public Criteria additionalCritieria;
public Class<?> type;
+ public boolean mergeJoin;
}
private IDGenerator idGenerator;
@@ -143,7 +146,7 @@
// Find strings of criteria and merge them, removing duplicates
List<PlanNode> criteriaChains = new ArrayList<PlanNode>();
- findCriteriaChains(plan, criteriaChains);
+ findCriteriaChains(plan, criteriaChains, analysisRecord);
// Merge chains
for (PlanNode critNode : criteriaChains) {
@@ -158,7 +161,7 @@
* @param node Root node to search
* @param foundNodes Roots of criteria chains
*/
- void findCriteriaChains(PlanNode root, List<PlanNode> foundNodes)
+ void findCriteriaChains(PlanNode root, List<PlanNode> foundNodes, AnalysisRecord analysisRecord)
throws QueryPlannerException, TeiidComponentException {
PlanNode recurseRoot = root;
@@ -167,7 +170,7 @@
// Walk to end of the chain and change recurse root
while(recurseRoot.getType() == NodeConstants.Types.SELECT) {
// Look for opportunities to replace with a semi-join
- recurseRoot = planSemiJoin(recurseRoot, root);
+ recurseRoot = planMergeJoin(recurseRoot, root, analysisRecord);
if (root.getChildCount() == 0) {
root = recurseRoot.getFirstChild();
if (root.getType() != NodeConstants.Types.SELECT) {
@@ -186,7 +189,7 @@
if (recurseRoot.getType() != NodeConstants.Types.ACCESS) {
for (PlanNode child : recurseRoot.getChildren()) {
- findCriteriaChains(child, foundNodes);
+ findCriteriaChains(child, foundNodes, analysisRecord);
}
}
}
@@ -242,24 +245,24 @@
*
* TODO: it would be good to have a hint to force
*/
- private PlanNode planSemiJoin(PlanNode current, PlanNode root) throws QueryMetadataException,
+ private PlanNode planMergeJoin(PlanNode current, PlanNode root, AnalysisRecord analysisRecord) throws QueryMetadataException,
TeiidComponentException {
- float sourceCost = NewCalculateCostUtil.computeCostForTree(current, metadata);
- if (sourceCost != NewCalculateCostUtil.UNKNOWN_VALUE
- && sourceCost < RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY) {
- //TODO: see if a dependent join applies
- return current;
- }
+ float sourceCost = NewCalculateCostUtil.computeCostForTree(current.getFirstChild(), metadata);
Criteria crit = (Criteria)current.getProperty(NodeConstants.Info.SELECT_CRITERIA);
PlannedResult plannedResult = findSubquery(crit);
if (plannedResult.query == null) {
return current;
}
+ if (sourceCost != NewCalculateCostUtil.UNKNOWN_VALUE
+ && sourceCost < RuleChooseDependent.DEFAULT_INDEPENDENT_CARDINALITY && !plannedResult.mergeJoin) {
+ //TODO: see if a dependent join applies the other direction
+ return current;
+ }
RelationalPlan originalPlan = (RelationalPlan)plannedResult.query.getProcessorPlan();
Number originalCardinality = originalPlan.getRootNode().getEstimateNodeCardinality();
- if (originalCardinality.floatValue() == NewCalculateCostUtil.UNKNOWN_VALUE) {
+ if (!plannedResult.mergeJoin && originalCardinality.floatValue() == NewCalculateCostUtil.UNKNOWN_VALUE) {
//TODO: this check isn't really accurate - exists and scalarsubqueries will always have cardinality 2/1
//if it's currently unknown, removing criteria won't make it any better
return current;
@@ -268,6 +271,9 @@
Collection<GroupSymbol> leftGroups = FrameUtil.findJoinSourceNode(current).getGroups();
if (!planQuery(leftGroups, false, plannedResult)) {
+ if (plannedResult.mergeJoin && analysisRecord != null && analysisRecord.recordAnnotations()) {
+ this.analysisRecord.addAnnotation(new Annotation(Annotation.HINTS, "could not plan as a merge join: " + crit, "ignoring hint", Priority.MEDIUM)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
return current;
}
@@ -283,18 +289,26 @@
List<SingleElementSymbol> projectedSymbols = LanguageObject.Util.deepClone(plannedResult.query.getProjectedSymbols(), SingleElementSymbol.class);
//NOTE: we could tap into the relationalplanner at a lower level to get this in a plan node form,
//the major benefit would be to reuse the dependent join planning logic if possible.
+ if (analysisRecord != null && analysisRecord.recordDebug()) {
+ analysisRecord.println("Attempting to plan " + crit + " as a mege join"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
RelationalPlan subPlan = (RelationalPlan)QueryOptimizer.optimizePlan(plannedResult.query, metadata, idGenerator, capFinder, analysisRecord, context);
- Number planCardinality = subPlan.getRootNode().getEstimateNodeCardinality();
+ Number planCardinality = subPlan.getRootNode().getEstimateNodeCardinality();
- if (planCardinality.floatValue() == NewCalculateCostUtil.UNKNOWN_VALUE
- || planCardinality.floatValue() > 10000000
- || (sourceCost == NewCalculateCostUtil.UNKNOWN_VALUE && planCardinality.floatValue() > 1000)
- || (sourceCost != NewCalculateCostUtil.UNKNOWN_VALUE && sourceCost * originalCardinality.floatValue() < planCardinality.floatValue() / (100 * Math.log(Math.max(4, sourceCost))))) {
- //bail-out if both are unknown or the new plan is too large
- return current;
- }
+ if (!plannedResult.mergeJoin) {
+ //if we don't have a specific hint, then use costing
+ if (planCardinality.floatValue() == NewCalculateCostUtil.UNKNOWN_VALUE
+ || planCardinality.floatValue() > 10000000
+ || (sourceCost == NewCalculateCostUtil.UNKNOWN_VALUE && planCardinality.floatValue() > 1000)
+ || (sourceCost != NewCalculateCostUtil.UNKNOWN_VALUE && sourceCost * originalCardinality.floatValue() < planCardinality.floatValue() / (100 * Math.log(Math.max(4, sourceCost))))) {
+ //bail-out if both are unknown or the new plan is too large
+ if (analysisRecord != null && analysisRecord.recordDebug()) {
+ analysisRecord.println("Failed to use mege join, as the cost was not favorable. Use the MJ hint to force."); //$NON-NLS-1$
+ }
+ return current;
+ }
+ }
- //TODO: don't allow if too large
PlanNode semiJoin = NodeFactory.getNewNode(NodeConstants.Types.JOIN);
semiJoin.addGroups(current.getGroups());
semiJoin.setProperty(NodeConstants.Info.JOIN_STRATEGY, JoinStrategyType.MERGE);
@@ -336,6 +350,7 @@
SubquerySetCriteria ssc = (SubquerySetCriteria)crit;
result.not ^= ssc.isNegated();
result.type = crit.getClass();
+ result.mergeJoin = ssc.isMergeJoin();
crit = new SubqueryCompareCriteria(ssc.getExpression(), ssc.getCommand(), SubqueryCompareCriteria.EQ, SubqueryCompareCriteria.SOME);
} else if (crit instanceof CompareCriteria) {
//convert to the quantified form
@@ -343,6 +358,7 @@
if (cc.getRightExpression() instanceof ScalarSubquery) {
ScalarSubquery ss = (ScalarSubquery)cc.getRightExpression();
result.type = ss.getClass();
+ //we can only use a semi-join if we know that 1 row will be present
if (ss.getCommand() instanceof Query) {
Query query = (Query)ss.getCommand();
if (query.getGroupBy() == null && query.hasAggregates()) {
@@ -378,8 +394,10 @@
return result;
}
result.type = crit.getClass();
+ result.not = exists.isNegated();
//the correlations can only be in where (if no group by or aggregates) or having
result.query = (Query)exists.getCommand();
+ result.mergeJoin = exists.isMergeJoin();
}
return result;
}
@@ -466,8 +484,6 @@
}
if (plannedResult.leftExpressions.isEmpty()) {
- //there's no equi-join
- //TODO: if there are correlations a "cross" join may still be preferable
return false;
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -39,6 +39,7 @@
import org.teiid.query.sql.lang.QueryCommand;
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.proc.CriteriaSelector;
+import org.teiid.query.sql.visitor.SQLStringVisitor;
public class SQLParserUtil {
@@ -165,8 +166,18 @@
}
}
}
-
- private String getComment(Token t) {
+
+ boolean isMergeJoin(Token t) {
+ String[] parts = getComment(t).split("\\s"); //$NON-NLS-1$
+ for (int i = 0; i < parts.length; i++) {
+ if (parts[i].equalsIgnoreCase(SQLStringVisitor.MJ)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ String getComment(Token t) {
Token optToken = t.specialToken;
if (optToken == null) {
return ""; //$NON-NLS-1$
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -1134,7 +1134,7 @@
}
rewriteSubqueryContainer((SubqueryContainer)criteria, true);
if (!RelationalNodeUtil.shouldExecute(exists.getCommand(), false, true)) {
- return FALSE_CRITERIA;
+ return exists.isNegated()?TRUE_CRITERIA:FALSE_CRITERIA;
}
if (exists.getCommand().getProcessorPlan() == null) {
addImplicitLimit(exists, 1);
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ExistsCriteria.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -27,6 +27,7 @@
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.lang.PredicateCriteria.Negatable;
import org.teiid.query.sql.symbol.ContextReference;
import org.teiid.query.sql.symbol.Expression;
@@ -37,13 +38,15 @@
* "EXISTS (Select EmployeeID FROM Employees WHERE EmployeeName = 'Smith')".
*/
public class ExistsCriteria extends PredicateCriteria
-implements SubqueryContainer<QueryCommand>, ContextReference {
+implements SubqueryContainer<QueryCommand>, ContextReference, Negatable {
private static AtomicInteger ID = new AtomicInteger();
private QueryCommand command;
private String id = "$ec/id" + ID.getAndIncrement(); //$NON-NLS-1$
private boolean shouldEvaluate;
+ private boolean mergeJoin;
+ private boolean negated;
/**
* Default constructor
@@ -51,6 +54,14 @@
public ExistsCriteria() {
super();
}
+
+ public void setMergeJoin(boolean semiJoin) {
+ this.mergeJoin = semiJoin;
+ }
+
+ public boolean isMergeJoin() {
+ return mergeJoin;
+ }
public ExistsCriteria(QueryCommand subqueryCommand){
this.command = subqueryCommand;
@@ -104,7 +115,6 @@
* @return True if equal
*/
public boolean equals(Object obj) {
- // Use super.equals() to check obvious stuff and variable
if(obj == this) {
return true;
}
@@ -112,8 +122,12 @@
if(!(obj instanceof ExistsCriteria)) {
return false;
}
+
+ ExistsCriteria other = (ExistsCriteria)obj;
- return EquivalenceUtil.areEqual(getCommand(), ((ExistsCriteria)obj).getCommand());
+ return EquivalenceUtil.areEqual(getCommand(), other.getCommand()) &&
+ this.negated == other.negated &&
+ this.mergeJoin == other.mergeJoin;
}
/**
@@ -124,6 +138,22 @@
* @see java.lang.Object#clone()
*/
public Object clone() {
- return new ExistsCriteria((QueryCommand) this.command.clone());
+ ExistsCriteria ec = new ExistsCriteria((QueryCommand) this.command.clone());
+ ec.setMergeJoin(this.mergeJoin);
+ ec.setNegated(this.negated);
+ return ec;
}
+
+ public boolean isNegated() {
+ return negated;
+ }
+
+ public void setNegated(boolean negated) {
+ this.negated = negated;
+ }
+
+ @Override
+ public void negate() {
+ this.negated = !this.negated;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/JoinType.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/JoinType.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/JoinType.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -22,7 +22,8 @@
package org.teiid.query.sql.lang;
-import org.teiid.query.sql.*;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.visitor.SQLStringVisitor;
/**
@@ -102,10 +103,6 @@
return outer;
}
- public boolean isSemi() {
- return this.equals(JOIN_ANTI_SEMI) || this.equals(JOIN_SEMI);
- }
-
/**
* Override Object.equals() to compare objects
* @param other Other object
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/SubquerySetCriteria.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -42,6 +42,7 @@
private QueryCommand command;
private String id = "$ssc/id" + ID.getAndIncrement(); //$NON-NLS-1$
+ private boolean mergeJoin;
/**
* Constructor for SubquerySetCriteria.
@@ -55,6 +56,14 @@
setCommand(subCommand);
}
+ public boolean isMergeJoin() {
+ return mergeJoin;
+ }
+
+ public void setMergeJoin(boolean semiJoin) {
+ this.mergeJoin = semiJoin;
+ }
+
@Override
public String getContextSymbol() {
return id;
@@ -114,12 +123,11 @@
}
SubquerySetCriteria sc = (SubquerySetCriteria)obj;
- if (isNegated() ^ sc.isNegated()) {
- return false;
- }
- return EquivalenceUtil.areEqual(getExpression(), sc.getExpression()) &&
- EquivalenceUtil.areEqual(getCommand(), sc.getCommand());
+ return this.isNegated() == sc.isNegated() &&
+ EquivalenceUtil.areEqual(getExpression(), sc.getExpression()) &&
+ EquivalenceUtil.areEqual(getCommand(), sc.getCommand()) &&
+ this.mergeJoin == sc.mergeJoin;
}
/**
@@ -128,7 +136,7 @@
* (see #setValueIterator setValueIterator}).
* @return Deep copy of object
*/
- public Object clone() {
+ public SubquerySetCriteria clone() {
Expression copy = null;
if(getExpression() != null) {
copy = (Expression) getExpression().clone();
@@ -141,6 +149,7 @@
SubquerySetCriteria criteriaCopy = new SubquerySetCriteria(copy, copyCommand);
criteriaCopy.setNegated(isNegated());
+ criteriaCopy.mergeJoin = this.mergeJoin;
return criteriaCopy;
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -144,6 +144,7 @@
private static final String BEGIN_HINT = "/*+"; //$NON-NLS-1$
private static final String END_HINT = "*/"; //$NON-NLS-1$
private static final char ID_ESCAPE_CHAR = '\"';
+ public static String MJ = "MJ"; //$NON-NLS-1$
protected StringBuilder parts = new StringBuilder();
@@ -1066,6 +1067,14 @@
append(SPACE);
}
append(IN);
+ if (obj.isMergeJoin()) {
+ append(SPACE);
+ append(BEGIN_HINT);
+ append(SPACE);
+ append(MJ);
+ append(SPACE);
+ append(END_HINT);
+ }
append(" ("); //$NON-NLS-1$
visitNode(obj.getCommand());
append(")"); //$NON-NLS-1$
@@ -1546,8 +1555,19 @@
}
public void visit( ExistsCriteria obj ) {
- // operator and beginning of list
+ if (obj.isNegated()) {
+ append(NOT);
+ append(SPACE);
+ }
append(EXISTS);
+ if (obj.isMergeJoin()) {
+ append(SPACE);
+ append(BEGIN_HINT);
+ append(SPACE);
+ append(MJ);
+ append(SPACE);
+ append(END_HINT);
+ }
append(" ("); //$NON-NLS-1$
visitNode(obj.getCommand());
append(")"); //$NON-NLS-1$
Modified: trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -119,11 +119,11 @@
}
if(groupExpressions == null) {
- if (symbol instanceof ElementSymbol) {
+ if (symbol instanceof ElementSymbol && !((ElementSymbol)symbol).isExternalReference()) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0037", symbol), symbol); //$NON-NLS-1$
}
} else if(! groupExpressions.contains(symbol)) {
- if (symbol instanceof ElementSymbol) {
+ if (symbol instanceof ElementSymbol && !((ElementSymbol)symbol).isExternalReference()) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0038", symbol), symbol); //$NON-NLS-1$
}
} else {
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-03-18 18:50:32 UTC (rev 3008)
@@ -2680,11 +2680,23 @@
QueryCommand subquery(ParseInfo info) :
{
+ Object[] result = null;
+}
+{
+ result = subqueryAndHint(info)
+ {
+ return (QueryCommand)result[0];
+ }
+}
+
+Object[] subqueryAndHint(ParseInfo info) :
+{
QueryCommand subquery = null;
StoredProcedure proc = null;
+ Token lparen = null;
}
{
- <LPAREN>
+ lparen = <LPAREN>
( subquery = queryExpression(info) |
(
proc = storedProcedure(info, new StoredProcedure()) //deprecated
@@ -2695,7 +2707,7 @@
)
<RPAREN>
{
- return subquery;
+ return new Object[] {subquery, isMergeJoin(lparen)};
}
}
@@ -2838,7 +2850,7 @@
{
Expression value = null;
List setList = new ArrayList();
- QueryCommand command = null;
+ Object[] command = null;
boolean negated = false;
AbstractSetCriteria criteria = null;
}
@@ -2846,7 +2858,7 @@
[<NOT> {negated = true;}]
<IN>
(
- LOOKAHEAD(subquery(info)) (command = subquery(info)) |
+ LOOKAHEAD(subquery(info)) (command = subqueryAndHint(info)) |
(
<LPAREN>
value = commonValueExpression(info)
@@ -2862,14 +2874,11 @@
<RPAREN>
)
)
-
-
{
- if(setList.size() == 1 && setList.get(0) instanceof ScalarSubquery) {
- ScalarSubquery subqueryExpr = (ScalarSubquery) setList.get(0);
- criteria = new SubquerySetCriteria(expression, subqueryExpr.getCommand());
- } else if (command != null) {
- criteria = new SubquerySetCriteria(expression, command);
+ if (command != null) {
+ SubquerySetCriteria ssc = new SubquerySetCriteria(expression, (QueryCommand)command[0]);
+ ssc.setMergeJoin((Boolean)command[1]);
+ criteria = ssc;
} else {
criteria = new SetCriteria(expression, setList);
}
@@ -2885,15 +2894,15 @@
*/
ExistsCriteria existsCriteria(ParseInfo info) :
{
- ExistsCriteria existsCrit = null;
- QueryCommand subquery = null;
+ Object[] subquery = null;
}
{
<EXISTS>
- subquery = subquery(info)
+ subquery = subqueryAndHint(info)
{
- existsCrit = new ExistsCriteria(subquery);
+ ExistsCriteria existsCrit = new ExistsCriteria((QueryCommand)subquery[0]);
+ existsCrit.setMergeJoin((Boolean)subquery[1]);
return existsCrit;
}
}
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestExistsCriteriaImpl.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestExistsCriteriaImpl.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/TestExistsCriteriaImpl.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -23,12 +23,12 @@
package org.teiid.dqp.internal.datamgr;
+import junit.framework.TestCase;
+
import org.teiid.language.Exists;
+import org.teiid.language.Not;
import org.teiid.query.sql.lang.ExistsCriteria;
-
-import junit.framework.TestCase;
-
/**
*/
public class TestExistsCriteriaImpl extends TestCase {
@@ -41,17 +41,22 @@
super(name);
}
- public static ExistsCriteria helpExample() {
+ public static ExistsCriteria helpExample(boolean negated) {
ExistsCriteria crit = new ExistsCriteria(TestQueryImpl.helpExample(true));
+ crit.setNegated(negated);
return crit;
}
public static Exists example() throws Exception {
- return (Exists)TstLanguageBridgeFactory.factory.translate(helpExample());
+ return (Exists)TstLanguageBridgeFactory.factory.translate(helpExample(false));
}
public void testGetQuery() throws Exception {
assertNotNull(example().getSubquery());
}
+ public void testNegated() throws Exception {
+ assertTrue(TstLanguageBridgeFactory.factory.translate(helpExample(true)) instanceof Not);
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -631,7 +631,7 @@
null, capFinder,
new String[] {"SELECT g_0.\"MONTH\" AS c_0, g_0.\"YEAR\" AS c_1 FROM msModel.\"TIME\" AS g_0 WHERE g_0.\"YEAR\" = '1999' ORDER BY c_0", //$NON-NLS-1$
"SELECT g_0.\"MONTH\" AS c_0, g_0.CITY AS c_1, SUM(g_0.SALES) AS c_2 FROM db2model.SALES AS g_0 WHERE (g_0.\"MONTH\" IN (<dependent values>)) AND (g_0.CITY IN (<dependent values>)) GROUP BY g_0.\"MONTH\", g_0.CITY ORDER BY c_0", //$NON-NLS-1$
- "SELECT g_0.CITY, g_0.REGION FROM oraclemodel.GEOGRAPHY AS g_0 WHERE g_0.REGION IN ('BORDEAUX', 'POLINESIA')"}, //$NON-NLS-1$
+ "SELECT g_0.CITY AS c_0, g_0.REGION AS c_1 FROM oraclemodel.GEOGRAPHY AS g_0 WHERE g_0.REGION IN ('BORDEAUX', 'POLINESIA') ORDER BY c_0"}, //$NON-NLS-1$
ComparisonMode.EXACT_COMMAND_STRING );
checkNodeTypes(plan, new int[] {
@@ -679,7 +679,7 @@
null, capFinder,
new String[] {"SELECT g_0.\"MONTH\" AS c_0, g_0.\"YEAR\" AS c_1 FROM msModel.\"TIME\" AS g_0 WHERE g_0.\"YEAR\" = '1999' ORDER BY c_0", //$NON-NLS-1$
"SELECT g_0.\"MONTH\" AS c_0, g_0.CITY AS c_1, SUM(g_0.SALES) AS c_2 FROM db2model.SALES AS g_0 WHERE (g_0.\"MONTH\" IN (<dependent values>)) AND (g_0.CITY IN (<dependent values>)) GROUP BY g_0.\"MONTH\", g_0.CITY ORDER BY c_0", //$NON-NLS-1$
- "SELECT g_0.CITY, g_0.REGION FROM oraclemodel.GEOGRAPHY AS g_0 WHERE g_0.REGION IN ('BORDEAUX', 'POLINESIA')"}, //$NON-NLS-1$
+ "SELECT g_0.CITY AS c_0, g_0.REGION AS c_1 FROM oraclemodel.GEOGRAPHY AS g_0 WHERE g_0.REGION IN ('BORDEAUX', 'POLINESIA') ORDER BY c_0"}, //$NON-NLS-1$
ComparisonMode.EXACT_COMMAND_STRING );
checkNodeTypes(plan, new int[] {
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -77,6 +77,7 @@
import org.teiid.query.resolver.TestResolver;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.visitor.GroupCollectorVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
@@ -95,6 +96,7 @@
public interface DependentJoin {}
public interface DependentSelectNode {}
public interface SemiJoin {}
+ public interface AntiSemiJoin {}
public interface DependentProjectNode {}
public interface DupRemoveNode {}
public interface DupRemoveSortNode {}
@@ -385,9 +387,11 @@
Class<?> nodeType = relationalNode.getClass();
if(nodeType.equals(JoinNode.class)) {
JoinStrategy strategy = ((JoinNode)relationalNode).getJoinStrategy();
- if (((JoinNode)relationalNode).getJoinType().isSemi()) {
+ if (((JoinNode)relationalNode).getJoinType().equals(JoinType.JOIN_SEMI)) {
updateCounts(SemiJoin.class, counts, types);
- }
+ } else if (((JoinNode)relationalNode).getJoinType().equals(JoinType.JOIN_ANTI_SEMI)) {
+ updateCounts(AntiSemiJoin.class, counts, types);
+ }
if (strategy instanceof NestedLoopJoinStrategy) {
updateCounts(NestedLoopJoinStrategy.class, counts, types);
} else if (strategy instanceof MergeJoinStrategy) {
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestSubqueryPushdown.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -24,10 +24,13 @@
import static org.teiid.query.optimizer.TestOptimizer.*;
+import org.junit.Ignore;
import org.junit.Test;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.optimizer.TestOptimizer.AntiSemiJoin;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
+import org.teiid.query.optimizer.TestOptimizer.SemiJoin;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.DefaultCapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
@@ -836,6 +839,103 @@
});
}
+ /**
+ * This will not plan as a semi-join since the cost seems too high
+ */
+ @Test public void testNonSemiJoinExistsCosting() {
+ ProcessorPlan plan = helpPlan("Select e1 from pm1.g2 as o where exists (select 1 from pm3.g1 where e1 = o.e1 having o.e2 = count(e2))", FakeMetadataFactory.example4(), //$NON-NLS-1$
+ new String[] { "SELECT g_0.e1, g_0.e2 FROM pm1.g2 AS g_0" }); //$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
+ });
+ }
+
+ /**
+ * Same as above, but the source is much larger, so a semi-join is favorable
+ */
+ @Test public void testSemiJoinExistsCosting() {
+ ProcessorPlan plan = helpPlan("Select e1 from pm2.g2 as o where exists (select 1 from pm3.g1 where e1 = o.e1 having o.e2 = count(e2))", FakeMetadataFactory.example4(), //$NON-NLS-1$
+ new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm2.g2 AS g_0 ORDER BY c_0, c_1" }); //$NON-NLS-1$
+ checkNodeTypes(plan, new int[] {
+ 1, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 1, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ checkJoinCounts(plan, 1, 0);
+ }
+
+ @Test public void testAntiSemiJoinExistsHint() {
+ ProcessorPlan plan = helpPlan("Select e1 from pm1.g2 as o where not exists /*+ MJ */ (select 1 from pm3.g1 where e1 = o.e1 having o.e2 = count(e2))", FakeMetadataFactory.example4(), //$NON-NLS-1$
+ new String[] { "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm1.g2 AS g_0 ORDER BY c_0, c_1" }); //$NON-NLS-1$
+ checkNodeTypes(plan, new int[] {
+ 1, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 1, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ checkJoinCounts(plan, 0, 1);
+ }
+
+ @Test public void testSemiJoinInHint() {
+ ProcessorPlan plan = helpPlan("Select e1 from pm1.g2 as o where e2 IN /*+ MJ */ (select count(e2) from pm3.g1 where e1 = o.e1)", FakeMetadataFactory.example4(), //$NON-NLS-1$
+ new String[] { "SELECT g_0.e2 AS c_0, g_0.e1 AS c_1 FROM pm1.g2 AS g_0 ORDER BY c_1, c_0" }); //$NON-NLS-1$
+ checkNodeTypes(plan, new int[] {
+ 1, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 0, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 1, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ checkJoinCounts(plan, 1, 0);
+ }
+
+ void checkJoinCounts(ProcessorPlan plan, int semi, int antiSemi) {
+ checkNodeTypes(plan, new int[] {semi, antiSemi}, new Class[] {SemiJoin.class, AntiSemiJoin.class});
+ }
+
@Test public void testNonSemiJoin() throws Exception {
ProcessorPlan plan = helpPlan("Select x from xmltable('/a/b' passing convert('<a/>', xml) columns x integer path '@x') as t where x = (select count(e2) FROM pm1.g2)", FakeMetadataFactory.example4(), //$NON-NLS-1$
new String[] {}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
@@ -877,4 +977,27 @@
new String[] { "SELECT g_0.e1 FROM pm1.g1 AS g_0 WHERE g_0.e1 <= (SELECT MAX(X.e1) FROM (SELECT e1 FROM pm2.g1) AS X)" }, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
checkNodeTypes(plan, FULL_PUSHDOWN);
}
+
+ @Ignore
+ @Test public void testUncorrelatedSet() {
+ ProcessorPlan plan = helpPlan("Select e1 from pm1.g1 where e1 in (select e1 FROM pm2.g1)", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
+ new String[] { "SELECT e1, pm1.g1.e2 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
+ });
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestOptionsAndHints.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -22,7 +22,7 @@
package org.teiid.query.parser;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1144,4 +1144,16 @@
TestParser.helpTest(sql, "/*+ cache */ ? = EXEC proc()", sp); //$NON-NLS-1$
}
+ @Test public void testSemiJoinHint() {
+ String sql = "SELECT e1 FROM m.g2 WHERE EXISTS /*+ MJ */ (SELECT e1 FROM m.g1)"; //$NON-NLS-1$
+ Query q = TestParser.exampleExists(true);
+ TestParser.helpTest(sql, "SELECT e1 FROM m.g2 WHERE EXISTS /*+ MJ */ (SELECT e1 FROM m.g1)", q); //$NON-NLS-1$
+ }
+
+ @Test public void testSemiJoinHint1() {
+ String sql = "SELECT a FROM db.g WHERE b IN /*+ MJ */ (SELECT a FROM db.g WHERE a2 = 5)"; //$NON-NLS-1$
+ Query q = TestParser.exampleIn(true);
+ TestParser.helpTest(sql, "SELECT a FROM db.g WHERE b IN /*+ MJ */ (SELECT a FROM db.g WHERE a2 = 5)", q); //$NON-NLS-1$
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -4955,7 +4955,15 @@
@Test public void testSubquerySetCriteria0() {
//test wrap up command with subquerySetCriteria
- GroupSymbol g = new GroupSymbol("db.g"); //$NON-NLS-1$
+ Query outer = exampleIn(false);
+
+ helpTest("SELECT a FROM db.g WHERE b IN (SELECT a FROM db.g WHERE a2 = 5)", //$NON-NLS-1$
+ "SELECT a FROM db.g WHERE b IN (SELECT a FROM db.g WHERE a2 = 5)", //$NON-NLS-1$
+ outer);
+ }
+
+ static Query exampleIn(boolean semiJoin) {
+ GroupSymbol g = new GroupSymbol("db.g"); //$NON-NLS-1$
From from = new From();
from.addGroup(g);
@@ -4972,16 +4980,13 @@
query.setFrom(from);
query.setCriteria(criteria);
SubquerySetCriteria subCrit = new SubquerySetCriteria(expr, query);
-
+ subCrit.setMergeJoin(semiJoin);
Query outer = new Query();
outer.setSelect(select);
outer.setFrom(from);
outer.setCriteria(subCrit);
-
- helpTest("SELECT a FROM db.g WHERE b IN (SELECT a FROM db.g WHERE a2 = 5)", //$NON-NLS-1$
- "SELECT a FROM db.g WHERE b IN (SELECT a FROM db.g WHERE a2 = 5)", //$NON-NLS-1$
- outer);
- }
+ return outer;
+ }
@Test public void testSubquerySetCriteria1() {
@@ -5710,7 +5715,14 @@
@Test public void testExistsPredicateCriteria(){
- Select s1 = new Select();
+ Query q2 = exampleExists(false);
+
+ helpTest("SELECT e1 FROM m.g2 WHERE Exists (SELECT e1 FROM m.g1)", //$NON-NLS-1$
+ "SELECT e1 FROM m.g2 WHERE EXISTS (SELECT e1 FROM m.g1)", //$NON-NLS-1$
+ q2);
+ }
+ static Query exampleExists(boolean semiJoin) {
+ Select s1 = new Select();
s1.addSymbol(new ElementSymbol("e1")); //$NON-NLS-1$
From f1 = new From();
f1.addGroup(new GroupSymbol("m.g1")); //$NON-NLS-1$
@@ -5722,16 +5734,14 @@
s2.addSymbol(new ElementSymbol("e1")); //$NON-NLS-1$
From f2 = new From();
f2.addGroup(new GroupSymbol("m.g2")); //$NON-NLS-1$
- Criteria existsCrit = new ExistsCriteria(q1);
+ ExistsCriteria existsCrit = new ExistsCriteria(q1);
+ existsCrit.setMergeJoin(semiJoin);
Query q2 = new Query();
q2.setSelect(s2);
q2.setFrom(f2);
q2.setCriteria(existsCrit);
-
- helpTest("SELECT e1 FROM m.g2 WHERE Exists (SELECT e1 FROM m.g1)", //$NON-NLS-1$
- "SELECT e1 FROM m.g2 WHERE EXISTS (SELECT e1 FROM m.g1)", //$NON-NLS-1$
- q2);
- }
+ return q2;
+ }
@Test public void testAnyQuantifierSubqueryComparePredicate(){
Modified: trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java
===================================================================
--- trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java 2011-03-18 15:30:08 UTC (rev 3007)
+++ trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java 2011-03-18 18:50:32 UTC (rev 3008)
@@ -191,7 +191,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT custsale.cntrycode, COUNT(*) AS numcust, SUM(c_acctbal) AS totacctbal FROM (SELECT left(C_PHONE, 2) AS cntrycode, CUSTOMER.C_ACCTBAL FROM CUSTOMER WHERE (left(C_PHONE, 2) IN ('13','31','23','29','30','18','17')) AND (CUSTOMER.C_ACCTBAL > (SELECT AVG(CUSTOMER.C_ACCTBAL) FROM CUSTOMER WHERE (CUSTOMER.C_ACCTBAL > 0.0) AND (left(C_PHONE, 2) IN ('13','31','23','29','30','18','17')))) AND (NOT (EXISTS (SELECT * FROM ORDERS WHERE O_CUSTKEY = C_CUSTKEY)))) AS custsale GROUP BY custsale.cntrycode ORDER BY custsale.cntrycode", //$NON-NLS-1$
METADATA, null, finder,
- new String[] {"SELECT v_0.c_0, COUNT(*) AS c_1, SUM(v_0.c_1) AS c_2 FROM (SELECT left(g_0.C_PHONE, 2) AS c_0, g_0.C_ACCTBAL AS c_1 FROM TPCR_Oracle_9i.CUSTOMER AS g_0 WHERE (left(g_0.C_PHONE, 2) IN ('13', '17', '18', '23', '29', '30', '31')) AND (g_0.C_ACCTBAL > (SELECT AVG(g_1.C_ACCTBAL) FROM TPCR_Oracle_9i.CUSTOMER AS g_1 WHERE (g_1.C_ACCTBAL > 0E-15) AND (left(g_1.C_PHONE, 2) IN ('13', '17', '18', '23', '29', '30', '31')))) AND (NOT (EXISTS (SELECT 1 FROM TPCR_Oracle_9i.ORDERS AS g_2 WHERE g_2.O_CUSTKEY = g_0.C_CUSTKEY)))) AS v_0 GROUP BY v_0.c_0 ORDER BY c_0 NULLS FIRST"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+ new String[] {"SELECT v_0.c_0, COUNT(*) AS c_1, SUM(v_0.c_1) AS c_2 FROM (SELECT left(g_0.C_PHONE, 2) AS c_0, g_0.C_ACCTBAL AS c_1 FROM TPCR_Oracle_9i.CUSTOMER AS g_0 WHERE (left(g_0.C_PHONE, 2) IN ('13', '17', '18', '23', '29', '30', '31')) AND (g_0.C_ACCTBAL > (SELECT AVG(g_1.C_ACCTBAL) FROM TPCR_Oracle_9i.CUSTOMER AS g_1 WHERE (g_1.C_ACCTBAL > 0E-15) AND (left(g_1.C_PHONE, 2) IN ('13', '17', '18', '23', '29', '30', '31')))) AND (NOT EXISTS (SELECT 1 FROM TPCR_Oracle_9i.ORDERS AS g_2 WHERE g_2.O_CUSTKEY = g_0.C_CUSTKEY))) AS v_0 GROUP BY v_0.c_0 ORDER BY c_0 NULLS FIRST"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
More information about the teiid-commits
mailing list