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(),

Reply via email to