You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2012/01/16 20:31:56 UTC

[2/9] git commit: add ALTER COLUMNFAMILY WITH

add ALTER COLUMNFAMILY WITH

allows modification of columnfamily properties after creation

patch by pcannon; reviewed by jbellis for CASSANDRA-3523


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

Branch: refs/heads/trunk
Commit: f458cc1ad94acb06cc8a7b59d15b03d4150ad353
Parents: 890fcc9
Author: paul cannon <pa...@datastax.com>
Authored: Fri Jan 13 14:48:39 2012 -0600
Committer: Jonathan Ellis <jb...@apache.org>
Committed: Mon Jan 16 13:28:40 2012 -0600

----------------------------------------------------------------------
 bin/cqlsh                                          |   21 ++++-
 doc/cql/CQL.textile                                |   17 +++-
 .../apache/cassandra/cql/AlterTableStatement.java  |   77 ++++++++++++++-
 src/java/org/apache/cassandra/cql/CFPropDefs.java  |    5 +
 src/java/org/apache/cassandra/cql/Cql.g            |    9 ++-
 5 files changed, 119 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f458cc1a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 0f02a0c..ccbd495 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -1366,17 +1366,19 @@ class Shell(cmd.Cmd):
         ALTER COLUMNFAMILY <cfname> ALTER <columnname> TYPE <type>;
         ALTER COLUMNFAMILY <cfname> ADD <columnname> <type>;
         ALTER COLUMNFAMILY <cfname> DROP <columnname>;
+        ALTER COLUMNFAMILY <cfname> WITH <optionname> = <val> [AND <optionname> = <val> [...]];
 
         An ALTER statement is used to manipulate column family column
-        metadata. It allows you to add new columns, drop existing columns, or
-        change the data storage type of existing columns. No results are
-        returned.
+        metadata. It allows you to add new columns, drop existing columns,
+        change the data storage type of existing columns, or change column
+        family properties. No results are returned.
 
         See one of the following for more information:
 
           HELP ALTER_ALTER;
           HELP ALTER_ADD;
           HELP ALTER_DROP;
+          HELP ALTER_WITH;
         """
 
     def help_alter_alter(self):
@@ -1419,6 +1421,19 @@ class Shell(cmd.Cmd):
         according to a certain type.
         """
 
+    def help_alter_with(self):
+        print """
+        ALTER COLUMNFAMILY: changing column family properties
+
+          ALTER COLUMNFAMILY addamsFamily WITH comment = 'Glad to be here!'
+                                           AND read_repair_chance = 0.2;
+
+        An ALTER COLUMNFAMILY ... WITH statement makes adjustments to the
+        column family properties, as defined when the column family was created
+        (see HELP CREATE_COLUMNFAMILY_OPTIONS, and your Cassandra documentation
+        for information about the supported parameter names and values).
+        """
+
     def printout(self, text, color=None, newline=True, out=sys.stdout):
         if not color or not self.color:
             out.write(text)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f458cc1a/doc/cql/CQL.textile
----------------------------------------------------------------------
diff --git a/doc/cql/CQL.textile b/doc/cql/CQL.textile
index 08b276b..4fd3d74 100644
--- a/doc/cql/CQL.textile
+++ b/doc/cql/CQL.textile
@@ -533,7 +533,7 @@ CREATE ... ( ... , name1 type1, name2 type2, ... ) ...
 
 It is possible to assign columns a type during column family creation. Columns configured with a type are validated accordingly when a write occurs, and intelligent CQL drivers and interfaces will be able to decode the column values correctly when receiving them. Column types are specified as a parenthesized, comma-separated list of column term and type pairs. See "Data Storage Types":#storageTypes for the list of recognized types.
 
-h3. Column Family Options (optional)
+h3(#cfopts). Column Family Options (optional)
 
 bc(sample). 
 CREATE COLUMNFAMILY ... WITH keyword1 = arg1 AND keyword2 = arg2;
@@ -621,11 +621,13 @@ bc(syntax).
 <alterInstructions> ::= "ALTER" <name> "TYPE" <storageType>
                       | "ADD" <name> <storageType>
                       | "DROP" <name>
+                      | "WITH" <optionName> "=" <cfOptionVal>
+                               ( "AND" <optionName> "=" <cfOptionVal> )*
                       ;
 
-An @ALTER@ statement is used to manipulate column family column metadata. It allows you to add new columns, drop existing columns, or change the data storage type of existing columns. No results are returned.
+An @ALTER@ statement is used to manipulate column family column metadata. It allows you to add new columns, drop existing columns, data storage type of existing columns, or change the column family properties. No results are returned.
 
-Specify the name of the column family to be changed after the @ALTER COLUMNFAMILY@ keywords, and the name of the column to be changed, added, or dropped after the keyword corresponding to the type of change desired (@ALTER@, @ADD@, @DROP@).
+Specify the name of the column family to be changed after the @ALTER COLUMNFAMILY@ keywords, followed by the type of change desired (@ALTER@, @ADD@, @DROP@, or @WITH@), and provide the rest of the needed information, as explained below.
 
 h3. Changing the type of a typed column
 
@@ -648,6 +650,15 @@ ALTER COLUMNFAMILY addamsFamily DROP gender;
 
 An @ALTER COLUMNFAMILY ... DROP@ statement removes the type of a column from the column family metadata. Note that this does _not_ remove the column from current rows; it just removes the metadata saying that the bytes stored under that column are expected to be deserializable according to a certain type.
 
+h3. Modifying column family properties
+
+bc(sample). 
+ALTER COLUMNFAMILY addamsFamily WITH comment = 'A most excellent and useful column family' AND read_repair_chance = 0.2;
+
+An @ALTER COLUMNFAMILY ... WITH@ statement makes adjustments to the column family properties, as defined when the column family was created (see "CREATE COLUMNFAMILY options":#cfopts for information about the supported options and values).
+
+Note that setting any @compaction_strategy_options:*@ parameters has the effect of erasing all previous @compaction_strategy_options:*@ parameters, so you will need to re-specify any such parameters which have already been set, if you want to keep them. The same note applies to the set of @compression_parameters:*@ parameters.
+
 h2. Common Idioms
 
 h3(#consistency). Specifying Consistency

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f458cc1a/src/java/org/apache/cassandra/cql/AlterTableStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/AlterTableStatement.java b/src/java/org/apache/cassandra/cql/AlterTableStatement.java
index 930cb8e..6f10f50 100644
--- a/src/java/org/apache/cassandra/cql/AlterTableStatement.java
+++ b/src/java/org/apache/cassandra/cql/AlterTableStatement.java
@@ -20,6 +20,7 @@
  */
 package org.apache.cassandra.cql;
 
+import org.apache.avro.util.Utf8;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.db.marshal.TypeParser;
 import org.apache.cassandra.db.migration.avro.CfDef;
@@ -27,16 +28,19 @@ import org.apache.cassandra.db.migration.avro.ColumnDef;
 import org.apache.cassandra.thrift.InvalidRequestException;
 
 import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
 
 public class AlterTableStatement
 {
     public static enum OperationType
     {
-        ADD, ALTER, DROP
+        ADD, ALTER, DROP, OPTS
     }
 
     public final OperationType oType;
     public final String columnFamily, columnName, validator;
+    private final CFPropDefs cfProps = new CFPropDefs();
 
     public AlterTableStatement(String columnFamily, OperationType type, String columnName)
     {
@@ -45,10 +49,23 @@ public class AlterTableStatement
 
     public AlterTableStatement(String columnFamily, OperationType type, String columnName, String validator)
     {
+        this(columnFamily, type, columnName, validator, null);
+    }
+
+    public AlterTableStatement(String columnFamily, OperationType type, String columnName, String validator, Map<String, String> propertyMap)
+    {
         this.columnFamily = columnFamily;
         this.oType = type;
         this.columnName = columnName;
         this.validator = CFPropDefs.comparators.get(validator); // used only for ADD/ALTER commands
+
+        if (propertyMap != null)
+        {
+            for (Map.Entry<String, String> prop : propertyMap.entrySet())
+            {
+                cfProps.addProperty(prop.getKey(), prop.getValue());
+            }
+        }
     }
 
     public CfDef getCfDef(String keyspace) throws ConfigurationException, InvalidRequestException
@@ -57,7 +74,8 @@ public class AlterTableStatement
 
         CfDef cfDef = meta.toAvro();
 
-        ByteBuffer columnName = meta.comparator.fromString(this.columnName);
+        ByteBuffer columnName = this.oType == OperationType.OPTS ? null
+                                                                 : meta.comparator.fromString(this.columnName);
 
         switch (oType)
         {
@@ -108,6 +126,14 @@ public class AlterTableStatement
                 // some where deep inside of Avro
                 cfDef.column_metadata.remove(toDelete);
                 break;
+
+            case OPTS:
+                if (cfProps == null)
+                    throw new InvalidRequestException(String.format("ALTER COLUMNFAMILY WITH invoked, but no parameters found"));
+
+                cfProps.validate();
+                applyPropertiesToCfDef(cfDef, cfProps);
+                break;
         }
 
         return cfDef;
@@ -122,4 +148,51 @@ public class AlterTableStatement
                              validator);
     }
 
+    public static void applyPropertiesToCfDef(CfDef cfDef, CFPropDefs cfProps) throws InvalidRequestException
+    {
+        if (cfProps.hasProperty(CFPropDefs.KW_COMPARATOR))
+        {
+            throw new InvalidRequestException("Can't change CF comparator after creation");
+        }
+        if (cfProps.hasProperty(CFPropDefs.KW_COMMENT))
+        {
+            cfDef.comment = new Utf8(cfProps.getProperty(CFPropDefs.KW_COMMENT));
+        }
+        if (cfProps.hasProperty(CFPropDefs.KW_DEFAULTVALIDATION))
+        {
+            try
+            {
+                cfDef.default_validation_class = new Utf8(cfProps.getValidator().toString());
+            }
+            catch (ConfigurationException e)
+            {
+                throw new InvalidRequestException(String.format("Invalid validation type %s",
+                                                                cfProps.getProperty(CFPropDefs.KW_DEFAULTVALIDATION)));
+            }
+        }
+
+        cfDef.read_repair_chance = cfProps.getPropertyDouble(CFPropDefs.KW_READREPAIRCHANCE, cfDef.read_repair_chance);
+        cfDef.gc_grace_seconds = cfProps.getPropertyInt(CFPropDefs.KW_GCGRACESECONDS, cfDef.gc_grace_seconds);
+        cfDef.replicate_on_write = cfProps.getPropertyBoolean(CFPropDefs.KW_REPLICATEONWRITE, cfDef.replicate_on_write);
+        cfDef.min_compaction_threshold = cfProps.getPropertyInt(CFPropDefs.KW_MINCOMPACTIONTHRESHOLD, cfDef.min_compaction_threshold);
+        cfDef.max_compaction_threshold = cfProps.getPropertyInt(CFPropDefs.KW_MAXCOMPACTIONTHRESHOLD, cfDef.max_compaction_threshold);
+
+        if (!cfProps.compactionStrategyOptions.isEmpty())
+        {
+            cfDef.compaction_strategy_options = new HashMap<CharSequence, CharSequence>();
+            for (Map.Entry<String, String> entry : cfProps.compactionStrategyOptions.entrySet())
+            {
+                cfDef.compaction_strategy_options.put(new Utf8(entry.getKey()), new Utf8(entry.getValue()));
+            }
+        }
+
+        if (!cfProps.compressionParameters.isEmpty())
+        {
+            cfDef.compression_options = new HashMap<CharSequence, CharSequence>();
+            for (Map.Entry<String, String> entry : cfProps.compressionParameters.entrySet())
+            {
+                cfDef.compression_options.put(new Utf8(entry.getKey()), new Utf8(entry.getValue()));
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f458cc1a/src/java/org/apache/cassandra/cql/CFPropDefs.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/CFPropDefs.java b/src/java/org/apache/cassandra/cql/CFPropDefs.java
index 94b5178..5103b24 100644
--- a/src/java/org/apache/cassandra/cql/CFPropDefs.java
+++ b/src/java/org/apache/cassandra/cql/CFPropDefs.java
@@ -172,6 +172,11 @@ public class CFPropDefs {
         properties.put(name, value);
     }
 
+    public Boolean hasProperty(String name)
+    {
+        return properties.containsKey(name);
+    }
+
     /* If not comparator/validator is not specified, default to text (BytesType is the wrong default for CQL
      * since it uses hex terms).  If the value specified is not found in the comparators map, assume the user
      * knows what they are doing (a custom comparator/validator for example), and pass it on as-is.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f458cc1a/src/java/org/apache/cassandra/cql/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql/Cql.g b/src/java/org/apache/cassandra/cql/Cql.g
index b911a8e..b6d4545 100644
--- a/src/java/org/apache/cassandra/cql/Cql.g
+++ b/src/java/org/apache/cassandra/cql/Cql.g
@@ -426,6 +426,7 @@ alterTableStatement returns [AlterTableStatement expr]
     {
         OperationType type = null;
         String columnFamily = null, columnName = null, validator = null;
+        Map<String, String> propertyMap = null;
     }
     K_ALTER K_COLUMNFAMILY name=( IDENT | STRING_LITERAL | INTEGER ) { columnFamily = $name.text; }
           ( K_ALTER { type = OperationType.ALTER; }
@@ -435,12 +436,16 @@ alterTableStatement returns [AlterTableStatement expr]
                (col=( IDENT | STRING_LITERAL | INTEGER ) { columnName = $col.text; })
                addValidator=comparatorType { validator = $addValidator.text; }
           | K_DROP { type = OperationType.DROP; }
-               (col=( IDENT | STRING_LITERAL | INTEGER ) { columnName = $col.text; }))
+               (col=( IDENT | STRING_LITERAL | INTEGER ) { columnName = $col.text; })
+          | K_WITH { type = OperationType.OPTS; propertyMap = new HashMap<String, String>(); }
+               prop1=(COMPIDENT | IDENT) '=' arg1=createCfamKeywordArgument { propertyMap.put($prop1.text, $arg1.arg); }
+               ( K_AND propN=(COMPIDENT | IDENT) '=' argN=createCfamKeywordArgument { propertyMap.put($propN.text, $argN.arg); } )* )
     endStmnt
       {
-          $expr = new AlterTableStatement(columnFamily, type, columnName, validator);
+          $expr = new AlterTableStatement(columnFamily, type, columnName, validator, propertyMap);
       }
     ;
+
 /** DROP COLUMNFAMILY <CF>; */
 dropColumnFamilyStatement returns [String cfam]
     : K_DROP K_COLUMNFAMILY name=( IDENT | STRING_LITERAL | INTEGER ) endStmnt { $cfam = $name.text; }