cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alek...@apache.org
Subject [1/2] git commit: Add ability for CQL3 to list partition keys
Date Wed, 21 Aug 2013 16:17:14 GMT
Updated Branches:
  refs/heads/trunk 43105f7f1 -> 0da21de3e


Add ability for CQL3 to list partition keys

patch by Aleksey Yeschenko and Dan Jatnieks;
reviewed by Sylvain Lebresne for CASSANDRA-4536


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

Branch: refs/heads/trunk
Commit: b362aebd304144235121350913839b9a7ba3a5b0
Parents: bfb0647
Author: Aleksey Yeschenko <aleksey@apache.org>
Authored: Wed Aug 21 19:09:58 2013 +0300
Committer: Aleksey Yeschenko <aleksey@apache.org>
Committed: Wed Aug 21 19:09:58 2013 +0300

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 bin/cqlsh                                       |  4 +-
 doc/cql3/CQL.textile                            |  9 ++-
 pylib/cqlshlib/cql3handling.py                  |  2 +-
 src/java/org/apache/cassandra/cql3/Cql.g        |  6 +-
 .../apache/cassandra/cql3/QueryProcessor.java   |  2 +-
 .../cql3/statements/ModificationStatement.java  |  2 +-
 .../cql3/statements/SelectStatement.java        | 63 ++++++++++++++++----
 8 files changed, 69 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 8335423..cdc79c1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -6,6 +6,7 @@
  * Use a range aware scanner for cleanup (CASSANDRA-2524)
  * Cleanup doesn't need to inspect sstables that contain only local data 
    (CASSANDRA-5722)
+ * Add ability for CQL3 to list partition keys (CASSANDRA-4536)
 
 
 2.0.0

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 0f51c7f..b1764db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -32,7 +32,7 @@ exit 1
 from __future__ import with_statement
 
 description = "CQL Shell for Apache Cassandra"
-version = "4.0.0"
+version = "4.0.1"
 
 from StringIO import StringIO
 from itertools import groupby
@@ -132,7 +132,7 @@ if os.path.exists(OLD_HISTORY):
 
 DEFAULT_HOST = 'localhost'
 DEFAULT_PORT = 9160
-DEFAULT_CQLVER = '3.1.0'
+DEFAULT_CQLVER = '3.1.1'
 DEFAULT_TRANSPORT_FACTORY = 'cqlshlib.tfactory.regular_transport_factory'
 
 DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S%z'

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/doc/cql3/CQL.textile
----------------------------------------------------------------------
diff --git a/doc/cql3/CQL.textile b/doc/cql3/CQL.textile
index c87b9a5..e8f991b 100644
--- a/doc/cql3/CQL.textile
+++ b/doc/cql3/CQL.textile
@@ -1,6 +1,6 @@
 <link rel="StyleSheet" href="CQL.css" type="text/css" media="screen">
 
-h1. Cassandra Query Language (CQL) v3.1.0
+h1. Cassandra Query Language (CQL) v3.1.1
 
 
  <span id="tableOfContents">
@@ -604,7 +604,7 @@ bc(syntax)..
                   ( LIMIT <integer> )?
                   ( ALLOW FILTERING )?
 
-<select-clause> ::= <selection-list>
+<select-clause> ::= DISTINCT? <selection-list>
                   | COUNT '(' ( '*' | '1' ) ')' (AS <identifier>)?
 
 <selection-list> ::= <selector> (AS <identifier>)? ( ',' <selector>
(AS <identifier>)? )*
@@ -1077,12 +1077,17 @@ CQL distinguishes between _reserved_ and _non-reserved_ keywords.
Reserved keywo
 | @WHERE@        | yes |
 | @WITH@         | yes |
 | @WRITETIME@    | no  |
+| @DISTINCT@     | no  |
 
 
 h2(#changes). Changes
 
 The following describes the addition/changes brought for each version of CQL.
 
+h3. 3.1.1
+
+* @SELECT@ statement now allows listing the partition keys (using the @DISTINCT@ modifier).
See "CASSANDRA-4536":https://issues.apache.org/jira/browse/CASSANDRA-4536.
+
 h3. 3.1.0
 
 * "ALTER TABLE":#alterTableStmt @DROP@ option has been reenabled for CQL3 tables and has
new semantics now: the space formerly used by dropped columns will now be eventually reclaimed
(post-compaction). You should not readd previously dropped columns unless you use timestamps
with microsecond precision (see "CASSANDRA-3919":https://issues.apache.org/jira/browse/CASSANDRA-3919
for more details).

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index eacc433..0b38d04 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -568,7 +568,7 @@ syntax_rules += r'''
                              ")" ("=" | "<" | ">" | "<=" | ">=") <tokenDefinition>
              | [rel_lhs]=<cident> "IN" "(" <term> ( "," <term> )* ")"
              ;
-<selectClause> ::= <selector> ("AS" <cident>)? ("," <selector> ("AS"
<cident>)?)*
+<selectClause> ::= "DISTINCT"? <selector> ("AS" <cident>)? ("," <selector>
("AS" <cident>)?)*
                  | "*"
                  | "COUNT" "(" star=( "*" | "1" ) ")" ("AS" <cident>)?
                  ;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/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 0035c41..a46927f 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -212,13 +212,14 @@ useStatement returns [UseStatement stmt]
  */
 selectStatement returns [SelectStatement.RawStatement expr]
     @init {
+        boolean isDistinct = false;
         boolean isCount = false;
         ColumnIdentifier countAlias = null;
         Term.Raw limit = null;
         Map<ColumnIdentifier, Boolean> orderings = new LinkedHashMap<ColumnIdentifier,
Boolean>();
         boolean allowFiltering = false;
     }
-    : K_SELECT ( sclause=selectClause
+    : K_SELECT ( ( K_DISTINCT { isDistinct = true; } )? sclause=selectClause
                | (K_COUNT '(' sclause=selectCountClause ')' { isCount = true; } (K_AS c=cident
{ countAlias = c; })?) )
       K_FROM cf=columnFamilyName
       ( K_WHERE wclause=whereClause )?
@@ -227,6 +228,7 @@ selectStatement returns [SelectStatement.RawStatement expr]
       ( K_ALLOW K_FILTERING  { allowFiltering = true; } )?
       {
           SelectStatement.Parameters params = new SelectStatement.Parameters(orderings,
+                                                                             isDistinct,
                                                                              isCount,
                                                                              countAlias,
                                                                              allowFiltering);
@@ -939,6 +941,7 @@ unreserved_function_keyword returns [String str]
         | K_EXISTS
         | K_CUSTOM
         | K_TRIGGER
+        | K_DISTINCT
         ) { $str = $k.text; }
     | t=native_type { $str = t.toString(); }
     ;
@@ -957,6 +960,7 @@ K_WITH:        W I T H;
 K_LIMIT:       L I M I T;
 K_USING:       U S I N G;
 K_USE:         U S E;
+K_DISTINCT:    D I S T I N C T;
 K_COUNT:       C O U N T;
 K_SET:         S E T;
 K_BEGIN:       B E G I N;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/src/java/org/apache/cassandra/cql3/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index e593289..6d48d2d 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -38,7 +38,7 @@ import org.apache.cassandra.utils.SemanticVersion;
 
 public class QueryProcessor
 {
-    public static final SemanticVersion CQL_VERSION = new SemanticVersion("3.1.0");
+    public static final SemanticVersion CQL_VERSION = new SemanticVersion("3.1.1");
 
     private static final Logger logger = LoggerFactory.getLogger(QueryProcessor.class);
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index e9141f9..2fce619 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -438,7 +438,7 @@ public abstract class ModificationStatement implements CQLStatement
 
         long now = System.currentTimeMillis();
         Selection.ResultSetBuilder builder = selection.resultSetBuilder(now);
-        SelectStatement.forSelection(cfDef, selection).processColumnFamily(key, cf, Collections.<ByteBuffer>emptyList(),
Integer.MAX_VALUE, now, builder);
+        SelectStatement.forSelection(cfDef, selection).processColumnFamily(key, cf, Collections.<ByteBuffer>emptyList(),
now, builder);
 
         return builder.build();
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/b362aebd/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index 2ac94df..8e09fe5 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.statements;
 import java.nio.ByteBuffer;
 import java.util.*;
 
+import com.google.common.base.Objects;
 import com.google.common.base.Predicate;
 import com.google.common.collect.AbstractIterator;
 import com.google.common.collect.Iterables;
@@ -80,7 +81,7 @@ public class SelectStatement implements CQLStatement
     private Map<CFDefinition.Name, Integer> orderingIndexes;
 
     // Used by forSelection below
-    private static final Parameters defaultParameters = new Parameters(Collections.<ColumnIdentifier,
Boolean>emptyMap(), false, null, false);
+    private static final Parameters defaultParameters = new Parameters(Collections.<ColumnIdentifier,
Boolean>emptyMap(), false, false, null, false);
 
     private static enum Bound
     {
@@ -306,7 +307,7 @@ public class SelectStatement implements CQLStatement
         AbstractBounds<RowPosition> keyBounds = getKeyBounds(variables);
         return keyBounds == null
              ? null
-             : new RangeSliceCommand(keyspace(), columnFamily(), now,  filter, keyBounds,
expressions, limit, true, false);
+             : new RangeSliceCommand(keyspace(), columnFamily(), now,  filter, keyBounds,
expressions, limit, !parameters.isDistinct, false);
     }
 
     private AbstractBounds<RowPosition> getKeyBounds(List<ByteBuffer> variables)
throws InvalidRequestException
@@ -369,7 +370,11 @@ public class SelectStatement implements CQLStatement
     private IDiskAtomFilter makeFilter(List<ByteBuffer> variables, int limit)
     throws InvalidRequestException
     {
-        if (isColumnRange())
+        if (parameters.isDistinct)
+        {
+            return new SliceQueryFilter(ColumnSlice.ALL_COLUMNS_ARRAY, false, 1, -1);
+        }
+        else if (isColumnRange())
         {
             // For sparse, we used to ask for 'defined columns' * 'asked limit' (where defined
columns includes the row marker)
             // to account for the grouping of columns.
@@ -826,7 +831,7 @@ public class SelectStatement implements CQLStatement
             if (row.cf == null)
                 continue;
 
-            processColumnFamily(row.key.key, row.cf, variables, limit, now, result);
+            processColumnFamily(row.key.key, row.cf, variables, now, result);
         }
 
         ResultSet cqlRows = result.build();
@@ -843,13 +848,24 @@ public class SelectStatement implements CQLStatement
     }
 
     // Used by ModificationStatement for CAS operations
-    void processColumnFamily(ByteBuffer key, ColumnFamily cf, List<ByteBuffer> variables,
int limit, long now, Selection.ResultSetBuilder result) throws InvalidRequestException
+    void processColumnFamily(ByteBuffer key, ColumnFamily cf, List<ByteBuffer> variables,
long now, Selection.ResultSetBuilder result)
+    throws InvalidRequestException
     {
         ByteBuffer[] keyComponents = cfDef.hasCompositeKey
                                    ? ((CompositeType)cfDef.cfm.getKeyValidator()).split(key)
                                    : new ByteBuffer[]{ key };
 
-        if (cfDef.isCompact)
+        if (parameters.isDistinct)
+        {
+            if (!cf.hasOnlyTombstones(now))
+            {
+                result.newRow();
+                // selection.getColumnsList() will contain only the partition key components
- all of them.
+                for (CFDefinition.Name name : selection.getColumnsList())
+                    result.add(keyComponents[name.position]);
+            }
+        }
+        else if (cfDef.isCompact)
         {
             // One cqlRow per column
             for (Column c : columnsInOrder(cf, variables))
@@ -1055,6 +1071,9 @@ public class SelectStatement implements CQLStatement
                                 ? Selection.wildcard(cfDef)
                                 : Selection.fromSelectors(cfDef, selectClause);
 
+            if (parameters.isDistinct)
+                validateDistinctSelection(selection.getColumnsList(), cfDef.keys.values());
+
             Term prepLimit = null;
             if (limit != null)
             {
@@ -1370,6 +1389,18 @@ public class SelectStatement implements CQLStatement
             return new ParsedStatement.Prepared(stmt, Arrays.<ColumnSpecification>asList(names));
         }
 
+        private void validateDistinctSelection(Collection<CFDefinition.Name> requestedColumns,
Collection<CFDefinition.Name> partitionKey)
+        throws InvalidRequestException
+        {
+            for (CFDefinition.Name name : requestedColumns)
+                if (!partitionKey.contains(name))
+                    throw new InvalidRequestException(String.format("SELECT DISTINCT queries
must only request partition key columns (not %s)", name));
+
+            for (CFDefinition.Name name : partitionKey)
+                if (!requestedColumns.contains(name))
+                    throw new InvalidRequestException(String.format("SELECT DISTINCT queries
must request all the partition key columns (missing %s)", name));
+        }
+
         private boolean containsAlias(final ColumnIdentifier name)
         {
             return Iterables.any(selectClause, new Predicate<RawSelector>()
@@ -1443,11 +1474,13 @@ public class SelectStatement implements CQLStatement
         @Override
         public String toString()
         {
-            return String.format("SelectRawStatement[name=%s, selectClause=%s, whereClause=%s,
isCount=%s]",
-                    cfName,
-                    selectClause,
-                    whereClause,
-                    parameters.isCount);
+            return Objects.toStringHelper(this)
+                          .add("name", cfName)
+                          .add("selectClause", selectClause)
+                          .add("whereClause", whereClause)
+                          .add("isDistinct", parameters.isDistinct)
+                          .add("isCount", parameters.isCount)
+                          .toString();
         }
     }
 
@@ -1592,13 +1625,19 @@ public class SelectStatement implements CQLStatement
     public static class Parameters
     {
         private final Map<ColumnIdentifier, Boolean> orderings;
+        private final boolean isDistinct;
         private final boolean isCount;
         private final ColumnIdentifier countAlias;
         private final boolean allowFiltering;
 
-        public Parameters(Map<ColumnIdentifier, Boolean> orderings, boolean isCount,
ColumnIdentifier countAlias, boolean allowFiltering)
+        public Parameters(Map<ColumnIdentifier, Boolean> orderings,
+                          boolean isDistinct,
+                          boolean isCount,
+                          ColumnIdentifier countAlias,
+                          boolean allowFiltering)
         {
             this.orderings = orderings;
+            this.isDistinct = isDistinct;
             this.isCount = isCount;
             this.countAlias = countAlias;
             this.allowFiltering = allowFiltering;


Mime
View raw message