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 +