Author: shawkins
Date: 2011-02-14 15:34:03 -0500 (Mon, 14 Feb 2011)
New Revision: 2906
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
Log:
TEIID-1471 reusing the assign element logic to filter elements prior to optional join
removal and merge virtual
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -437,6 +437,10 @@
if (hints.hasJoin && hints.hasOptionalJoin) {
rules.push(RuleConstants.REMOVE_OPTIONAL_JOINS);
}
+ if (hints.hasVirtualGroups || (hints.hasJoin && hints.hasOptionalJoin))
{
+ //do initial filtering to make merging and optional join logic easier
+ rules.push(RuleConstants.ASSIGN_OUTPUT_ELEMENTS);
+ }
rules.push(RuleConstants.PLACE_ACCESS);
return rules;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -123,15 +123,6 @@
int nodeType = root.getType();
- //fix no output elements if possible
- if(outputElements.isEmpty() && (nodeType == NodeConstants.Types.ACCESS ||
nodeType == NodeConstants.Types.SOURCE)) {
- PlanNode groupSource = FrameUtil.findJoinSourceNode(root);
- ElementSymbol symbol = selectOutputElement(groupSource.getGroups(),
metadata);
- if (symbol != null) {//can be null for procedures
- outputElements.add(symbol);
- }
- }
-
// Update this node's output columns based on parent's columns
root.setProperty(NodeConstants.Info.OUTPUT_COLS, outputElements);
@@ -153,11 +144,21 @@
//add missing sort columns
OrderBy elements = (OrderBy) root.getProperty(NodeConstants.Info.SORT_ORDER);
outputElements = new ArrayList<SingleElementSymbol>(outputElements);
+ boolean hasUnrelated = false;
for (OrderByItem item : elements.getOrderByItems()) {
- if (!outputElements.contains(item.getSymbol())) {
- outputElements.add(item.getSymbol());
+ if (item.getExpressionPosition() == -1) {
+ int index = outputElements.indexOf(item.getSymbol());
+ if (index != -1) {
+ item.setExpressionPosition(index);
+ } else {
+ hasUnrelated = true;
+ outputElements.add(item.getSymbol());
+ }
}
}
+ if (!hasUnrelated) {
+ root.setProperty(NodeConstants.Info.UNRELATED_SORT, false);
+ }
}
assignOutputElements(root.getLastChild(), outputElements, metadata, capFinder,
rules, analysisRecord, context);
break;
@@ -165,24 +166,6 @@
outputElements = (List<SingleElementSymbol>)determineSourceOutput(root,
outputElements, metadata, capFinder);
root.setProperty(NodeConstants.Info.OUTPUT_COLS, outputElements);
List<SingleElementSymbol> childElements = filterVirtualElements(root,
outputElements, metadata);
- SymbolMap symbolMap =
(SymbolMap)root.getProperty(NodeConstants.Info.SYMBOL_MAP);
- int size = symbolMap.asMap().size();
- symbolMap.asUpdatableMap().keySet().retainAll(outputElements);
- //if we have removed projected symbols, then we need to update the sort
columns
- if (size > outputElements.size()) {
- PlanNode sortNode = NodeEditor.findNodePreOrder(root,
NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
- if (sortNode != null &&
!sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
- List<Expression> symbolOrder = symbolMap.getValues();
- OrderBy elements = (OrderBy)
sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
- for (OrderByItem item : elements.getOrderByItems()) {
- int position = symbolOrder.indexOf(SymbolMap.getExpression(item.getSymbol()));
- item.setExpressionPosition(position);
- if (position == -1) {
- sortNode.setProperty(NodeConstants.Info.UNRELATED_SORT, true);
- }
- }
- }
- }
assignOutputElements(root.getFirstChild(), childElements, metadata,
capFinder, rules, analysisRecord, context);
break;
}
@@ -202,7 +185,29 @@
execute(intoRoot.getFirstChild(), metadata, capFinder, rules,
analysisRecord, context);
return;
}
- root.setProperty(NodeConstants.Info.PROJECT_COLS, outputElements);
+ List<SingleElementSymbol> projectCols = outputElements;
+ boolean modifiedProject = false;
+ PlanNode sortNode = NodeEditor.findParent(root, NodeConstants.Types.SORT,
NodeConstants.Types.SOURCE);
+ if (sortNode != null &&
sortNode.hasBooleanProperty(NodeConstants.Info.UNRELATED_SORT)) {
+ //if this is the initial rule run, remove unrelated order before changing
the project cols
+ if (rules.contains(RuleConstants.ASSIGN_OUTPUT_ELEMENTS)) {
+ OrderBy elements = (OrderBy)
sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
+ projectCols = new ArrayList<SingleElementSymbol>(projectCols);
+ for (OrderByItem item : elements.getOrderByItems()) {
+ if (item.getExpressionPosition() == -1) {
+ projectCols.remove(item.getSymbol());
+ }
+ }
+ } else {
+ modifiedProject = true;
+ }
+ }
+ root.setProperty(NodeConstants.Info.PROJECT_COLS, projectCols);
+ if (modifiedProject) {
+ root.getGroups().clear();
+ root.addGroups(GroupsUsedByElementsVisitor.getGroups(projectCols));
+
root.addGroups(GroupsUsedByElementsVisitor.getGroups(root.getCorrelatedReferenceElements()));
+ }
}
List<SingleElementSymbol> requiredInput =
collectRequiredInputSymbols(root);
@@ -292,33 +297,6 @@
}
/**
- * Find a selectable element in the specified groups. This is a helper for fixing
- * the "no elements" case.
- *
- * @param groups Bunch of groups
- * @param metadata Metadata implementation
- * @throws QueryPlannerException
- */
- private ElementSymbol selectOutputElement(Collection<GroupSymbol> groups,
QueryMetadataInterface metadata)
- throws QueryMetadataException, TeiidComponentException {
-
- // Find a group with selectable elements and pick the first one
- for (GroupSymbol group : groups) {
- List<ElementSymbol> elements =
(List<ElementSymbol>)ResolverUtil.resolveElementsInGroup(group, metadata);
-
- for (ElementSymbol element : elements) {
- if(metadata.elementSupports(element.getMetadataID(),
SupportConstants.Element.SELECT)) {
- element = (ElementSymbol)element.clone();
- element.setGroupSymbol(group);
- return element;
- }
- }
- }
-
- return null;
- }
-
- /**
* <p>This method looks at a source node, which defines a virtual group, and
filters the
* virtual elements defined by the group down into just the output elements needed
* by that source node. This means, for instance, that the PROJECT node at the top
@@ -347,13 +325,29 @@
Arrays.fill(filteredIndex, -1);
SymbolMap symbolMap =
(SymbolMap)sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
- List originalOrder = symbolMap.getKeys();
+ List<ElementSymbol> originalOrder = symbolMap.getKeys();
+
+ boolean updateGroups = outputColumns.size() != originalOrder.size();
+ boolean[] seenIndex = new boolean[outputColumns.size()];
+
for (int i = 0; i < outputColumns.size(); i++) {
Expression expr = outputColumns.get(i);
filteredIndex[i] = originalOrder.indexOf(expr);
+ if (!updateGroups) {
+ seenIndex[filteredIndex[i]] = true;
+ }
}
+ if (!updateGroups) {
+ for (boolean b : seenIndex) {
+ if (!b) {
+ updateGroups = true;
+ break;
+ }
+ }
+ }
+
List<SingleElementSymbol> newCols = null;
for(int i=allProjects.size()-1; i>=0; i--) {
PlanNode projectNode = allProjects.get(i);
@@ -365,8 +359,51 @@
}
projectNode.setProperty(NodeConstants.Info.PROJECT_COLS, newCols);
+ if (updateGroups) {
+ projectNode.getGroups().clear();
+ projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(newCols));
+
projectNode.addGroups(GroupsUsedByElementsVisitor.getGroups(projectNode.getCorrelatedReferenceElements()));
+ }
}
+
+ if (!updateGroups) {
+ for (int i : filteredIndex) {
+ if (i != filteredIndex[i]) {
+ updateGroups = true;
+ break;
+ }
+ }
+ }
+
+ if (updateGroups) {
+ SymbolMap newMap = new SymbolMap();
+ List<Expression> originalExpressionOrder = symbolMap.getValues();
+ for (int i = 0; i < filteredIndex.length; i++) {
+ newMap.addMapping(originalOrder.get(filteredIndex[i]),
originalExpressionOrder.get(filteredIndex[i]));
+ }
+ PlanNode sortNode = NodeEditor.findNodePreOrder(sourceNode,
NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
+ if (sortNode != null) {
+ OrderBy elements = (OrderBy)
sortNode.getProperty(NodeConstants.Info.SORT_ORDER);
+ for (OrderByItem item : elements.getOrderByItems()) {
+ if (item.getExpressionPosition() == -1) {
+ continue;
+ }
+ item.setExpressionPosition(-1);
+ for (int i = 0; i < filteredIndex.length; i++) {
+ if (item.getExpressionPosition() == filteredIndex[i]) {
+ item.setExpressionPosition(i);
+ break;
+ }
+ }
+ if (item.getExpressionPosition() == -1) {
+ sortNode.setProperty(NodeConstants.Info.UNRELATED_SORT, true);
+ }
+ }
+ }
+ sourceNode.setProperty(NodeConstants.Info.SYMBOL_MAP, newMap);
+ }
+
// Create output columns for virtual group project
return newCols;
}
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 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -23,6 +23,7 @@
package org.teiid.query.optimizer.relational.rules;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -33,6 +34,7 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.optimizer.relational.OptimizerRule;
@@ -68,7 +70,10 @@
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.lang.SetQuery.Operation;
import org.teiid.query.sql.navigator.DeepPostOrderNavigator;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
@@ -234,9 +239,45 @@
if (!CapabilitiesUtil.useAnsiJoin(RuleRaiseAccess.getModelIDFromAccess(accessRoot,
metadata), metadata, capFinder)) {
simplifyFromClause(query);
}
+ if (columns.isEmpty()) {
+ if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION,
RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata), metadata, capFinder)) {
+ select.addSymbol(new ExpressionSymbol("dummy", new Constant(1)));
//$NON-NLS-1$
+ } else {
+ //TODO: need to ensure the type is consistent
+ //- should be rare as the source would typically support select expression if
it supports union
+ select.addSymbol(selectOutputElement(query.getFrom().getGroups(), metadata));
+ }
+ }
return query;
}
+
+ /**
+ * Find a selectable element in the specified groups. This is a helper for fixing
+ * the "no elements" case.
+ *
+ * @param groups Bunch of groups
+ * @param metadata Metadata implementation
+ * @throws QueryPlannerException
+ */
+ private ElementSymbol selectOutputElement(Collection<GroupSymbol> groups,
QueryMetadataInterface metadata)
+ throws QueryMetadataException, TeiidComponentException {
+ // Find a group with selectable elements and pick the first one
+ for (GroupSymbol group : groups) {
+ List<ElementSymbol> elements =
(List<ElementSymbol>)ResolverUtil.resolveElementsInGroup(group, metadata);
+
+ for (ElementSymbol element : elements) {
+ if(metadata.elementSupports(element.getMetadataID(),
SupportConstants.Element.SELECT)) {
+ element = (ElementSymbol)element.clone();
+ element.setGroupSymbol(group);
+ return element;
+ }
+ }
+ }
+
+ return null;
+ }
+
void buildQuery(PlanNode accessRoot, PlanNode node, Query query,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder) throws
QueryMetadataException, TeiidComponentException, QueryPlannerException {
//visit source and join nodes as they appear
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -341,7 +341,6 @@
}
}
- //TODO: in each of the cases below, check to see if the offending projected
symbol is actually used in the upper frame
List<ElementSymbol> virtualElements = symbolMap.getKeys();
for (int i = 0; i < selectSymbols.size(); i++) {
SingleElementSymbol symbol = selectSymbols.get(i);
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 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -407,7 +407,9 @@
List<SingleElementSymbol> projectedViewSymbols =
Util.deepClone(symbolMap.getKeys(), SingleElementSymbol.class);
- SymbolMap viewMapping =
SymbolMap.createSymbolMap(NodeEditor.findParent(unionSource,
NodeConstants.Types.SOURCE).getGroups().iterator().next(), projectedViewSymbols,
metadata);
+ PlanNode parent = NodeEditor.findParent(unionSource,
NodeConstants.Types.SOURCE);
+ SymbolMap parentMap = (SymbolMap)
parent.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ SymbolMap viewMapping = SymbolMap.createSymbolMap(parentMap.getKeys(),
projectedViewSymbols);
for (AggregateSymbol agg : aggregates) {
agg = (AggregateSymbol)agg.clone();
ExpressionMappingVisitor.mapExpressions(agg, viewMapping.asMap());
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -23,16 +23,15 @@
package org.teiid.query.optimizer.relational.rules;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
-import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.core.TeiidComponentException;
-import org.teiid.core.util.Assertion;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -42,16 +41,14 @@
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
import org.teiid.query.resolver.util.ResolverUtil;
-import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.lang.JoinType;
-import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.util.SymbolMap;
-import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
import org.teiid.query.util.CommandContext;
@@ -71,155 +68,42 @@
QueryMetadataException,
TeiidComponentException {
- try {
- removeOptionalJoinNodes(plan, metadata, capFinder, null);
- } catch (QueryResolverException e) {
- throw new TeiidComponentException(e);
- }
+ List<PlanNode> joinNodes = NodeEditor.findAllNodes(plan,
NodeConstants.Types.JOIN);
+ HashSet<PlanNode> removedNodes = new HashSet<PlanNode>();
+ for (PlanNode planNode : joinNodes) {
+ if (removedNodes.contains(planNode)) {
+ continue;
+ }
+ Set<GroupSymbol> groups =
GroupsUsedByElementsVisitor.getGroups((Collection<? extends
LanguageObject>)planNode.getProperty(NodeConstants.Info.OUTPUT_COLS));
+ List<PlanNode> removed = removeJoin(groups, planNode,
planNode.getFirstChild(), metadata);
+ if (removed != null) {
+ removedNodes.addAll(removed);
+ continue;
+ }
+ removed = removeJoin(groups, planNode, planNode.getLastChild(), metadata);
+ if (removed != null) {
+ removedNodes.addAll(removed);
+ }
+ }
return plan;
}
/**
- * remove optional from top to bottom
- * @throws QueryResolverException
- */
- private boolean removeOptionalJoinNodes(PlanNode node,
- QueryMetadataInterface metadata,
- CapabilitiesFinder capFinder,
Set<ElementSymbol> elements) throws QueryPlannerException,
-
QueryMetadataException,
-
TeiidComponentException, QueryResolverException {
- if (node.getChildCount() == 0) {
- return false;
- }
-
- boolean isRoot = false;
-
- switch (node.getType()) {
-
- case NodeConstants.Types.JOIN:
- {
- if (removedJoin(node, node.getFirstChild(), elements, metadata)) {
- return true;
- }
- if (removedJoin(node, node.getLastChild(), elements, metadata)) {
- return true;
- }
- List crits = (List)node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
- ElementCollectorVisitor.getElements(crits, elements);
- elements.addAll(node.getCorrelatedReferenceElements());
- break;
- }
- case NodeConstants.Types.PROJECT:
- {
- //skip to the child project
- if (node.getProperty(NodeConstants.Info.INTO_GROUP) != null) {
- elements = null;
- node = NodeEditor.findNodePreOrder(node.getFirstChild(),
NodeConstants.Types.PROJECT);
- }
-
- if (elements == null) {
- isRoot = true;
- elements = new HashSet<ElementSymbol>();
- }
-
- //if it is a grouping scenario just make it a root
- if (!isRoot && NodeEditor.findNodePreOrder(node.getFirstChild(),
NodeConstants.Types.GROUP, NodeConstants.Types.PROJECT) != null) {
- isRoot = true;
- }
-
- if (isRoot) {
- List columns =
(List)node.getProperty(NodeConstants.Info.PROJECT_COLS);
- ElementCollectorVisitor.getElements(columns, elements);
- elements.addAll(node.getCorrelatedReferenceElements());
- }
-
- break;
- }
- case NodeConstants.Types.SOURCE:
- {
- if (elements == null) {
- break;
- }
- SymbolMap symbolMap =
(SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP);
- Set convertedElements = new HashSet();
- for (ElementSymbol element : elements) {
- Expression convertedExpression =
symbolMap.getMappedExpression(element);
- if (convertedExpression != null) {
- ElementCollectorVisitor.getElements(convertedExpression,
convertedElements);
- }
- }
- elements = convertedElements;
- isRoot = true;
- break;
- }
- case NodeConstants.Types.SELECT: //covers having as well
- {
- if (elements != null) {
- Criteria crit =
(Criteria)node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
- ElementCollectorVisitor.getElements(crit, elements);
- elements.addAll(node.getCorrelatedReferenceElements());
- }
- break;
- }
- case NodeConstants.Types.SORT:
- {
- if (elements != null) {
- OrderBy sortOrder =
(OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER);
- ElementCollectorVisitor.getElements(sortOrder, elements);
- }
- break;
- }
- case NodeConstants.Types.SET_OP:
- case NodeConstants.Types.DUP_REMOVE:
- {
- //allow project nodes to be seen as roots
- elements = null;
- break;
- }
- }
-
- //if this is a root then keep removing optional nodes until none can be removed
- if (isRoot) {
- boolean optionalRemoved = false;
- do {
- optionalRemoved = removeOptionalJoinNodes(node.getFirstChild(), metadata,
capFinder, elements);
- } while (optionalRemoved);
- return false;
- }
-
- //otherwise recurse through the children
- Iterator iter = node.getChildren().iterator();
-
- while (node.getChildCount() >= 1 && iter.hasNext()) {
- if (removeOptionalJoinNodes((PlanNode)iter.next(), metadata, capFinder,
elements)) {
- return true;
- }
- }
- return false;
- }
-
- /**
* remove the optional node if possible
* @throws QueryPlannerException
+ * @throws TeiidComponentException
+ * @throws QueryMetadataException
*/
- private boolean removedJoin(PlanNode joinNode, PlanNode optionalNode,
- Set elements, QueryMetadataInterface metadata)
throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
- Set groups = optionalNode.getGroups();
-
- Assertion.isNotNull(elements);
-
- for (Iterator i = elements.iterator(); i.hasNext();) {
- ElementSymbol symbol = (ElementSymbol)i.next();
- if (groups.contains(symbol.getGroupSymbol())) {
- return false; //groups contain an output symbol, don't remove
- }
+ private List<PlanNode> removeJoin(Set<GroupSymbol> groups, PlanNode
joinNode, PlanNode optionalNode, QueryMetadataInterface metadata) throws
QueryPlannerException, QueryMetadataException, TeiidComponentException {
+ if (!Collections.disjoint(optionalNode.getGroups(), groups)) {
+ return null;
}
-
+
JoinType jt = (JoinType)joinNode.getProperty(NodeConstants.Info.JOIN_TYPE);
if (!optionalNode.hasBooleanProperty(NodeConstants.Info.IS_OPTIONAL) &&
(jt != JoinType.JOIN_LEFT_OUTER || optionalNode != joinNode.getLastChild() ||
useNonDistinctRows(joinNode.getParent()))) {
- return false;
+ return null;
}
// remove the parent node and move the sibling node upward
PlanNode parentNode = joinNode.getParent();
@@ -227,16 +111,16 @@
NodeEditor.removeChildNode(parentNode, joinNode);
// correct the parent nodes that may be using optional elements
- for (GroupSymbol optionalGroup : optionalNode.getGroups()) {
+ /*for (GroupSymbol optionalGroup : optionalNode.getGroups()) {
List<ElementSymbol> optionalElements =
ResolverUtil.resolveElementsInGroup(optionalGroup, metadata);
List<Constant> replacements = new
ArrayList<Constant>(optionalElements.size());
for (ElementSymbol elementSymbol : optionalElements) {
replacements.add(new Constant(null, elementSymbol.getType()));
}
FrameUtil.convertFrame(parentNode, optionalGroup, null,
SymbolMap.createSymbolMap(optionalElements, replacements).asMap(), metadata);
- }
+ }*/
- return true;
+ return NodeEditor.findAllNodes(optionalNode, NodeConstants.Types.JOIN);
}
/**
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/FunctionCollectorVisitor.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -48,7 +48,7 @@
*/
public class FunctionCollectorVisitor extends LanguageVisitor {
- private Collection functions;
+ private Collection<Function> functions;
private String functionName;
@@ -58,7 +58,7 @@
* @param elements Collection to use for elements
* @throws IllegalArgumentException If elements is null
*/
- public FunctionCollectorVisitor(Collection functions) {
+ public FunctionCollectorVisitor(Collection<Function> functions) {
this(functions, null);
}
@@ -68,7 +68,7 @@
* @param elements Collection to use for elements
* @throws IllegalArgumentException If elements is null
*/
- public FunctionCollectorVisitor(Collection functions, String functionName) {
+ public FunctionCollectorVisitor(Collection<Function> functions, String
functionName) {
if(functions == null) {
throw new
IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0022"));
//$NON-NLS-1$
}
@@ -81,7 +81,7 @@
* after the visitor has been run on the language object tree.
* @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
*/
- public Collection getFunctions() {
+ public Collection<Function> getFunctions() {
return this.functions;
}
@@ -101,7 +101,7 @@
* @param obj Language object
* @param elements Collection to collect elements in
*/
- public static final void getFunctions(LanguageObject obj, Collection functions) {
+ public static final void getFunctions(LanguageObject obj, Collection<Function>
functions) {
getFunctions(obj, functions, false);
}
@@ -110,7 +110,7 @@
* @param obj Language object
* @param elements Collection to collect elements in
*/
- public static final void getFunctions(LanguageObject obj, Collection functions,
boolean deep) {
+ public static final void getFunctions(LanguageObject obj, Collection<Function>
functions, boolean deep) {
FunctionCollectorVisitor visitor = new FunctionCollectorVisitor(functions);
if (!deep) {
PreOrderNavigator.doVisit(obj, visitor);
@@ -127,16 +127,16 @@
* @param removeDuplicates True to remove duplicates
* @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
*/
- public static final Collection getFunctions(LanguageObject obj, boolean
removeDuplicates) {
+ public static final Collection<Function> getFunctions(LanguageObject obj,
boolean removeDuplicates) {
return getFunctions(obj, removeDuplicates, false);
}
- public static final Collection getFunctions(LanguageObject obj, boolean
removeDuplicates, boolean deep) {
- Collection functions = null;
+ public static final Collection<Function> getFunctions(LanguageObject obj,
boolean removeDuplicates, boolean deep) {
+ Collection<Function> functions = null;
if(removeDuplicates) {
- functions = new HashSet();
+ functions = new HashSet<Function>();
} else {
- functions = new ArrayList();
+ functions = new ArrayList<Function>();
}
getFunctions(obj, functions, deep);
return functions;
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAccessPatterns.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -213,7 +213,7 @@
@Test public void testPushingCriteriaThroughFrameAccessPattern0() {
TestOptimizer.helpPlan("select * from vm1.g9 where
vm1.g9.e1='abc'", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
- new String[] { "SELECT pm4.g1.e1 FROM pm4.g1 WHERE pm4.g1.e1 =
'abc'", //$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm4.g1 WHERE pm4.g1.e1 =
'abc'", //$NON-NLS-1$
"SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1 WHERE pm1.g1.e1
= 'abc'" } ); //$NON-NLS-1$
}
@@ -232,7 +232,7 @@
@Test public void testPushingCriteriaThroughFrameAccessPattern3() {
TestOptimizer.helpPlan("select * from vm1.g1, vm1.g9 where
vm1.g1.e1='abc' and vm1.g1.e1=vm1.g9.e1",
FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
- new String[] {"SELECT pm4.g1.e1 FROM pm4.g1 WHERE pm4.g1.e1 =
'abc'", //$NON-NLS-1$
+ new String[] {"SELECT 1 FROM pm4.g1 WHERE pm4.g1.e1 =
'abc'", //$NON-NLS-1$
"SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1 WHERE pm1.g1.e1 =
'abc'", //$NON-NLS-1$
"SELECT g1__1.e1, g1__1.e2, g1__1.e3, g1__1.e4 FROM pm1.g1
AS g1__1 WHERE g1__1.e1 = 'abc'"} ); //$NON-NLS-1$
}
Modified:
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -22,6 +22,7 @@
package org.teiid.query.optimizer;
+import org.junit.Test;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
@@ -29,18 +30,16 @@
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.unittest.FakeMetadataFactory;
-import junit.framework.TestCase;
-
/**
* expressions in group use lacks robust support in MySQL, PostGres, and Derby
Expressions and it's nothing more than syntactic sugar for an inline view,
* a new approach was taken to use inline views rather than a non ANSI group by
construct.
*
* Later we can add a connector binding property to support non-select expressions in
group by.
*/
-public class TestExpressionsInGroupBy extends TestCase {
+public class TestExpressionsInGroupBy {
- public void testCase1565() throws Exception {
+ @Test public void testCase1565() throws Exception {
// Create query
String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date)
AS x FROM bqt1.smalla) as y GROUP BY x"; //$NON-NLS-1$
@@ -64,7 +63,7 @@
}
// Merge across multiple virtual groups - should be same outcome as testCase1565
- public void testCase1565_2() throws Exception {
+ @Test public void testCase1565_2() throws Exception {
// Create query
String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date)
AS x FROM (SELECT TimestampValue from bqt1.smalla) as z) as y GROUP BY x";
//$NON-NLS-1$
@@ -88,7 +87,7 @@
}
// Merge across multiple virtual groups above the physical
- public void testCase1565_3() throws Exception {
+ @Test public void testCase1565_3() throws Exception {
String sql = "SELECT x, COUNT(*) FROM (SELECT convert(TimestampValue, date)
AS x FROM (SELECT TimestampValue from bqt1.smalla) as z) as y GROUP BY x";
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -115,7 +114,7 @@
}
// Test what happens when not all the functions in the virtual SELECT can be pushed
- public void testCase1565_4() throws Exception {
+ @Test public void testCase1565_4() throws Exception {
// Create query
String sql = "SELECT x, y FROM (SELECT convert(TimestampValue, date) as x,
length(stringkey) as y from bqt1.smalla) as z GROUP BY x, y"; //$NON-NLS-1$
@@ -153,7 +152,7 @@
}
// Test nested functions
- public void testCase1565_5() throws Exception {
+ @Test public void testCase1565_5() throws Exception {
// Create query
String sql = "SELECT x, COUNT(*) FROM (SELECT convert(intkey + 5, string) AS
x FROM bqt1.smalla) as y GROUP BY x"; //$NON-NLS-1$
@@ -191,7 +190,7 @@
}
// SELECT SUM(x) FROM (SELECT IntKey+1 AS x FROM BQT1.SmallA) AS g
- public void testAggregateNoGroupByWithNestedFunction() {
+ @Test public void testAggregateNoGroupByWithNestedFunction() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT SUM(x) FROM (SELECT
IntKey+1 AS x FROM BQT1.SmallA) AS g", FakeMetadataFactory.exampleBQTCached(),
//$NON-NLS-1$
new String[] { "SELECT IntKey FROM BQT1.SmallA" }); //$NON-NLS-1$
@@ -216,7 +215,7 @@
/**
* Without inline view support the agg is not pushed down
*/
- public void testFunctionInGroupBy() {
+ @Test public void testFunctionInGroupBy() {
String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
"FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000
+' else '0-999' end"; //$NON-NLS-1$
@@ -261,7 +260,7 @@
*
* @since 4.2
*/
- public void testFunctionInGroupByCantPush() {
+ @Test public void testFunctionInGroupByCantPush() {
String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
"FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000
+' else '0-999' end"; //$NON-NLS-1$
@@ -305,7 +304,7 @@
*
* @since 4.2
*/
- public void testFunctionInGroupByHavingCantPush() {
+ @Test public void testFunctionInGroupByHavingCantPush() {
String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
"FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
"HAVING case when IntKey>=5000 then '5000 +' else
'0-999' end = '5000 +'"; //$NON-NLS-1$
@@ -349,7 +348,7 @@
*
* @since 4.2
*/
- public void testFunctionInGroupByCantPushRewritten() {
+ @Test public void testFunctionInGroupByCantPushRewritten() {
String sql = "SELECT SUM(IntKey), c FROM (SELECT IntKey, case when
IntKey>=5000 then '5000 +' else '0-999' end AS c FROM BQT1.SmallA) AS
temp GROUP BY c"; //$NON-NLS-1$
// Plan query
@@ -386,7 +385,7 @@
});
}
- public void testFunctionOfAggregateCantPush2() {
+ @Test public void testFunctionOfAggregateCantPush2() {
String sql = "SELECT SUM(length(StringKey || 'x')) + 1 AS x FROM
BQT1.SmallA GROUP BY StringKey || 'x' HAVING space(MAX(length((StringKey ||
'x') || 'y'))) = ' '"; //$NON-NLS-1$
// Plan query
@@ -419,7 +418,7 @@
}
- public void testDontPushGroupByUnsupportedFunction() throws Exception {
+ @Test public void testDontPushGroupByUnsupportedFunction() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinOptimization.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -154,7 +154,7 @@
metadata,
null,
capFinder,
- new String[] {"SELECT
bqt1.smalla.intkey FROM bqt1.smalla", "SELECT BQT2.SmallA.IntKey FROM
bqt2.smalla"}, true ); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT
bqt1.smalla.intkey FROM bqt1.smalla", "SELECT 1 FROM bqt2.smalla"}, true );
//$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -266,7 +266,7 @@
String sql = "select bqt1.smalla.intkey from bqt1.smalla inner join (select
bqt3.smalla.intkey from bqt2.smalla left outer join bqt3.smalla on bqt2.smalla.intkey =
bqt3.smalla.intkey and bqt3.smalla.intkey = 1) foo on bqt1.smalla.intkey =
foo.intkey"; //$NON-NLS-1$
// Plan query
- ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.intkey FROM
bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT g_0.IntKey FROM bqt2.smalla AS
g_0", "SELECT g_0.intkey AS c_0 FROM bqt1.smalla AS g_0 ORDER BY c_0"});
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.intkey FROM
bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT 1 FROM bqt2.smalla AS
g_0", "SELECT g_0.intkey AS c_0 FROM bqt1.smalla AS g_0 ORDER BY c_0"});
//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
TestOptimizer.checkNodeTypes(plan, new int[] {
3, // Access
@@ -293,7 +293,7 @@
String sql = "select bqt1.smalla.intkey from bqt1.smalla left outer join
(select bqt3.smalla.intkey from bqt3.smalla where bqt3.smalla.intkey = 1) foo on
bqt1.smalla.intkey = foo.intkey"; //$NON-NLS-1$
// Plan query
- ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT g_0.IntKey FROM
bqt3.smalla AS g_0 WHERE g_0.intkey = 1", "SELECT g_0.intkey FROM bqt1.smalla AS
g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(), new String[] {"SELECT 1 FROM bqt3.smalla AS
g_0 WHERE g_0.intkey = 1", "SELECT g_0.intkey FROM bqt1.smalla AS g_0"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java 2011-02-14
20:12:15 UTC (rev 2905)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestJoinWithFunction.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -130,8 +130,8 @@
String leftQuery = "SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4,
RAND() AS RandomLeft " //$NON-NLS-1$
+ "FROM pm1.g1"; //$NON-NLS-1$
// source query for other side of a JOIN
- String rightQuery = "SELECT pm2.g2.e1 as ID, pm2.g2.e2, pm2.g2.e3, pm2.g2.e4
" //$NON-NLS-1$
- + "FROM pm2.g2"; //$NON-NLS-1$
+ String rightQuery = "SELECT pm1.g2.e1 as ID, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4
" //$NON-NLS-1$
+ + "FROM pm1.g2"; //$NON-NLS-1$
// User Command
/*
@@ -147,7 +147,7 @@
// The user command should result in two atomic commands
String[] expected = new String[] {
"SELECT g_0.e1, g_0.e2, g_0.e3, g_0.e4 FROM pm1.g1 AS g_0", //$NON-NLS-1$
- "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm2.g2
AS g_0 ORDER BY c_0", //$NON-NLS-1$
+ "SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2, g_0.e4 AS c_3 FROM pm1.g2
AS g_0 ORDER BY c_0", //$NON-NLS-1$
};
// create a plan and assert our atomic queries
@@ -169,7 +169,40 @@
0 // UnionAll
});
}
+
+ /**
+ * Note that we detect the lower rand is not used
+ */
+ public void testNonDeterministicPreJoin1() throws Exception {
+ // source query for one side of a JOIN
+ String leftQuery = "SELECT pm1.g1.e1 as ID, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4,
RAND() AS RandomLeft " //$NON-NLS-1$
+ + "FROM pm1.g1"; //$NON-NLS-1$
+ // source query for other side of a JOIN
+ String rightQuery = "SELECT pm1.g2.e1 as ID, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4
" //$NON-NLS-1$
+ + "FROM pm1.g2"; //$NON-NLS-1$
+ // User Command
+ /*
+ * Return everything from the JOIN. TopRandom is the use of RAND() on
+ * the user command while RandomLeft is the use of RAND() within a
+ * source node.
+ */
+ String sql = "SELECT l.ID, l.e2, l.e3, l.e4, r.ID, r.e2, r.e3, r.e4 " +
//$NON-NLS-1$
+ "FROM (" + leftQuery + ") AS l, " + //$NON-NLS-1$ //$NON-NLS-2$
+ "(" + rightQuery + ") AS r " + //$NON-NLS-1$ //$NON-NLS-2$
+ "WHERE l.ID = r.ID"; //$NON-NLS-1$
+
+ // The user command should result in two atomic commands
+ String[] expected = new String[] {
+ "SELECT g_0.e1, g_0.e2, g_0.e3, g_0.e4, g_1.e1, g_1.e2, g_1.e3, g_1.e4 FROM
pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE g_0.e1 = g_1.e1", //$NON-NLS-1$
+ };
+
+ // create a plan and assert our atomic queries
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql, TestOptimizer.example1(),
expected,
+ ComparisonMode.EXACT_COMMAND_STRING);
+ TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
+ }
+
/**
* <p>Test the use of a non-deterministic function on the sub-command of a user
* command and the user command itself, which performs a JOIN of two sources.</p>
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-02-14
20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -949,8 +949,8 @@
/** defect #4997 */
@Test public void testCountStarNoRows() {
ProcessorPlan plan = helpPlan("select count(*) from vm1.u4",
example1(), //$NON-NLS-1$
- new String[] { "SELECT e1 FROM pm1.g2", //$NON-NLS-1$
- "SELECT e1 FROM pm1.g1" } ); //$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g2", //$NON-NLS-1$
+ "SELECT 1 FROM pm1.g1" } ); //$NON-NLS-1$
checkNodeTypes(plan, new int[] {
2, // Access
0, // DependentAccess
@@ -962,7 +962,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
1 // UnionAll
@@ -971,7 +971,7 @@
@Test public void testPushingCriteriaWithCopy() {
ProcessorPlan plan = helpPlan("select vm1.u1.e1 from vm1.u1, pm1.g1 where
vm1.u1.e1='abc' and vm1.u1.e1=pm1.g1.e1", example1(), //$NON-NLS-1$
- new String[] { "SELECT pm1.g1.e1 FROM pm1.g1 WHERE pm1.g1.e1 =
'abc'", //$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g1 WHERE pm1.g1.e1 = 'abc'",
//$NON-NLS-1$
"SELECT pm1.g3.e1, pm1.g3.e2, pm1.g3.e3, pm1.g3.e4 FROM
pm1.g3 WHERE pm1.g3.e1 = 'abc'", //$NON-NLS-1$
"SELECT pm1.g2.e1, pm1.g2.e2, pm1.g2.e3, pm1.g2.e4 FROM pm1.g2 WHERE
pm1.g2.e1 = 'abc'", //$NON-NLS-1$
"SELECT pm1.g1.e1, pm1.g1.e2, pm1.g1.e3, pm1.g1.e4 FROM pm1.g1 WHERE
pm1.g1.e1 = 'abc'" } ); //$NON-NLS-1$
@@ -1057,17 +1057,17 @@
@Test public void testDefect5282_1() {
helpPlan("select * FROM vm1.a4 WHERE vm1.a4.count > 0", example1(),
//$NON-NLS-1$
- new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );
//$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g1" } ); //$NON-NLS-1$
}
@Test public void testDefect5282_2() {
helpPlan("select count(*) FROM vm1.a4", example1(), //$NON-NLS-1$
- new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );
//$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g1" } ); //$NON-NLS-1$
}
@Test public void testDefect5282_3() {
helpPlan("select * FROM vm1.a5 WHERE vm1.a5.count > 0", example1(),
//$NON-NLS-1$
- new String[] { "SELECT pm1.g1.e1 FROM pm1.g1" } );
//$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g1" } ); //$NON-NLS-1$
}
@Test public void testDepJoinHintBaseline() throws Exception {
@@ -1100,8 +1100,8 @@
@Test public void testDefect6425_2() {
helpPlan("select count(*) from vm1.u9", example1(), //$NON-NLS-1$
- new String[] { "SELECT e1 FROM pm1.g1", //$NON-NLS-1$
- "SELECT e1 FROM pm1.g2" } ); //$NON-NLS-1$
+ new String[] { "SELECT 1 FROM pm1.g1", //$NON-NLS-1$
+ "SELECT 1 FROM pm1.g2" } ); //$NON-NLS-1$
}
@Test public void testPushMatchCritWithReference() {
@@ -2714,7 +2714,7 @@
*/
@Test public void testCrossJoinNoElementCriteriaOptimization2() {
ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y
where {b'true'} = {b'true'}", example1(), //$NON-NLS-1$
- new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1", "SELECT
pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[]{"SELECT 1 FROM pm1.g1 AS g1__1", "SELECT
pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
checkNodeTypes(plan, new int[] {
2, // Access
0, // DependentAccess
@@ -2738,7 +2738,7 @@
*/
@Test public void testCrossJoinNoElementCriteriaOptimization3() {
ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y
where {b'true'} in (select e3 FROM vm1.g1)", example1(), //$NON-NLS-1$
- new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1", "SELECT
pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[]{"SELECT 1 FROM pm1.g1 AS g1__1", "SELECT
pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}); //$NON-NLS-1$ //$NON-NLS-2$
checkNodeTypes(plan, new int[] {
2, // Access
0, // DependentAccess
@@ -2768,7 +2768,7 @@
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
ProcessorPlan plan = helpPlan("select Y.e1, Y.e2 FROM vm1.g1 X, vm1.g1 Y
where {b'true'} in (select e3 FROM vm1.g1)", example1(), null, capFinder,
//$NON-NLS-1$
- new String[]{"SELECT g1__1.e1 FROM pm1.g1 AS g1__1 WHERE TRUE IN (SELECT
pm1.g1.e3 FROM pm1.g1)", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, true);
//$NON-NLS-1$ //$NON-NLS-2$
+ new String[]{"SELECT 1 FROM pm1.g1 AS g1__1 WHERE TRUE IN (SELECT
pm1.g1.e3 FROM pm1.g1)", "SELECT pm1.g1.e1, pm1.g1.e2 FROM pm1.g1"}, true);
//$NON-NLS-1$ //$NON-NLS-2$
checkNodeTypes(plan, new int[] {
2, // Access
0, // DependentAccess
@@ -4488,7 +4488,7 @@
ProcessorPlan plan = helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
null, capFinder,
- new String[] {"SELECT '' AS y FROM
BQT1.SmallA AS a UNION ALL SELECT '' FROM bqt1.smallb AS b"}, //$NON-NLS-1$
+ new String[] {"SELECT 1 AS c_0 FROM
BQT1.SmallA AS a UNION ALL SELECT 1 AS c_0 FROM bqt1.smallb AS b"}, //$NON-NLS-1$
SHOULD_SUCCEED );
checkNodeTypes(plan, new int[] {
@@ -6409,7 +6409,7 @@
capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
helpPlan("select pm2.g1.e1 FROM pm2.g1 CROSS JOIN pm2.g2", example1(),
null, capFinder, //$NON-NLS-1$
- new String[] { "SELECT pm2.g1.e1 FROM pm2.g1", "SELECT
pm2.g2.e1 FROM pm2.g2"}, true ); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] { "SELECT pm2.g1.e1 FROM pm2.g1", "SELECT 1 FROM
pm2.g2"}, true ); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -6430,7 +6430,7 @@
String sql = "select count(*) from (select intkey from bqt1.smalla union all
select intkey from bqt1.smallb) as a"; //$NON-NLS-1$
ProcessorPlan plan = helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null,
capFinder,
- new String[] {"SELECT COUNT(*) FROM (SELECT
intkey FROM bqt1.smalla UNION ALL SELECT intkey FROM bqt1.smallb) AS a"},
TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
+ new String[] {"SELECT COUNT(*) FROM (SELECT 1
FROM bqt1.smalla UNION ALL SELECT 1 FROM bqt1.smallb) AS a"},
TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$
checkNodeTypes(plan, FULL_PUSHDOWN);
}
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java 2011-02-14
20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestRuleRaiseNull.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -22,8 +22,11 @@
package org.teiid.query.optimizer;
+import static org.junit.Assert.*;
+
import java.util.Arrays;
+import org.junit.Test;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.BasicSourceCapabilities;
import org.teiid.query.optimizer.capabilities.FakeCapabilitiesFinder;
@@ -33,11 +36,7 @@
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.unittest.FakeMetadataFactory;
-import junit.framework.TestCase;
-
-
-
-public class TestRuleRaiseNull extends TestCase {
+public class TestRuleRaiseNull {
public static final int[] FULLY_NULL = new int[] {
0, // Access
@@ -64,7 +63,7 @@
* never equals anything). Expected behavior is that a NullNode is inserted in place
of the
* unnecessary access node.
*/
- public void testUnionCriteriaOptimization() {
+ @Test public void testUnionCriteriaOptimization() {
String sql = "select * from ( select intkey as cola, null as colb, intnum as
colc from bqt1.smalla union all select null, intkey, intnum from bqt2.smalla) as X where
X.cola = 1"; //$NON-NLS-1$
@@ -75,7 +74,7 @@
}
- public void testRaiseNullWithInnerJoin() {
+ @Test public void testRaiseNullWithInnerJoin() {
String sql = "select b.intkey from (select intkey from bqt1.smalla where 1 =
0) a inner join (select intkey from bqt1.smallb) b on (a.intkey = b.intkey)";
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -83,7 +82,7 @@
TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
}
- public void testRaiseNullWithFullOuterJoin() {
+ @Test public void testRaiseNullWithFullOuterJoin() {
String sql = "select b.intkey from (select intkey from bqt1.smalla) a full
outer join (select intkey from bqt1.smallb where 1 = 0) b on (a.intkey = b.intkey)";
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -91,7 +90,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithOuterJoin() {
+ @Test public void testRaiseNullWithOuterJoin() {
String sql = "select b.intkey from (select intkey from bqt1.smalla) a left
outer join (select intkey from bqt1.smallb where 1 = 0) b on (a.intkey = b.intkey)";
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -99,7 +98,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithOuterJoin1() {
+ @Test public void testRaiseNullWithOuterJoin1() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
@@ -112,7 +111,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnion() {
+ @Test public void testRaiseNullWithUnion() {
String sql = "select b.x from (select intkey as x from bqt1.smalla where 1 =
0 union all select intnum as y from bqt1.smalla) b"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -122,7 +121,7 @@
assertEquals(Arrays.asList(new Object[] {new ElementSymbol("b.x")}),
plan.getOutputElements()); //$NON-NLS-1$
}
- public void testRaiseNullWithUnion1() {
+ @Test public void testRaiseNullWithUnion1() {
String sql = "select b.intkey from (select intkey from bqt1.smalla union all
select intnum from bqt1.smalla where 1 = 0) b"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -130,7 +129,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnion2() {
+ @Test public void testRaiseNullWithUnion2() {
String sql = "select b.intkey, b.x from (select intkey, intnum as x from
bqt1.smalla where 1 = 0 union all select intnum as a, null from bqt1.smalla union all
select 1 as z, intkey as b from bqt1.smallb) b"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -153,7 +152,7 @@
});
}
- public void testRaiseNullWithUnion3() {
+ @Test public void testRaiseNullWithUnion3() {
String sql = "select intkey, intnum as x from bqt1.smalla where 1 = 0 union
all select intnum, intkey as z from bqt1.smalla where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -161,7 +160,7 @@
TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
}
- public void testRaiseNullWithUnion4() throws Exception {
+ @Test public void testRaiseNullWithUnion4() throws Exception {
String sql = "select b.intkey, b.x from (select intkey, intnum as x from
bqt1.smalla where 1 = 0 union all select 1 as z, intkey as b from bqt1.smallb) b inner
join bqt1.smalla on b.intkey = bqt1.smalla.intkey"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -169,7 +168,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnion5() {
+ @Test public void testRaiseNullWithUnion5() {
String sql = "select intkey from bqt1.smalla union all select intkey from
bqt2.smalla where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -177,7 +176,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnion6() {
+ @Test public void testRaiseNullWithUnion6() {
String sql = "select intkey from bqt1.smalla union all select intkey from
bqt2.smalla union all select intkey from bqt2.smalla where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -200,17 +199,17 @@
});
}
- public void testPushCriteriaThroughUnion9() {
+ @Test public void testPushCriteriaThroughUnion9() {
TestOptimizer.helpPlan("select * from vm1.u8 where const =
's1'", TestOptimizer.example1(), //$NON-NLS-1$
new String[] { "SELECT 's1', e1 FROM pm1.g1" } );
//$NON-NLS-1$
}
- public void testPushCriteriaThroughUnion10() {
+ @Test public void testPushCriteriaThroughUnion10() {
TestOptimizer.helpPlan("select * from vm1.u8 where const =
's3'", TestOptimizer.example1(), //$NON-NLS-1$
new String[] { "SELECT 's3', e1 FROM pm1.g3" } );
//$NON-NLS-1$
}
- public void testRaiseNullWithOuterJoinAndHaving() {
+ @Test public void testRaiseNullWithOuterJoinAndHaving() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
@@ -242,7 +241,7 @@
* Ensures proper handling of the removal of the first branch and
* duplicate symbol names in the next branch
*/
- public void testRaiseNullWithUnion7() throws Exception {
+ @Test public void testRaiseNullWithUnion7() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -260,7 +259,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnionOrderBy() {
+ @Test public void testRaiseNullWithUnionOrderBy() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -276,7 +275,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithGroupBy() {
+ @Test public void testRaiseNullWithGroupBy() {
String sql = "select max(e2), e1 from pm1.g1 where 1 = 0 group by e1";
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.example1Cached(), new String[]{});
@@ -284,7 +283,7 @@
TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
}
- public void testRaiseNullWithGroupBy1() {
+ @Test public void testRaiseNullWithGroupBy1() {
String sql = "select max(e2) from pm1.g1 where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.example1Cached(), new String[]{});
@@ -307,7 +306,7 @@
});
}
- public void testRaiseNullWithExcept() {
+ @Test public void testRaiseNullWithExcept() {
String sql = "select e1 from pm1.g1 except select e2 from pm1.g2 where 1 =
0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.example1Cached(), new String[]{"SELECT DISTINCT g_0.e1 FROM
pm1.g1 AS g_0"}); //$NON-NLS-1$
@@ -315,7 +314,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithIntersect() {
+ @Test public void testRaiseNullWithIntersect() {
String sql = "select max(e2) from pm1.g1 intersect select e2 from pm1.g2
where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.example1Cached(), new String[]{});
@@ -328,19 +327,19 @@
* but instead is cleaned up properly later
* See defect 9865
*/
- public void testCrossJoinNoElementCriteriaOptimization() {
+ @Test public void testCrossJoinNoElementCriteriaOptimization() {
ProcessorPlan plan = TestOptimizer.helpPlan("select Y.e1, Y.e2 FROM vm1.g1
X, vm1.g1 Y where {b'true'} = {b'false'}", TestOptimizer.example1(),
//$NON-NLS-1$
new String[0]);
TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
}
- public void testSelectLiteralFalseCriteria() {
+ @Test public void testSelectLiteralFalseCriteria() {
ProcessorPlan plan = TestOptimizer.helpPlan("Select 'x' from pm1.g1
where 1=0", TestOptimizer.example1(), //$NON-NLS-1$
new String[] { });
TestOptimizer.checkNodeTypes(plan, FULLY_NULL);
}
- public void testRaiseNullWithUnionNotAll() {
+ @Test public void testRaiseNullWithUnionNotAll() {
String sql = "select intkey from bqt2.smalla union select intkey from
bqt2.smalla where 1 = 0"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
FakeMetadataFactory.exampleBQTCached(),
@@ -348,7 +347,7 @@
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
- public void testRaiseNullWithUnionAndAliases() {
+ @Test public void testRaiseNullWithUnionAndAliases() {
String sql = "select pm1.g1.e1 from pm1.g1, (select e1 from pm1.g1 where (1
= 0) union all select e1 as x from pm1.g2) x where pm1.g1.e1 <> x.e1";
//$NON-NLS-1$
RelationalPlan plan = (RelationalPlan)TestOptimizer.helpPlan(sql,
FakeMetadataFactory.example1Cached(),
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-14
20:12:15 UTC (rev 2905)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-14
20:34:03 UTC (rev 2906)
@@ -6213,8 +6213,8 @@
// Construct data manager with data
HardcodedDataManager dataManager = new HardcodedDataManager();
- dataManager.addData("SELECT g_0.a FROM p1.t AS g_0", //$NON-NLS-1$
- new List[] { Arrays.asList(new Object[] { new Integer(1)
})});
+ dataManager.addData("SELECT 1 AS c_0 FROM p1.t AS g_1 UNION ALL SELECT 1 AS
c_0 FROM p1.t AS g_0", //$NON-NLS-1$
+ new List[] { Arrays.asList(1), Arrays.asList(1)});
helpProcess(plan, dataManager, expected);
}