Author: jbellis
Date: Thu Nov 11 14:21:16 2010
New Revision: 1033949
URL: http://svn.apache.org/viewvc?rev=1033949&view=rev
Log:
add lexicaluuid(), timeuuid() functions
patch by Pavel Yaskevich; reviewed by jbellis for CASSANDRA-1687
Modified:
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/Cli.g
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliClient.java
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliUserHelp.java
cassandra/branches/cassandra-0.7/test/unit/org/apache/cassandra/cli/CliTest.java
Modified:
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/Cli.g
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/Cli.g?rev=1033949&r1=1033948&r2=1033949&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/Cli.g
(original)
+++ cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/Cli.g
Thu Nov 11 14:21:16 2010
@@ -439,7 +439,7 @@ columnFamily
;
rowKey
- : (Identifier | StringLiteral)
+ : (Identifier | StringLiteral | IntegerLiteral)
;
value
@@ -447,8 +447,8 @@ value
;
functionCall
- : functionName=Identifier '(' functionArgument ')'
- -> ^(FUNCTION_CALL $functionName functionArgument)
+ : functionName=Identifier '(' functionArgument? ')'
+ -> ^(FUNCTION_CALL $functionName functionArgument?)
;
functionArgument
@@ -464,7 +464,7 @@ endKey
;
columnOrSuperColumn
- : (Identifier | IntegerLiteral | StringLiteral)
+ : (Identifier | IntegerLiteral | StringLiteral | functionCall)
;
host
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=1033949&r1=1033948&r2=1033949&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
Thu Nov 11 14:21:16 2010
@@ -29,6 +29,7 @@ import org.apache.cassandra.utils.FBUtil
import org.apache.cassandra.utils.UUIDGen;
import org.apache.thrift.TBaseHelper;
import org.apache.thrift.TException;
+import org.safehaus.uuid.UUIDGenerator;
import java.math.BigInteger;
import java.nio.ByteBuffer;
@@ -300,7 +301,7 @@ public class CliClient extends CliUserHe
ColumnParent parent = new ColumnParent(columnFamily);
if(superColumnName != null)
parent.setSuper_column(superColumnName);
-
+
SliceRange range = new SliceRange(FBUtilities.EMPTY_BYTE_BUFFER,
FBUtilities.EMPTY_BYTE_BUFFER, true, 1000000);
List<ColumnOrSuperColumn> columns =
thriftClient.get_slice(ByteBuffer.wrap(key.getBytes(Charsets.UTF_8)),parent,
new
SlicePredicate().setColumn_names(null).setSlice_range(range),
ConsistencyLevel.ONE);
@@ -370,7 +371,7 @@ public class CliClient extends CliUserHe
return;
Tree columnFamilySpec = statement.getChild(0);
-
+
String key = CliCompiler.getKey(columnFamilySpec);
String columnFamily = CliCompiler.getColumnFamily(columnFamilySpec);
int columnSpecCnt = CliCompiler.numColumnSpecifiers(columnFamilySpec);
@@ -389,22 +390,20 @@ public class CliClient extends CliUserHe
// table.cf['key']['column'] -- slice of a super, or get of a standard
else if (columnSpecCnt == 1)
{
+ columnName = getColumnName(columnFamily,
columnFamilySpec.getChild(2));
+
if (isSuper)
{
- superColumnName =
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
+ superColumnName = columnName.array();
doSlice(keySpace, key, columnFamily, superColumnName);
return;
}
- else
- {
- columnName =
columnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
- }
}
// table.cf['key']['column']['column'] -- get of a sub-column
else if (columnSpecCnt == 2)
{
- superColumnName =
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), cfDef);
- columnName =
subColumnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 1), cfDef);
+ superColumnName = getColumnName(columnFamily,
columnFamilySpec.getChild(2)).array();
+ columnName = getSubColumnName(columnFamily,
columnFamilySpec.getChild(3));
}
// The parser groks an arbitrary number of these so it is possible to
get here.
else
@@ -563,7 +562,6 @@ public class CliClient extends CliUserHe
// ^(NODE_COLUMN_ACCESS <cf> <key> <column>)
Tree columnFamilySpec = statement.getChild(0);
-
String key = CliCompiler.getKey(columnFamilySpec);
String columnFamily = CliCompiler.getColumnFamily(columnFamilySpec);
int columnSpecCnt = CliCompiler.numColumnSpecifiers(columnFamilySpec);
@@ -583,18 +581,16 @@ public class CliClient extends CliUserHe
else if (columnSpecCnt == 1)
{
// get the column name
- columnName =
columnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 0), columnFamily);
+ columnName = getColumnName(columnFamily,
columnFamilySpec.getChild(2));
}
// table.cf['key']['super_column']['column'] = 'value'
else
{
assert (columnSpecCnt == 2) : "serious parsing error (this is a
bug).";
-
- // get the super column and column names
- superColumnName =
columnNameAsByteArray(CliCompiler.getColumn(columnFamilySpec, 0), columnFamily);
- columnName =
subColumnNameAsBytes(CliCompiler.getColumn(columnFamilySpec, 1), columnFamily);
- }
+ superColumnName = getColumnName(columnFamily,
columnFamilySpec.getChild(2)).array();
+ columnName = getSubColumnName(columnFamily,
columnFamilySpec.getChild(3));
+ }
ByteBuffer columnValueInBytes;
@@ -610,17 +606,18 @@ public class CliClient extends CliUserHe
ColumnParent parent = new ColumnParent(columnFamily);
if(superColumnName != null)
parent.setSuper_column(superColumnName);
-
+
// do the insert
AbstractType keyComparator = this.cfKeysComparators.get(columnFamily);
ByteBuffer keyBytes = keyComparator == null
? ByteBuffer.wrap(key.getBytes(Charsets.UTF_8))
: getBytesAccordingToType(key, keyComparator);
+
thriftClient.insert(keyBytes, parent, new Column(columnName,
columnValueInBytes, FBUtilities.timestampMicros()), ConsistencyLevel.ONE);
sessionState.out.println("Value inserted.");
}
-
+
private void executeShowClusterName() throws TException
{
if (!CliMain.isConnected())
@@ -1440,7 +1437,12 @@ public class CliClient extends CliUserHe
}
else if (comparator instanceof LexicalUUIDType || comparator
instanceof TimeUUIDType)
{
- UUID uuid = UUID.fromString(object);
+ // generate new time based UUID if object is empty
+ // this means that we have timeuuid() call
+ if (comparator instanceof TimeUUIDType && object.isEmpty())
+ return
ByteBuffer.wrap(UUIDGenerator.getInstance().generateTimeBasedUUID().asByteArray());
+
+ UUID uuid = (object.isEmpty()) ? UUID.randomUUID() :
UUID.fromString(object);
if (comparator instanceof TimeUUIDType && uuid.version() != 1)
throw new IllegalArgumentException("TimeUUID supports only
version 1 UUIDs");
@@ -1680,23 +1682,12 @@ public class CliClient extends CliUserHe
private ByteBuffer convertValueByFunction(Tree functionCall, CfDef
columnFamily, ByteBuffer columnName, boolean withUpdate)
{
String functionName = functionCall.getChild(0).getText();
- String functionArg =
CliUtils.unescapeSQLString(functionCall.getChild(1).getText());
- Function function;
+ Tree argumentTree = functionCall.getChild(1);
+ String functionArg = (argumentTree == null) ? "" :
CliUtils.unescapeSQLString(argumentTree.getText());
+ AbstractType validator = getTypeByFunction(functionName);
try
{
- function = Function.valueOf(functionName.toUpperCase());
- }
- catch (IllegalArgumentException e)
- {
- StringBuilder errorMessage = new StringBuilder("Function '" +
functionName + "' not found. ");
- errorMessage.append("Available functions: ");
- throw new
RuntimeException(errorMessage.append(Function.getFunctionNames()).toString());
- }
-
- try
- {
- AbstractType validator = function.getValidator();
ByteBuffer value = getBytesAccordingToType(functionArg, validator);
// performing ColumnDef local validator update
@@ -1714,6 +1705,29 @@ public class CliClient extends CliUserHe
}
/**
+ * Get AbstractType by function name
+ * @param functionName - name of the function e.g. utf8, integer, long etc.
+ * @return AbstractType type corresponding to the function name
+ */
+ public static AbstractType getTypeByFunction(String functionName)
+ {
+ Function function;
+
+ try
+ {
+ function = Function.valueOf(functionName.toUpperCase());
+ }
+ catch (IllegalArgumentException e)
+ {
+ StringBuilder errorMessage = new StringBuilder("Function '" +
functionName + "' not found. ");
+ errorMessage.append("Available functions: ");
+ throw new
RuntimeException(errorMessage.append(Function.getFunctionNames()).toString());
+ }
+
+ return function.getValidator();
+ }
+
+ /**
* Used to locally update column family definition with new column metadata
* @param columnFamily - CfDef record
* @param columnName - column name represented as byte[]
@@ -1838,4 +1852,19 @@ public class CliClient extends CliUserHe
{
return getFormatTypeForColumn(getCfDef(keyspace,
columnFamily).comparator_type).getString(ByteBuffer.wrap(column.getName()));
}
+
+ private ByteBuffer getColumnName(String columnFamily, Tree columnTree)
+ {
+ return (columnTree.getType() == CliParser.FUNCTION_CALL)
+ ? convertValueByFunction(columnTree, null, null)
+ :
columnNameAsBytes(CliUtils.unescapeSQLString(columnTree.getText()),
columnFamily);
+ }
+
+ private ByteBuffer getSubColumnName(String columnFamily, Tree columnTree)
+ {
+ return (columnTree.getType() == CliParser.FUNCTION_CALL)
+ ? convertValueByFunction(columnTree, null, null)
+ :
subColumnNameAsBytes(CliUtils.unescapeSQLString(columnTree.getText()),
columnFamily);
+ }
+
}
Modified:
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliUserHelp.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliUserHelp.java?rev=1033949&r1=1033948&r2=1033949&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliUserHelp.java
(original)
+++
cassandra/branches/cassandra-0.7/src/java/org/apache/cassandra/cli/CliUserHelp.java
Thu Nov 11 14:21:16 2010
@@ -227,15 +227,19 @@ public class CliUserHelp {
state.out.println("get <cf>['<key>']");
state.out.println("get <cf>['<key>']['<col>'] (as <type>)*");
state.out.println("get <cf>['<key>']['<super>']");
+ state.out.println("get <cf>['<key>'][<function>]");
+ state.out.println("get
<cf>['<key>'][<function>(<super>)][<function>(<col>)]");
state.out.println("get <cf> where <column> = <value> [and
<column> > <value> and ...] [limit <integer>]");
state.out.println("Default LIMIT is 100. Available operations:
=, >, >=, <, <=\n");
state.out.println("get <cf>['<key>']['<super>']['<col>'] (as
<type>)*");
state.out.print("Note: `as <type>` is optional, it dynamically
converts column value to the specified type");
state.out.println(", column value validator will be set to
<type>.");
+ state.out.println("Available functions: " +
CliClient.Function.getFunctionNames());
state.out.println("Available types: IntegerType, LongType,
UTF8Type, ASCIIType, TimeUUIDType, LexicalUUIDType.\n");
state.out.println("examples:");
state.out.println("get bar[testkey]");
state.out.println("get bar[testkey][test_column] as
IntegerType");
+ state.out.println("get bar[testkey][utf8(hello)]");
break;
case CliParser.NODE_THRIFT_SET:
@@ -243,11 +247,13 @@ public class CliUserHelp {
state.out.println("set <cf>['<key>']['<super>']['<col>'] =
<value>");
state.out.println("set <cf>['<key>']['<col>'] =
<function>(<argument>)");
state.out.println("set <cf>['<key>']['<super>']['<col>'] =
<function>(<argument>)");
+ state.out.println("set <cf>[<key>][<function>(<col>)] =
<value> || <function>");
state.out.println("Available functions: " +
CliClient.Function.getFunctionNames() + "\n");
state.out.println("examples:");
state.out.println("set bar['testkey']['my super']['test
col']='this is a test'");
state.out.println("set baz['testkey']['test col']='this is
also a test'");
state.out.println("set diz[testkey][testcol] = utf8('this is
utf8 string.')");
+ state.out.println("set bar[testkey][timeuuid()] = utf('hello
world')");
break;
case CliParser.NODE_THRIFT_DEL:
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=1033949&r1=1033948&r2=1033949&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
Thu Nov 11 14:21:16 2010
@@ -84,7 +84,17 @@ public class CliTest extends CleanupHelp
"assume CF1 comparator as utf8",
"assume CF1 sub_comparator as integer",
"assume CF1 validator as lexicaluuid",
- "assume CF1 keys as timeuuid"
+ "assume CF1 keys as timeuuid",
+ "create column family CF7",
+ "set CF7[1][timeuuid()] = utf8(test1)",
+ "set CF7[2][lexicaluuid()] = utf8('hello world!')",
+ "set CF7[3][lexicaluuid(550e8400-e29b-41d4-a716-446655440000)] =
utf8(test2)",
+ "set CF7[key2][timeuuid()] = utf8(test3)",
+ "assume CF7 comparator as lexicaluuid",
+ "assume CF7 keys as utf8",
+ "list CF7",
+ "get CF7[3]",
+ "get CF7[3][lexicaluuid(550e8400-e29b-41d4-a716-446655440000)]"
};
@Test