You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ee...@apache.org on 2010/11/12 20:33:07 UTC

svn commit: r1034538 - in /cassandra/trunk: drivers/py/cql/ interface/ src/java/org/apache/cassandra/cql/ test/system/

Author: eevans
Date: Fri Nov 12 19:33:06 2010
New Revision: 1034538

URL: http://svn.apache.org/viewvc?rev=1034538&view=rev
Log:
SELECT COUNT(...) FROM support

Patch by eevans

Modified:
    cassandra/trunk/drivers/py/cql/__init__.py
    cassandra/trunk/interface/cassandra.genavro
    cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
    cassandra/trunk/test/system/test_cql.py

Modified: cassandra/trunk/drivers/py/cql/__init__.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/py/cql/__init__.py?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/drivers/py/cql/__init__.py (original)
+++ cassandra/trunk/drivers/py/cql/__init__.py Fri Nov 12 19:33:06 2010
@@ -51,6 +51,9 @@ class Connection(object):
 
         if response['type'] == 'ROWS':
             return response['rows']
+        if response['type'] == 'INT':
+            return response['num']
+
         return None
 
     @classmethod

Modified: cassandra/trunk/interface/cassandra.genavro
URL: http://svn.apache.org/viewvc/cassandra/trunk/interface/cassandra.genavro?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/interface/cassandra.genavro (original)
+++ cassandra/trunk/interface/cassandra.genavro Fri Nov 12 19:33:06 2010
@@ -381,7 +381,7 @@ protocol Cassandra {
     }
 
     enum CqlResultType {
-        ROWS, VOID
+        ROWS, VOID, INT
     }
 
     record CqlRow {
@@ -392,6 +392,7 @@ protocol Cassandra {
     record CqlResult {
         CqlResultType type;
         union { array<CqlRow>, null } rows;
+        union { int, null } num;
     }
 
     /**

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g Fri Nov 12 19:33:06 2010
@@ -65,15 +65,22 @@ useStatement returns [String keyspace]
 selectStatement returns [SelectStatement expr]
     : { 
           int numRecords = 10000;
+          SelectExpression expression = null;
+          boolean isCountOp = false;
           ConsistencyLevel cLevel = ConsistencyLevel.ONE;
       }
-      K_SELECT selectExpression K_FROM columnFamily=IDENT
+      K_SELECT
+          ( s1=selectExpression                 { expression = s1; }
+          | K_COUNT '(' s2=selectExpression ')' { expression = s2; isCountOp = true; }
+          )
+          K_FROM columnFamily=IDENT
           ( K_USING K_CONSISTENCY '.' K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text); } )?
           ( K_WHERE whereClause )?
           ( K_LIMIT rows=INTEGER { numRecords = Integer.parseInt($rows.text); } )?
           endStmnt
       {
-          return new SelectStatement($selectExpression.expr,
+          return new SelectStatement(expression,
+                                     isCountOp,
                                      $columnFamily.text,
                                      cLevel,
                                      $whereClause.clause,
@@ -169,6 +176,7 @@ K_LEVEL:       ( O N E 
 K_USE:         U S E;
 K_FIRST:       F I R S T;
 K_REVERSED:    R E V E R S E D;
+K_COUNT:       C O U N T;
 
 // Case-insensitive alpha characters
 fragment A: ('a'|'A');

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java Fri Nov 12 19:33:06 2010
@@ -235,6 +235,9 @@ public class QueryProcessor
     /* Test for SELECT-specific taboos */
     private static void validateSelect(String keyspace, SelectStatement select) throws InvalidRequestException
     {
+        if (select.isCountOperation() && (select.isKeyRange() || select.getKeys().size() < 1))
+            throw newInvalidRequestException("Counts can only be performed for a single record (Hint: KEY=term)");
+        
         // Finish key w/o start key (KEY < foo)
         if (!select.isKeyRange() && (select.getKeyFinish() != null))
             throw newInvalidRequestException("Key range clauses must include a start key (i.e. KEY > term)");
@@ -282,14 +285,23 @@ public class QueryProcessor
                 validateColumnFamily(keyspace, select.getColumnFamily());
                 validateSelect(keyspace, select);
                 
-                List<CqlRow> avroRows = new ArrayList<CqlRow>();
-                avroResult.type = CqlResultType.ROWS;
                 List<org.apache.cassandra.db.Row> rows = null;
                 
                 // By-key
                 if (!select.isKeyRange() && (select.getKeys().size() > 0))
                 {
                     rows = getSlice(keyspace, select);
+                    
+                    // Only return the column count, (of the at-most 1 row).
+                    if (select.isCountOperation())
+                    {
+                        avroResult.type = CqlResultType.INT;
+                        if (rows.size() > 0)
+                            avroResult.num = rows.get(0).cf != null ? rows.get(0).cf.getSortedColumns().size() : 0;
+                        else
+                            avroResult.num = 0;
+                        return avroResult;
+                    }
                 }
                 else
                 {
@@ -305,6 +317,9 @@ public class QueryProcessor
                     }
                 }
                 
+                List<CqlRow> avroRows = new ArrayList<CqlRow>();
+                avroResult.type = CqlResultType.ROWS;
+                
                 // Create the result set
                 for (org.apache.cassandra.db.Row row : rows)
                 {

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/SelectStatement.java Fri Nov 12 19:33:06 2010
@@ -32,15 +32,17 @@ import org.apache.cassandra.thrift.Consi
 public class SelectStatement
 {
     private final SelectExpression expression;
+    private final boolean isCountOper;
     private final String columnFamily;
     private final ConsistencyLevel cLevel;
     private final WhereClause clause;
     private final int numRecords;
     
-    public SelectStatement(SelectExpression expression, String columnFamily, ConsistencyLevel cLevel,
-            WhereClause clause, int numRecords)
+    public SelectStatement(SelectExpression expression, boolean isCountOper, String columnFamily,
+            ConsistencyLevel cLevel, WhereClause clause, int numRecords)
     {
         this.expression = expression;
+        this.isCountOper = isCountOper;
         this.columnFamily = columnFamily;
         this.cLevel = cLevel;
         this.clause = (clause != null) ? clause : new WhereClause();
@@ -116,4 +118,9 @@ public class SelectStatement
     {
         return expression.getColumnsLimit();
     }
+    
+    public boolean isCountOperation()
+    {
+        return isCountOper;
+    }
 }

Modified: cassandra/trunk/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/system/test_cql.py?rev=1034538&r1=1034537&r2=1034538&view=diff
==============================================================================
--- cassandra/trunk/test/system/test_cql.py (original)
+++ cassandra/trunk/test/system/test_cql.py Fri Nov 12 19:33:06 2010
@@ -151,3 +151,9 @@ class TestCql(AvroTester):
         assert r[1]['key'] == "kb"
         assert r[2]['key'] == "kc"
 
+    def test_column_count(self):
+        "getting a result count instead of results"
+        conn = init()
+        r = conn.execute('SELECT COUNT(1L..4L) FROM StandardLong1 WHERE KEY = "aa";')
+        assert r == 4
+