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
----------------------------------------------------------------------