You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ee...@apache.org on 2011/04/04 22:05:20 UTC

svn commit: r1088766 - in /cassandra/trunk: src/java/org/apache/cassandra/cql/ test/system/

Author: eevans
Date: Mon Apr  4 20:05:19 2011
New Revision: 1088766

URL: http://svn.apache.org/viewvc?rev=1088766&view=rev
Log:
CQL INSERT implementation

Patch by Pavel Yaskevich and eevans for CASSANDRA-2409

Modified:
    cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/StatementType.java
    cassandra/trunk/src/java/org/apache/cassandra/cql/UpdateStatement.java
    cassandra/trunk/test/system/test_cql.py

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g?rev=1088766&r1=1088765&r2=1088766&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/Cql.g Mon Apr  4 20:05:19 2011
@@ -31,6 +31,8 @@ options {
     import java.util.Map;
     import java.util.HashMap;
     import java.util.Collections;
+    import java.util.List;
+    import java.util.ArrayList;
     import org.apache.cassandra.thrift.ConsistencyLevel;
     import org.apache.cassandra.thrift.InvalidRequestException;
 }
@@ -100,6 +102,7 @@ options {
 
 query returns [CQLStatement stmnt]
     : selectStatement   { $stmnt = new CQLStatement(StatementType.SELECT, $selectStatement.expr); }
+    | insertStatement   { $stmnt = new CQLStatement(StatementType.INSERT, $insertStatement.expr); }
     | updateStatement endStmnt { $stmnt = new CQLStatement(StatementType.UPDATE, $updateStatement.expr); }
     | batchUpdateStatement { $stmnt = new CQLStatement(StatementType.BATCH_UPDATE, $batchUpdateStatement.expr); }
     | useStatement      { $stmnt = new CQLStatement(StatementType.USE, $useStatement.keyspace); }
@@ -176,6 +179,36 @@ whereClause returns [WhereClause clause]
     ;
 
 /**
+ * INSERT INTO
+ *    <CF>
+ *    (KEY, <column>, <column>, ...)
+ * VALUES
+ *    (<key>, <value>, <value>, ...)
+ * (USING
+ *    CONSISTENCY <level>)?;
+ *
+ * Consistency level is set to ONE by default
+ */
+insertStatement returns [UpdateStatement expr]
+    : {
+          ConsistencyLevel cLevel = ConsistencyLevel.ONE;
+          Map<Term, Term> columns = new HashMap<Term, Term>();
+
+          List<Term> columnNames  = new ArrayList<Term>();
+          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); } )+ ')'
+        K_VALUES
+          '(' key=term ( ',' column_value=term { columnValues.add($column_value.item); })+ ')'
+        ( K_USING K_CONSISTENCY K_LEVEL { cLevel = ConsistencyLevel.valueOf($K_LEVEL.text); } )?
+      endStmnt
+      {
+          return new UpdateStatement($columnFamily.text, cLevel, columnNames, columnValues, key);
+      }
+    ;
+
+/**
  * BEGIN BATCH [USING CONSISTENCY.<LVL>]
  * UPDATE <CF> SET name1 = value1 WHERE KEY = keyname1;
  * UPDATE <CF> SET name2 = value2 WHERE KEY = keyname2;
@@ -350,6 +383,7 @@ K_WHERE:       W H E R E;
 K_AND:         A N D;
 K_KEY:         K E Y;
 K_COLUMN:      C O L (U M N)?;
+K_INSERT:      I N S E R T;
 K_UPDATE:      U P D A T E;
 K_WITH:        W I T H;
 K_ROW:         R O W;
@@ -381,6 +415,8 @@ K_INDEX:       I N D E X;
 K_ON:          O N;
 K_DROP:        D R O P;
 K_PRIMARY:     P R I M A R Y;
+K_INTO:        I N T O;
+K_VALUES:      V A L U E S;
 
 // Case-insensitive alpha characters
 fragment A: ('a'|'A');

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1088766&r1=1088765&r2=1088766&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/QueryProcessor.java Mon Apr  4 20:05:19 2011
@@ -545,7 +545,8 @@ public class QueryProcessor
                 
                 avroResult.rows = avroRows;
                 return avroResult;
-                
+
+            case INSERT: // insert uses UpdateStatement
             case UPDATE:
                 UpdateStatement update = (UpdateStatement)statement.statement;
                 batchUpdate(clientState, Collections.singletonList(update), update.getConsistencyLevel());

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/StatementType.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/StatementType.java?rev=1088766&r1=1088765&r2=1088766&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/StatementType.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/StatementType.java Mon Apr  4 20:05:19 2011
@@ -24,7 +24,7 @@ import java.util.EnumSet;
 
 public enum StatementType
 {
-    SELECT, UPDATE, BATCH_UPDATE, USE, TRUNCATE, DELETE, CREATE_KEYSPACE, CREATE_COLUMNFAMILY, CREATE_INDEX,
+    SELECT, INSERT, UPDATE, BATCH_UPDATE, USE, TRUNCATE, DELETE, CREATE_KEYSPACE, CREATE_COLUMNFAMILY, CREATE_INDEX,
         DROP_KEYSPACE, DROP_COLUMNFAMILY;
     
     // Statement types that don't require a keyspace to be set.

Modified: cassandra/trunk/src/java/org/apache/cassandra/cql/UpdateStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cql/UpdateStatement.java?rev=1088766&r1=1088765&r2=1088766&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cql/UpdateStatement.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cql/UpdateStatement.java Mon Apr  4 20:05:19 2011
@@ -21,11 +21,14 @@
 package org.apache.cassandra.cql;
 
 import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.thrift.ConsistencyLevel;
+import org.apache.cassandra.thrift.InvalidRequestException;
 
 /**
  * An <code>UPDATE</code> statement parsed from a CQL query statement.
@@ -37,6 +40,7 @@ public class UpdateStatement
     private String columnFamily;
     private ConsistencyLevel cLevel = null;
     private Map<Term, Term> columns;
+    private List<Term> columnNames, columnValues;
     private Term key;
     
     /**
@@ -68,6 +72,26 @@ public class UpdateStatement
     {
         this(columnFamily, null, columns, key);
     }
+    
+    /**
+     * Creates a new UpdateStatement from a column family name, a consistency level,
+     * key, and lists of column names and values.  It is intended for use with the
+     * alternate update format, <code>INSERT</code>.
+     * 
+     * @param columnFamily column family name
+     * @param cLevel the thrift consistency level
+     * @param columnNames list of column names
+     * @param columnValues list of column values (corresponds to names)
+     * @param key the key name
+     */
+    public UpdateStatement(String columnFamily, ConsistencyLevel cLevel, List<Term> columnNames, List<Term> columnValues, Term key)
+    {
+        this.columnFamily = columnFamily;
+        this.cLevel = cLevel;
+        this.columnNames = columnNames;
+        this.columnValues = columnValues;
+        this.key = key;
+    }
 
     /**
      * Returns the consistency level of this <code>UPDATE</code> statement, either
@@ -100,8 +124,25 @@ public class UpdateStatement
         return key;
     }
     
-    public Map<Term, Term> getColumns()
+    public Map<Term, Term> getColumns() throws InvalidRequestException
     {
+        // Created from an UPDATE
+        if (columns != null)
+            return columns;
+        
+        // Created from an INSERT
+        
+        // Don't hate, validate.
+        if (columnNames.size() != columnValues.size())
+            throw new InvalidRequestException("unmatched column names/values");
+        if (columnNames.size() < 1)
+            throw new InvalidRequestException("no columns specified for INSERT");
+        
+        columns = new HashMap<Term, Term>();
+        
+        for (int i = 0; i < columnNames.size(); i++)
+            columns.put(columnNames.get(i), columnValues.get(i));
+        
         return columns;
     }
     

Modified: cassandra/trunk/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/system/test_cql.py?rev=1088766&r1=1088765&r2=1088766&view=diff
==============================================================================
--- cassandra/trunk/test/system/test_cql.py (original)
+++ cassandra/trunk/test/system/test_cql.py Mon Apr  4 20:05:19 2011
@@ -602,3 +602,39 @@ class TestCql(ThriftTester):
         
         # FIXME: The above is woefully inadequate, but the test config uses
         # CollatingOrderPreservingPartitioner which only supports UTF8.
+        
+    def test_write_using_insert(self):
+        "peforming writes using \"insert\""
+        conn = init()
+        conn.execute("INSERT INTO StandardUtf82 (KEY, ?, ?) VALUES (?, ?, ?)",
+                     "pork",
+                     "beef",
+                     "meat",
+                     "bacon",
+                     "brisket")
+        
+        r = conn.execute("SELECT * FROM StandardUtf82 WHERE KEY = ?", "meat")
+        assert r[0][0].name == "beef"
+        assert r[0][0].value == "brisket"
+        assert r[0][1].name == "pork"
+        assert r[0][1].value == "bacon"
+        
+        # Bad writes.
+        
+        # Too many column values
+        assert_raises(CQLException,
+                      conn.execute,
+                      "INSERT INTO StandardUtf82 (KEY, ?) VALUES (?, ?, ?)",
+                      "name1",
+                      "key0",
+                      "value1",
+                      "value2")
+                      
+        # Too many column names, (not enough column values)
+        assert_raises(CQLException,
+                      conn.execute,
+                      "INSERT INTO StandardUtf82 (KEY, ?, ?) VALUES (?, ?)",
+                      "name1",
+                      "name2",
+                      "key0",
+                      "value1")