cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jbel...@apache.org
Subject svn commit: r1134502 - in /cassandra/branches/cassandra-0.8: ./ doc/cql/ src/java/org/apache/cassandra/config/ src/java/org/apache/cassandra/cql/ test/system/
Date Sat, 11 Jun 2011 01:45:17 GMT
Author: jbellis
Date: Sat Jun 11 01:45:16 2011
New Revision: 1134502

URL: http://svn.apache.org/viewvc?rev=1134502&view=rev
Log:
add cql key alias support
patch by pyaskevich; reviewed by jbellis for CASSANDRA-2480

Modified:
    cassandra/branches/cassandra-0.8/CHANGES.txt
    cassandra/branches/cassandra-0.8/doc/cql/CQL.textile
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/config/CFMetaData.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/AbstractModification.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/UpdateStatement.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java
    cassandra/branches/cassandra-0.8/test/system/test_cql.py

Modified: cassandra/branches/cassandra-0.8/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/CHANGES.txt?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8/CHANGES.txt Sat Jun 11 01:45:16 2011
@@ -10,6 +10,7 @@
    - DROP INDEX (CASSANDRA-2617)
    - add SCHEMA/TABLE as aliases for KS/CF (CASSANDRA-2743)
    - server handles wait-for-schema-agreement (CASSANDRA-2756)
+   - key alias support (CASSANDRA-2480)
  * add support for comparator parameters and a generic ReverseType
    (CASSANDRA-2355)
  * add CompositeType and DynamicCompositeType (CASSANDRA-2231)

Modified: cassandra/branches/cassandra-0.8/doc/cql/CQL.textile
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/doc/cql/CQL.textile?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/doc/cql/CQL.textile (original)
+++ cassandra/branches/cassandra-0.8/doc/cql/CQL.textile Sat Jun 11 01:45:16 2011
@@ -54,11 +54,11 @@ Following the column family clause is an
 h3. Filtering rows
 
 bc. 
-SELECT ... WHERE KEY = keyname AND name1 = value1
-SELECT ... WHERE KEY >= startkey and KEY =< endkey AND name1 = value1
-SELECT ... WHERE KEY IN ('<key>', '<key>', '<key>', ...)
+SELECT ... WHERE <KEY> = keyname AND name1 = value1
+SELECT ... WHERE <KEY> >= startkey and <KEY> =< endkey AND name1 = value1
+SELECT ... WHERE <KEY> IN ('<key>', '<key>', '<key>', ...)
 
-The WHERE clause provides for filtering the rows that appear in results.  The clause can
filter on a key name, or range of keys, and in the case of indexed columns, on column values.
 Key filters are specified using the @KEY@ keyword, a relational operator, (one of @=@, @>@,
@>=@, @<@, and @<=@), and a term value.  When terms appear on both sides of a relational
operator it is assumed the filter applies to an indexed column. With column index filters,
the term on the left of the operator is the name, the term on the right is the value to filter
__on__.
+The WHERE clause provides for filtering the rows that appear in results.  The clause can
filter on a key name, or range of keys, and in the case of indexed columns, on column values.
 Key filters are specified using the @KEY@ keyword or key alias name, a relational operator,
(one of @=@, @>@, @>=@, @<@, and @<=@), and a term value.  When terms appear on
both sides of a relational operator it is assumed the filter applies to an indexed column.
With column index filters, the term on the left of the operator is the name, the term on the
right is the value to filter __on__.
 
 __Note: The greater-than and less-than operators (@>@ and @<@) result in key ranges
that are inclusive of the terms. There is no supported notion of "strictly" greater-than or
less-than; these operators are merely supported as aliases to @>=@ and @<=@.__  
 
@@ -85,7 +85,7 @@ h2. INSERT
 _Synopsis:_
 
 bc.
-INSERT INTO <COLUMN FAMILY> (KEY, <col>, <col>, ...) VALUES (<key>,
<val>, <val>, ...) [USING CONSISTENCY <LEVEL> [AND TIMESTAMP <timestamp>]
[AND TTL <timeToLive>]];
+INSERT INTO <COLUMN FAMILY> (<KEY>, <col>, <col>, ...) VALUES (<key>,
<val>, <val>, ...) [USING CONSISTENCY <LEVEL> [AND TIMESTAMP <timestamp>]
[AND TTL <timeToLive>]];
 
 An @INSERT@ is used to write one or more columns to a record in a Cassandra column family.
No results are returned. 
 
@@ -97,9 +97,9 @@ _Synopsis:_
 
 bc. 
 UPDATE <COLUMN FAMILY> [USING <CONSISTENCY> [AND TIMESTAMP <timestamp>]
[AND TTL <timeToLive>]]
-        SET name1 = value1, name2 = value2 WHERE KEY = keyname;
+        SET name1 = value1, name2 = value2 WHERE <KEY> = keyname;
         
-An @UPDATE@ is used to write one or more columns to a record in a Cassandra column family.
No results are returned.
+An @UPDATE@ is used to write one or more columns to a record in a Cassandra column family.
No results are returned. Key can be given using @KEY@ keyword or by alias set per ColumnFamily.
 
 h3. Column Family
 
@@ -132,20 +132,20 @@ UPDATE ... [USING TTL <timeToLive>] ...
 h3. Specifying Columns and Row
 
 bc. 
-UPDATE ... SET name1 = value1, name2 = value2 WHERE KEY = keyname;
-UPDATE ... SET name1 = value1, name2 = value2 WHERE KEY IN ('<key>', '<key>',
...)
+UPDATE ... SET name1 = value1, name2 = value2 WHERE <KEY> = keyname;
+UPDATE ... SET name1 = value1, name2 = value2 WHERE <KEY> IN ('<key>', '<key>',
...)
 
-Rows are created or updated by supplying column names and values in term assignment format.
Multiple columns can be set by separating the name/value pairs using commas.  Each update
statement requires exactly one key to be specified using a WHERE clause and the @KEY@ keyword.
+Rows are created or updated by supplying column names and values in term assignment format.
Multiple columns can be set by separating the name/value pairs using commas.  Each update
statement requires exactly one key to be specified using a WHERE clause and the @KEY@ keyword
or key alias.
 
 h2. DELETE
 
 _Synopsis:_
 
 bc. 
-DELETE [COLUMNS] FROM <COLUMN FAMILY> [USING <CONSISTENCY>] WHERE KEY = keyname1
-DELETE [COLUMNS] FROM <COLUMN FAMILY> [USING <CONSISTENCY>] WHERE KEY IN (keyname1,
keyname2);
+DELETE [COLUMNS] FROM <COLUMN FAMILY> [USING <CONSISTENCY>] WHERE <KEY>
= keyname1
+DELETE [COLUMNS] FROM <COLUMN FAMILY> [USING <CONSISTENCY>] WHERE <KEY>
IN (keyname1, keyname2);
 
-A @DELETE@ is used to perform the removal of one or more columns from one or more rows.
+A @DELETE@ is used to perform the removal of one or more columns from one or more rows. Key
can be given using @KEY@ keyword or by alias set per ColumnFamily.
 
 h3. Specifying Columns
 
@@ -171,10 +171,10 @@ Following the column family identifier i
 h3(#deleterows). Specifying Rows
 
 bc. 
-DELETE ... WHERE KEY = keyname1
-DELETE ... WHERE KEY IN (keyname1, keyname2)
+DELETE ... WHERE <KEY> = keyname1
+DELETE ... WHERE <KEY> IN (keyname1, keyname2)
 
-The @WHERE@ clause is used to determine which row(s) a @DELETE@ applies to.  The first form
allows the specification of a single keyname using the @KEY@ keyword and the @=@ operator.
 The second form allows a list of keyname terms to be specified using the @IN@ notation and
a parenthesized list of comma-delimited keyname terms.
+The @WHERE@ clause is used to determine which row(s) a @DELETE@ applies to. The first form
allows the specification of a single keyname using the @KEY@ keyword (or by key alias) and
the @=@ operator.  The second form allows a list of keyname terms to be specified using the
@IN@ notation and a parenthesized list of comma-delimited keyname terms.
 
 h2. BATCH
 
@@ -229,8 +229,8 @@ h2. CREATE COLUMNFAMILY
 _Synopsis:_
 
 bc. 
-CREATE COLUMNFAMILY <COLUMN FAMILY> (KEY <type> PRIMARY KEY [, name1 type, name2
type, ...]);
-CREATE COLUMNFAMILY <COLUMN FAMILY> (KEY <type> PRIMARY KEY [, name1 type, name2
type, ...])
+CREATE COLUMNFAMILY <COLUMN FAMILY> (<KEY> <type> PRIMARY KEY [, name1
type, name2 type, ...]);
+CREATE COLUMNFAMILY <COLUMN FAMILY> (<KEY> <type> PRIMARY KEY [, name1
type, name2 type, ...])
     [WITH keyword1 = arg1 [AND keyword2 = arg2 [AND ...]]];
 
 @CREATE COLUMNFAMILY@ statements create new column family namespaces under the current keyspace.
Valid column family names are strings of alphanumeric characters and underscores, which begin
with a letter.
@@ -238,14 +238,14 @@ CREATE COLUMNFAMILY <COLUMN FAMILY> (KEY
 h3(#keytypes). Specifying Key Type
 
 bc. 
-CREATE ... (KEY <type> PRIMARY KEY) ...
+CREATE ... (<KEY> <type> PRIMARY KEY) ...
 
-When creating a new column family, you must specify key type.  The list of possible key types
is identical to column comparators/validators, (see "Specifying Column Type":columntypes).
 It's important to note that the key type must be compatible with the partitioner in use,
for example @OrderPreservingPartitioner@ and @CollatingOrderPreservingPartitioner@ both require
UTF-8 keys.
+When creating a new column family, you must specify key type.  The list of possible key types
is identical to column comparators/validators, (see "Specifying Column Type":columntypes).
 It's important to note that the key type must be compatible with the partitioner in use,
for example @OrderPreservingPartitioner@ and @CollatingOrderPreservingPartitioner@ both require
UTF-8 keys. If you use name instead of @KEY@ keyword, name alias will be set automatically.
 
 h3(#columntypes). Specifying Column Type (optional)
 
 bc. 
-CREATE ... (KEY <type> PRIMARY KEY, name1 type, name2 type) ...
+CREATE ... (<KEY> <type> PRIMARY KEY, name1 type, name2 type) ...
 
 It is possible to assign columns a type during column family creation.  Columns configured
with a type are validated accordingly when a write occurs. Column types are specified as a
parenthesized, comma-separated list of column term and type pairs.  The list of recognized
types are:
 

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/config/CFMetaData.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/config/CFMetaData.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/config/CFMetaData.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/config/CFMetaData.java
Sat Jun 11 01:45:16 2011
@@ -61,7 +61,8 @@ public final class CFMetaData
     public final static double DEFAULT_MEMTABLE_OPERATIONS_IN_MILLIONS = sizeMemtableOperations(DEFAULT_MEMTABLE_THROUGHPUT_IN_MB);
     public final static double DEFAULT_MERGE_SHARDS_CHANCE = 0.1;
     public final static String DEFAULT_ROW_CACHE_PROVIDER = "org.apache.cassandra.cache.ConcurrentLinkedHashCacheProvider";
-    
+    public final static ByteBuffer DEFAULT_KEY_NAME = ByteBufferUtil.bytes("KEY");
+
     private static final int MIN_CF_ID = 1000;
     private static final AtomicInteger idGen = new AtomicInteger(MIN_CF_ID);
     
@@ -73,7 +74,6 @@ public final class CFMetaData
     public static final CFMetaData SchemaCf = newSystemMetadata(Migration.SCHEMA_CF, 3, "current
state of the schema", UTF8Type.instance, null, DEFAULT_SYSTEM_MEMTABLE_THROUGHPUT_IN_MB);
     public static final CFMetaData IndexCf = newSystemMetadata(SystemTable.INDEX_CF, 5, "indexes
that have been completed", UTF8Type.instance, null, DEFAULT_SYSTEM_MEMTABLE_THROUGHPUT_IN_MB);
     public static final CFMetaData NodeIdCf = newSystemMetadata(SystemTable.NODE_ID_CF, 6,
"nodeId and their metadata", TimeUUIDType.instance, null, DEFAULT_SYSTEM_MEMTABLE_THROUGHPUT_IN_MB);
-    private static final ByteBuffer DEFAULT_KEY_NAME = ByteBufferUtil.bytes("KEY");
 
     /**
      * @return A calculated memtable throughput size for this machine.

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/AbstractModification.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/AbstractModification.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/AbstractModification.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/AbstractModification.java
Sat Jun 11 01:45:16 2011
@@ -20,14 +20,13 @@
  */
 package org.apache.cassandra.cql;
 
+import java.util.List;
+
 import org.apache.cassandra.db.IMutation;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.ConsistencyLevel;
 import org.apache.cassandra.thrift.InvalidRequestException;
 
-import java.nio.ByteBuffer;
-import java.util.List;
-
 public abstract class AbstractModification
 {
     public static final ConsistencyLevel defaultConsistency = ConsistencyLevel.ONE;
@@ -36,18 +35,20 @@ public abstract class AbstractModificati
     protected final ConsistencyLevel cLevel;
     protected final Long timestamp;
     protected final int timeToLive;
+    protected final String keyName;
 
-    public AbstractModification(String columnFamily, Attributes attrs)
+    public AbstractModification(String columnFamily, String keyAlias, Attributes attrs)
     {
-        this(columnFamily, attrs.getConsistencyLevel(), attrs.getTimestamp(), attrs.getTimeToLive());
+        this(columnFamily, keyAlias, attrs.getConsistencyLevel(), attrs.getTimestamp(), attrs.getTimeToLive());
     }
 
-    public AbstractModification(String columnFamily, ConsistencyLevel cLevel, Long timestamp,
int timeToLive)
+    public AbstractModification(String columnFamily, String keyAlias, ConsistencyLevel cLevel,
Long timestamp, int timeToLive)
     {
         this.columnFamily = columnFamily;
         this.cLevel = cLevel;
         this.timestamp = timestamp;
         this.timeToLive = timeToLive;
+        this.keyName = keyAlias.toUpperCase();
     }
 
     public String getColumnFamily()

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g Sat Jun 11 01:45:16
2011
@@ -185,8 +185,9 @@ whereClause returns [WhereClause clause]
     }
     : first=relation { $clause = new WhereClause(first); } 
           (K_AND next=relation { $clause.and(next); })*
-      | K_KEY K_IN '(' f1=term { inClause.andKeyEquals(f1); }
-                      (',' fN=term { inClause.andKeyEquals(fN); } )* ')'
+      | key_alias=term { inClause.setKeyAlias(key_alias.getText()); }
+           K_IN '(' f1=term { inClause.andKeyEquals(f1); }
+                  (',' fN=term { inClause.andKeyEquals(fN); } )* ')'
         { $clause = inClause; }
     ;
 
@@ -212,12 +213,12 @@ insertStatement returns [UpdateStatement
           List<Term> columnValues = new ArrayList<Term>();
       }
       K_INSERT K_INTO columnFamily=( IDENT | STRING_LITERAL | INTEGER )
-          '(' K_KEY    ( ',' column_name=term  { columnNames.add($column_name.item); } )+
')'
+          '(' key_alias=term ( ',' column_name=term  { columnNames.add($column_name.item);
} )+ ')'
         K_VALUES
           '(' key=term ( ',' column_value=term { columnValues.add($column_value.item); })+
')'
         ( usingClause[attrs] )?
       {
-          return new UpdateStatement($columnFamily.text, columnNames, columnValues, Collections.singletonList(key),
attrs);
+          return new UpdateStatement($columnFamily.text, key_alias.getText(), columnNames,
columnValues, Collections.singletonList(key), attrs);
       }
     ;
 
@@ -298,11 +299,11 @@ updateStatement returns [UpdateStatement
       K_UPDATE columnFamily=( IDENT | STRING_LITERAL | INTEGER )
           ( usingClause[attrs] )?
           K_SET termPairWithOperation[columns] (',' termPairWithOperation[columns])*
-          K_WHERE ( K_KEY '=' key=term { keyList = Collections.singletonList(key); }
-                    |
-                    K_KEY K_IN '(' keys=termList { keyList = $keys.items; } ')' )
+          K_WHERE ( key_alias=term ('=' key=term { keyList = Collections.singletonList(key);
}
+                                    |
+                                    K_IN '(' keys=termList { keyList = $keys.items; } ')'
))
       {
-          return new UpdateStatement($columnFamily.text, columns, keyList, attrs);
+          return new UpdateStatement($columnFamily.text, key_alias.getText(), columns, keyList,
attrs);
       }
     ;
 
@@ -326,11 +327,11 @@ deleteStatement returns [DeleteStatement
           ( cols=termList { columnsList = $cols.items; })?
           K_FROM columnFamily=( IDENT | STRING_LITERAL | INTEGER )
           ( K_USING K_CONSISTENCY K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text);
} )?
-          K_WHERE ( K_KEY '=' key=term           { keyList = Collections.singletonList(key);
}
-                  | K_KEY K_IN '(' keys=termList { keyList = $keys.items; } ')'
+          K_WHERE ( key_alias=term ('=' key=term           { keyList = Collections.singletonList(key);
}
+                                   | K_IN '(' keys=termList { keyList = $keys.items; } ')')
                   )?
       {
-          return new DeleteStatement(columnsList, $columnFamily.text, cLevel, keyList);
+          return new DeleteStatement(columnsList, $columnFamily.text, key_alias.getText(),
cLevel, keyList);
       }
     ;
 
@@ -366,7 +367,7 @@ createColumnFamilyStatement returns [Cre
 
 createCfamColumns[CreateColumnFamilyStatement expr]
     : n=term v=createCfamColumnValidator { $expr.addColumn(n, $v.validator); }
-    | K_KEY v=createCfamColumnValidator K_PRIMARY K_KEY { $expr.setKeyType($v.validator);
}
+    | k=term v=createCfamColumnValidator K_PRIMARY K_KEY { $expr.setKeyAlias(k.getText());
$expr.setKeyType($v.validator); }
     ;
 
 createCfamColumnValidator returns [String validator]
@@ -451,9 +452,8 @@ termPairWithOperation[Map<Term, Operatio
 
 // Note: ranges are inclusive so >= and >, and < and <= all have the same semantics.
 
 relation returns [Relation rel]
-    : { Term entity = new Term("KEY", STRING_LITERAL); }
-      (name=term { entity = $name.item; } ) type=('=' | '<' | '<=' | '>=' | '>')
t=term
-      { return new Relation(entity, $type.text, $t.item); }
+    : name=term type=('=' | '<' | '<=' | '>=' | '>') t=term
+      { return new Relation($name.item, $type.text, $t.item); }
     ;
 
 // TRUNCATE <CF>;

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/CreateColumnFamilyStatement.java
Sat Jun 11 01:45:16 2011
@@ -35,6 +35,7 @@ import org.apache.cassandra.db.ColumnFam
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.TypeParser;
 import org.apache.cassandra.thrift.InvalidRequestException;
+import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 
 /** A <code>CREATE COLUMNFAMILY</code> parsed from a CQL query statement. */
@@ -95,7 +96,8 @@ public class CreateColumnFamilyStatement
     private final Map<Term, String> columns = new HashMap<Term, String>();
     private final Map<String, String> properties = new HashMap<String, String>();
     private List<String> keyValidator = new ArrayList<String>();
-    
+    private ByteBuffer keyAlias = null;
+
     public CreateColumnFamilyStatement(String name)
     {
         this.name = name;
@@ -180,7 +182,14 @@ public class CreateColumnFamilyStatement
     {
         return keyValidator.get(0);
     }
-    
+
+    public void setKeyAlias(String alias)
+    {
+        // if we got KEY in input we don't need to set an alias
+        if (!alias.toUpperCase().equals("KEY"))
+            keyAlias = ByteBufferUtil.bytes(alias);
+    }
+
     /** Map a keyword to the corresponding value */
     public void addProperty(String name, String value)
     {
@@ -268,7 +277,8 @@ public class CreateColumnFamilyStatement
                    .mergeShardsChance(0.0)
                    .columnMetadata(getColumns(comparator))
                    .keyValidator(TypeParser.parse(comparators.get(getKeyType())))
-                   .rowCacheProvider(FBUtilities.newCacheProvider(getPropertyString(KW_ROW_CACHE_PROVIDER,
CFMetaData.DEFAULT_ROW_CACHE_PROVIDER)));
+                   .rowCacheProvider(FBUtilities.newCacheProvider(getPropertyString(KW_ROW_CACHE_PROVIDER,
CFMetaData.DEFAULT_ROW_CACHE_PROVIDER)))
+                   .keyAlias(keyAlias);
         }
         catch (ConfigurationException e)
         {

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/DeleteStatement.java
Sat Jun 11 01:45:16 2011
@@ -47,9 +47,9 @@ public class DeleteStatement extends Abs
     private List<Term> columns;
     private List<Term> keys;
     
-    public DeleteStatement(List<Term> columns, String columnFamily, ConsistencyLevel
cLevel, List<Term> keys)
+    public DeleteStatement(List<Term> columns, String columnFamily, String keyName,
ConsistencyLevel cLevel, List<Term> keys)
     {
-        super(columnFamily, cLevel, null, 0);
+        super(columnFamily, keyName, cLevel, null, 0);
 
         this.columns = columns;
         this.keys = keys;
@@ -102,6 +102,7 @@ public class DeleteStatement extends Abs
     public void mutationForKey(RowMutation mutation, String keyspace, Long timestamp) throws
InvalidRequestException
     {
         CFMetaData metadata = validateColumnFamily(keyspace, columnFamily);
+        QueryProcessor.validateKeyAlias(metadata, keyName);
 
         AbstractType comparator = metadata.getComparatorFor(null);
 

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
Sat Jun 11 01:45:16 2011
@@ -65,6 +65,8 @@ public class QueryProcessor
 
     private static final long timeLimitForSchemaAgreement = 10 * 1000;
 
+    public static final String DEFAULT_KEY_NAME = bufferToString(CFMetaData.DEFAULT_KEY_NAME);
+
     private static List<org.apache.cassandra.db.Row> getSlice(String keyspace, SelectStatement
select)
     throws InvalidRequestException, TimedOutException, UnavailableException
     {
@@ -401,6 +403,14 @@ public class QueryProcessor
         }
     }
 
+    public static void validateKeyAlias(CFMetaData cfm, String key) throws InvalidRequestException
+    {
+        assert key.toUpperCase().equals(key); // should always be uppercased by caller
+        String realKeyAlias = bufferToString(cfm.getKeyName()).toUpperCase();
+        if (!realKeyAlias.equals(key))
+            throw new InvalidRequestException(String.format("Expected key '%s' to be present
in WHERE clause for '%s'", key, cfm.cfName));
+    }
+
     private static void validateColumnNames(Iterable<ByteBuffer> columns)
     throws InvalidRequestException
     {
@@ -500,8 +510,15 @@ public class QueryProcessor
                 SelectStatement select = (SelectStatement)statement.statement;
                 clientState.hasColumnFamilyAccess(select.getColumnFamily(), Permission.READ);
                 metadata = validateColumnFamily(keyspace, select.getColumnFamily());
+
+                // need to do this in here because we need a CFMD.getKeyName()
+                select.extractKeyAliasFromColumns(metadata);
+
+                if (select.getKeys().size() > 0)
+                    validateKeyAlias(metadata, select.getKeyAlias());
+
                 validateSelect(keyspace, select);
-                
+
                 List<org.apache.cassandra.db.Row> rows;
 
                 // By-key
@@ -969,4 +986,16 @@ public class QueryProcessor
 
         throw new SchemaDisagreementException();
     }
+
+    private static String bufferToString(ByteBuffer string)
+    {
+        try
+        {
+            return ByteBufferUtil.string(string);
+        }
+        catch (CharacterCodingException e)
+        {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
 }

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java
Sat Jun 11 01:45:16 2011
@@ -23,6 +23,7 @@ package org.apache.cassandra.cql;
 import java.nio.ByteBuffer;
 import java.util.List;
 
+import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.thrift.ConsistencyLevel;
@@ -142,6 +143,16 @@ public class SelectStatement
         return clause.includeFinishKey();
     }
 
+    public String getKeyAlias()
+    {
+        return clause.getKeyAlias();
+    }
+
+    public void extractKeyAliasFromColumns(CFMetaData cfm)
+    {
+        clause.extractKeysFromColumns(cfm);
+    }
+
     public AbstractType getComparator(String keyspace)
     {
         return DatabaseDescriptor.getComparator(keyspace, columnFamily);

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/UpdateStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/UpdateStatement.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/UpdateStatement.java
(original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/UpdateStatement.java
Sat Jun 11 01:45:16 2011
@@ -49,22 +49,24 @@ public class UpdateStatement extends Abs
     private Map<Term, Operation> columns;
     private List<Term> columnNames, columnValues;
     private List<Term> keys;
-    
+
     /**
      * Creates a new UpdateStatement from a column family name, columns map, consistency
      * level, and key term.
      * 
      * @param columnFamily column family name
+     * @param keyName alias key name
      * @param columns a map of column name/values pairs
      * @param keys the keys to update
      * @param attrs additional attributes for statement (CL, timestamp, timeToLive)
      */
     public UpdateStatement(String columnFamily,
+                           String keyName,
                            Map<Term, Operation> columns,
                            List<Term> keys,
                            Attributes attrs)
     {
-        super(columnFamily, attrs);
+        super(columnFamily, keyName, attrs);
 
         this.columns = columns;
         this.keys = keys;
@@ -76,18 +78,20 @@ public class UpdateStatement extends Abs
      * alternate update format, <code>INSERT</code>.
      * 
      * @param columnFamily column family name
+     * @param keyName alias key name
      * @param columnNames list of column names
      * @param columnValues list of column values (corresponds to names)
      * @param keys the keys to update
      * @param attrs additional attributes for statement (CL, timestamp, timeToLive)
      */
     public UpdateStatement(String columnFamily,
+                           String keyName,
                            List<Term> columnNames,
                            List<Term> columnValues,
                            List<Term> keys,
                            Attributes attrs)
     {
-        super(columnFamily, attrs);
+        super(columnFamily, keyName, attrs);
 
         this.columnNames = columnNames;
         this.columnValues = columnValues;
@@ -139,6 +143,8 @@ public class UpdateStatement extends Abs
 
         CFMetaData metadata = validateColumnFamily(keyspace, columnFamily, hasCommutativeOperation);
 
+        QueryProcessor.validateKeyAlias(metadata, keyName);
+
         // Avoid unnecessary authorizations.
         if (!(cfamsSeen.contains(columnFamily)))
         {

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java Sat
Jun 11 01:45:16 2011
@@ -21,7 +21,15 @@ package org.apache.cassandra.cql;
  */
 
 
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.thrift.InvalidRequestException;
+import org.apache.cassandra.thrift.ThriftValidation;
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -30,10 +38,13 @@ import java.util.List;
  */
 public class WhereClause
 {
+    // added to either by the parser, e.g. from an IN clause, or by extractKeysFromColumns
     private List<Term> keys = new ArrayList<Term>();
     private Term startKey, finishKey;
     private List<Relation> columns = new ArrayList<Relation>();
     private boolean includeStartKey = false, includeFinishKey = false;
+    // set by extractKeysFromColumns
+    private String keyAlias = null;
 
     /**
      * Create a new WhereClause with the first parsed relation.
@@ -96,11 +107,6 @@ public class WhereClause
         return startKey != null;
     }
     
-    public boolean isKeyList()
-    {
-        return !isKeyRange();
-    }
-    
     public Term getStartKey()
     {
         return startKey;
@@ -125,4 +131,47 @@ public class WhereClause
     {
         return includeFinishKey;
     }
+
+    public void setKeyAlias(String alias)
+    {
+        keyAlias = alias.toUpperCase();
+    }
+
+    public String getKeyAlias()
+    {
+        // TODO fix special casing here, key alias should always be set post-extract
+        // key alias as not related to keys in here, it can be unset when we have a query
like
+        // SELECT * FROM <CF> WHERE key = 1 and col > 2 and col < 3;
+        // it will be always set when statement looks like this
+        // SELECT * FROM <CF> WHERE <key> IN (.., .., ..);
+        // key is NULL when KEY keyword is used or when key alias given by user was not recognized
+        // validateKeyAlias will throw an exception for us in that case
+        return keyAlias == null ? QueryProcessor.DEFAULT_KEY_NAME : keyAlias;
+    }
+
+    public void extractKeysFromColumns(CFMetaData cfm)
+    {
+        ByteBuffer realKeyAlias = cfm.getKeyName();
+
+        if (!keys.isEmpty())
+            return; // we already have key(s) set
+
+        Iterator<Relation> iter = columns.iterator();
+
+        while (iter.hasNext())
+        {
+            Relation relation = iter.next();
+
+            ByteBuffer name = ByteBufferUtil.bytes(relation.getEntity().getText());
+
+            if (name.equals(realKeyAlias))
+            {
+                // setting found key as an alias
+                keyAlias = relation.getEntity().getText().toUpperCase();
+                keys.add(relation.getValue()); // add a key value to the keys list
+                iter.remove(); // removing it from the columns
+                break;
+            }
+        }
+    }
 }

Modified: cassandra/branches/cassandra-0.8/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/system/test_cql.py?rev=1134502&r1=1134501&r2=1134502&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/system/test_cql.py (original)
+++ cassandra/branches/cassandra-0.8/test/system/test_cql.py Sat Jun 11 01:45:16 2011
@@ -1185,3 +1185,90 @@ class TestCql(ThriftTester):
         assert_raises(cql.ProgrammingError,
                       cursor.execute,
                       "UPDATE CounterCF SET count_me = count_not_me + 2 WHERE key = 'counter1'")
+
+    def test_key_alias_support(self):
+        "should be possible to use alias instead of KEY keyword"
+        cursor = init()
+
+        cursor.execute("""
+               CREATE SCHEMA KeyAliasKeyspace WITH strategy_options:replication_factor =
'1'
+                   AND strategy_class = 'SimpleStrategy';
+        """)
+        cursor.execute("USE KeyAliasKeyspace;")
+
+        # create a Column Family with key alias
+        cursor.execute("""
+            CREATE COLUMNFAMILY KeyAliasCF (
+                'id' varint PRIMARY KEY,
+                'username' text
+            ) WITH comment = 'shiny, new, cf' AND default_validation = ascii;
+        """)
+
+        # TODO: temporary (until this can be done with CQL).
+        ksdef = thrift_client.describe_keyspace("KeyAliasKeyspace")
+        cfdef = ksdef.cf_defs[0]
+
+        assert len(ksdef.cf_defs) == 1, \
+            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        assert cfdef.key_alias == 'id', "expected 'id' alias, got %s" % cfdef.key_alias
+
+        # try do insert/update
+        cursor.execute("INSERT INTO KeyAliasCF (id, username) VALUES (1, jbellis)")
+
+        # check if we actually stored anything
+        cursor.execute("SELECT * FROM KeyAliasCF WHERE id = 1")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+        assert len(colnames) == 2
+
+        r = cursor.fetchone()
+        assert len(r) == 2, "expected 2, got %d" % len(r)
+        assert r[0] == 1
+        assert r[1] == 'jbellis'
+
+        cursor.execute("UPDATE KeyAliasCF SET username = 'xedin' WHERE id = 2")
+
+        # check if we actually stored anything
+        cursor.execute("SELECT * FROM KeyAliasCF WHERE id = 2")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+        colnames = [col_d[0] for col_d in cursor.description]
+        assert len(colnames) == 2
+
+        r = cursor.fetchone()
+        assert len(r) == 2, "expected 2, got %d" % len(r)
+        assert r[0] == 2
+        assert r[1] == 'xedin'
+
+        # delete with key alias
+        cursor.execute("DELETE FROM KeyAliasCF WHERE id = 2")
+        # check if we actually stored anything
+        cursor.execute("SELECT * FROM KeyAliasCF WHERE id = 2")
+        assert cursor.rowcount == 1, "expected 1 results, got %d" % cursor.rowcount
+
+        r = cursor.fetchone()
+        assert len(r) == 1, "expected 1, got %s" % r
+        assert r[0] == 2, "expected id = 2, got %d" % r[0]
+
+        # if alias was set you can't use KEY keyword anymore
+        assert_raises(cql.ProgrammingError,
+                      cursor.execute,
+                      "INSERT INTO KeyAliasCF (KEY, username) VALUES (6, jbellis)")
+
+        assert_raises(cql.ProgrammingError,
+                      cursor.execute,
+                      "UPDATE KeyAliasCF SET username = 'xedin' WHERE KEY = 7")
+
+        assert_raises(cql.ProgrammingError,
+                      cursor.execute,
+                      "DELETE FROM KeyAliasCF WHERE KEY = 2")
+
+        assert_raises(cql.ProgrammingError,
+                      cursor.execute,
+                      "SELECT * FROM KeyAliasCF WHERE KEY = 2")
+
+        assert_raises(cql.ProgrammingError,
+                      cursor.execute,
+                      "SELECT * FROM KeyAliasCF WHERE KEY IN (1, 2)")
+
+        cursor.execute("USE Keyspace1")
+        cursor.execute("DROP KEYSPACE KeyAliasKeyspace")



Mime
View raw message