Skip to content

Commit

Permalink
TEIID-2801 addressing hive having support and having support in general
Browse files Browse the repository at this point in the history
  • Loading branch information
shawkins committed Jan 15, 2014
1 parent 7120940 commit 44983de
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 10 deletions.
Expand Up @@ -21,14 +21,7 @@
*/
package org.teiid.translator.hive;

import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.BIG_INTEGER;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.DATE;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.DOUBLE;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.FLOAT;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.INTEGER;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.OBJECT;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.STRING;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.TIMESTAMP;
import static org.teiid.translator.TypeFacility.RUNTIME_NAMES.*;

import java.sql.ResultSet;
import java.sql.SQLException;
Expand Down Expand Up @@ -388,4 +381,9 @@ protected FunctionMethod addAggregatePushDownFunction(String qualifier, String n
method.setAggregateAttributes(attr);
return method;
}

@Override
public boolean supportsHaving() {
return false; //only having with group by
}
}
Expand Up @@ -260,6 +260,57 @@ private QueryCommand createQuery(CommandContext context, CapabilitiesFinder capF
ExpressionMappingVisitor.mapExpressions(query.getSelect(), symbolMap.asMap(), true);
ExpressionMappingVisitor.mapExpressions(query.getHaving(), symbolMap.asMap(), true);

if (query.getHaving() != null && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder)) {
Select sel = query.getSelect();
GroupBy groupBy = query.getGroupBy();
Criteria having = query.getHaving();
query.setHaving(null);
OrderBy orderBy = query.getOrderBy();
query.setOrderBy(null);
Limit limit = query.getLimit();
query.setLimit(null);
Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(having, true));
Set<Expression> expr = new HashSet<Expression>();
for (Expression ex : sel.getProjectedSymbols()) {
Expression selectExpression = SymbolMap.getExpression(ex);
aggs.remove(selectExpression);
expr.add(selectExpression);
}
int originalSelect = sel.getSymbols().size();
sel.addSymbols(aggs);
if (groupBy != null) {
for (Expression ex : groupBy.getSymbols()) {
ex = SymbolMap.getExpression(ex);
if (expr.add(ex)) {
sel.addSymbol(ex);
}
}
}
Query outerQuery = null;
try {
outerQuery = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"), query, metadata, query.getSelect().getProjectedSymbols()); //$NON-NLS-1$
} catch (TeiidException err) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30257, err);
}
Iterator<Expression> iter = outerQuery.getSelect().getProjectedSymbols().iterator();
HashMap<Expression, Expression> expressionMap = new HashMap<Expression, Expression>();
for (Expression symbol : query.getSelect().getProjectedSymbols()) {
//need to unwrap on both sides as the select expression could be aliased
//TODO: could add an option to createInlineViewQuery to disable alias creation
expressionMap.put(SymbolMap.getExpression(symbol), SymbolMap.getExpression(iter.next()));
}
ExpressionMappingVisitor.mapExpressions(having, expressionMap, true);
outerQuery.setCriteria(having);
ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap, true);
outerQuery.setOrderBy(orderBy);
outerQuery.setLimit(limit);
ExpressionMappingVisitor.mapExpressions(select, expressionMap, true);
outerQuery.getSelect().setSymbols(outerQuery.getSelect().getProjectedSymbols().subList(0, originalSelect));
outerQuery.setOption(query.getOption());
query = outerQuery;

}
if (!CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, modelID, metadata, capFinder)) {
//if group by expressions are not support, add an inline view to compensate
query = RuleCollapseSource.rewriteGroupByAsView(query, metadata, false);
Expand Down
Expand Up @@ -465,7 +465,8 @@ static boolean canRaiseOverSelect(PlanNode accessNode,
return false;
}

if (parentNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING) && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder)) {
if (parentNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING) && !CapabilitiesUtil.supports(Capability.QUERY_HAVING, modelID, metadata, capFinder)
&& !CapabilitiesUtil.supports(Capability.QUERY_FROM_INLINE_VIEWS, modelID, metadata, capFinder)) {
parentNode.recordDebugAnnotation("having is not supported by source", modelID, "cannot push having", record, metadata); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
Expand Down
Expand Up @@ -1307,5 +1307,29 @@ null, new DefaultCapabilitiesFinder(bsc),
ProcessorPlan plan = TestOptimizer.helpPlan("select FIRST_VALUE(e1) OVER (ORDER BY e2) from pm1.g2", metadata, null, capFinder, //$NON-NLS-1$
new String[]{"SELECT FIRST_VALUE(ALL g_0.e1) OVER (ORDER BY g_0.e2) FROM pm1.g2 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
}

@Test public void testHavingPushdown() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = getAggregateCapabilities();
caps.setCapabilitySupport(Capability.QUERY_HAVING, false);
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$

ProcessorPlan plan = TestOptimizer.helpPlan("select max(e2) from pm1.g2 having min(e2) > 1", RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
new String[]{"SELECT v_0.c_0 FROM (SELECT MAX(g_0.e2) AS c_0, MIN(g_0.e2) AS c_1 FROM pm1.g2 AS g_0) AS v_0 WHERE v_0.c_1 > 1"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}

@Test public void testHavingPushdown1() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = getAggregateCapabilities();
caps.setCapabilitySupport(Capability.QUERY_HAVING, false);
caps.setFunctionSupport("concat", true);
caps.setFunctionSupport("convert", true);
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$

ProcessorPlan plan = TestOptimizer.helpPlan("select max(e2) from pm1.g2 group by e1 having min(e2) || e1 > '1'", RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
new String[]{"SELECT v_0.c_0 FROM (SELECT MAX(g_0.e2) AS c_0, MIN(g_0.e2) AS c_1, g_0.e1 AS c_2 FROM pm1.g2 AS g_0 GROUP BY g_0.e1) AS v_0 WHERE concat(convert(v_0.c_1, string), v_0.c_2) > '1'"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
}

0 comments on commit 44983de

Please sign in to comment.