Repository: phoenix Updated Branches: refs/heads/4.x-HBase-1.0 688c8274f -> 16810a8af
PHOENIX-2965 Use DistinctPrefixFilter logic for COUNT(DISTINCT ...) and COUNT(...) GROUP BY. Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/16810a8a Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/16810a8a Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/16810a8a Branch: refs/heads/4.x-HBase-1.0 Commit: 16810a8af46a1ef5fe07eaaa8bac64670e4a990e Parents: 688c827 Author: Lars Hofhansl <la...@apache.org> Authored: Thu Jun 9 14:31:31 2016 -0700 Committer: Lars Hofhansl <la...@apache.org> Committed: Thu Jun 9 14:32:50 2016 -0700 ---------------------------------------------------------------------- .../phoenix/end2end/DistinctPrefixFilterIT.java | 165 +++++++++---------- .../apache/phoenix/compile/GroupByCompiler.java | 44 +++-- .../phoenix/compile/OrderPreservingTracker.java | 15 ++ .../phoenix/iterate/BaseResultIterators.java | 2 +- 4 files changed, 124 insertions(+), 102 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/16810a8a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctPrefixFilterIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctPrefixFilterIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctPrefixFilterIT.java index c2776ed..45eb798 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctPrefixFilterIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/DistinctPrefixFilterIT.java @@ -19,9 +19,10 @@ import org.junit.BeforeClass; import org.junit.Test; public class DistinctPrefixFilterIT extends BaseHBaseManagedTimeTableReuseIT { - private static String testTableF = generateRandomString(); - private static String testTableV = generateRandomString(); - private static String testSeq = testTableF + "_seq"; + private static final String testTableF = generateRandomString(); + private static final String testTableV = generateRandomString(); + private static final String testSeq = testTableF + "_seq"; + private static final String PREFIX = "SERVER DISTINCT PREFIX"; private static Connection conn; @BeforeClass @@ -118,104 +119,53 @@ public class DistinctPrefixFilterIT extends BaseHBaseManagedTimeTableReuseIT { @Test public void testPlans() throws Exception { - final String PREFIX = "SERVER DISTINCT PREFIX"; - // use the filter even when the SkipScan filter is used - String dataSql = "SELECT DISTINCT prefix1, prefix2 FROM "+testTableF+ " WHERE prefix1 IN (1,2)"; - ResultSet rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(PREFIX)); - - dataSql = "SELECT prefix1, 1, 2 FROM "+testTableF+" GROUP BY prefix1 HAVING prefix1 = 1"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(PREFIX)); - - dataSql = "SELECT prefix1 FROM "+testTableF+" GROUP BY prefix1, TRUNC(prefix1), TRUNC(prefix2)"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(PREFIX)); - - dataSql = "SELECT DISTINCT prefix1, prefix2 FROM "+testTableV+ " WHERE prefix1 IN ('1','2')"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(PREFIX)); - - dataSql = "SELECT prefix1, 1, 2 FROM "+testTableV+" GROUP BY prefix1 HAVING prefix1 = '1'"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(PREFIX)); + testPlan("SELECT DISTINCT prefix1, prefix2 FROM "+testTableF+ " WHERE prefix1 IN (1,2)", true); + testPlan("SELECT prefix1, 1, 2 FROM "+testTableF+" GROUP BY prefix1 HAVING prefix1 = 1", true); + testPlan("SELECT prefix1 FROM "+testTableF+" GROUP BY prefix1, TRUNC(prefix1), TRUNC(prefix2)", true); + testPlan("SELECT DISTINCT prefix1, prefix2 FROM "+testTableV+ " WHERE prefix1 IN ('1','2')", true); + testPlan("SELECT prefix1, 1, 2 FROM "+testTableV+" GROUP BY prefix1 HAVING prefix1 = '1'", true); + // make sure we do not mis-optimize this case + testPlan("SELECT DISTINCT SUM(prefix1) FROM "+testTableF+" GROUP BY prefix1", false); testCommonPlans(testTableF, PREFIX); testCommonPlans(testTableV, PREFIX); } private void testCommonPlans(String testTable, String contains) throws Exception { - - String dataSql = "SELECT DISTINCT prefix1 FROM "+testTable; - ResultSet rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT /*+ RANGE_SCAN */ DISTINCT prefix1 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT DISTINCT prefix1, prefix2 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - + testPlan("SELECT DISTINCT prefix1 FROM "+testTable, true); + testPlan("SELECT COUNT(DISTINCT prefix1) FROM "+testTable, true); + testPlan("SELECT COUNT(DISTINCT prefix1), COUNT(DISTINCT prefix2) FROM "+testTable, true); + testPlan("SELECT COUNT(DISTINCT prefix1), COUNT(DISTINCT (prefix1,prefix2)) FROM "+testTable, true); + // a plain aggregate, cannot optimize + testPlan("SELECT COUNT(prefix1), COUNT(DISTINCT prefix1) FROM "+testTable, false); + testPlan("SELECT COUNT(*) FROM (SELECT DISTINCT(prefix1) FROM "+testTable+")", true); + testPlan("SELECT /*+ RANGE_SCAN */ DISTINCT prefix1 FROM "+testTable, false); + testPlan("SELECT DISTINCT prefix1, prefix2 FROM "+testTable, true); // use the filter even when the boolean expression filter is used - dataSql = "SELECT DISTINCT prefix1, prefix2 FROM "+testTable+ " WHERE col1 > 0.5"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - + testPlan("SELECT DISTINCT prefix1, prefix2 FROM "+testTable+ " WHERE col1 > 0.5", true); // do not use the filter when the distinct is on the entire key - dataSql = "SELECT DISTINCT prefix1, prefix2, prefix3 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT DISTINCT (prefix1, prefix2, prefix3) FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT DISTINCT prefix1, prefix2, col1, prefix3 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT DISTINCT prefix1, prefix2, col1 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT DISTINCT col1, prefix1, prefix2 FROM "+testTable; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1 FROM "+testTable+" GROUP BY prefix1"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1, count(*) FROM "+testTable+" GROUP BY prefix1"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, prefix2"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, prefix2, prefix3"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT (prefix1, prefix2, prefix3) FROM "+testTable+" GROUP BY (prefix1, prefix2, prefix3)"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1, 1, 2 FROM "+testTable+" GROUP BY prefix1"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); - - dataSql = "SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, col1"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertFalse(QueryUtil.getExplainPlan(rs).contains(contains)); + testPlan("SELECT DISTINCT prefix1, prefix2, prefix3 FROM "+testTable, false); + testPlan("SELECT DISTINCT (prefix1, prefix2, prefix3) FROM "+testTable, false); + testPlan("SELECT DISTINCT prefix1, prefix2, col1, prefix3 FROM "+testTable, false); + testPlan("SELECT DISTINCT prefix1, prefix2, col1 FROM "+testTable, false); + testPlan("SELECT DISTINCT col1, prefix1, prefix2 FROM "+testTable, false);; + testPlan("SELECT prefix1 FROM "+testTable+" GROUP BY prefix1", true); + testPlan("SELECT COUNT(prefix1) FROM (SELECT prefix1 FROM "+testTable+" GROUP BY prefix1)", true); + // aggregate over the group by, cannot optimize + testPlan("SELECT prefix1, count(*) FROM "+testTable+" GROUP BY prefix1", false); + testPlan("SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, prefix2", true); + // again using full key + testPlan("SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, prefix2, prefix3", false); + testPlan("SELECT (prefix1, prefix2, prefix3) FROM "+testTable+" GROUP BY (prefix1, prefix2, prefix3)", false); + testPlan("SELECT prefix1, 1, 2 FROM "+testTable+" GROUP BY prefix1", true); + testPlan("SELECT prefix1 FROM "+testTable+" GROUP BY prefix1, col1", false); + testPlan("SELECT DISTINCT prefix1, prefix2 FROM "+testTable+" WHERE col1 > 0.5", true); + } - dataSql = "SELECT DISTINCT prefix1, prefix2 FROM "+testTable+" WHERE col1 > 0.5"; - rs = conn.createStatement().executeQuery("EXPLAIN "+dataSql); - assertTrue(QueryUtil.getExplainPlan(rs).contains(contains)); + private void testPlan(String query, boolean optimizable) throws Exception { + ResultSet rs = conn.createStatement().executeQuery("EXPLAIN "+query); + assertEquals(QueryUtil.getExplainPlan(rs).contains(PREFIX), optimizable); } @Test @@ -260,6 +210,9 @@ public class DistinctPrefixFilterIT extends BaseHBaseManagedTimeTableReuseIT { // mix distinct and boolean expression filters testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTableF + " WHERE col1 > 0.99 AND prefix1 IN (1,2)", -1); + testCount("SELECT %s COUNT(DISTINCT prefix1), COUNT(DISTINCT (prefix1, prefix2)) FROM " + testTableF + " WHERE prefix2=2", 3, 3); + testCount("SELECT %s COUNT(DISTINCT prefix1), COUNT(DISTINCT (prefix1, prefix2)) FROM " + testTableF + " WHERE prefix1=2", 1, 3); + // mix distinct prefix and SkipScan filters testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTableV + " WHERE prefix1 IN ('1','2')", 6); testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTableV + " WHERE prefix1 IN ('3','22')", 5); @@ -282,6 +235,14 @@ public class DistinctPrefixFilterIT extends BaseHBaseManagedTimeTableReuseIT { testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTable + " ORDER BY prefix1, prefix2 DESC", 11); testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTable + " WHERE col1 > 0.99", -1); testSkipRange("SELECT %s DISTINCT prefix1, prefix2 FROM " + testTable + " WHERE col1 > 0.99 ORDER BY prefix1, prefix2 DESC", -1); + + testCount("SELECT %s COUNT(DISTINCT prefix1) FROM " + testTable, 4); + testCount("SELECT COUNT(*) FROM (SELECT %s DISTINCT prefix1, prefix2 FROM " + testTable + ")", 11); + testCount("SELECT %s COUNT(DISTINCT prefix1) FROM " + testTable + " WHERE col1 > 0.99", -1); + testCount("SELECT COUNT(*) FROM (SELECT %s DISTINCT prefix1, prefix2 FROM " + testTable + " WHERE col1 > 0.99)", -1); + testCount("SELECT %s COUNT(DISTINCT prefix1), COUNT(DISTINCT prefix2) FROM " + testTable, 4, 4); + testCount("SELECT %s COUNT(DISTINCT prefix1), COUNT(DISTINCT (prefix1, prefix2)) FROM " + testTable, 4, 11); + testCount("SELECT %s COUNT(DISTINCT prefix1), COUNT(DISTINCT (prefix1, prefix2)) FROM " + testTable + " WHERE col1 > 0.99", -1, -1); } @Test @@ -335,6 +296,28 @@ public class DistinctPrefixFilterIT extends BaseHBaseManagedTimeTableReuseIT { assertEquals(count, count1); } + private void testCount(String q, int... expected) throws SQLException { + String q1 = String.format(q, ""); + PreparedStatement stmt = conn.prepareStatement(q1); + ResultSet res = stmt.executeQuery(); + int[] count = new int[expected.length]; + assertTrue(res.next()); + for (int i=0; i<expected.length; i++) { + count[i] = res.getInt(i+1); + if (expected[i] > 0) assertEquals(expected[i], count[i]); + } + assertFalse(res.next()); + + q1 = String.format(q, "/*+ RANGE_SCAN */"); + stmt = conn.prepareStatement(q1); + res = stmt.executeQuery(); + assertTrue(res.next()); + for (int i=0; i<expected.length; i++) { + assertEquals(count[i], res.getInt(i+1)); + } + assertFalse(res.next()); + } + private static void insertPrefixF(int prefix1, int prefix2) throws SQLException { String query = "UPSERT INTO " + testTableF + "(prefix1, prefix2, prefix3, col1) VALUES(?,?,NEXT VALUE FOR "+testSeq+",rand())"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/16810a8a/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java index fd6d6e9..0d5b423 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/GroupByCompiler.java @@ -59,6 +59,7 @@ public class GroupByCompiler { private final List<Expression> keyExpressions; private final boolean isOrderPreserving; private final int orderPreservingColumnCount; + private final boolean isUngroupedAggregate; public static final GroupByCompiler.GroupBy EMPTY_GROUP_BY = new GroupBy(new GroupByBuilder()) { @Override public GroupBy compile(StatementContext context, TupleProjector tupleProjector) throws SQLException { @@ -98,6 +99,7 @@ public class GroupByCompiler { ImmutableList.copyOf(builder.keyExpressions); this.isOrderPreserving = builder.isOrderPreserving; this.orderPreservingColumnCount = builder.orderPreservingColumnCount; + this.isUngroupedAggregate = builder.isUngroupedAggregate; } public List<Expression> getExpressions() { @@ -109,9 +111,13 @@ public class GroupByCompiler { } public String getScanAttribName() { - return isOrderPreserving ? - BaseScannerRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS : - BaseScannerRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS; + if (isUngroupedAggregate) { + return BaseScannerRegionObserver.UNGROUPED_AGG; + } else if (isOrderPreserving) { + return BaseScannerRegionObserver.KEY_ORDERED_GROUP_BY_EXPRESSIONS; + } else { + return BaseScannerRegionObserver.UNORDERED_GROUP_BY_EXPRESSIONS; + } } public boolean isEmpty() { @@ -122,6 +128,10 @@ public class GroupByCompiler { return isOrderPreserving; } + public boolean isUngroupedAggregate() { + return isUngroupedAggregate; + } + public int getOrderPreservingColumnCount() { return orderPreservingColumnCount; } @@ -145,7 +155,9 @@ public class GroupByCompiler { if (isOrderPreserving) { return new GroupBy.GroupByBuilder(this).setOrderPreservingColumnCount(orderPreservingColumnCount).build(); } - + if (isUngroupedAggregate) { + return UNGROUPED_GROUP_BY; + } List<Expression> expressions = Lists.newArrayListWithExpectedSize(this.expressions.size()); List<Expression> keyExpressions = expressions; List<Pair<Integer,Expression>> groupBys = Lists.newArrayListWithExpectedSize(this.expressions.size()); @@ -243,6 +255,7 @@ public class GroupByCompiler { private int orderPreservingColumnCount; private List<Expression> expressions = Collections.emptyList(); private List<Expression> keyExpressions = Collections.emptyList(); + private boolean isUngroupedAggregate; public GroupByBuilder() { } @@ -252,6 +265,7 @@ public class GroupByCompiler { this.orderPreservingColumnCount = groupBy.orderPreservingColumnCount; this.expressions = groupBy.expressions; this.keyExpressions = groupBy.keyExpressions; + this.isUngroupedAggregate = groupBy.isUngroupedAggregate; } public GroupByBuilder setExpressions(List<Expression> expressions) { @@ -269,6 +283,11 @@ public class GroupByCompiler { return this; } + public GroupByBuilder setIsUngroupedAggregate(boolean isUngroupedAggregate) { + this.isUngroupedAggregate = isUngroupedAggregate; + return this; + } + public GroupByBuilder setOrderPreservingColumnCount(int orderPreservingColumnCount) { this.orderPreservingColumnCount = orderPreservingColumnCount; return this; @@ -280,7 +299,9 @@ public class GroupByCompiler { } public void explain(List<String> planSteps, Integer limit) { - if (isOrderPreserving) { + if (isUngroupedAggregate) { + planSteps.add(" SERVER AGGREGATE INTO SINGLE ROW"); + } else if (isOrderPreserving) { planSteps.add(" SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY " + getExpressions() + (limit == null ? "" : " LIMIT " + limit + " GROUP" + (limit.intValue() == 1 ? "" : "S"))); } else { planSteps.add(" SERVER AGGREGATE INTO DISTINCT ROWS BY " + getExpressions() + (limit == null ? "" : " LIMIT " + limit + " GROUP" + (limit.intValue() == 1 ? "" : "S"))); @@ -303,11 +324,11 @@ public class GroupByCompiler { * Otherwise, we need to insert a step after the Merge that dedups. * Order by only allowed on columns in the select distinct */ + boolean isUngroupedAggregate = false; if (groupByNodes.isEmpty()) { if (statement.isAggregate()) { - return GroupBy.UNGROUPED_GROUP_BY; - } - if (!statement.isDistinct()) { + isUngroupedAggregate = true; + } else if (!statement.isDistinct()) { return GroupBy.EMPTY_GROUP_BY; } @@ -325,7 +346,7 @@ public class GroupByCompiler { ParseNode node = groupByNodes.get(i); Expression expression = node.accept(compiler); if (!expression.isStateless()) { - if (compiler.isAggregate()) { + if (!isUngroupedAggregate && compiler.isAggregate()) { throw new SQLExceptionInfo.Builder(SQLExceptionCode.AGGREGATE_IN_GROUP_BY) .setMessage(expression.toString()).build().buildException(); } @@ -337,7 +358,10 @@ public class GroupByCompiler { if (expressions.isEmpty()) { return GroupBy.EMPTY_GROUP_BY; } - GroupBy groupBy = new GroupBy.GroupByBuilder().setIsOrderPreserving(isOrderPreserving).setExpressions(expressions).setKeyExpressions(expressions).build(); + GroupBy groupBy = new GroupBy.GroupByBuilder() + .setIsOrderPreserving(isOrderPreserving) + .setExpressions(expressions).setKeyExpressions(expressions) + .setIsUngroupedAggregate(isUngroupedAggregate).build(); return groupBy; } http://git-wip-us.apache.org/repos/asf/phoenix/blob/16810a8a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java index 8f09337..c17838e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/OrderPreservingTracker.java @@ -21,8 +21,10 @@ import org.apache.phoenix.expression.Expression; import org.apache.phoenix.expression.ProjectedColumnExpression; import org.apache.phoenix.expression.RowKeyColumnExpression; import org.apache.phoenix.expression.RowValueConstructorExpression; +import org.apache.phoenix.expression.function.DistinctCountAggregateFunction; import org.apache.phoenix.expression.function.FunctionExpression.OrderPreserving; import org.apache.phoenix.expression.function.ScalarFunction; +import org.apache.phoenix.expression.function.SingleAggregateFunction; import org.apache.phoenix.expression.visitor.StatelessTraverseNoExpressionVisitor; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.SortOrder; @@ -233,6 +235,19 @@ public class OrderPreservingTracker { } @Override + public Iterator<Expression> visitEnter(SingleAggregateFunction node) { + return node instanceof DistinctCountAggregateFunction ? + node.getChildren().iterator() : + Iterators.<Expression> emptyIterator(); + } + + @Override + public Info visitLeave(SingleAggregateFunction node, List<Info> l) { + if (l.isEmpty()) { return null; } + return l.get(0); + } + + @Override public Iterator<Expression> visitEnter(ScalarFunction node) { return node.preservesOrder() == OrderPreserving.NO ? Iterators.<Expression> emptyIterator() : Iterators .singletonIterator(node.getChildren().get(node.getKeyFormationTraversalIndex())); http://git-wip-us.apache.org/repos/asf/phoenix/blob/16810a8a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java index f9c4a1a..bc962c3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/iterate/BaseResultIterators.java @@ -230,7 +230,7 @@ public abstract class BaseResultIterators extends ExplainTable implements Result !plan.getStatement().getHint().hasHint(HintNode.Hint.RANGE_SCAN) && cols < plan.getTableRef().getTable().getRowKeySchema().getFieldCount() && plan.getGroupBy().isOrderPreserving() && - (plan.getStatement().isDistinct() || context.getAggregationManager().isEmpty())) + (context.getAggregationManager().isEmpty() || plan.getGroupBy().isUngroupedAggregate())) { ScanUtil.andFilterAtEnd(context.getScan(), new DistinctPrefixFilter(plan.getTableRef().getTable().getRowKeySchema(),