You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2012/01/26 16:26:15 UTC

git commit: Update CqlPreparedResult to provide type information

Updated Branches:
  refs/heads/trunk 0fdab63d3 -> e10eb19e8


Update CqlPreparedResult to provide type information

patch by slebresne; reviewed by jbellis for CASSANDRA-3753


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/e10eb19e
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/e10eb19e
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/e10eb19e

Branch: refs/heads/trunk
Commit: e10eb19e85834aeea4514a968613d41e1dc0d247
Parents: 0fdab63
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Thu Jan 26 16:25:18 2012 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Thu Jan 26 16:25:18 2012 +0100

----------------------------------------------------------------------
 CHANGES.txt                                        |    2 +-
 interface/cassandra.thrift                         |    3 +-
 .../org/apache/cassandra/thrift/Cassandra.java     |  332 +++++++--------
 .../apache/cassandra/thrift/CqlPreparedResult.java |  135 ++++++-
 .../org/apache/cassandra/cql3/CQLStatement.java    |   28 +-
 src/java/org/apache/cassandra/cql3/Cql.g           |    4 +-
 .../org/apache/cassandra/cql3/QueryProcessor.java  |   30 +-
 src/java/org/apache/cassandra/cql3/Term.java       |    8 +-
 .../cassandra/cql3/statements/BatchStatement.java  |   22 +-
 .../cassandra/cql3/statements/CFStatement.java     |    2 +-
 .../statements/CreateColumnFamilyStatement.java    |    6 +-
 .../cassandra/cql3/statements/DeleteStatement.java |   16 +-
 .../cql3/statements/ModificationStatement.java     |    2 +-
 .../cassandra/cql3/statements/ParsedStatement.java |   68 +++
 .../cassandra/cql3/statements/Preprocessable.java  |   27 --
 .../cql3/statements/SchemaAlteringStatement.java   |    9 +-
 .../cassandra/cql3/statements/SelectStatement.java |   51 ++-
 .../cql3/statements/TruncateStatement.java         |    7 +-
 .../cassandra/cql3/statements/UpdateStatement.java |   71 ++--
 .../cassandra/cql3/statements/UseStatement.java    |   11 +-
 20 files changed, 531 insertions(+), 303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 96d41de..77e88f7 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -56,7 +56,7 @@
  * Add SnapshotCommand to trigger snapshot on remote node (CASSANDRA-3721)
  * Make CFMetaData conversions to/from thrift/native schema inverses
    (CASSANDRA_3559)
- * Add initial code for CQL 3.0-beta (CASSANDRA-3781)
+ * Add initial code for CQL 3.0-beta (CASSANDRA-3781, 3753)
  * Add wide row support for ColumnFamilyInputFormat (CASSANDRA-3264)
  * Allow extending CompositeType comparator (CASSANDRA-3657)
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/interface/cassandra.thrift
----------------------------------------------------------------------
diff --git a/interface/cassandra.thrift b/interface/cassandra.thrift
index 211c4c8..99e7d1c 100644
--- a/interface/cassandra.thrift
+++ b/interface/cassandra.thrift
@@ -466,7 +466,8 @@ struct CqlResult {
 
 struct CqlPreparedResult {
     1: required i32 itemId,
-    2: required i32 count
+    2: required i32 count,
+    3: optional list<string> variable_types
 }
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
----------------------------------------------------------------------
diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
index 406429b..5b79e18 100644
--- a/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
+++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
@@ -7176,14 +7176,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list91 = iprot.readListBegin();
-                this.success = new ArrayList<ColumnOrSuperColumn>(_list91.size);
-                for (int _i92 = 0; _i92 < _list91.size; ++_i92)
+                org.apache.thrift.protocol.TList _list95 = iprot.readListBegin();
+                this.success = new ArrayList<ColumnOrSuperColumn>(_list95.size);
+                for (int _i96 = 0; _i96 < _list95.size; ++_i96)
                 {
-                  ColumnOrSuperColumn _elem93; // required
-                  _elem93 = new ColumnOrSuperColumn();
-                  _elem93.read(iprot);
-                  this.success.add(_elem93);
+                  ColumnOrSuperColumn _elem97; // required
+                  _elem97 = new ColumnOrSuperColumn();
+                  _elem97.read(iprot);
+                  this.success.add(_elem97);
                 }
                 iprot.readListEnd();
               }
@@ -7233,9 +7233,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (ColumnOrSuperColumn _iter94 : this.success)
+          for (ColumnOrSuperColumn _iter98 : this.success)
           {
-            _iter94.write(oprot);
+            _iter98.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -8526,8 +8526,6 @@ public class Cassandra {
 
     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
       try {
-        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
-        __isset_bit_vector = new BitSet(1);
         read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
       } catch (org.apache.thrift.TException te) {
         throw new java.io.IOException(te);
@@ -9037,13 +9035,13 @@ public class Cassandra {
           case 1: // KEYS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list95 = iprot.readListBegin();
-                this.keys = new ArrayList<ByteBuffer>(_list95.size);
-                for (int _i96 = 0; _i96 < _list95.size; ++_i96)
+                org.apache.thrift.protocol.TList _list99 = iprot.readListBegin();
+                this.keys = new ArrayList<ByteBuffer>(_list99.size);
+                for (int _i100 = 0; _i100 < _list99.size; ++_i100)
                 {
-                  ByteBuffer _elem97; // required
-                  _elem97 = iprot.readBinary();
-                  this.keys.add(_elem97);
+                  ByteBuffer _elem101; // required
+                  _elem101 = iprot.readBinary();
+                  this.keys.add(_elem101);
                 }
                 iprot.readListEnd();
               }
@@ -9093,9 +9091,9 @@ public class Cassandra {
         oprot.writeFieldBegin(KEYS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.keys.size()));
-          for (ByteBuffer _iter98 : this.keys)
+          for (ByteBuffer _iter102 : this.keys)
           {
-            oprot.writeBinary(_iter98);
+            oprot.writeBinary(_iter102);
           }
           oprot.writeListEnd();
         }
@@ -9684,26 +9682,26 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map99 = iprot.readMapBegin();
-                this.success = new HashMap<ByteBuffer,List<ColumnOrSuperColumn>>(2*_map99.size);
-                for (int _i100 = 0; _i100 < _map99.size; ++_i100)
+                org.apache.thrift.protocol.TMap _map103 = iprot.readMapBegin();
+                this.success = new HashMap<ByteBuffer,List<ColumnOrSuperColumn>>(2*_map103.size);
+                for (int _i104 = 0; _i104 < _map103.size; ++_i104)
                 {
-                  ByteBuffer _key101; // required
-                  List<ColumnOrSuperColumn> _val102; // required
-                  _key101 = iprot.readBinary();
+                  ByteBuffer _key105; // required
+                  List<ColumnOrSuperColumn> _val106; // required
+                  _key105 = iprot.readBinary();
                   {
-                    org.apache.thrift.protocol.TList _list103 = iprot.readListBegin();
-                    _val102 = new ArrayList<ColumnOrSuperColumn>(_list103.size);
-                    for (int _i104 = 0; _i104 < _list103.size; ++_i104)
+                    org.apache.thrift.protocol.TList _list107 = iprot.readListBegin();
+                    _val106 = new ArrayList<ColumnOrSuperColumn>(_list107.size);
+                    for (int _i108 = 0; _i108 < _list107.size; ++_i108)
                     {
-                      ColumnOrSuperColumn _elem105; // required
-                      _elem105 = new ColumnOrSuperColumn();
-                      _elem105.read(iprot);
-                      _val102.add(_elem105);
+                      ColumnOrSuperColumn _elem109; // required
+                      _elem109 = new ColumnOrSuperColumn();
+                      _elem109.read(iprot);
+                      _val106.add(_elem109);
                     }
                     iprot.readListEnd();
                   }
-                  this.success.put(_key101, _val102);
+                  this.success.put(_key105, _val106);
                 }
                 iprot.readMapEnd();
               }
@@ -9753,14 +9751,14 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.LIST, this.success.size()));
-          for (Map.Entry<ByteBuffer, List<ColumnOrSuperColumn>> _iter106 : this.success.entrySet())
+          for (Map.Entry<ByteBuffer, List<ColumnOrSuperColumn>> _iter110 : this.success.entrySet())
           {
-            oprot.writeBinary(_iter106.getKey());
+            oprot.writeBinary(_iter110.getKey());
             {
-              oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, _iter106.getValue().size()));
-              for (ColumnOrSuperColumn _iter107 : _iter106.getValue())
+              oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, _iter110.getValue().size()));
+              for (ColumnOrSuperColumn _iter111 : _iter110.getValue())
               {
-                _iter107.write(oprot);
+                _iter111.write(oprot);
               }
               oprot.writeListEnd();
             }
@@ -10348,13 +10346,13 @@ public class Cassandra {
           case 1: // KEYS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list108 = iprot.readListBegin();
-                this.keys = new ArrayList<ByteBuffer>(_list108.size);
-                for (int _i109 = 0; _i109 < _list108.size; ++_i109)
+                org.apache.thrift.protocol.TList _list112 = iprot.readListBegin();
+                this.keys = new ArrayList<ByteBuffer>(_list112.size);
+                for (int _i113 = 0; _i113 < _list112.size; ++_i113)
                 {
-                  ByteBuffer _elem110; // required
-                  _elem110 = iprot.readBinary();
-                  this.keys.add(_elem110);
+                  ByteBuffer _elem114; // required
+                  _elem114 = iprot.readBinary();
+                  this.keys.add(_elem114);
                 }
                 iprot.readListEnd();
               }
@@ -10404,9 +10402,9 @@ public class Cassandra {
         oprot.writeFieldBegin(KEYS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.keys.size()));
-          for (ByteBuffer _iter111 : this.keys)
+          for (ByteBuffer _iter115 : this.keys)
           {
-            oprot.writeBinary(_iter111);
+            oprot.writeBinary(_iter115);
           }
           oprot.writeListEnd();
         }
@@ -10991,15 +10989,15 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map112 = iprot.readMapBegin();
-                this.success = new HashMap<ByteBuffer,Integer>(2*_map112.size);
-                for (int _i113 = 0; _i113 < _map112.size; ++_i113)
+                org.apache.thrift.protocol.TMap _map116 = iprot.readMapBegin();
+                this.success = new HashMap<ByteBuffer,Integer>(2*_map116.size);
+                for (int _i117 = 0; _i117 < _map116.size; ++_i117)
                 {
-                  ByteBuffer _key114; // required
-                  int _val115; // required
-                  _key114 = iprot.readBinary();
-                  _val115 = iprot.readI32();
-                  this.success.put(_key114, _val115);
+                  ByteBuffer _key118; // required
+                  int _val119; // required
+                  _key118 = iprot.readBinary();
+                  _val119 = iprot.readI32();
+                  this.success.put(_key118, _val119);
                 }
                 iprot.readMapEnd();
               }
@@ -11049,10 +11047,10 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.I32, this.success.size()));
-          for (Map.Entry<ByteBuffer, Integer> _iter116 : this.success.entrySet())
+          for (Map.Entry<ByteBuffer, Integer> _iter120 : this.success.entrySet())
           {
-            oprot.writeBinary(_iter116.getKey());
-            oprot.writeI32(_iter116.getValue());
+            oprot.writeBinary(_iter120.getKey());
+            oprot.writeI32(_iter120.getValue());
           }
           oprot.writeMapEnd();
         }
@@ -12236,14 +12234,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list117 = iprot.readListBegin();
-                this.success = new ArrayList<KeySlice>(_list117.size);
-                for (int _i118 = 0; _i118 < _list117.size; ++_i118)
+                org.apache.thrift.protocol.TList _list121 = iprot.readListBegin();
+                this.success = new ArrayList<KeySlice>(_list121.size);
+                for (int _i122 = 0; _i122 < _list121.size; ++_i122)
                 {
-                  KeySlice _elem119; // required
-                  _elem119 = new KeySlice();
-                  _elem119.read(iprot);
-                  this.success.add(_elem119);
+                  KeySlice _elem123; // required
+                  _elem123 = new KeySlice();
+                  _elem123.read(iprot);
+                  this.success.add(_elem123);
                 }
                 iprot.readListEnd();
               }
@@ -12293,9 +12291,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (KeySlice _iter120 : this.success)
+          for (KeySlice _iter124 : this.success)
           {
-            _iter120.write(oprot);
+            _iter124.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -13488,14 +13486,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list121 = iprot.readListBegin();
-                this.success = new ArrayList<KeySlice>(_list121.size);
-                for (int _i122 = 0; _i122 < _list121.size; ++_i122)
+                org.apache.thrift.protocol.TList _list125 = iprot.readListBegin();
+                this.success = new ArrayList<KeySlice>(_list125.size);
+                for (int _i126 = 0; _i126 < _list125.size; ++_i126)
                 {
-                  KeySlice _elem123; // required
-                  _elem123 = new KeySlice();
-                  _elem123.read(iprot);
-                  this.success.add(_elem123);
+                  KeySlice _elem127; // required
+                  _elem127 = new KeySlice();
+                  _elem127.read(iprot);
+                  this.success.add(_elem127);
                 }
                 iprot.readListEnd();
               }
@@ -13545,9 +13543,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (KeySlice _iter124 : this.success)
+          for (KeySlice _iter128 : this.success)
           {
-            _iter124.write(oprot);
+            _iter128.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -14731,14 +14729,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list125 = iprot.readListBegin();
-                this.success = new ArrayList<KeySlice>(_list125.size);
-                for (int _i126 = 0; _i126 < _list125.size; ++_i126)
+                org.apache.thrift.protocol.TList _list129 = iprot.readListBegin();
+                this.success = new ArrayList<KeySlice>(_list129.size);
+                for (int _i130 = 0; _i130 < _list129.size; ++_i130)
                 {
-                  KeySlice _elem127; // required
-                  _elem127 = new KeySlice();
-                  _elem127.read(iprot);
-                  this.success.add(_elem127);
+                  KeySlice _elem131; // required
+                  _elem131 = new KeySlice();
+                  _elem131.read(iprot);
+                  this.success.add(_elem131);
                 }
                 iprot.readListEnd();
               }
@@ -14788,9 +14786,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (KeySlice _iter128 : this.success)
+          for (KeySlice _iter132 : this.success)
           {
-            _iter128.write(oprot);
+            _iter132.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -17735,8 +17733,6 @@ public class Cassandra {
 
     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
       try {
-        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
-        __isset_bit_vector = new BitSet(1);
         read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
       } catch (org.apache.thrift.TException te) {
         throw new java.io.IOException(te);
@@ -19635,38 +19631,38 @@ public class Cassandra {
           case 1: // MUTATION_MAP
             if (field.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map129 = iprot.readMapBegin();
-                this.mutation_map = new HashMap<ByteBuffer,Map<String,List<Mutation>>>(2*_map129.size);
-                for (int _i130 = 0; _i130 < _map129.size; ++_i130)
+                org.apache.thrift.protocol.TMap _map133 = iprot.readMapBegin();
+                this.mutation_map = new HashMap<ByteBuffer,Map<String,List<Mutation>>>(2*_map133.size);
+                for (int _i134 = 0; _i134 < _map133.size; ++_i134)
                 {
-                  ByteBuffer _key131; // required
-                  Map<String,List<Mutation>> _val132; // required
-                  _key131 = iprot.readBinary();
+                  ByteBuffer _key135; // required
+                  Map<String,List<Mutation>> _val136; // required
+                  _key135 = iprot.readBinary();
                   {
-                    org.apache.thrift.protocol.TMap _map133 = iprot.readMapBegin();
-                    _val132 = new HashMap<String,List<Mutation>>(2*_map133.size);
-                    for (int _i134 = 0; _i134 < _map133.size; ++_i134)
+                    org.apache.thrift.protocol.TMap _map137 = iprot.readMapBegin();
+                    _val136 = new HashMap<String,List<Mutation>>(2*_map137.size);
+                    for (int _i138 = 0; _i138 < _map137.size; ++_i138)
                     {
-                      String _key135; // required
-                      List<Mutation> _val136; // required
-                      _key135 = iprot.readString();
+                      String _key139; // required
+                      List<Mutation> _val140; // required
+                      _key139 = iprot.readString();
                       {
-                        org.apache.thrift.protocol.TList _list137 = iprot.readListBegin();
-                        _val136 = new ArrayList<Mutation>(_list137.size);
-                        for (int _i138 = 0; _i138 < _list137.size; ++_i138)
+                        org.apache.thrift.protocol.TList _list141 = iprot.readListBegin();
+                        _val140 = new ArrayList<Mutation>(_list141.size);
+                        for (int _i142 = 0; _i142 < _list141.size; ++_i142)
                         {
-                          Mutation _elem139; // required
-                          _elem139 = new Mutation();
-                          _elem139.read(iprot);
-                          _val136.add(_elem139);
+                          Mutation _elem143; // required
+                          _elem143 = new Mutation();
+                          _elem143.read(iprot);
+                          _val140.add(_elem143);
                         }
                         iprot.readListEnd();
                       }
-                      _val132.put(_key135, _val136);
+                      _val136.put(_key139, _val140);
                     }
                     iprot.readMapEnd();
                   }
-                  this.mutation_map.put(_key131, _val132);
+                  this.mutation_map.put(_key135, _val136);
                 }
                 iprot.readMapEnd();
               }
@@ -19700,19 +19696,19 @@ public class Cassandra {
         oprot.writeFieldBegin(MUTATION_MAP_FIELD_DESC);
         {
           oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.MAP, this.mutation_map.size()));
-          for (Map.Entry<ByteBuffer, Map<String,List<Mutation>>> _iter140 : this.mutation_map.entrySet())
+          for (Map.Entry<ByteBuffer, Map<String,List<Mutation>>> _iter144 : this.mutation_map.entrySet())
           {
-            oprot.writeBinary(_iter140.getKey());
+            oprot.writeBinary(_iter144.getKey());
             {
-              oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.LIST, _iter140.getValue().size()));
-              for (Map.Entry<String, List<Mutation>> _iter141 : _iter140.getValue().entrySet())
+              oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.LIST, _iter144.getValue().size()));
+              for (Map.Entry<String, List<Mutation>> _iter145 : _iter144.getValue().entrySet())
               {
-                oprot.writeString(_iter141.getKey());
+                oprot.writeString(_iter145.getKey());
                 {
-                  oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, _iter141.getValue().size()));
-                  for (Mutation _iter142 : _iter141.getValue())
+                  oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, _iter145.getValue().size()));
+                  for (Mutation _iter146 : _iter145.getValue())
                   {
-                    _iter142.write(oprot);
+                    _iter146.write(oprot);
                   }
                   oprot.writeListEnd();
                 }
@@ -21621,25 +21617,25 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.MAP) {
               {
-                org.apache.thrift.protocol.TMap _map143 = iprot.readMapBegin();
-                this.success = new HashMap<String,List<String>>(2*_map143.size);
-                for (int _i144 = 0; _i144 < _map143.size; ++_i144)
+                org.apache.thrift.protocol.TMap _map147 = iprot.readMapBegin();
+                this.success = new HashMap<String,List<String>>(2*_map147.size);
+                for (int _i148 = 0; _i148 < _map147.size; ++_i148)
                 {
-                  String _key145; // required
-                  List<String> _val146; // required
-                  _key145 = iprot.readString();
+                  String _key149; // required
+                  List<String> _val150; // required
+                  _key149 = iprot.readString();
                   {
-                    org.apache.thrift.protocol.TList _list147 = iprot.readListBegin();
-                    _val146 = new ArrayList<String>(_list147.size);
-                    for (int _i148 = 0; _i148 < _list147.size; ++_i148)
+                    org.apache.thrift.protocol.TList _list151 = iprot.readListBegin();
+                    _val150 = new ArrayList<String>(_list151.size);
+                    for (int _i152 = 0; _i152 < _list151.size; ++_i152)
                     {
-                      String _elem149; // required
-                      _elem149 = iprot.readString();
-                      _val146.add(_elem149);
+                      String _elem153; // required
+                      _elem153 = iprot.readString();
+                      _val150.add(_elem153);
                     }
                     iprot.readListEnd();
                   }
-                  this.success.put(_key145, _val146);
+                  this.success.put(_key149, _val150);
                 }
                 iprot.readMapEnd();
               }
@@ -21673,14 +21669,14 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.LIST, this.success.size()));
-          for (Map.Entry<String, List<String>> _iter150 : this.success.entrySet())
+          for (Map.Entry<String, List<String>> _iter154 : this.success.entrySet())
           {
-            oprot.writeString(_iter150.getKey());
+            oprot.writeString(_iter154.getKey());
             {
-              oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, _iter150.getValue().size()));
-              for (String _iter151 : _iter150.getValue())
+              oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, _iter154.getValue().size()));
+              for (String _iter155 : _iter154.getValue())
               {
-                oprot.writeString(_iter151);
+                oprot.writeString(_iter155);
               }
               oprot.writeListEnd();
             }
@@ -22279,14 +22275,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list152 = iprot.readListBegin();
-                this.success = new ArrayList<KsDef>(_list152.size);
-                for (int _i153 = 0; _i153 < _list152.size; ++_i153)
+                org.apache.thrift.protocol.TList _list156 = iprot.readListBegin();
+                this.success = new ArrayList<KsDef>(_list156.size);
+                for (int _i157 = 0; _i157 < _list156.size; ++_i157)
                 {
-                  KsDef _elem154; // required
-                  _elem154 = new KsDef();
-                  _elem154.read(iprot);
-                  this.success.add(_elem154);
+                  KsDef _elem158; // required
+                  _elem158 = new KsDef();
+                  _elem158.read(iprot);
+                  this.success.add(_elem158);
                 }
                 iprot.readListEnd();
               }
@@ -22320,9 +22316,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (KsDef _iter155 : this.success)
+          for (KsDef _iter159 : this.success)
           {
-            _iter155.write(oprot);
+            _iter159.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -24035,14 +24031,14 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list156 = iprot.readListBegin();
-                this.success = new ArrayList<TokenRange>(_list156.size);
-                for (int _i157 = 0; _i157 < _list156.size; ++_i157)
+                org.apache.thrift.protocol.TList _list160 = iprot.readListBegin();
+                this.success = new ArrayList<TokenRange>(_list160.size);
+                for (int _i161 = 0; _i161 < _list160.size; ++_i161)
                 {
-                  TokenRange _elem158; // required
-                  _elem158 = new TokenRange();
-                  _elem158.read(iprot);
-                  this.success.add(_elem158);
+                  TokenRange _elem162; // required
+                  _elem162 = new TokenRange();
+                  _elem162.read(iprot);
+                  this.success.add(_elem162);
                 }
                 iprot.readListEnd();
               }
@@ -24076,9 +24072,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, this.success.size()));
-          for (TokenRange _iter159 : this.success)
+          for (TokenRange _iter163 : this.success)
           {
-            _iter159.write(oprot);
+            _iter163.write(oprot);
           }
           oprot.writeListEnd();
         }
@@ -26540,6 +26536,8 @@ public class Cassandra {
 
     private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
       try {
+        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+        __isset_bit_vector = new BitSet(1);
         read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
       } catch (org.apache.thrift.TException te) {
         throw new java.io.IOException(te);
@@ -26880,13 +26878,13 @@ public class Cassandra {
           case 0: // SUCCESS
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list160 = iprot.readListBegin();
-                this.success = new ArrayList<String>(_list160.size);
-                for (int _i161 = 0; _i161 < _list160.size; ++_i161)
+                org.apache.thrift.protocol.TList _list164 = iprot.readListBegin();
+                this.success = new ArrayList<String>(_list164.size);
+                for (int _i165 = 0; _i165 < _list164.size; ++_i165)
                 {
-                  String _elem162; // required
-                  _elem162 = iprot.readString();
-                  this.success.add(_elem162);
+                  String _elem166; // required
+                  _elem166 = iprot.readString();
+                  this.success.add(_elem166);
                 }
                 iprot.readListEnd();
               }
@@ -26920,9 +26918,9 @@ public class Cassandra {
         oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.success.size()));
-          for (String _iter163 : this.success)
+          for (String _iter167 : this.success)
           {
-            oprot.writeString(_iter163);
+            oprot.writeString(_iter167);
           }
           oprot.writeListEnd();
         }
@@ -34059,13 +34057,13 @@ public class Cassandra {
           case 2: // VALUES
             if (field.type == org.apache.thrift.protocol.TType.LIST) {
               {
-                org.apache.thrift.protocol.TList _list164 = iprot.readListBegin();
-                this.values = new ArrayList<ByteBuffer>(_list164.size);
-                for (int _i165 = 0; _i165 < _list164.size; ++_i165)
+                org.apache.thrift.protocol.TList _list168 = iprot.readListBegin();
+                this.values = new ArrayList<ByteBuffer>(_list168.size);
+                for (int _i169 = 0; _i169 < _list168.size; ++_i169)
                 {
-                  ByteBuffer _elem166; // required
-                  _elem166 = iprot.readBinary();
-                  this.values.add(_elem166);
+                  ByteBuffer _elem170; // required
+                  _elem170 = iprot.readBinary();
+                  this.values.add(_elem170);
                 }
                 iprot.readListEnd();
               }
@@ -34098,9 +34096,9 @@ public class Cassandra {
         oprot.writeFieldBegin(VALUES_FIELD_DESC);
         {
           oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.values.size()));
-          for (ByteBuffer _iter167 : this.values)
+          for (ByteBuffer _iter171 : this.values)
           {
-            oprot.writeBinary(_iter167);
+            oprot.writeBinary(_iter171);
           }
           oprot.writeListEnd();
         }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/interface/thrift/gen-java/org/apache/cassandra/thrift/CqlPreparedResult.java
----------------------------------------------------------------------
diff --git a/interface/thrift/gen-java/org/apache/cassandra/thrift/CqlPreparedResult.java b/interface/thrift/gen-java/org/apache/cassandra/thrift/CqlPreparedResult.java
index 122449c..7c67083 100644
--- a/interface/thrift/gen-java/org/apache/cassandra/thrift/CqlPreparedResult.java
+++ b/interface/thrift/gen-java/org/apache/cassandra/thrift/CqlPreparedResult.java
@@ -47,14 +47,17 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
 
   private static final org.apache.thrift.protocol.TField ITEM_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("itemId", org.apache.thrift.protocol.TType.I32, (short)1);
   private static final org.apache.thrift.protocol.TField COUNT_FIELD_DESC = new org.apache.thrift.protocol.TField("count", org.apache.thrift.protocol.TType.I32, (short)2);
+  private static final org.apache.thrift.protocol.TField VARIABLE_TYPES_FIELD_DESC = new org.apache.thrift.protocol.TField("variable_types", org.apache.thrift.protocol.TType.LIST, (short)3);
 
   public int itemId; // required
   public int count; // required
+  public List<String> variable_types; // required
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements org.apache.thrift.TFieldIdEnum {
     ITEM_ID((short)1, "itemId"),
-    COUNT((short)2, "count");
+    COUNT((short)2, "count"),
+    VARIABLE_TYPES((short)3, "variable_types");
 
     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
 
@@ -73,6 +76,8 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
           return ITEM_ID;
         case 2: // COUNT
           return COUNT;
+        case 3: // VARIABLE_TYPES
+          return VARIABLE_TYPES;
         default:
           return null;
       }
@@ -124,6 +129,9 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
     tmpMap.put(_Fields.COUNT, new org.apache.thrift.meta_data.FieldMetaData("count", org.apache.thrift.TFieldRequirementType.REQUIRED, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+    tmpMap.put(_Fields.VARIABLE_TYPES, new org.apache.thrift.meta_data.FieldMetaData("variable_types", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
+        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
     metaDataMap = Collections.unmodifiableMap(tmpMap);
     org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(CqlPreparedResult.class, metaDataMap);
   }
@@ -150,6 +158,13 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     __isset_bit_vector.or(other.__isset_bit_vector);
     this.itemId = other.itemId;
     this.count = other.count;
+    if (other.isSetVariable_types()) {
+      List<String> __this__variable_types = new ArrayList<String>();
+      for (String other_element : other.variable_types) {
+        __this__variable_types.add(other_element);
+      }
+      this.variable_types = __this__variable_types;
+    }
   }
 
   public CqlPreparedResult deepCopy() {
@@ -162,6 +177,7 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     this.itemId = 0;
     setCountIsSet(false);
     this.count = 0;
+    this.variable_types = null;
   }
 
   public int getItemId() {
@@ -210,6 +226,45 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     __isset_bit_vector.set(__COUNT_ISSET_ID, value);
   }
 
+  public int getVariable_typesSize() {
+    return (this.variable_types == null) ? 0 : this.variable_types.size();
+  }
+
+  public java.util.Iterator<String> getVariable_typesIterator() {
+    return (this.variable_types == null) ? null : this.variable_types.iterator();
+  }
+
+  public void addToVariable_types(String elem) {
+    if (this.variable_types == null) {
+      this.variable_types = new ArrayList<String>();
+    }
+    this.variable_types.add(elem);
+  }
+
+  public List<String> getVariable_types() {
+    return this.variable_types;
+  }
+
+  public CqlPreparedResult setVariable_types(List<String> variable_types) {
+    this.variable_types = variable_types;
+    return this;
+  }
+
+  public void unsetVariable_types() {
+    this.variable_types = null;
+  }
+
+  /** Returns true if field variable_types is set (has been assigned a value) and false otherwise */
+  public boolean isSetVariable_types() {
+    return this.variable_types != null;
+  }
+
+  public void setVariable_typesIsSet(boolean value) {
+    if (!value) {
+      this.variable_types = null;
+    }
+  }
+
   public void setFieldValue(_Fields field, Object value) {
     switch (field) {
     case ITEM_ID:
@@ -228,6 +283,14 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
       }
       break;
 
+    case VARIABLE_TYPES:
+      if (value == null) {
+        unsetVariable_types();
+      } else {
+        setVariable_types((List<String>)value);
+      }
+      break;
+
     }
   }
 
@@ -239,6 +302,9 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     case COUNT:
       return Integer.valueOf(getCount());
 
+    case VARIABLE_TYPES:
+      return getVariable_types();
+
     }
     throw new IllegalStateException();
   }
@@ -254,6 +320,8 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
       return isSetItemId();
     case COUNT:
       return isSetCount();
+    case VARIABLE_TYPES:
+      return isSetVariable_types();
     }
     throw new IllegalStateException();
   }
@@ -289,6 +357,15 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
         return false;
     }
 
+    boolean this_present_variable_types = true && this.isSetVariable_types();
+    boolean that_present_variable_types = true && that.isSetVariable_types();
+    if (this_present_variable_types || that_present_variable_types) {
+      if (!(this_present_variable_types && that_present_variable_types))
+        return false;
+      if (!this.variable_types.equals(that.variable_types))
+        return false;
+    }
+
     return true;
   }
 
@@ -306,6 +383,11 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     if (present_count)
       builder.append(count);
 
+    boolean present_variable_types = true && (isSetVariable_types());
+    builder.append(present_variable_types);
+    if (present_variable_types)
+      builder.append(variable_types);
+
     return builder.toHashCode();
   }
 
@@ -337,6 +419,16 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
         return lastComparison;
       }
     }
+    lastComparison = Boolean.valueOf(isSetVariable_types()).compareTo(typedOther.isSetVariable_types());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetVariable_types()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.variable_types, typedOther.variable_types);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     return 0;
   }
 
@@ -370,6 +462,23 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
             org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
           }
           break;
+        case 3: // VARIABLE_TYPES
+          if (field.type == org.apache.thrift.protocol.TType.LIST) {
+            {
+              org.apache.thrift.protocol.TList _list91 = iprot.readListBegin();
+              this.variable_types = new ArrayList<String>(_list91.size);
+              for (int _i92 = 0; _i92 < _list91.size; ++_i92)
+              {
+                String _elem93; // required
+                _elem93 = iprot.readString();
+                this.variable_types.add(_elem93);
+              }
+              iprot.readListEnd();
+            }
+          } else { 
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
         default:
           org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
       }
@@ -397,6 +506,20 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     oprot.writeFieldBegin(COUNT_FIELD_DESC);
     oprot.writeI32(this.count);
     oprot.writeFieldEnd();
+    if (this.variable_types != null) {
+      if (isSetVariable_types()) {
+        oprot.writeFieldBegin(VARIABLE_TYPES_FIELD_DESC);
+        {
+          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.variable_types.size()));
+          for (String _iter94 : this.variable_types)
+          {
+            oprot.writeString(_iter94);
+          }
+          oprot.writeListEnd();
+        }
+        oprot.writeFieldEnd();
+      }
+    }
     oprot.writeFieldStop();
     oprot.writeStructEnd();
   }
@@ -413,6 +536,16 @@ public class CqlPreparedResult implements org.apache.thrift.TBase<CqlPreparedRes
     sb.append("count:");
     sb.append(this.count);
     first = false;
+    if (isSetVariable_types()) {
+      if (!first) sb.append(", ");
+      sb.append("variable_types:");
+      if (this.variable_types == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.variable_types);
+      }
+      first = false;
+    }
     sb.append(")");
     return sb.toString();
   }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/CQLStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQLStatement.java b/src/java/org/apache/cassandra/cql3/CQLStatement.java
index 90277c0..49963dd 100644
--- a/src/java/org/apache/cassandra/cql3/CQLStatement.java
+++ b/src/java/org/apache/cassandra/cql3/CQLStatement.java
@@ -19,36 +19,31 @@
 package org.apache.cassandra.cql3;
 
 import java.nio.ByteBuffer;
+import java.util.Collections;
 import java.util.List;
 
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.CqlResult;
 import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.cassandra.thrift.SchemaDisagreementException;
 import org.apache.cassandra.thrift.TimedOutException;
 import org.apache.cassandra.thrift.UnavailableException;
+import org.apache.cassandra.utils.Pair;
 
-public abstract class CQLStatement
+public interface CQLStatement
 {
-    private int boundTerms;
-
-    public int getBoundsTerms()
-    {
-        return boundTerms;
-    }
-
-    // Used by the parser and preparable statement
-    public void setBoundTerms(int boundTerms)
-    {
-        this.boundTerms = boundTerms;
-    }
+    /**
+     * Returns the number of bound terms in this statement.
+     */
+    public int getBoundsTerms();
 
     /**
      * Perform any access verification necessary for the statement.
      *
      * @param state the current client state
      */
-    public abstract void checkAccess(ClientState state) throws InvalidRequestException;
+    public void checkAccess(ClientState state) throws InvalidRequestException;
 
     /**
      * Perform additional validation required by the statment.
@@ -56,8 +51,7 @@ public abstract class CQLStatement
      *
      * @param state the current client state
      */
-    public void validate(ClientState state) throws InvalidRequestException, SchemaDisagreementException
-    {}
+    public void validate(ClientState state) throws InvalidRequestException, SchemaDisagreementException;
 
     /**
      * Execute the statement and return the resulting result or null if there is no result.
@@ -66,5 +60,5 @@ public abstract class CQLStatement
      * @param variables the values for bounded variables. The implementation
      * can assume that each bound term have a corresponding value.
      */
-    public abstract CqlResult execute(ClientState state, List<ByteBuffer> variables) throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException;
+    public CqlResult execute(ClientState state, List<ByteBuffer> variables) throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException;
 }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/Cql.g
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Cql.g b/src/java/org/apache/cassandra/cql3/Cql.g
index 2ccfc5a..4c9cfe4 100644
--- a/src/java/org/apache/cassandra/cql3/Cql.g
+++ b/src/java/org/apache/cassandra/cql3/Cql.g
@@ -115,11 +115,11 @@ options {
 
 /** STATEMENTS **/
 
-query returns [CQLStatement stmnt]
+query returns [ParsedStatement stmnt]
     : st=cqlStatement (';')* EOF { $stmnt = st; }
     ;
 
-cqlStatement returns [CQLStatement stmt]
+cqlStatement returns [ParsedStatement stmt]
     @after{ if (stmt != null) stmt.setBoundTerms(currentBindMarkerIdx + 1); }
     : st1= selectStatement             { $stmt = st1; }
     | st2= insertStatement             { $stmt = st2; }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/QueryProcessor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index 7c82616..4413d80 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -31,6 +31,7 @@ import org.apache.cassandra.cql3.statements.*;
 import org.apache.cassandra.config.*;
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.TypeParser;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.*;
 import org.apache.cassandra.thrift.Column;
@@ -122,7 +123,7 @@ public class QueryProcessor
     throws RecognitionException, UnavailableException, InvalidRequestException, TimedOutException, SchemaDisagreementException
     {
         logger.trace("CQL QUERY: {}", queryString);
-        return processStatement(getStatement(queryString, clientState), clientState, Collections.<ByteBuffer>emptyList());
+        return processStatement(getStatement(queryString, clientState).statement, clientState, Collections.<ByteBuffer>emptyList());
     }
 
     public static CqlPreparedResult prepare(String queryString, ClientState clientState)
@@ -130,16 +131,18 @@ public class QueryProcessor
     {
         logger.trace("CQL QUERY: {}", queryString);
 
-        CQLStatement statement = getStatement(queryString, clientState);
+        ParsedStatement.Prepared prepared = getStatement(queryString, clientState);
         int statementId = makeStatementId(queryString);
-        logger.trace("Discovered "+ statement.getBoundsTerms() + " bound variables.");
-
-        clientState.getCQL3Prepared().put(statementId, statement);
+        clientState.getCQL3Prepared().put(statementId, prepared.statement);
         logger.trace(String.format("Stored prepared statement #%d with %d bind markers",
                                    statementId,
-                                   statement.getBoundsTerms()));
+                                   prepared.statement.getBoundsTerms()));
 
-        return new CqlPreparedResult(statementId, statement.getBoundsTerms());
+        assert prepared.statement.getBoundsTerms() == prepared.boundTypes.size();
+        List<String> types = new ArrayList<String>(prepared.boundTypes.size());
+        for (AbstractType<?> t : prepared.boundTypes)
+            types.add(TypeParser.getShortName(t));
+        return new CqlPreparedResult(statementId, types.size()).setVariable_types(types);
     }
 
     public static CqlResult processPrepared(CQLStatement statement, ClientState clientState, List<ByteBuffer> variables)
@@ -169,21 +172,18 @@ public class QueryProcessor
         return cql.hashCode();
     }
 
-    private static CQLStatement getStatement(String queryStr, ClientState clientState) throws InvalidRequestException, RecognitionException
+    private static ParsedStatement.Prepared getStatement(String queryStr, ClientState clientState) throws InvalidRequestException, RecognitionException
     {
-        CQLStatement statement = parseStatement(queryStr);
+        ParsedStatement statement = parseStatement(queryStr);
 
         // Set keyspace for statement that require login
         if (statement instanceof CFStatement)
             ((CFStatement)statement).prepareKeyspace(clientState);
 
-        if (statement instanceof Preprocessable)
-            statement = ((Preprocessable)statement).preprocess();
-
-        return statement;
+        return statement.prepare();
     }
 
-    private static CQLStatement parseStatement(String queryStr) throws InvalidRequestException, RecognitionException
+    private static ParsedStatement parseStatement(String queryStr) throws InvalidRequestException, RecognitionException
     {
         // Lexer and parser
         CharStream stream = new ANTLRStringStream(queryStr);
@@ -192,7 +192,7 @@ public class QueryProcessor
         CqlParser parser = new CqlParser(tokenStream);
 
         // Parse the query string to a statement instance
-        CQLStatement statement = parser.query();
+        ParsedStatement statement = parser.query();
 
         // The lexer and parser queue up any errors they may have encountered
         // along the way, if necessary, we turn them into exceptions here.

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/Term.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/Term.java b/src/java/org/apache/cassandra/cql3/Term.java
index 8648012..07e1625 100644
--- a/src/java/org/apache/cassandra/cql3/Term.java
+++ b/src/java/org/apache/cassandra/cql3/Term.java
@@ -34,12 +34,13 @@ public class Term
 {
     private final String text;
     private final TermType type;
-    private int bindIndex = -1;
+    public final int bindIndex;
 
     public Term(String text, TermType type)
     {
         this.text = text == null ? "" : text;
         this.type = type;
+        this.bindIndex = -1;
     }
 
     /**
@@ -51,7 +52,7 @@ public class Term
      */
     public Term(String text, int type)
     {
-        this(text == null ? "" : text, TermType.forInt(type));
+        this(text, TermType.forInt(type));
     }
 
     public Term(long value, TermType type)
@@ -61,7 +62,8 @@ public class Term
 
     public Term(String text, int type, int index)
     {
-        this(text, type);
+        this.text = text == null ? "" : text;
+        this.type = TermType.forInt(type);
         this.bindIndex = index;
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
index 077d76d..208d629 100644
--- a/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/BatchStatement.java
@@ -19,18 +19,14 @@
 package org.apache.cassandra.cql3.statements;
 
 import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.cql3.*;
 import org.apache.cassandra.db.IMutation;
 import org.apache.cassandra.db.RowMutation;
 import org.apache.cassandra.db.CounterMutation;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.cassandra.thrift.RequestType;
@@ -81,7 +77,6 @@ public class BatchStatement extends ModificationStatement
         }
     }
 
-    @Override
     public void validate(ClientState state) throws InvalidRequestException
     {
         if (getTimeToLive() != 0)
@@ -105,7 +100,6 @@ public class BatchStatement extends ModificationStatement
     public List<IMutation> getMutations(ClientState clientState, List<ByteBuffer> variables)
     throws InvalidRequestException
     {
-
         Map<Pair<String, ByteBuffer>, RowAndCounterMutation> mutations = new HashMap<Pair<String, ByteBuffer>, RowAndCounterMutation>();
         for (ModificationStatement statement : statements)
         {
@@ -153,6 +147,18 @@ public class BatchStatement extends ModificationStatement
         return batch;
     }
 
+    public ParsedStatement.Prepared prepare() throws InvalidRequestException
+    {
+        List<AbstractType<?>> boundTypes = new ArrayList<AbstractType<?>>();
+        // XXX: we use our knowledge that Modification don't create new
+        // statement upon call to prepare()
+        for (ModificationStatement statement : statements)
+        {
+            boundTypes.addAll(statement.prepare().boundTypes);
+        }
+        return new ParsedStatement.Prepared(this, boundTypes);
+    }
+
     public String toString()
     {
         return String.format("BatchStatement(statements=%s, consistency=%s)", statements, cLevel);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CFStatement.java b/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
index 15e88d7..1ea68ec 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CFStatement.java
@@ -26,7 +26,7 @@ import org.apache.cassandra.thrift.InvalidRequestException;
 /**
  * Abstract class for statements that apply on a given column family.
  */
-public abstract class CFStatement extends CQLStatement
+public abstract class CFStatement extends ParsedStatement
 {
     protected final CFName cfName;
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
index f652a77..48f4c61 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateColumnFamilyStatement.java
@@ -137,7 +137,7 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement
         return newCFMD;
     }
 
-    public static class RawStatement extends CFStatement implements Preprocessable
+    public static class RawStatement extends CFStatement
     {
         private final Map<ColumnIdentifier, String> definitions = new HashMap<ColumnIdentifier, String>();
         private final CFPropDefs properties = new CFPropDefs();
@@ -156,7 +156,7 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement
         /**
          * Transform this raw statement into a CreateColumnFamilyStatement.
          */
-        public CreateColumnFamilyStatement preprocess() throws InvalidRequestException
+        public ParsedStatement.Prepared prepare() throws InvalidRequestException
         {
             try
             {
@@ -238,7 +238,7 @@ public class CreateColumnFamilyStatement extends SchemaAlteringStatement
                     stmt.defaultValidator = CFDefinition.definitionType;
                 }
 
-                return stmt;
+                return new ParsedStatement.Prepared(stmt);
             }
             catch (ConfigurationException e)
             {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
index 25ae4c5..702ca5b 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DeleteStatement.java
@@ -20,6 +20,7 @@ package org.apache.cassandra.cql3.statements;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.HashMap;
@@ -31,6 +32,7 @@ import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.db.IMutation;
 import org.apache.cassandra.db.RowMutation;
 import org.apache.cassandra.db.filter.QueryPath;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.cassandra.thrift.ThriftValidation;
@@ -40,6 +42,7 @@ import org.apache.cassandra.thrift.ThriftValidation;
  */
 public class DeleteStatement extends ModificationStatement
 {
+    private CFDefinition cfDef;
     private final List<ColumnIdentifier> columns;
     private final List<Relation> whereClause;
 
@@ -55,11 +58,6 @@ public class DeleteStatement extends ModificationStatement
 
     public List<IMutation> getMutations(ClientState clientState, List<ByteBuffer> variables) throws InvalidRequestException
     {
-        clientState.hasColumnFamilyAccess(columnFamily(), Permission.WRITE);
-        CFMetaData metadata = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
-        CFDefinition cfDef = metadata.getCfDef();
-
-        preprocess(cfDef);
 
         // Check key
         List<Term> keys = processedKeys.get(cfDef.key.name);
@@ -148,9 +146,13 @@ public class DeleteStatement extends ModificationStatement
         return rm;
     }
 
-    private void preprocess(CFDefinition cfDef) throws InvalidRequestException
+    public ParsedStatement.Prepared prepare() throws InvalidRequestException
     {
-        UpdateStatement.processKeys(cfDef, whereClause, processedKeys);
+        CFMetaData metadata = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
+        cfDef = metadata.getCfDef();
+        AbstractType[] types = new AbstractType[getBoundsTerms()];
+        UpdateStatement.processKeys(cfDef, whereClause, processedKeys, types);
+        return new ParsedStatement.Prepared(this, Arrays.<AbstractType<?>>asList(types));
     }
 
     public String toString()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
index c21f5ac..c56bf02 100644
--- a/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/ModificationStatement.java
@@ -38,7 +38,7 @@ import org.apache.cassandra.thrift.UnavailableException;
 /**
  * Abstract class for statements that apply on a given column family.
  */
-public abstract class ModificationStatement extends CFStatement
+public abstract class ModificationStatement extends CFStatement implements CQLStatement
 {
     public static final ConsistencyLevel defaultConsistency = ConsistencyLevel.ONE;
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java b/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
new file mode 100644
index 0000000..74905dc
--- /dev/null
+++ b/src/java/org/apache/cassandra/cql3/statements/ParsedStatement.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cassandra.cql3.statements;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cassandra.cql3.*;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.service.ClientState;
+import org.apache.cassandra.thrift.CqlResult;
+import org.apache.cassandra.thrift.InvalidRequestException;
+import org.apache.cassandra.thrift.SchemaDisagreementException;
+import org.apache.cassandra.thrift.TimedOutException;
+import org.apache.cassandra.thrift.UnavailableException;
+import org.apache.cassandra.utils.Pair;
+
+public abstract class ParsedStatement
+{
+    private int boundTerms;
+
+    public int getBoundsTerms()
+    {
+        return boundTerms;
+    }
+
+    // Used by the parser and preparable statement
+    public void setBoundTerms(int boundTerms)
+    {
+        this.boundTerms = boundTerms;
+    }
+
+    public abstract Prepared prepare() throws InvalidRequestException;
+
+    public static class Prepared
+    {
+        public final CQLStatement statement;
+        public final List<AbstractType<?>> boundTypes;
+
+        public Prepared(CQLStatement statement, List<AbstractType<?>> boundTypes)
+        {
+            this.statement = statement;
+            this.boundTypes = boundTypes;
+        }
+
+        public Prepared(CQLStatement statement)
+        {
+            this(statement, Collections.<AbstractType<?>>emptyList());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/Preprocessable.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/Preprocessable.java b/src/java/org/apache/cassandra/cql3/statements/Preprocessable.java
deleted file mode 100644
index 5b5bb2e..0000000
--- a/src/java/org/apache/cassandra/cql3/statements/Preprocessable.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.cassandra.cql3.statements;
-
-import org.apache.cassandra.cql3.CQLStatement;
-import org.apache.cassandra.thrift.InvalidRequestException;
-
-public interface Preprocessable
-{
-    public CQLStatement preprocess() throws InvalidRequestException;
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/SchemaAlteringStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SchemaAlteringStatement.java b/src/java/org/apache/cassandra/cql3/statements/SchemaAlteringStatement.java
index 6142488..573d0eb 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SchemaAlteringStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SchemaAlteringStatement.java
@@ -20,12 +20,14 @@ package org.apache.cassandra.cql3.statements;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 
+import org.apache.cassandra.cql3.CQLStatement;
 import org.apache.cassandra.auth.Permission;
 import org.apache.cassandra.db.migration.*;
 import org.apache.cassandra.concurrent.Stage;
@@ -45,7 +47,7 @@ import com.google.common.collect.Maps;
 /**
  * Abstract class for statements that alter the schema.
  */
-public abstract class SchemaAlteringStatement extends CFStatement
+public abstract class SchemaAlteringStatement extends CFStatement implements CQLStatement
 {
     private static final long timeLimitForSchemaAgreement = 10 * 1000;
 
@@ -70,6 +72,11 @@ public abstract class SchemaAlteringStatement extends CFStatement
             super.prepareKeyspace(state);
     }
 
+    public Prepared prepare() throws InvalidRequestException
+    {
+        return new Prepared(this);
+    }
+
     public abstract Migration getMigration() throws InvalidRequestException, IOException, ConfigurationException;
 
     public void checkAccess(ClientState state) throws InvalidRequestException

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
index a468350..4eaf72a 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -40,6 +40,7 @@ import org.apache.cassandra.db.SliceFromReadCommand;
 import org.apache.cassandra.db.Table;
 import org.apache.cassandra.db.context.CounterContext;
 import org.apache.cassandra.db.filter.QueryPath;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.CompositeType;
 import org.apache.cassandra.db.marshal.TypeParser;
 import org.apache.cassandra.dht.AbstractBounds;
@@ -75,28 +76,40 @@ import org.apache.cassandra.utils.Pair;
  * column family, expression, result count, and ordering clause.
  *
  */
-public class SelectStatement extends CQLStatement
+public class SelectStatement implements CQLStatement
 {
     private static final Logger logger = LoggerFactory.getLogger(SelectStatement.class);
     private final static ByteBuffer countColumn = ByteBufferUtil.bytes("count");
 
+    private final int boundTerms;
     public final CFDefinition cfDef;
     public final Parameters parameters;
     private final List<Pair<CFDefinition.Name, ColumnIdentifier>> selectedNames = new ArrayList<Pair<CFDefinition.Name, ColumnIdentifier>>(); // empty => wildcard
     private final Map<ColumnIdentifier, Restriction> restrictions = new HashMap<ColumnIdentifier, Restriction>();
     private boolean hasIndexedExpression;
 
-    public SelectStatement(CFDefinition cfDef, Parameters parameters)
+    public SelectStatement(CFDefinition cfDef, int boundTerms, Parameters parameters)
     {
         this.cfDef = cfDef;
+        this.boundTerms = boundTerms;
         this.parameters = parameters;
     }
 
+    public int getBoundsTerms()
+    {
+        return boundTerms;
+    }
+
     public void checkAccess(ClientState state) throws InvalidRequestException
     {
         state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.READ);
     }
 
+    public void validate(ClientState state) throws InvalidRequestException
+    {
+        // Nothing to do, all validation has been done by RawStatement.prepare()
+    }
+
     public CqlResult execute(ClientState state, List<ByteBuffer> variables) throws InvalidRequestException, UnavailableException, TimedOutException
     {
         List<Row> rows;
@@ -719,7 +732,7 @@ public class SelectStatement extends CQLStatement
         return new CqlRow(key, thriftColumns);
     }
 
-    public static class RawStatement extends CFStatement implements Preprocessable
+    public static class RawStatement extends CFStatement
     {
         private final Parameters parameters;
         private final List<ColumnIdentifier> selectClause;
@@ -733,7 +746,7 @@ public class SelectStatement extends CQLStatement
             this.whereClause = whereClause == null ? Collections.<Relation>emptyList() : whereClause;
         }
 
-        public SelectStatement preprocess() throws InvalidRequestException
+        public ParsedStatement.Prepared prepare() throws InvalidRequestException
         {
             CFMetaData cfm = ThriftValidation.validateColumnFamily(keyspace(), columnFamily());
             ThriftValidation.validateConsistencyLevel(keyspace(), parameters.consistencyLevel, RequestType.READ);
@@ -742,8 +755,8 @@ public class SelectStatement extends CQLStatement
                 throw new InvalidRequestException("LIMIT must be strictly positive");
 
             CFDefinition cfDef = cfm.getCfDef();
-            SelectStatement stmt = new SelectStatement(cfDef, parameters);
-            stmt.setBoundTerms(getBoundsTerms());
+            SelectStatement stmt = new SelectStatement(cfDef, getBoundsTerms(), parameters);
+            AbstractType[] types = new AbstractType[getBoundsTerms()];
 
             // Select clause
             if (parameters.isCount)
@@ -783,6 +796,19 @@ public class SelectStatement extends CQLStatement
                 if (name.kind == CFDefinition.Name.Kind.VALUE_ALIAS)
                     throw new InvalidRequestException(String.format("Restricting the value of a compact CF (%s) is not supported", name.name));
 
+                if (rel.operator() == Relation.Type.IN)
+                {
+                    for (Term value : rel.getInValues())
+                        if (value.isBindMarker())
+                            types[value.bindIndex] = name.type;
+                }
+                else
+                {
+                    Term value = rel.getValue();
+                    if (value.isBindMarker())
+                        types[value.bindIndex] = name.type;
+                }
+
                 Restriction restriction = stmt.restrictions.get(name.name);
                 switch (rel.operator())
                 {
@@ -902,7 +928,8 @@ public class SelectStatement extends CQLStatement
                 if (r == null || !r.isEquality())
                     throw new InvalidRequestException("Descending order is only supported is the first part of the PRIMARY KEY is restricted by an Equal or a IN");
             }
-            return stmt;
+
+            return new ParsedStatement.Prepared(stmt, Arrays.<AbstractType<?>>asList(types));
         }
 
         @Override
@@ -916,16 +943,6 @@ public class SelectStatement extends CQLStatement
                     parameters.consistencyLevel,
                     parameters.limit);
         }
-
-        public void checkAccess(ClientState state)
-        {
-            throw new UnsupportedOperationException();
-        }
-
-        public CqlResult execute(ClientState state, List<ByteBuffer> variables)
-        {
-            throw new UnsupportedOperationException();
-        }
     }
 
     // A rather raw class that simplify validation and query for select

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java b/src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java
index d4c19c7..ca37dae 100644
--- a/src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/TruncateStatement.java
@@ -32,13 +32,18 @@ import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.cassandra.thrift.ThriftValidation;
 import org.apache.cassandra.thrift.UnavailableException;
 
-public class TruncateStatement extends CFStatement
+public class TruncateStatement extends CFStatement implements CQLStatement
 {
     public TruncateStatement(CFName name)
     {
         super(name);
     }
 
+    public Prepared prepare() throws InvalidRequestException
+    {
+        return new Prepared(this);
+    }
+
     public void checkAccess(ClientState state) throws InvalidRequestException
     {
         state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.WRITE);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
index 14fed1b..584af58 100644
--- a/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/UpdateStatement.java
@@ -27,6 +27,7 @@ import org.apache.cassandra.db.CounterMutation;
 import org.apache.cassandra.db.IMutation;
 import org.apache.cassandra.db.RowMutation;
 import org.apache.cassandra.db.filter.QueryPath;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.db.marshal.LongType;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.InvalidRequestException;
@@ -43,6 +44,7 @@ import static org.apache.cassandra.thrift.ThriftValidation.validateCommutativeFo
  */
 public class UpdateStatement extends ModificationStatement
 {
+    private CFDefinition cfDef;
     private final Map<ColumnIdentifier, Operation> columns;
     private final List<ColumnIdentifier> columnNames;
     private final List<Term> columnValues;
@@ -101,29 +103,6 @@ public class UpdateStatement extends ModificationStatement
     /** {@inheritDoc} */
     public List<IMutation> getMutations(ClientState clientState, List<ByteBuffer> variables) throws InvalidRequestException
     {
-        boolean hasCommutativeOperation = false;
-
-        if (columns != null)
-        {
-            for (Map.Entry<ColumnIdentifier, Operation> column : columns.entrySet())
-            {
-                if (!column.getValue().isUnary())
-                    hasCommutativeOperation = true;
-
-                if (hasCommutativeOperation && column.getValue().isUnary())
-                    throw new InvalidRequestException("Mix of commutative and non-commutative operations is not allowed.");
-            }
-
-        }
-
-        // Deal here with the keyspace overwrite thingy to avoid mistake
-        CFMetaData metadata = validateColumnFamily(keyspace(), columnFamily(), hasCommutativeOperation);
-        if (hasCommutativeOperation)
-            validateCommutativeForWrite(metadata, cLevel);
-
-        CFDefinition cfDef = metadata.getCfDef();
-        preprocess(cfDef);
-
         // Check key
         List<Term> keys = processedKeys.get(cfDef.key.name);
         if (keys == null || keys.isEmpty())
@@ -254,8 +233,30 @@ public class UpdateStatement extends ModificationStatement
         }
     }
 
-    private void preprocess(CFDefinition cfDef) throws InvalidRequestException
+    public ParsedStatement.Prepared prepare() throws InvalidRequestException
     {
+        boolean hasCommutativeOperation = false;
+        AbstractType[] types = new AbstractType[getBoundsTerms()];
+
+        if (columns != null)
+        {
+            for (Map.Entry<ColumnIdentifier, Operation> column : columns.entrySet())
+            {
+                if (!column.getValue().isUnary())
+                    hasCommutativeOperation = true;
+
+                if (hasCommutativeOperation && column.getValue().isUnary())
+                    throw new InvalidRequestException("Mix of commutative and non-commutative operations is not allowed.");
+            }
+        }
+
+        // Deal here with the keyspace overwrite thingy to avoid mistake
+        CFMetaData metadata = validateColumnFamily(keyspace(), columnFamily(), hasCommutativeOperation);
+        if (hasCommutativeOperation)
+            validateCommutativeForWrite(metadata, cLevel);
+
+        cfDef = metadata.getCfDef();
+
         if (columns == null)
         {
             // Created from an INSERT
@@ -271,19 +272,23 @@ public class UpdateStatement extends ModificationStatement
                 if (name == null)
                     throw new InvalidRequestException(String.format("Unknown identifier %s", columnNames.get(i)));
 
+                Term value = columnValues.get(i);
+                if (value.isBindMarker())
+                    types[value.bindIndex] = name.type;
+
                 switch (name.kind)
                 {
                     case KEY_ALIAS:
                     case COLUMN_ALIAS:
                         if (processedKeys.containsKey(name.name))
                             throw new InvalidRequestException(String.format("Multiple definition found for PRIMARY KEY part %s", name));
-                        processedKeys.put(name.name, Collections.singletonList(columnValues.get(i)));
+                        processedKeys.put(name.name, Collections.singletonList(value));
                         break;
                     case VALUE_ALIAS:
                     case COLUMN_METADATA:
                         if (processedColumns.containsKey(name.name))
                             throw new InvalidRequestException(String.format("Multiple definition found for column %s", name));
-                        processedColumns.put(name.name, new Operation(columnValues.get(i)));
+                        processedColumns.put(name.name, new Operation(value));
                         break;
                 }
             }
@@ -306,16 +311,21 @@ public class UpdateStatement extends ModificationStatement
                     case COLUMN_METADATA:
                         if (processedColumns.containsKey(name.name))
                             throw new InvalidRequestException(String.format("Multiple definition found for column %s", name));
-                        processedColumns.put(name.name, entry.getValue());
+                        Operation op = entry.getValue();
+                        if (op.value.isBindMarker())
+                            types[op.value.bindIndex] = name.type;
+                        processedColumns.put(name.name, op);
                         break;
                 }
             }
-            processKeys(cfDef, whereClause, processedKeys);
+            processKeys(cfDef, whereClause, processedKeys, types);
         }
+
+        return new ParsedStatement.Prepared(this, Arrays.<AbstractType<?>>asList(types));
     }
 
     // Reused by DeleteStatement
-    static void processKeys(CFDefinition cfDef, List<Relation> keys, Map<ColumnIdentifier, List<Term>> processed) throws InvalidRequestException
+    static void processKeys(CFDefinition cfDef, List<Relation> keys, Map<ColumnIdentifier, List<Term>> processed, AbstractType[] types) throws InvalidRequestException
     {
         for (Relation rel : keys)
         {
@@ -337,6 +347,9 @@ public class UpdateStatement extends ModificationStatement
 
                     if (processed.containsKey(name.name))
                         throw new InvalidRequestException(String.format("Multiple definition found for PRIMARY KEY part %s", name));
+                    for (Term value : values)
+                        if (value.isBindMarker())
+                            types[value.bindIndex] = name.type;
                     processed.put(name.name, values);
                     break;
                 case VALUE_ALIAS:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/e10eb19e/src/java/org/apache/cassandra/cql3/statements/UseStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/UseStatement.java b/src/java/org/apache/cassandra/cql3/statements/UseStatement.java
index 6a63c2a..c8b3ef6 100644
--- a/src/java/org/apache/cassandra/cql3/statements/UseStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/UseStatement.java
@@ -26,7 +26,7 @@ import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.thrift.CqlResult;
 import org.apache.cassandra.thrift.InvalidRequestException;
 
-public class UseStatement extends CQLStatement
+public class UseStatement extends ParsedStatement implements CQLStatement
 {
     private final String keyspace;
 
@@ -35,11 +35,20 @@ public class UseStatement extends CQLStatement
         this.keyspace = keyspace;
     }
 
+    public Prepared prepare() throws InvalidRequestException
+    {
+        return new Prepared(this);
+    }
+
     public void checkAccess(ClientState state)
     {
         // No specific access
     }
 
+    public void validate(ClientState state) throws InvalidRequestException
+    {
+    }
+
     public CqlResult execute(ClientState state, List<ByteBuffer> variables) throws InvalidRequestException
     {
         state.setKeyspace(keyspace);