You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2012/09/04 19:42:52 UTC

[1/2] git commit: Update CQL pseudo-maps to real maps

Updated Branches:
  refs/heads/trunk f61d88488 -> 769fe895a


Update CQL pseudo-maps to real maps

patch by xedin; reviewed by slebresne for CASSANDRA-4497


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

Branch: refs/heads/trunk
Commit: 769fe895a36868c47101f681f5fdd721bee1ad62
Parents: 3bfe5fb
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Tue Sep 4 19:41:33 2012 +0200
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Tue Sep 4 19:41:33 2012 +0200

----------------------------------------------------------------------
 CHANGES.txt                                        |    1 +
 NEWS.txt                                           |   10 ++-
 .../org/apache/cassandra/config/CFMetaData.java    |    3 +-
 src/java/org/apache/cassandra/cql3/CFPropDefs.java |   59 +++++++++------
 src/java/org/apache/cassandra/cql3/Cql.g           |   41 ++++++++---
 .../cql3/statements/AlterTableStatement.java       |    6 +-
 .../statements/CreateColumnFamilyStatement.java    |    7 +--
 .../cql3/statements/CreateKeyspaceStatement.java   |   31 +++++---
 8 files changed, 103 insertions(+), 55 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 256d5ec..d6b40ba 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -46,6 +46,7 @@
  * (cql3) fix defining more than one PK to be invalid (CASSANDRA-4477)
  * remove schema agreement checking from all external APIs (Thrift, CQL and CQL3) (CASSANDRA-4487)
  * add Murmur3Partitioner and make it default for new installations (CASSANDRA-3772)
+ * (cql3) update pseudo-map syntax to use map syntax (CASSANDRA-4497)
 
 
 1.1.5

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/NEWS.txt
----------------------------------------------------------------------
diff --git a/NEWS.txt b/NEWS.txt
index 56bb1dc..731040a 100644
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -31,7 +31,7 @@ Upgrading
       remove nodes in this way with a mixed 1.1 (or lower) / 1.2 cluster,
       is not supported.
     - The somewhat ill-concieved CollatingOrderPreservingPartitioner
-      has been removed.  Use RandomPartitioner (recommended) or
+      has been removed.  Use Murmur3Partitioner (recommended) or
       ByteOrderedPartitioner instead.
     - Global option hinted_handoff_throttle_delay_in_ms has been removed.
       hinted_handoff_throttle_in_kb has been added instead.
@@ -41,6 +41,14 @@ Upgrading
     - The default partitioner was changed from RandomPartitioner to
       Murmur3Partitioner which provides faster hashing as well as
       improved performance with secondary indexes.
+    - CQL3 is now considered final in this release. Compared to the beta
+      version that is part of 1.1, this final version has a few additions
+      (collections), but also some changes in the syntax for the options of the
+      create/alter keyspace/table statements. Typically, the syntax to create a
+      keyspace is now:
+        CREATE KEYSPACE ks WITH replication = { 'class' : 'CompactionStrategy',
+                                                'replication_faction' : 2 };
+      Please refer to the CQL3 documentation for details.
 
 Features
 --------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java
index bb9a5a6..dbe0c6f 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -149,8 +149,7 @@ public final class CFMetaData
                                                          + "mutation blob,"
                                                          + "PRIMARY KEY (target_id, hint_id, message_version)"
                                                          + ") WITH COMPACT STORAGE "
-                                                         + "AND COMPACTION_STRATEGY_OPTIONS:MIN_COMPACTION_THRESHOLD=0 "
-                                                         + "AND COMPACTION_STRATEGY_OPTIONS:MAX_COMPACTION_THRESHOLD=0 "
+                                                         + "AND COMPACTION={'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 0, 'max_threshold' : 0} "
                                                          + "AND COMMENT='hints awaiting delivery'");
 
     public static final CFMetaData PeersCf = compile(12, "CREATE TABLE " + SystemTable.PEERS_CF + " ("

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/CFPropDefs.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CFPropDefs.java b/src/java/org/apache/cassandra/cql3/CFPropDefs.java
index db85522..b7207fe 100644
--- a/src/java/org/apache/cassandra/cql3/CFPropDefs.java
+++ b/src/java/org/apache/cassandra/cql3/CFPropDefs.java
@@ -20,8 +20,8 @@ package org.apache.cassandra.cql3;
 import com.google.common.collect.Sets;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.ConfigurationException;
-import org.apache.cassandra.io.compress.CompressionParameters;
 import org.apache.cassandra.db.compaction.AbstractCompactionStrategy;
+import org.apache.cassandra.io.compress.CompressionParameters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,10 +38,10 @@ public class CFPropDefs
     public static final String KW_READREPAIRCHANCE = "read_repair_chance";
     public static final String KW_DCLOCALREADREPAIRCHANCE = "dclocal_read_repair_chance";
     public static final String KW_GCGRACESECONDS = "gc_grace_seconds";
-    public static final String KW_MINCOMPACTIONTHRESHOLD = "min_compaction_threshold";
-    public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_compaction_threshold";
+    public static final String KW_MINCOMPACTIONTHRESHOLD = "min_threshold";
+    public static final String KW_MAXCOMPACTIONTHRESHOLD = "max_threshold";
     public static final String KW_REPLICATEONWRITE = "replicate_on_write";
-    public static final String KW_COMPACTION_STRATEGY_CLASS = "compaction_strategy_class";
+    public static final String KW_COMPACTION_STRATEGY_CLASS = "class";
     public static final String KW_CACHING = "caching";
     public static final String KW_BF_FP_CHANCE = "bloom_filter_fp_chance";
 
@@ -50,8 +50,8 @@ public class CFPropDefs
     public static final Set<String> obsoleteKeywords = new HashSet<String>();
     public static final Set<String> allowedKeywords = new HashSet<String>();
 
-    public static final String COMPACTION_OPTIONS_PREFIX = "compaction_strategy_options";
-    public static final String COMPRESSION_PARAMETERS_PREFIX = "compression_parameters";
+    public static final String COMPACTION_PARAMETERS = "compaction";
+    public static final String COMPRESSION_PARAMETERS = "compression";
 
     static
     {
@@ -60,10 +60,16 @@ public class CFPropDefs
         keywords.add(KW_DCLOCALREADREPAIRCHANCE);
         keywords.add(KW_GCGRACESECONDS);
         keywords.add(KW_REPLICATEONWRITE);
-        keywords.add(KW_COMPACTION_STRATEGY_CLASS);
         keywords.add(KW_CACHING);
         keywords.add(KW_BF_FP_CHANCE);
 
+        obsoleteKeywords.add("compaction_strategy_class");
+        obsoleteKeywords.add("compaction_strategy_options");
+        obsoleteKeywords.add("min_compaction_threshold");
+        obsoleteKeywords.add("max_compaction_threshold");
+        obsoleteKeywords.add("compaction_parameters");
+        obsoleteKeywords.add("compression_parameters");
+
         allowedKeywords.addAll(keywords);
         allowedKeywords.addAll(obsoleteKeywords);
     }
@@ -85,31 +91,38 @@ public class CFPropDefs
         for (String obsolete : Sets.intersection(properties.keySet(), obsoleteKeywords))
             logger.warn("Ignoring obsolete property {}", obsolete);
 
-        if (properties.containsKey(KW_COMPACTION_STRATEGY_CLASS))
+        if (!compactionStrategyOptions.isEmpty())
         {
-            compactionStrategyClass = CFMetaData.createCompactionStrategy(properties.get(KW_COMPACTION_STRATEGY_CLASS));
-            compactionStrategyOptions.remove(KW_COMPACTION_STRATEGY_CLASS);
+            if (compactionStrategyOptions.containsKey(KW_COMPACTION_STRATEGY_CLASS))
+            {
+                compactionStrategyClass = CFMetaData.createCompactionStrategy(compactionStrategyOptions.get(KW_COMPACTION_STRATEGY_CLASS));
+                compactionStrategyOptions.remove(KW_COMPACTION_STRATEGY_CLASS);
+            }
+            else
+            {
+                throw new ConfigurationException("Missing sub-option '" + KW_COMPACTION_STRATEGY_CLASS + "' for the '" + COMPACTION_PARAMETERS + "' option.");
+            }
         }
     }
 
     /** Map a keyword to the corresponding value */
     public void addProperty(String name, String value)
     {
-        String[] composite = name.split(":");
-        if (composite.length > 1)
+        properties.put(name, value);
+    }
+
+    public void addProperty(String name, Map<String, String> value)
+    {
+        if (name.equalsIgnoreCase(COMPACTION_PARAMETERS))
         {
-            if (composite[0].equals(COMPACTION_OPTIONS_PREFIX))
-            {
-                compactionStrategyOptions.put(composite[1], value);
-                return;
-            }
-            else if (composite[0].equals(COMPRESSION_PARAMETERS_PREFIX))
-            {
-                compressionParameters.put(composite[1], value);
-                return;
-            }
+            for (Map.Entry<String, String> entry : value.entrySet())
+                compactionStrategyOptions.put(entry.getKey().toLowerCase(), entry.getValue());
+        }
+        else if (name.equalsIgnoreCase(COMPRESSION_PARAMETERS))
+        {
+            for (Map.Entry<String, String> entry : value.entrySet())
+                compressionParameters.put(entry.getKey().toLowerCase(), entry.getValue());
         }
-        properties.put(name, value);
     }
 
     public void addAll(Map<String, String> propertyMap)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/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 5a67820..8c43851 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -76,6 +76,26 @@ options {
         if (op == null && (value.isBindMarker() || Long.parseLong(value.getText()) > 0))
             throw new MissingTokenException(102, stream, value);
     }
+
+    public Map<String, String> convertMap(Map<Term, Term> terms)
+    {
+        if (terms == null || terms.isEmpty())
+            return Collections.<String, String>emptyMap();
+
+        Map<String, String> res = new HashMap<String, String>(terms.size());
+
+        for (Map.Entry<Term, Term> entry : terms.entrySet())
+        {
+            // Because the parser tries to be smart and recover on error (to
+            // allow displaying more than one error I suppose), we have null
+            // entries in there. Just skip those, a proper error will be thrown in the end.
+            if (entry.getKey() == null || entry.getValue() == null)
+                break;
+            res.put(entry.getKey().getText(), entry.getValue().getText());
+        }
+
+        return res;
+    }
 }
 
 @lexer::header {
@@ -349,7 +369,7 @@ batchStatementObjective returns [ModificationStatement statement]
  */
 createKeyspaceStatement returns [CreateKeyspaceStatement expr]
     : K_CREATE K_KEYSPACE ks=keyspaceName
-      K_WITH props=properties { $expr = new CreateKeyspaceStatement(ks, props); }
+      K_WITH props=mapProperties { $expr = new CreateKeyspaceStatement(ks, props); }
     ;
 
 /**
@@ -380,7 +400,7 @@ pkDef[CreateColumnFamilyStatement.RawStatement expr]
     ;
 
 cfamProperty[CreateColumnFamilyStatement.RawStatement expr]
-    : k=property '=' v=propertyValue { $expr.addProperty(k, v); }
+    : property[expr.properties]
     | K_COMPACT K_STORAGE { $expr.setCompactStorage(); }
     | K_CLUSTERING K_ORDER K_BY '(' cfamOrdering[expr] (',' cfamOrdering[expr])* ')'
     ;
@@ -407,13 +427,14 @@ createIndexStatement returns [CreateIndexStatement expr]
 alterTableStatement returns [AlterTableStatement expr]
     @init {
         AlterTableStatement.Type type = null;
-        props = new HashMap<String, String>();
+        CFPropDefs props = new CFPropDefs();
     }
     : K_ALTER K_COLUMNFAMILY cf=columnFamilyName
           ( K_ALTER id=cident K_TYPE v=comparatorType { type = AlterTableStatement.Type.ALTER; }
           | K_ADD   id=cident v=comparatorType        { type = AlterTableStatement.Type.ADD; }
           | K_DROP  id=cident                         { type = AlterTableStatement.Type.DROP; }
-          | K_WITH  props=properties                  { type = AlterTableStatement.Type.OPTS; }
+          | K_WITH  (property[props]
+                     ( K_AND property[props] )* { type = AlterTableStatement.Type.OPTS; })
           )
     {
         $expr = new AlterTableStatement(cf, type, id, v, props);
@@ -553,9 +574,9 @@ operation returns [Operation op]
     | '+' ml=map_literal { $op = MapOperation.Put(ml); }
     ;
 
-property returns [String str]
-    @init{ StringBuilder sb = new StringBuilder(); }
-    : c1=cident { sb.append(c1); } ( ':' cn=cident { sb.append(':').append(cn); } )* { $str = sb.toString(); }
+property[CFPropDefs props]
+    : k=cident '=' (simple=propertyValue { $props.addProperty(k.toString(), simple); }
+                   |   map=map_literal   { $props.addProperty(k.toString(), convertMap(map)); })
     ;
 
 propertyValue returns [String str]
@@ -563,9 +584,9 @@ propertyValue returns [String str]
     | u=unreserved_keyword                         { $str = u; }
     ;
 
-properties returns [Map<String, String> props]
-    @init{ $props = new HashMap<String, String>(); }
-    : k1=property '=' v1=propertyValue { $props.put(k1, v1); } (K_AND kn=property '=' vn=propertyValue { $props.put(kn, vn); } )*
+mapProperties returns [Map<String, Map<String, String>> props]
+    @init { $props = new HashMap<String, Map<String, String>>(); }
+    : k=cident '=' v=map_literal { $props.put(k.toString(), convertMap(v)); } (K_AND kn=cident '=' vn=map_literal { $props.put(kn.toString(), convertMap(vn)); } )*
     ;
 
 // Either a string or a list of terms

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
index ff24945..c9d4f45 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTableStatement.java
@@ -42,15 +42,15 @@ public class AlterTableStatement extends SchemaAlteringStatement
     public final Type oType;
     public final ParsedType validator;
     public final ColumnIdentifier columnName;
-    private final CFPropDefs cfProps = new CFPropDefs();
+    private final CFPropDefs cfProps;
 
-    public AlterTableStatement(CFName name, Type type, ColumnIdentifier columnName, ParsedType validator, Map<String, String> propertyMap)
+    public AlterTableStatement(CFName name, Type type, ColumnIdentifier columnName, ParsedType validator, CFPropDefs cfProps)
     {
         super(name);
         this.oType = type;
         this.columnName = columnName;
         this.validator = validator; // used only for ADD/ALTER commands
-        this.cfProps.addAll(propertyMap);
+        this.cfProps = cfProps;
     }
 
     public void announceMigration() throws InvalidRequestException, ConfigurationException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
index b8618b0..3c97f90 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
@@ -131,7 +131,7 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement
     public static class RawStatement extends CFStatement
     {
         private final Map<ColumnIdentifier, ParsedType> definitions = new HashMap<ColumnIdentifier, ParsedType>();
-        private final CFPropDefs properties = new CFPropDefs();
+        public final CFPropDefs properties = new CFPropDefs();
 
         private final List<List<ColumnIdentifier>> keyAliases = new ArrayList<List<ColumnIdentifier>>();
         private final List<ColumnIdentifier> columnAliases = new ArrayList<ColumnIdentifier>();
@@ -334,11 +334,6 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement
             columnAliases.add(alias);
         }
 
-        public void addProperty(String name, String value)
-        {
-            properties.addProperty(name, value);
-        }
-
         public void setOrdering(ColumnIdentifier alias, boolean reversed)
         {
             definedOrdering.put(alias, reversed);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/769fe895/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java
index 262c6aa..0c426b3 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateKeyspaceStatement.java
@@ -34,8 +34,11 @@ import org.apache.cassandra.thrift.ThriftValidation;
 /** A <code>CREATE KEYSPACE</code> statement parsed from a CQL query. */
 public class CreateKeyspaceStatement extends SchemaAlteringStatement
 {
+    private static String REPLICATION_PARAMETERS_PREFIX = "replication";
+    private static String REPLICATION_STRATEGY_CLASS_KEY = "class";
+
     private final String name;
-    private final Map<String, String> attrs;
+    private final Map<String, Map<String, String>> attrs;
     private String strategyClass;
     private final Map<String, String> strategyOptions = new HashMap<String, String>();
 
@@ -46,7 +49,7 @@ public class CreateKeyspaceStatement extends SchemaAlteringStatement
      * @param name the name of the keyspace to create
      * @param attrs map of the raw keyword arguments that followed the <code>WITH</code> keyword.
      */
-    public CreateKeyspaceStatement(String name, Map<String, String> attrs)
+    public CreateKeyspaceStatement(String name, Map<String, Map<String, String>> attrs)
     {
         super();
         this.name = name;
@@ -72,15 +75,23 @@ public class CreateKeyspaceStatement extends SchemaAlteringStatement
         if (name.length() > Schema.NAME_LENGTH)
             throw new InvalidRequestException(String.format("Keyspace names shouldn't be more than %s characters long (got \"%s\")", Schema.NAME_LENGTH, name));
 
-        // required
-        if (!attrs.containsKey("strategy_class"))
-            throw new InvalidRequestException("missing required argument \"strategy_class\"");
-        strategyClass = attrs.get("strategy_class");
+        if (!attrs.containsKey(REPLICATION_PARAMETERS_PREFIX))
+            throw new InvalidRequestException("missing required argument '" +  REPLICATION_PARAMETERS_PREFIX + "'");
+
+        Map<String, String> replication_parameters = attrs.get(REPLICATION_PARAMETERS_PREFIX);
+
+        strategyClass = replication_parameters.get(REPLICATION_STRATEGY_CLASS_KEY);
+
+        if (strategyClass == null)
+            throw new InvalidRequestException("missing required field '" + REPLICATION_STRATEGY_CLASS_KEY + "' for '" + REPLICATION_PARAMETERS_PREFIX + "' option");
 
-        // optional
-        for (String key : attrs.keySet())
-            if ((key.contains(":")) && (key.startsWith("strategy_options")))
-                strategyOptions.put(key.split(":")[1], attrs.get(key));
+        for (Map.Entry<String, String> entry : replication_parameters.entrySet())
+        {
+            if (entry.getKey().equals(REPLICATION_STRATEGY_CLASS_KEY))
+                continue;
+
+            strategyOptions.put(entry.getKey(), entry.getValue());
+        }
 
         // trial run to let ARS validate class + per-class options
         try