[teiid-commits] teiid SVN: r1888 - in trunk/engine/src: test/java/com/metamatrix/query/optimizer and 1 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Tue Mar 2 22:29:07 EST 2010
Author: shawkins
Date: 2010-03-02 22:29:06 -0500 (Tue, 02 Mar 2010)
New Revision: 1888
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestExpressionsInGroupBy.java
trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestLimit.java
trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptionalJoins.java
trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestRuleMergeVirtual.java
trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
Log:
TEIID-1007 enhancing the rulemergevirtual logic to check for columns used in a group by clause
Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleAssignOutputElements.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -162,7 +162,26 @@
case NodeConstants.Types.SOURCE: {
outputElements = (List<SingleElementSymbol>)determineSourceOutput(root, outputElements);
root.setProperty(NodeConstants.Info.OUTPUT_COLS, outputElements);
- assignOutputElements(root.getFirstChild(), filterVirtualElements(root, outputElements, metadata), metadata, capFinder, rules, analysisRecord, context);
+ 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;
}
case NodeConstants.Types.SET_OP: {
@@ -228,31 +247,7 @@
SymbolMap symbolMap = (SymbolMap) root.getProperty(NodeConstants.Info.SYMBOL_MAP);
return symbolMap.getKeys();
}
- PlanNode limit = NodeEditor.findNodePreOrder(root, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.PROJECT);
- if (limit == null) {
- return outputElements;
- }
- //reset the output elements to be the output columns + what's required by the sort
- PlanNode sort = NodeEditor.findNodePreOrder(limit, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
- if (sort == null) {
- return outputElements;
- }
- OrderBy sortOrder = (OrderBy)sort.getProperty(NodeConstants.Info.SORT_ORDER);
- List<SingleElementSymbol> topCols = FrameUtil.findTopCols(sort);
-
- SymbolMap symbolMap = (SymbolMap)root.getProperty(NodeConstants.Info.SYMBOL_MAP);
-
- List<ElementSymbol> symbolOrder = symbolMap.getKeys();
-
- for (OrderByItem item : sortOrder.getOrderByItems()) {
- final Expression expr = item.getSymbol();
- int index = topCols.indexOf(expr);
- ElementSymbol symbol = symbolOrder.get(index);
- if (!outputElements.contains(symbol)) {
- outputElements.add(symbol);
- }
- }
- return outputElements;
+ return outputElements;
}
/**
Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RuleMergeVirtual.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -133,15 +133,20 @@
}
PlanNode parentGroup = NodeEditor.findParent(frame, NodeConstants.Types.GROUP, NodeConstants.Types.SOURCE);
+ List<SingleElementSymbol> groupCols = null;
+ if (parentGroup != null) {
+ groupCols = (List<SingleElementSymbol>)parentGroup.getProperty(NodeConstants.Info.GROUP_COLS);
+ }
- if (!checkProjectedSymbols(projectNode, virtualGroup, parentJoin, parentGroup, metadata)) {
+ SymbolMap symbolMap = (SymbolMap)frame.getProperty(NodeConstants.Info.SYMBOL_MAP);
+
+ if (!checkProjectedSymbols(projectNode, virtualGroup, parentJoin, groupCols, symbolMap, metadata)) {
return root;
}
// Otherwise merge should work
// Convert parent frame before merge
- SymbolMap symbolMap = (SymbolMap)frame.getProperty(NodeConstants.Info.SYMBOL_MAP);
FrameUtil.convertFrame(frame, virtualGroup, FrameUtil.findJoinSourceNode(projectNode).getGroups(), symbolMap.asMap(), metadata);
PlanNode parentBottom = frame.getParent();
@@ -195,7 +200,7 @@
return root;
}
- List<? extends SingleElementSymbol> requiredElements = RuleAssignOutputElements.determineSourceOutput(frame, new ArrayList<SingleElementSymbol>());
+ List<? extends SingleElementSymbol> requiredElements = getNecessaryOutput(frame);
List<SingleElementSymbol> selectSymbols = (List<SingleElementSymbol>)parentProject.getProperty(NodeConstants.Info.PROJECT_COLS);
// check that it only performs simple projection and that all required symbols are projected
@@ -267,6 +272,42 @@
return root;
}
+
+ private static List<? extends SingleElementSymbol> getNecessaryOutput(PlanNode root) {
+ List<SingleElementSymbol> outputElements = new ArrayList<SingleElementSymbol>();
+ List<? extends SingleElementSymbol> result = RuleAssignOutputElements.determineSourceOutput(root, outputElements);
+ if (!result.isEmpty()) {
+ return result;
+ }
+ PlanNode limit = NodeEditor.findNodePreOrder(root, NodeConstants.Types.TUPLE_LIMIT, NodeConstants.Types.PROJECT);
+ if (limit == null) {
+ return outputElements;
+ }
+ //reset the output elements to be the output columns + what's required by the sort
+ PlanNode sort = NodeEditor.findNodePreOrder(limit, NodeConstants.Types.SORT, NodeConstants.Types.PROJECT);
+ if (sort == null) {
+ return outputElements;
+ }
+ OrderBy sortOrder = (OrderBy)sort.getProperty(NodeConstants.Info.SORT_ORDER);
+ List<SingleElementSymbol> topCols = FrameUtil.findTopCols(sort);
+
+ SymbolMap symbolMap = (SymbolMap)root.getProperty(NodeConstants.Info.SYMBOL_MAP);
+
+ List<ElementSymbol> symbolOrder = symbolMap.getKeys();
+
+ for (OrderByItem item : sortOrder.getOrderByItems()) {
+ final Expression expr = item.getSymbol();
+ int index = topCols.indexOf(expr);
+ if (index < 0) {
+ continue;
+ }
+ ElementSymbol symbol = symbolOrder.get(index);
+ if (!outputElements.contains(symbol)) {
+ outputElements.add(symbol);
+ }
+ }
+ return outputElements;
+ }
/**
* Check to ensure that we are not projecting a subquery or null dependent expressions
@@ -274,7 +315,8 @@
private static boolean checkProjectedSymbols(PlanNode projectNode,
GroupSymbol virtualGroup,
PlanNode parentJoin,
- PlanNode parentGroup,
+ List<SingleElementSymbol> parentGroupingCols,
+ SymbolMap symbolMap,
QueryMetadataInterface metadata) {
List<SingleElementSymbol> selectSymbols = (List<SingleElementSymbol>)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS);
@@ -302,7 +344,9 @@
}
//TODO: in each of the cases below, check to see if the offending projected symbol is actually used in the upper frame
- for (SingleElementSymbol symbol : selectSymbols) {
+ List<ElementSymbol> virtualElements = symbolMap.getKeys();
+ for (int i = 0; i < selectSymbols.size(); i++) {
+ SingleElementSymbol symbol = selectSymbols.get(i);
Collection scalarSubqueries = ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(symbol);
if (!scalarSubqueries.isEmpty()) {
return false;
@@ -310,7 +354,7 @@
if (checkForNullDependent && JoinUtil.isNullDependent(metadata, groups, SymbolMap.getExpression(symbol))) {
return false;
}
- if (parentGroup != null && !(SymbolMap.getExpression(symbol) instanceof SingleElementSymbol)) {
+ if (parentGroupingCols != null && !(SymbolMap.getExpression(symbol) instanceof SingleElementSymbol) && parentGroupingCols.contains(virtualElements.get(i))) {
return false;
}
// TEIID-16: We do not want to merge a non-deterministic scalar function
Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestExpressionsInGroupBy.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestExpressionsInGroupBy.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestExpressionsInGroupBy.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -205,7 +205,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestLimit.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestLimit.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestLimit.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -865,7 +865,7 @@
public void testSortWithLimitInlineView() {
String sql = "select e1 from (select pm1.g1.e1, pm1.g1.e2 from pm1.g1 order by pm1.g1.e1, pm1.g1.e2 limit 1) x"; //$NON-NLS-1$
- ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[] {"SELECT g_0.e1 AS c_0, g_0.e2 AS c_1 FROM pm1.g1 AS g_0 ORDER BY c_0, c_1"}); //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.example1Cached(), new String[] {"SELECT g_0.e1 AS c_0 FROM pm1.g1 AS g_0 ORDER BY c_0, g_0.e2"}); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, new int[] {
1, // Access
Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptionalJoins.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptionalJoins.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestOptionalJoins.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -287,7 +287,7 @@
@Test public void testOptionalJoinWithNestedOrderBy() {
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT pm1.g3.e1 FROM pm1.g3 inner join (select pm1.g2.e1, pm1.g1.e2 as y from /* optional */ pm1.g1 inner join pm1.g2 on pm1.g1.e1 = pm1.g2.e1 order by pm1.g2.e1 limit 10000) AS x on pm1.g3.e2=x.y", FakeMetadataFactory.example1Cached(), //$NON-NLS-1$
- new String[] {"SELECT g_0.e2 AS c_0, g_0.e1 AS c_1 FROM pm1.g3 AS g_0 ORDER BY c_0", "SELECT g_0.e2 AS c_0, g_1.e1 AS c_1 FROM pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE g_0.e1 = g_1.e1 ORDER BY c_1"} ); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.e2 AS c_0, g_0.e1 AS c_1 FROM pm1.g3 AS g_0 ORDER BY c_0", "SELECT g_0.e2 AS c_0 FROM pm1.g1 AS g_0, pm1.g2 AS g_1 WHERE g_0.e1 = g_1.e1 ORDER BY g_1.e1"} ); //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
Modified: trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestRuleMergeVirtual.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestRuleMergeVirtual.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/test/java/com/metamatrix/query/optimizer/TestRuleMergeVirtual.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -22,11 +22,13 @@
package com.metamatrix.query.optimizer;
+import static junit.framework.Assert.*;
+
import org.junit.Test;
-import static junit.framework.Assert.*;
-
+import com.metamatrix.query.optimizer.TestOptimizer.ComparisonMode;
import com.metamatrix.query.optimizer.capabilities.BasicSourceCapabilities;
+import com.metamatrix.query.optimizer.capabilities.DefaultCapabilitiesFinder;
import com.metamatrix.query.optimizer.capabilities.FakeCapabilitiesFinder;
import com.metamatrix.query.optimizer.capabilities.SourceCapabilities.Capability;
import com.metamatrix.query.processor.ProcessorPlan;
@@ -303,5 +305,16 @@
SortNode node = (SortNode)plan.getRootNode();
assertTrue("Alias was not accounted for in sort node", node.getElements().containsAll(node.getSortElements())); //$NON-NLS-1$
}
+
+ @Test public void testMergeImplicitGroupBy() throws Exception {
+ BasicSourceCapabilities caps = TestAggregatePushdown.getAggregateCapabilities();
+ caps.setFunctionSupport("+", true); //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan("SELECT x FROM (SELECT min(y), max(x) as x FROM (select e1 x, e2 + 1 y from pm1.g1) a) AS b", //$NON-NLS-1$
+ FakeMetadataFactory.example1Cached(), null, new DefaultCapabilitiesFinder(caps),
+ new String[] {
+ "SELECT MAX(g_0.e1) FROM pm1.g1 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+
+ TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
+ }
}
Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java 2010-03-02 23:23:00 UTC (rev 1887)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcessor.java 2010-03-03 03:29:06 UTC (rev 1888)
@@ -6971,7 +6971,26 @@
sampleData1(manager);
helpProcess(plan, manager, expected);
}
+
+ /**
+ * A more direct test of 1, where the nested order by is unrelated
+ */
+ @Test public void testSortWithLimit3() {
+ String sql = "select c from (select pm1.g1.e3 c from pm1.g1 order by pm1.g1.e2 limit 1) x"; //$NON-NLS-1$
+
+ FakeMetadataFacade metadata = FakeMetadataFactory.example1Cached();
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql), metadata, TestOptimizer.getGenericFinder());
+
+ List[] expected = new List[] {
+ Arrays.asList(new Object[] { Boolean.FALSE }),
+ };
+ FakeDataManager manager = new FakeDataManager();
+ sampleData1(manager);
+ helpProcess(plan, manager, expected);
+ }
+
@Test public void testCountWithHaving() {
String sql = "select e1, count(*) from pm1.g1 group by e1 having count(*) > 1"; //$NON-NLS-1$
More information about the teiid-commits
mailing list