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 "))