Author: jbellis
Date: Wed Nov  3 16:40:39 2010
New Revision: 1030529

URL: http://svn.apache.org/viewvc?rev=1030529&view=rev
Log:
improve cli handlingof non-string column names
patch by Jim Ancona; reviewed by Pavel Yaskevich for CASSANDRA-1701

Modified:
    cassandra/branches/cassandra-0.7/CHANGES.txt
    
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java
    
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java

Modified: cassandra/branches/cassandra-0.7/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/CHANGES.txt?rev=1030529&r1=1030528&r2=1030529&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.7/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.7/CHANGES.txt Wed Nov  3 16:40:39 2010
@@ -14,6 +14,7 @@ dev
  * add friendlier error for UnknownHostException on startup (CASSANDRA-1697)
  * include jna dependency in RPM package (CASSANDRA-1690)
  * add --skip-keys option to stress.py (CASSANDRA-1696)
+ * improve cli handling of non-string column names (CASSANDRA-1701)
 
 
 0.7.0-beta3

Modified: 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java?rev=1030529&r1=1030528&r2=1030529&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java
 (original)
+++ 
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java
 Wed Nov  3 16:40:39 2010
@@ -18,7 +18,7 @@
 package org.apache.cassandra.cli;
 
 import com.google.common.base.Charsets;
-import org.antlr.runtime.tree.CommonTree;
+
 import org.antlr.runtime.tree.Tree;
 import org.apache.cassandra.auth.SimpleAuthenticator;
 import org.apache.cassandra.config.ConfigurationException;
@@ -27,6 +27,7 @@ import org.apache.cassandra.thrift.*;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.UUIDGen;
+import org.apache.thrift.TBaseHelper;
 import org.apache.thrift.TException;
 
 import java.math.BigInteger;
@@ -226,7 +227,7 @@ public class CliClient extends CliUserHe
        
        if (columnSpecCnt != 0)
        {
-           byte[] superColumn = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
+           byte[] superColumn = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), columnFamily);
            colParent = new 
ColumnParent(columnFamily).setSuper_column(superColumn);
        }
 
@@ -251,7 +252,8 @@ public class CliClient extends CliUserHe
 
         byte[] superColumnName = null;
         byte[] columnName = null;
-        boolean isSuper = getCfDef(columnFamily).column_type.equals("Super");
+        CfDef cfDef = getCfDef(columnFamily);
+        boolean isSuper = cfDef.column_type.equals("Super");
      
         if ((columnSpecCnt < 0) || (columnSpecCnt > 2))
         {
@@ -263,15 +265,15 @@ public class CliClient extends CliUserHe
         {
             // table.cf['key']['column']
             if (isSuper)
-                superColumnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
+                superColumnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
             else
-                columnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
+                columnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
         }
         else if (columnSpecCnt == 2)
         {
             // table.cf['key']['column']['column']
-            superColumnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
-            columnName = CliCompiler.getColumn(columnFamilySpec, 
1).getBytes(Charsets.UTF_8);
+            superColumnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
+            columnName = 
subColumnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 1), cfDef);
         }
 
         ColumnPath path = new ColumnPath(columnFamily);
@@ -367,11 +369,11 @@ public class CliClient extends CliUserHe
         String key = CliCompiler.getKey(columnFamilySpec);
         String columnFamily = CliCompiler.getColumnFamily(columnFamilySpec);
         int columnSpecCnt = CliCompiler.numColumnSpecifiers(columnFamilySpec);
-        CfDef columnFamilyDef = getCfDef(columnFamily);
-        boolean isSuper = columnFamilyDef.comparator_type.equals("Super");
+        CfDef cfDef = getCfDef(columnFamily);
+        boolean isSuper = cfDef.comparator_type.equals("Super");
         
         byte[] superColumnName = null;
-        String columnName;
+        ByteBuffer columnName;
 
         // table.cf['key'] -- row slice
         if (columnSpecCnt == 0)
@@ -384,20 +386,20 @@ public class CliClient extends CliUserHe
         {
             if (isSuper)
             {
-                superColumnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
+                superColumnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
                 doSlice(keySpace, key, columnFamily, superColumnName);
                 return;
             }
             else 
             {
-                 columnName = CliCompiler.getColumn(columnFamilySpec, 0);
+                 columnName = 
columnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
             }
         }
         // table.cf['key']['column']['column'] -- get of a sub-column
         else if (columnSpecCnt == 2)
         {
-            superColumnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
-            columnName = CliCompiler.getColumn(columnFamilySpec, 1);
+            superColumnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
+            columnName = 
subColumnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 1), cfDef);
         }
         // The parser groks an arbitrary number of these so it is possible to 
get here.
         else
@@ -406,14 +408,22 @@ public class CliClient extends CliUserHe
             return;
         }
 
-        ByteBuffer columnNameInBytes = columnNameAsBytes(columnName, 
columnFamily);
-        AbstractType validator = getValidatorForValue(columnFamilyDef, 
columnNameInBytes.array());
+        AbstractType validator = getValidatorForValue(cfDef, 
TBaseHelper.byteBufferToByteArray(columnName));
         
         // Perform a get()
         ColumnPath path = new ColumnPath(columnFamily);
         if(superColumnName != null) path.setSuper_column(superColumnName);
-        path.setColumn(columnNameInBytes);
-        Column column = 
thriftClient.get(ByteBuffer.wrap(key.getBytes(Charsets.UTF_8)), path, 
ConsistencyLevel.ONE).column;
+        path.setColumn(columnName);
+        Column column;
+        try
+        {
+            column = 
thriftClient.get(ByteBuffer.wrap(key.getBytes(Charsets.UTF_8)), path, 
ConsistencyLevel.ONE).column;
+        }
+        catch (NotFoundException e)
+        {
+            sessionState.out.println("Value was not found");
+            return;
+        }
 
         byte[] columnValue = column.getValue();       
         String valueAsString;
@@ -433,7 +443,7 @@ public class CliClient extends CliUserHe
             // setting value for output
             valueAsString = 
valueValidator.getString(ByteBuffer.wrap(columnValue));
             // updating column value validator class
-            updateColumnMetaData(columnFamilyDef, columnNameInBytes, 
valueValidator.getClass().getName());
+            updateColumnMetaData(cfDef, columnName, 
valueValidator.getClass().getName());
         }
         else
         {
@@ -556,7 +566,7 @@ public class CliClient extends CliUserHe
         Tree valueTree = statement.getChild(1);
         
         byte[] superColumnName = null;
-        String columnName;
+        ByteBuffer columnName;
 
         // table.cf['key']
         if (columnSpecCnt == 0)
@@ -568,7 +578,7 @@ public class CliClient extends CliUserHe
         else if (columnSpecCnt == 1)
         {
             // get the column name
-            columnName = CliCompiler.getColumn(columnFamilySpec, 0);
+            columnName = 
columnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 0), columnFamily);
         }
         // table.cf['key']['super_column']['column'] = 'value'
         else
@@ -576,21 +586,20 @@ public class CliClient extends CliUserHe
             assert (columnSpecCnt == 2) : "serious parsing error (this is a 
bug).";
             
             // get the super column and column names
-            superColumnName = CliCompiler.getColumn(columnFamilySpec, 
0).getBytes(Charsets.UTF_8);
-            columnName = CliCompiler.getColumn(columnFamilySpec, 1);
+            superColumnName = 
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), columnFamily);
+            columnName = 
subColumnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 1), columnFamily);
         }
 
 
-        ByteBuffer columnNameInBytes = columnNameAsBytes(columnName, 
columnFamily);
         ByteBuffer columnValueInBytes;
 
         switch (valueTree.getType())
         {
         case CliParser.FUNCTION_CALL:
-            columnValueInBytes = convertValueByFunction(valueTree, 
getCfDef(columnFamily), columnNameInBytes, true);
+            columnValueInBytes = convertValueByFunction(valueTree, 
getCfDef(columnFamily), columnName, true);
             break;
         default:
-            columnValueInBytes = columnValueAsBytes(columnNameInBytes, 
columnFamily, value);
+            columnValueInBytes = columnValueAsBytes(columnName, columnFamily, 
value);
         }
 
         ColumnParent parent = new ColumnParent(columnFamily);
@@ -599,7 +608,7 @@ public class CliClient extends CliUserHe
         
         // do the insert
         thriftClient.insert(ByteBuffer.wrap(key.getBytes(Charsets.UTF_8)), 
parent,
-                             new Column(columnNameInBytes, columnValueInBytes, 
FBUtilities.timestampMicros()), ConsistencyLevel.ONE);
+                             new Column(columnName, columnValueInBytes, 
FBUtilities.timestampMicros()), ConsistencyLevel.ONE);
         
         sessionState.out.println("Value inserted.");
     }
@@ -810,7 +819,7 @@ public class CliClient extends CliUserHe
                 Tree arrayOfMetaAttributes = statement.getChild(i + 1);
                 if (!arrayOfMetaAttributes.getText().equals("ARRAY"))
                     throw new RuntimeException("'column_metadata' format - [{ 
k:v, k:v, ..}, { ... }, ...]");
-                
cfDef.setColumn_metadata(getCFColumnMetaFromTree(arrayOfMetaAttributes));
+                cfDef.setColumn_metadata(getCFColumnMetaFromTree(cfDef, 
arrayOfMetaAttributes));
                 break;
             case MEMTABLE_OPERATIONS:
                 
cfDef.setMemtable_operations_in_millions(Double.parseDouble(mValue));
@@ -1244,12 +1253,13 @@ public class CliClient extends CliUserHe
     
     /**
      * Used to parse meta tree and compile meta attributes into List<ColumnDef>
+     * @param cfDef 
      * @param meta (Tree representing Array of the hashes with metadata 
attributes)
      * @return List<ColumnDef> List of the ColumnDef's
      * 
      * meta is in following format - ^(ARRAY ^(HASH ^(PAIR .. ..) ^(PAIR .. 
..)) ^(HASH ...))
      */
-    private List<ColumnDef> getCFColumnMetaFromTree(Tree meta)
+    private List<ColumnDef> getCFColumnMetaFromTree(CfDef cfDef, Tree meta)
     {
         // this list will be returned
         List<ColumnDef> columnDefinitions = new ArrayList<ColumnDef>();
@@ -1273,7 +1283,10 @@ public class CliClient extends CliUserHe
 
                 if (metaKey.equals("column_name"))
                 {
-                    columnDefinition.setName(metaVal.getBytes(Charsets.UTF_8));
+                    if (cfDef.column_type.equals("Super"))
+                        
columnDefinition.setName(subColumnNameAsByteArray(metaVal, cfDef));
+                    else
+                        
columnDefinition.setName(columnNameAsByteArray(metaVal, cfDef));
                 }
                 else if (metaKey.equals("validation_class"))
                 {
@@ -1391,20 +1404,94 @@ public class CliClient extends CliUserHe
      * Converts column name into byte[] according to comparator type
      * @param column - column name from parser
      * @param columnFamily - column family name from parser
-     * @return ByteBuffer - array of bytes in which column name was converted 
according to comparator type
-     * @throws NoSuchFieldException - raised from getFormatTypeForColumn call
-     * @throws InstantiationException - raised from getFormatTypeForColumn call
-     * @throws IllegalAccessException - raised from getFormatTypeForColumn call
+     * @return ByteBuffer - bytes into which column name was converted 
according to comparator type
      */
-    private ByteBuffer columnNameAsBytes(String column, String columnFamily) 
throws NoSuchFieldException, InstantiationException, IllegalAccessException
+    private ByteBuffer columnNameAsBytes(String column, String columnFamily) 
     {
-        CfDef columnFamilyDef   = getCfDef(columnFamily);
-        String comparatorClass  = columnFamilyDef.comparator_type;
-
+        CfDef columnFamilyDef = getCfDef(columnFamily);
+        return columnNameAsBytes(column, columnFamilyDef);
+    }
+    /**
+     * Converts column name into byte[] according to comparator type
+     * @param column - column name from parser
+     * @param columnFamilyDef - column family from parser
+     * @return ByteBuffer bytes - into which column name was converted 
according to comparator type
+     */
+    private ByteBuffer columnNameAsBytes(String column, CfDef columnFamilyDef) 
+    {
+        String comparatorClass = columnFamilyDef.comparator_type;
         return getBytesAccordingToType(column, 
getFormatTypeForColumn(comparatorClass));   
     }
 
     /**
+     * Converts column name into byte[] according to comparator type
+     * @param column - column name from parser
+     * @param columnFamily - column family name from parser
+     * @return bytes[] - into which column name was converted according to 
comparator type
+     */
+    private byte[] columnNameAsByteArray(String column, String columnFamily)
+    {
+        return TBaseHelper.byteBufferToByteArray(columnNameAsBytes(column, 
columnFamily));
+    }
+
+    /**
+     * Converts column name into byte[] according to comparator type
+     * @param column - column name from parser
+     * @param columnFamilyDef - column family from parser
+     * @return bytes[] - into which column name was converted according to 
comparator type
+     */
+    private byte[] columnNameAsByteArray(String column, CfDef cfDef)
+    {
+        return TBaseHelper.byteBufferToByteArray(columnNameAsBytes(column, 
cfDef));
+    }
+
+    /**
+     * Converts sub-column name into ByteBuffer according to comparator type
+     * @param superColumn - sub-column name from parser
+     * @param columnFamily - column family name from parser
+     * @return ByteBuffer bytes - into which column name was converted 
according to comparator type
+     */
+    private ByteBuffer subColumnNameAsBytes(String superColumn, String 
columnFamily)
+    {
+        CfDef columnFamilyDef = getCfDef(columnFamily);
+        return subColumnNameAsBytes(superColumn, columnFamilyDef);
+    }
+
+    /**
+     * Converts column name into ByteBuffer according to comparator type
+     * @param superColumn - sub-column name from parser
+     * @param columnFamilyDef - column family from parser
+     * @return ByteBuffer bytes - into which column name was converted 
according to comparator type
+     */
+    private ByteBuffer subColumnNameAsBytes(String superColumn, CfDef 
columnFamilyDef) 
+    {
+        String comparatorClass = columnFamilyDef.subcomparator_type;
+        return getBytesAccordingToType(superColumn, 
getFormatTypeForColumn(comparatorClass));   
+    }
+
+    /**
+     * Converts column name into byte[] according to comparator type
+     * @param superColumn - sub-column name from parser
+     * @param columnFamily - column family name from parser
+     * @return bytes[] - into which column name was converted according to 
comparator type
+     */
+    private byte[] subColumnNameAsByteArray(String superColumn, String 
columnFamily)
+    {
+        return 
TBaseHelper.byteBufferToByteArray(subColumnNameAsBytes(superColumn, 
columnFamily));
+    }
+
+    /**
+     * Converts sub-column name into byte[] according to comparator type
+     * @param superColumn - sub-column name from parser
+     * @param cfDef - column family from parser
+     * @return bytes[] - into which column name was converted according to 
comparator type
+     */
+    private byte[] subColumnNameAsByteArray(String superColumn, CfDef cfDef)
+    {
+        return 
TBaseHelper.byteBufferToByteArray(subColumnNameAsBytes(superColumn, cfDef));
+    }
+
+    /**
      * Converts column value into byte[] according to validation class
      * @param columnName - column name to which value belongs
      * @param columnFamilyName - column family name
@@ -1657,7 +1744,7 @@ public class CliClient extends CliUserHe
         sessionState.out.printf("\n%d Row%s Returned.\n", slices.size(), 
(slices.size() > 1 ? "s" : ""));
     }
 
-    // returns super column name in human-readable format
+    // returnsub-columnmn name in human-readable format
     private String formatSuperColumnName(String keyspace, String columnFamily, 
SuperColumn column)
             throws NotFoundException, TException, IllegalAccessException, 
InstantiationException, NoSuchFieldException
     {

Modified: 
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java
URL: 
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java?rev=1030529&r1=1030528&r2=1030529&view=diff
==============================================================================
--- 
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java
 (original)
+++ 
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java
 Wed Nov  3 16:40:39 2010
@@ -54,7 +54,30 @@ public class CliTest extends CleanupHelp
         "list CF3[:]",
         "list CF3[h:]",
         "list CF3 limit 10",
-        "list CF3[h:g] limit 10",
+        "list CF3[h:] limit 10",
+        "create column family CF4 with comparator=IntegerType and 
column_metadata=[{column_name:9999, validation_class:LongType}]",
+        "set CF4['hello'][9999] = 1234",
+        "get CF4['hello'][9999]",
+        "get CF4['hello'][9999] as Long",
+        "get CF4['hello'][9999] as Bytes",
+        "set CF4['hello'][9999] = Long(1234)",
+        "get CF4['hello'][9999]",
+        "get CF4['hello'][9999] as Long",
+        "del CF4['hello'][9999]",
+        "get CF4['hello'][9999]",
+        "create column family SCF1 with column_type=Super and 
comparator=IntegerType and subcomparator=LongType and 
column_metadata=[{column_name:9999, validation_class:LongType}]",
+        "set SCF1['hello'][1][9999] = 1234",
+        "get SCF1['hello'][1][9999]",
+        "get SCF1['hello'][1][9999] as Long",
+        "get SCF1['hello'][1][9999] as Bytes",
+        "set SCF1['hello'][1][9999] = Long(1234)",
+        "get SCF1['hello'][1][9999]",
+        "get SCF1['hello'][1][9999] as Long",
+        "del SCF1['hello'][1][9999]",
+        "get SCF1['hello'][1][9999]",
+        "set SCF1['hello'][1][9999] = Long(1234)",
+        "del SCF1['hello'][9999]",
+        "get SCF1['hello'][1][9999]",
         "truncate CF1",
         "update keyspace TestKeySpace with 
placement_strategy='org.apache.cassandra.locator.LocalStrategy'",
         "update keyspace TestKeySpace with replication_factor=1 and 
strategy_options=[{DC1:3, DC2:4, DC5:1}]"
@@ -83,9 +106,12 @@ public class CliTest extends CleanupHelp
 
         for (String statement : statements)
         {
+            errStream.reset();
+            // System.out.println("Executing statement: " + statement);
             CliMain.processStatement(statement);
             String result = outStream.toString();
-
+            // System.out.println("Result:\n" + result);
+            assertEquals("", errStream.toString());
             if (statement.startsWith("drop ") || statement.startsWith("create 
") || statement.startsWith("update "))
             {
                 
assertTrue(result.matches("(.{8})-(.{4})-(.{4})-(.{4})-(.{12})\n"));
@@ -102,7 +128,7 @@ public class CliTest extends CleanupHelp
                 }
                 else
                 {
-                    assertTrue(result.startsWith("=> (column="));
+                    assertTrue(result.startsWith("=> (column=") || 
result.startsWith("Value was not found"));
                 }
             }
             else if (statement.startsWith("truncate "))


Reply via email to