You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by bl...@apache.org on 2015/08/20 14:11:23 UTC

[1/2] cassandra git commit: Allow count(*) and count(1) to be use as normal aggregation

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-3.0 be2c26f18 -> 1964a82bf


Allow count(*) and count(1) to be use as normal aggregation

patch by Benjamin Lerer; reviewed by Stefania Alborghetti for CASSANDRA-10114


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/4fc58513
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/4fc58513
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/4fc58513

Branch: refs/heads/cassandra-3.0
Commit: 4fc58513dce5ee6acb83ba07d9f31c26812075f9
Parents: 62fc314
Author: blerer <be...@datastax.com>
Authored: Thu Aug 20 14:01:37 2015 +0200
Committer: blerer <be...@datastax.com>
Committed: Thu Aug 20 14:01:37 2015 +0200

----------------------------------------------------------------------
 NEWS.txt                                        |  1 +
 src/java/org/apache/cassandra/cql3/Cql.g        |  9 +----
 .../cassandra/cql3/functions/AggregateFcts.java | 11 ++++++
 .../selection/AbstractFunctionSelector.java     |  6 +++
 .../cassandra/cql3/selection/Selector.java      |  1 -
 .../validation/operations/AggregationTest.java  | 39 ++++++++++++++++++++
 6 files changed, 59 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index 37a1b9e..a9cf70d 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -100,6 +100,7 @@ New features
    - The toTimestamp(date) and toUnixTimestamp(date) functions have been added to allow
      to convert from date into timestamp type and bigint raw value.
    - SizeTieredCompactionStrategy parameter cold_reads_to_omit has been removed.
+   - COUNT(*) and COUNT(1) can be selected with other columns or functions
 
 
 2.1.9

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g
index 0db09b8..3d2aba5 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -295,8 +295,7 @@ selectStatement returns [SelectStatement.RawStatement expr]
     }
     : K_SELECT 
       ( K_JSON { isJson = true; } )?
-      ( ( K_DISTINCT { isDistinct = true; } )? sclause=selectClause
-        | sclause=selectCountClause )
+      ( ( K_DISTINCT { isDistinct = true; } )? sclause=selectClause )
       K_FROM cf=columnFamilyName
       ( K_WHERE wclause=whereClause )?
       ( K_ORDER K_BY orderByClause[orderings] ( ',' orderByClause[orderings] )* )?
@@ -324,6 +323,7 @@ selector returns [RawSelector s]
 unaliasedSelector returns [Selectable.Raw s]
     @init { Selectable.Raw tmp = null; }
     :  ( c=cident                                  { tmp = c; }
+       | K_COUNT '(' countArgument ')'             { tmp = new Selectable.WithFunction.Raw(FunctionName.nativeFunction("countRows"), Collections.<Selectable.Raw>emptyList());}
        | K_WRITETIME '(' c=cident ')'              { tmp = new Selectable.WritetimeOrTTL.Raw(c, true); }
        | K_TTL       '(' c=cident ')'              { tmp = new Selectable.WritetimeOrTTL.Raw(c, false); }
        | f=functionName args=selectionFunctionArgs { tmp = new Selectable.WithFunction.Raw(f, args); }
@@ -337,11 +337,6 @@ selectionFunctionArgs returns [List<Selectable.Raw> a]
       ')' { $a = args; }
     ;
 
-selectCountClause returns [List<RawSelector> expr]
-    @init{ ColumnIdentifier alias = new ColumnIdentifier("count", false); }
-    : K_COUNT '(' countArgument ')' (K_AS c=ident { alias = c; })? { $expr = new ArrayList<RawSelector>(); $expr.add( new RawSelector(new Selectable.WithFunction.Raw(FunctionName.nativeFunction("countRows"), Collections.<Selectable.Raw>emptyList()), alias));}
-    ;
-
 countArgument
     : '\*'
     | i=INTEGER { if (!i.getText().equals("1")) addRecognitionError("Only COUNT(1) is supported, got COUNT(" + i.getText() + ")");}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java b/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
index 1b22da6..41e43c0 100644
--- a/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
+++ b/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
@@ -38,6 +38,17 @@ import org.apache.cassandra.db.marshal.ShortType;
 public abstract class AggregateFcts
 {
     /**
+     * Checks if the specified function is the count rows (e.g. COUNT(*) or COUNT(1)) function.
+     *
+     * @param function the function to check
+     * @return <code>true</code> if the specified function is the count rows one, <code>false</code> otherwise.
+     */
+    public static boolean isCountRows(Function function)
+    {
+        return function == countRowsFunction;
+    }
+
+    /**
      * The function used to count the number of rows of a result set. This function is called when COUNT(*) or COUNT(1)
      * is specified.
      */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java b/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
index abf52e1..bf1234f 100644
--- a/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
+++ b/src/java/org/apache/cassandra/cql3/selection/AbstractFunctionSelector.java
@@ -22,8 +22,11 @@ import java.util.Arrays;
 import java.util.List;
 
 import com.google.common.collect.Iterables;
+
 import org.apache.commons.lang3.text.StrBuilder;
 
+import org.apache.cassandra.cql3.functions.AggregateFcts;
+
 import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.cql3.ColumnSpecification;
 import org.apache.cassandra.cql3.functions.Function;
@@ -53,6 +56,9 @@ abstract class AbstractFunctionSelector<T extends Function> extends Selector
         {
             protected String getColumnName()
             {
+                if (AggregateFcts.isCountRows(fun))
+                    return "count";
+
                 return new StrBuilder(fun.name().toString()).append('(')
                                                             .appendWithSeparators(factories.getColumnNames(), ", ")
                                                             .append(')')

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/src/java/org/apache/cassandra/cql3/selection/Selector.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/selection/Selector.java b/src/java/org/apache/cassandra/cql3/selection/Selector.java
index 9b7f0ba..d53fba1 100644
--- a/src/java/org/apache/cassandra/cql3/selection/Selector.java
+++ b/src/java/org/apache/cassandra/cql3/selection/Selector.java
@@ -21,7 +21,6 @@ import java.nio.ByteBuffer;
 import java.util.Collections;
 
 import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.cql3.AssignmentTestable;
 import org.apache.cassandra.cql3.ColumnIdentifier;
 import org.apache.cassandra.cql3.ColumnSpecification;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/4fc58513/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java
index 9881d73..b44fc71 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java
@@ -93,6 +93,45 @@ public class AggregationTest extends CQLTester
     }
 
     @Test
+    public void testCountStarFunction() throws Throwable
+    {
+        createTable("CREATE TABLE %s (a int, b int, c double, primary key (a, b))");
+
+        // Test with empty table
+        assertColumnNames(execute("SELECT COUNT(*) FROM %s"), "count");
+        assertRows(execute("SELECT COUNT(*) FROM %s"), row(0L));
+        assertColumnNames(execute("SELECT COUNT(1) FROM %s"), "count");
+        assertRows(execute("SELECT COUNT(1) FROM %s"), row(0L));
+        assertColumnNames(execute("SELECT COUNT(*), COUNT(*) FROM %s"), "count", "count");
+        assertRows(execute("SELECT COUNT(*), COUNT(*) FROM %s"), row(0L, 0L));
+
+        // Test with alias
+        assertColumnNames(execute("SELECT COUNT(*) as myCount FROM %s"), "mycount");
+        assertRows(execute("SELECT COUNT(*) as myCount FROM %s"), row(0L));
+        assertColumnNames(execute("SELECT COUNT(1) as myCount FROM %s"), "mycount");
+        assertRows(execute("SELECT COUNT(1) as myCount FROM %s"), row(0L));
+
+        // Test invalid call
+        assertInvalidSyntaxMessage("Only COUNT(1) is supported, got COUNT(2)", "SELECT COUNT(2) FROM %s");
+
+        // Test with other aggregates
+        assertColumnNames(execute("SELECT COUNT(*), max(b), b FROM %s"), "count", "system.max(b)", "b");
+        assertRows(execute("SELECT COUNT(*), max(b), b  FROM %s"), row(0L, null, null));
+        assertColumnNames(execute("SELECT COUNT(1), max(b), b FROM %s"), "count", "system.max(b)", "b");
+        assertRows(execute("SELECT COUNT(1), max(b), b  FROM %s"), row(0L, null, null));
+
+        execute("INSERT INTO %s (a, b, c) VALUES (1, 1, 11.5)");
+        execute("INSERT INTO %s (a, b, c) VALUES (1, 2, 9.5)");
+        execute("INSERT INTO %s (a, b, c) VALUES (1, 3, 9.0)");
+        execute("INSERT INTO %s (a, b, c) VALUES (1, 5, 1.0)");
+
+        assertRows(execute("SELECT COUNT(*) FROM %s"), row(4L));
+        assertRows(execute("SELECT COUNT(1) FROM %s"), row(4L));
+        assertRows(execute("SELECT max(b), b, COUNT(*) FROM %s"), row(5, 1, 4L));
+        assertRows(execute("SELECT max(b), COUNT(1), b FROM %s"), row(5, 4L, 1));
+    }
+
+    @Test
     public void testAggregateWithColumns() throws Throwable
     {
         createTable("CREATE TABLE %s (a int, b int, c int, primary key (a, b))");


[2/2] cassandra git commit: Merge cassandra-2.2 into cassandra-3.0

Posted by bl...@apache.org.
Merge cassandra-2.2 into cassandra-3.0

Conflicts:
	src/java/org/apache/cassandra/cql3/Cql.g


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1964a82b
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1964a82b
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1964a82b

Branch: refs/heads/cassandra-3.0
Commit: 1964a82bf0dea261ccb1f48c36cda0de7fa8d62e
Parents: be2c26f 4fc5851
Author: blerer <be...@datastax.com>
Authored: Thu Aug 20 14:10:11 2015 +0200
Committer: blerer <be...@datastax.com>
Committed: Thu Aug 20 14:10:11 2015 +0200

----------------------------------------------------------------------
 NEWS.txt                                        |  1 +
 src/java/org/apache/cassandra/cql3/Cql.g        |  9 +----
 .../cassandra/cql3/functions/AggregateFcts.java | 11 ++++++
 .../selection/AbstractFunctionSelector.java     |  6 +++
 .../cassandra/cql3/selection/Selector.java      |  1 -
 .../validation/operations/AggregationTest.java  | 39 ++++++++++++++++++++
 6 files changed, 59 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/1964a82b/NEWS.txt
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1964a82b/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1964a82b/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
index 153e5eb,41e43c0..7b5bdb8
--- a/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
+++ b/src/java/org/apache/cassandra/cql3/functions/AggregateFcts.java
@@@ -32,47 -37,18 +32,58 @@@ import org.apache.cassandra.db.marshal.
   */
  public abstract class AggregateFcts
  {
 +    public static Collection<AggregateFunction> all()
 +    {
 +        Collection<AggregateFunction> functions = new ArrayList<>();
 +
 +        functions.add(countRowsFunction);
 +
 +        // sum for primitives
 +        functions.add(sumFunctionForByte);
 +        functions.add(sumFunctionForShort);
 +        functions.add(sumFunctionForInt32);
 +        functions.add(sumFunctionForLong);
 +        functions.add(sumFunctionForFloat);
 +        functions.add(sumFunctionForDouble);
 +        functions.add(sumFunctionForDecimal);
 +        functions.add(sumFunctionForVarint);
 +
 +        // avg for primitives
 +        functions.add(avgFunctionForByte);
 +        functions.add(avgFunctionForShort);
 +        functions.add(avgFunctionForInt32);
 +        functions.add(avgFunctionForLong);
 +        functions.add(avgFunctionForFloat);
 +        functions.add(avgFunctionForDouble);
 +        functions.add(avgFunctionForDecimal);
 +        functions.add(avgFunctionForVarint);
 +
 +        // count, max, and min for all standard types
 +        for (CQL3Type type : CQL3Type.Native.values())
 +        {
 +            if (type != CQL3Type.Native.VARCHAR) // varchar and text both mapping to UTF8Type
 +            {
 +                functions.add(AggregateFcts.makeCountFunction(type.getType()));
 +                functions.add(AggregateFcts.makeMaxFunction(type.getType()));
 +                functions.add(AggregateFcts.makeMinFunction(type.getType()));
 +            }
 +        }
 +
 +        return functions;
 +    }
 +
      /**
+      * Checks if the specified function is the count rows (e.g. COUNT(*) or COUNT(1)) function.
+      *
+      * @param function the function to check
+      * @return <code>true</code> if the specified function is the count rows one, <code>false</code> otherwise.
+      */
+     public static boolean isCountRows(Function function)
+     {
+         return function == countRowsFunction;
+     }
+ 
+     /**
       * The function used to count the number of rows of a result set. This function is called when COUNT(*) or COUNT(1)
       * is specified.
       */

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1964a82b/src/java/org/apache/cassandra/cql3/selection/Selector.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/1964a82b/test/unit/org/apache/cassandra/cql3/validation/operations/AggregationTest.java
----------------------------------------------------------------------