You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2011/04/17 07:10:18 UTC

svn commit: r1094102 - in /cassandra/branches/cassandra-0.8: ./ drivers/java/src/org/apache/cassandra/cql/jdbc/ drivers/java/test/org/apache/cassandra/cql/ drivers/java/test/org/apache/cassandra/cql/jdbc/ interface/ interface/thrift/gen-java/org/apache...

Author: jbellis
Date: Sun Apr 17 05:10:17 2011
New Revision: 1094102

URL: http://svn.apache.org/viewvc?rev=1094102&view=rev
Log:
preserve column order in CQL result sets
patch by jbellis; reviewed by eevans for CASSANDRA-2493

Modified:
    cassandra/branches/cassandra-0.8/CHANGES.txt
    cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
    cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
    cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
    cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
    cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java
    cassandra/branches/cassandra-0.8/interface/cassandra.thrift
    cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java
    cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Constants.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordWriter.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/CassandraServer.java
    cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/ThriftValidation.java
    cassandra/branches/cassandra-0.8/test/system/test_cql.py
    cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/client/TestRingCache.java
    cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java

Modified: cassandra/branches/cassandra-0.8/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/CHANGES.txt?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8/CHANGES.txt Sun Apr 17 05:10:17 2011
@@ -4,7 +4,7 @@
    (CASSANDRA-1072, 1937, 1944, 1936, 2101, 2093, 2288, 2105, 2384, 2236, 2342,
    2454)
  * CQL (CASSANDRA-1703, 1704, 1705, 1706, 1707, 1708, 1710, 1711, 1940, 
-   2124, 2302, 2277)
+   2124, 2302, 2277, 2493)
  * avoid double RowMutation serialization on write path (CASSANDRA-1800)
  * make NetworkTopologyStrategy the default (CASSANDRA-1960)
  * configurable internode encryption (CASSANDRA-1567, 2152)

Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java Sun Apr 17 05:10:17 2011
@@ -75,11 +75,13 @@ class CassandraResultSet implements Resu
     private List<TypedColumn> values = new ArrayList<TypedColumn>();
     
     /** The value map. */
+    // TODO should map <String, TypedColumn> so we can throw appropriate exception if user asks for non-existant column name
     private Map<String, Object> valueMap = new WeakHashMap<String, Object>();
     
     private final RsMetaData meta;
     
     private final AbstractType nameType;
+    private boolean wasNull;
 
     /**
      * Instantiates a new cassandra result set.
@@ -356,7 +358,11 @@ class CassandraResultSet implements Resu
      */
     public byte[] getBytes(int index) throws SQLException
     {
-        return values.get(index-1) != null ? ((ByteBuffer)values.get(index-1).getValue()).array() : null;
+        TypedColumn column = values.get(index - 1);
+        assert column != null;
+        Object value = column.getValue();
+        wasNull = value == null;
+        return value == null ? null : ((ByteBuffer) value).array();
     }
 
     /**
@@ -367,7 +373,9 @@ class CassandraResultSet implements Resu
     public byte[] getBytes(String name) throws SQLException
     {
         String nameAsString = decoder.colNameAsString(keyspace, columnFamily, name);
-        return valueMap.get(nameAsString) != null ? ((ByteBuffer)valueMap.get(nameAsString)).array() : null;
+        Object value = valueMap.get(nameAsString);
+        wasNull = value == null;
+        return value == null ? null : ((ByteBuffer) value).array();
     }
 
     /**
@@ -544,7 +552,11 @@ class CassandraResultSet implements Resu
      */
     public int getInt(int index) throws SQLException
     {
-        return values.get(index-1) != null ? ((BigInteger)values.get(index-1).getValue()).intValue() : null;
+        TypedColumn column = values.get(index - 1);
+        assert column != null;
+        Object value = column.getValue();
+        wasNull = value == null;
+        return value == null ? 0 : ((BigInteger) value).intValue();
     }
 
     /**
@@ -555,7 +567,9 @@ class CassandraResultSet implements Resu
     public int getInt(String name) throws SQLException
     {
         String nameAsString = decoder.colNameAsString(keyspace, columnFamily, name);
-        return valueMap.get(nameAsString) != null ? ((BigInteger)valueMap.get(nameAsString)).intValue() : null;
+        Object value = valueMap.get(nameAsString);
+        wasNull = value == null;
+        return value == null ? 0 : ((BigInteger) value).intValue();
     }
 
     /**
@@ -565,7 +579,12 @@ class CassandraResultSet implements Resu
      */
     public long getLong(int index) throws SQLException
     {
-        return values.get(index-1) != null ? (Long)values.get(index-1).getValue() : null;
+        assert values != null;
+        TypedColumn column = values.get(index - 1);
+        assert column != null;
+        Object value = column.getValue();
+        wasNull = value == null;
+        return value == null ? 0 : (Long) value;
     }
 
     /**
@@ -576,7 +595,9 @@ class CassandraResultSet implements Resu
     public long getLong(String name) throws SQLException
     {
         String nameAsString = decoder.colNameAsString(keyspace, columnFamily, name);
-        return valueMap.get(nameAsString) != null ? (Long)valueMap.get(nameAsString) : null;
+        Object value = valueMap.get(nameAsString);
+        wasNull = value == null;
+        return value == null ? 0 : (Long) value;
     }
 
     /**
@@ -655,7 +676,11 @@ class CassandraResultSet implements Resu
      */
     public Object getObject(int index) throws SQLException
     {
-        return values.get(index-1) == null ? null : values.get(index-1).getValue();
+        TypedColumn column = values.get(index - 1);
+        assert column != null;
+        Object value = column.getValue();
+        wasNull = value == null;
+        return value;
     }
 
     /**
@@ -666,7 +691,9 @@ class CassandraResultSet implements Resu
     public Object getObject(String name) throws SQLException
     {
         String nameAsString = decoder.colNameAsString(keyspace, columnFamily, name);
-        return valueMap.get(nameAsString);
+        Object value = valueMap.get(nameAsString);
+        wasNull = value == null;
+        return value;
     }
 
     /**
@@ -796,7 +823,11 @@ class CassandraResultSet implements Resu
      */
     public String getString(int index) throws SQLException 
     {
-        return values.get(index-1) != null ? ColumnDecoder.colValueAsString(values.get(index-1).getValue()) : null;
+        TypedColumn column = values.get(index - 1);
+        assert column != null;
+        Object value = column.getValue();
+        wasNull = value == null;
+        return value == null ? null : ColumnDecoder.colValueAsString(value);
     }
 
     /**
@@ -807,7 +838,9 @@ class CassandraResultSet implements Resu
     public String getString(String name) throws SQLException
     {
         String nameAsString = this.decoder.colNameAsString(this.keyspace, this.columnFamily, name);
-        return valueMap.get(nameAsString) != null ? ColumnDecoder.colValueAsString(valueMap.get(nameAsString)) : null;
+        Object value = valueMap.get(nameAsString);
+        wasNull = value == null;
+        return value == null ? null : ColumnDecoder.colValueAsString(value);
     }
 
     /**
@@ -1999,7 +2032,7 @@ class CassandraResultSet implements Resu
      */
     public boolean wasNull() throws SQLException
     {
-        throw new UnsupportedOperationException("method not supported");
+        return wasNull;
     }
     
     /**

Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java Sun Apr 17 05:10:17 2011
@@ -181,7 +181,7 @@ class ColumnDecoder 
         else if (value instanceof byte[])
             return ByteBufferUtil.bytesToHex(ByteBuffer.wrap((byte[])value));
         else
-            return value.toString();
+            return value == null ? null : value.toString();
     }
     
     /** constructs a typed column */

Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java Sun Apr 17 05:10:17 2011
@@ -39,11 +39,11 @@ class TypedColumn<N, V>
     public TypedColumn(AbstractType<N> comparator, byte[] name, AbstractType<V> validator, byte[] value)
     {
         ByteBuffer bbName = ByteBuffer.wrap(name);
-        ByteBuffer bbValue = ByteBuffer.wrap(value);
+        ByteBuffer bbValue = value == null ? null : ByteBuffer.wrap(value);
         this.name = comparator.compose(bbName);
-        this.value = validator.compose(bbValue);
+        this.value = value == null ? null : validator.compose(bbValue);
         nameString = comparator.getString(bbName);
-        valueString = validator.getString(bbValue);
+        valueString = value == null ? null : validator.getString(bbValue);
         this.validator = validator;
     }
     

Modified: cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java Sun Apr 17 05:10:17 2011
@@ -398,8 +398,11 @@ public class JdbcDriverTest extends Embe
         {
             executeNoResults(con, statements[3*i]);
             ResultSet rs = executePreparedStatementWithResults(con, statements[3*i+1]);
-            assert !rs.next() : statements[3*i+1];
+            rs.next();
+            rs.getObject(1);
+            assert rs.wasNull();
             rs.close();
+
             rs = executePreparedStatementWithResults(con, statements[3*i+2]);
             assert rs.next() : statements[3*i+2];
         }

Modified: cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java Sun Apr 17 05:10:17 2011
@@ -80,7 +80,8 @@ public class PreparedStatementTest exten
             stmt.setBytes(2, FBUtilities.toByteArray(i+100));
             stmt.setBytes(3, key);
             ResultSet rs = stmt.executeQuery();
-            assert !rs.next();
+            rs.next();
+            assert rs.getString(1) == null;  assert rs.getString(2) == null;
             rs.close();
         }
     }
@@ -139,7 +140,8 @@ public class PreparedStatementTest exten
             stmt.setString(2, "2\u6543\u3435\u6554");
             stmt.setBytes(3, key);
             ResultSet rs = stmt.executeQuery();
-            assert !rs.next();
+            rs.next();
+            assert rs.getString(1) == null;  assert rs.getString(2) == null;
             rs.close();
         }
     }
@@ -198,7 +200,8 @@ public class PreparedStatementTest exten
             stmt.setString(2, "2");
             stmt.setBytes(3, key);
             ResultSet rs = stmt.executeQuery();
-            assert !rs.next();
+            rs.next();
+            assert rs.getString(1) == null;  assert rs.getString(2) == null;
             rs.close();
         }
     }
@@ -257,7 +260,9 @@ public class PreparedStatementTest exten
             stmt.setLong(2, 2);
             stmt.setBytes(3, key);
             ResultSet rs = stmt.executeQuery();
-            assert !rs.next();
+            rs.next();
+            rs.getLong(1);
+            assert rs.wasNull();
             rs.close();
         }
     }
@@ -316,7 +321,9 @@ public class PreparedStatementTest exten
             stmt.setInt(2, 2);
             stmt.setBytes(3, key);
             ResultSet rs = stmt.executeQuery();
-            assert !rs.next();
+            rs.next();
+            rs.getInt(1);
+            assert rs.wasNull();
             rs.close();
         }
     }

Modified: cassandra/branches/cassandra-0.8/interface/cassandra.thrift
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/interface/cassandra.thrift?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/interface/cassandra.thrift (original)
+++ cassandra/branches/cassandra-0.8/interface/cassandra.thrift Sun Apr 17 05:10:17 2011
@@ -46,7 +46,7 @@ namespace rb CassandraThrift
 #           for every edit that doesn't result in a change to major/minor.
 #
 # See the Semantic Versioning Specification (SemVer) http://semver.org.
-const string VERSION = "20.1.0"
+const string VERSION = "20.2.0"
 
 
 #
@@ -61,8 +61,8 @@ const string VERSION = "20.1.0"
  */
 struct Column {
    1: required binary name,
-   2: required binary value,
-   3: required i64 timestamp,
+   2: optional binary value,
+   3: optional i64 timestamp,
    4: optional i32 ttl,
 }
 

Modified: cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java (original)
+++ cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java Sun Apr 17 05:10:17 2011
@@ -139,9 +139,9 @@ public class Column implements org.apach
     Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
     tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.REQUIRED, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING        , true)));
-    tmpMap.put(_Fields.VALUE, new org.apache.thrift.meta_data.FieldMetaData("value", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+    tmpMap.put(_Fields.VALUE, new org.apache.thrift.meta_data.FieldMetaData("value", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING        , true)));
-    tmpMap.put(_Fields.TIMESTAMP, new org.apache.thrift.meta_data.FieldMetaData("timestamp", org.apache.thrift.TFieldRequirementType.REQUIRED, 
+    tmpMap.put(_Fields.TIMESTAMP, new org.apache.thrift.meta_data.FieldMetaData("timestamp", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
     tmpMap.put(_Fields.TTL, new org.apache.thrift.meta_data.FieldMetaData("ttl", org.apache.thrift.TFieldRequirementType.OPTIONAL, 
         new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
@@ -153,15 +153,10 @@ public class Column implements org.apach
   }
 
   public Column(
-    ByteBuffer name,
-    ByteBuffer value,
-    long timestamp)
+    ByteBuffer name)
   {
     this();
     this.name = name;
-    this.value = value;
-    this.timestamp = timestamp;
-    setTimestampIsSet(true);
   }
 
   /**
@@ -415,8 +410,8 @@ public class Column implements org.apach
         return false;
     }
 
-    boolean this_present_timestamp = true;
-    boolean that_present_timestamp = true;
+    boolean this_present_timestamp = true && this.isSetTimestamp();
+    boolean that_present_timestamp = true && that.isSetTimestamp();
     if (this_present_timestamp || that_present_timestamp) {
       if (!(this_present_timestamp && that_present_timestamp))
         return false;
@@ -450,7 +445,7 @@ public class Column implements org.apach
     if (present_value)
       builder.append(value);
 
-    boolean present_timestamp = true;
+    boolean present_timestamp = true && (isSetTimestamp());
     builder.append(present_timestamp);
     if (present_timestamp)
       builder.append(timestamp);
@@ -566,9 +561,6 @@ public class Column implements org.apach
     iprot.readStructEnd();
 
     // check for required fields of primitive type, which can't be checked in the validate method
-    if (!isSetTimestamp()) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'timestamp' was not found in serialized data! Struct: " + toString());
-    }
     validate();
   }
 
@@ -582,13 +574,17 @@ public class Column implements org.apach
       oprot.writeFieldEnd();
     }
     if (this.value != null) {
-      oprot.writeFieldBegin(VALUE_FIELD_DESC);
-      oprot.writeBinary(this.value);
+      if (isSetValue()) {
+        oprot.writeFieldBegin(VALUE_FIELD_DESC);
+        oprot.writeBinary(this.value);
+        oprot.writeFieldEnd();
+      }
+    }
+    if (isSetTimestamp()) {
+      oprot.writeFieldBegin(TIMESTAMP_FIELD_DESC);
+      oprot.writeI64(this.timestamp);
       oprot.writeFieldEnd();
     }
-    oprot.writeFieldBegin(TIMESTAMP_FIELD_DESC);
-    oprot.writeI64(this.timestamp);
-    oprot.writeFieldEnd();
     if (isSetTtl()) {
       oprot.writeFieldBegin(TTL_FIELD_DESC);
       oprot.writeI32(this.ttl);
@@ -610,18 +606,22 @@ public class Column implements org.apach
       org.apache.thrift.TBaseHelper.toString(this.name, sb);
     }
     first = false;
-    if (!first) sb.append(", ");
-    sb.append("value:");
-    if (this.value == null) {
-      sb.append("null");
-    } else {
-      org.apache.thrift.TBaseHelper.toString(this.value, sb);
+    if (isSetValue()) {
+      if (!first) sb.append(", ");
+      sb.append("value:");
+      if (this.value == null) {
+        sb.append("null");
+      } else {
+        org.apache.thrift.TBaseHelper.toString(this.value, sb);
+      }
+      first = false;
+    }
+    if (isSetTimestamp()) {
+      if (!first) sb.append(", ");
+      sb.append("timestamp:");
+      sb.append(this.timestamp);
+      first = false;
     }
-    first = false;
-    if (!first) sb.append(", ");
-    sb.append("timestamp:");
-    sb.append(this.timestamp);
-    first = false;
     if (isSetTtl()) {
       if (!first) sb.append(", ");
       sb.append("ttl:");
@@ -637,10 +637,6 @@ public class Column implements org.apach
     if (name == null) {
       throw new org.apache.thrift.protocol.TProtocolException("Required field 'name' was not present! Struct: " + toString());
     }
-    if (value == null) {
-      throw new org.apache.thrift.protocol.TProtocolException("Required field 'value' was not present! Struct: " + toString());
-    }
-    // alas, we cannot check 'timestamp' because it's a primitive and you chose the non-beans generator.
   }
 
   private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {

Modified: cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Constants.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Constants.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Constants.java (original)
+++ cassandra/branches/cassandra-0.8/interface/thrift/gen-java/org/apache/cassandra/thrift/Constants.java Sun Apr 17 05:10:17 2011
@@ -44,6 +44,6 @@ import org.slf4j.LoggerFactory;
 
 public class Constants {
 
-  public static final String VERSION = "20.1.0";
+  public static final String VERSION = "20.2.0";
 
 }

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cli/CliClient.java Sun Apr 17 05:10:17 2011
@@ -802,7 +802,7 @@ public class CliClient
         if(superColumnName != null)
             parent.setSuper_column(superColumnName);
 
-        Column columnToInsert = new Column(columnName, columnValueInBytes, FBUtilities.timestampMicros());
+        Column columnToInsert = new Column(columnName).setValue(columnValueInBytes).setTimestamp(FBUtilities.timestampMicros());
         
         // children count = 3 mean that we have ttl in arguments
         if (statement.getChildCount() == 3)

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Cql.g Sun Apr 17 05:10:17 2011
@@ -382,11 +382,9 @@ K_FROM:        F R O M;
 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;
 K_LIMIT:       L I M I T;
 K_USING:       U S I N G;
 K_CONSISTENCY: C O N S I S T E N C Y;

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/QueryProcessor.java Sun Apr 17 05:10:17 2011
@@ -470,12 +470,15 @@ public class QueryProcessor
         CqlResult result = new CqlResult();
         
         logger.debug("CQL statement type: {}", statement.type.toString());
+        CFMetaData metadata;
+        AbstractType<?> comparator;
         switch (statement.type)
         {
             case SELECT:
                 SelectStatement select = (SelectStatement)statement.statement;
                 clientState.hasColumnFamilyAccess(select.getColumnFamily(), Permission.READ);
-                validateColumnFamily(keyspace, select.getColumnFamily(), false);
+                metadata = validateColumnFamily(keyspace, select.getColumnFamily(), false);
+                comparator = metadata.getComparatorFor(null);
                 validateSelect(keyspace, select);
                 
                 List<org.apache.cassandra.db.Row> rows = null;
@@ -519,19 +522,8 @@ public class QueryProcessor
                     /// No results for this row
                     if (row.cf == null)
                         continue;
-                    
-                    List<Column> thriftColumns = new ArrayList<Column>();
-                    for (IColumn column : row.cf.getSortedColumns())
-                    {
-                        if (column.isMarkedForDelete())
-                            continue;
-                        Column c = new Column();
-                        c.name = column.name();
-                        c.value = column.value();
-                        c.timestamp = column.timestamp();
-                        thriftColumns.add(c);
-                    }
-                    
+
+                    List<Column> thriftColumns = extractThriftColumns(select, comparator, row);
                     // Create a new row, add the columns to it, and then add it to the list of rows
                     CqlRow cqlRow = new CqlRow();
                     cqlRow.key = row.key.key;
@@ -592,8 +584,8 @@ public class QueryProcessor
             case DELETE:
                 DeleteStatement delete = (DeleteStatement)statement.statement;
                 clientState.hasColumnFamilyAccess(delete.getColumnFamily(), Permission.WRITE);
-                CFMetaData metadata = validateColumnFamily(keyspace, delete.getColumnFamily(), false);
-                AbstractType<?> comparator = metadata.getComparatorFor(null);
+                metadata = validateColumnFamily(keyspace, delete.getColumnFamily(), false);
+                comparator = metadata.getComparatorFor(null);
                 AbstractType<?> keyType = DatabaseDescriptor.getCFMetaData(keyspace,
                                                                            delete.getColumnFamily()).getKeyValidator();
                 
@@ -792,7 +784,44 @@ public class QueryProcessor
         
         return null;    // We should never get here.
     }
-    
+
+    private static List<Column> extractThriftColumns(SelectStatement select, AbstractType<?> comparator, Row row)
+    {
+        List<Column> thriftColumns = new ArrayList<Column>();
+        if (select.isColumnRange())
+        {
+            // preserve comparator order
+            for (IColumn c : row.cf.getSortedColumns())
+            {
+                if (c.isMarkedForDelete())
+                    continue;
+                thriftColumns.add(new Column(c.name()).setValue(c.value()).setTimestamp(c.timestamp()));
+            }
+        }
+        else
+        {
+            // order columns in the order they were asked for
+            for (Term term : select.getColumnNames())
+            {
+                ByteBuffer name;
+                try
+                {
+                    name = term.getByteBuffer(comparator);
+                }
+                catch (InvalidRequestException e)
+                {
+                    throw new AssertionError(e);
+                }
+                IColumn c = row.cf.getColumn(name);
+                if (c == null || c.isMarkedForDelete())
+                    thriftColumns.add(new Column().setName(name));
+                else
+                    thriftColumns.add(new Column(c.name()).setValue(c.value()).setTimestamp(c.timestamp()));
+            }
+        }
+        return thriftColumns;
+    }
+
     private static CQLStatement getStatement(String queryStr) throws InvalidRequestException, RecognitionException
     {
         // Lexer and parser

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordWriter.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordWriter.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordWriter.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/hadoop/ColumnFamilyRecordWriter.java Sun Apr 17 05:10:17 2011
@@ -206,7 +206,7 @@ implements org.apache.hadoop.mapred.Reco
 
     private Column avroToThrift(org.apache.cassandra.hadoop.avro.Column acol)
     {
-        return new Column(acol.name, acol.value, acol.timestamp);
+        return new Column(acol.name).setValue(acol.value).setTimestamp(acol.timestamp);
     }
 
     /**

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/CassandraServer.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/CassandraServer.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/CassandraServer.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/CassandraServer.java Sun Apr 17 05:10:17 2011
@@ -146,7 +146,7 @@ public class CassandraServer implements 
             {
                 continue;
             }
-            Column thrift_column = new Column(column.name(), column.value(), column.timestamp());
+            Column thrift_column = new Column(column.name()).setValue(column.value()).setTimestamp(column.timestamp());
             if (column instanceof ExpiringColumn)
             {
                 thrift_column.setTtl(((ExpiringColumn) column).getTimeToLive());
@@ -195,7 +195,7 @@ public class CassandraServer implements 
             }
             else
             {
-                Column thrift_column = new Column(column.name(), column.value(), column.timestamp());
+                Column thrift_column = new Column(column.name()).setValue(column.value()).setTimestamp(column.timestamp());
                 if (column instanceof ExpiringColumn)
                 {
                     thrift_column.setTtl(((ExpiringColumn) column).getTimeToLive());

Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/ThriftValidation.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/ThriftValidation.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/ThriftValidation.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/thrift/ThriftValidation.java Sun Apr 17 05:10:17 2011
@@ -379,6 +379,10 @@ public class ThriftValidation
     public static void validateColumnData(CFMetaData metadata, Column column) throws InvalidRequestException
     {
         validateTtl(column);
+        if (!column.isSetValue())
+            throw new InvalidRequestException("Column value is required");
+        if (!column.isSetTimestamp())
+            throw new InvalidRequestException("Column timestamp is required");
         try
         {
             AbstractType validator = metadata.getValueValidator(column.name);

Modified: cassandra/branches/cassandra-0.8/test/system/test_cql.py
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/system/test_cql.py?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/system/test_cql.py (original)
+++ cassandra/branches/cassandra-0.8/test/system/test_cql.py Sun Apr 17 05:10:17 2011
@@ -136,13 +136,16 @@ class TestCql(ThriftTester):
     def test_select_columns(self):
         "retrieve multiple columns"
         cursor = init()
+        # we deliberately request columns in non-comparator order
         cursor.execute("""
-            SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
+            SELECT ca1, col, cd1 FROM StandardString1 WHERE KEY = 'kd'
         """)
 
         d = cursor.description
-        assert "cd1" in [col_dscptn[0] for col_dscptn in d]
-        assert "col" in [col_dscptn[0] for col_dscptn in d]
+        assert ['Row Key', 'ca1', 'col', 'cd1'] == [col_dscptn[0] for col_dscptn in d], d
+        row = cursor.fetchone()
+        # check that the column that didn't exist in the row comes back as null
+        assert ['kd', None, 'val', 'vd1'] == row, row
 
     def test_select_row_range(self):
         "retrieve a range of rows with columns"
@@ -307,9 +310,8 @@ class TestCql(ThriftTester):
         cursor.execute("""
             SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
         """)
-        colnames = [col_d[0] for col_d in cursor.description]
-        assert "cd1" in colnames
-        assert "col" in colnames
+        assert ['Row Key', 'cd1', 'col'] == [col_d[0] for col_d in cursor.description]
+
         cursor.execute("""
             DELETE 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
         """)
@@ -317,7 +319,7 @@ class TestCql(ThriftTester):
             SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
         """)
         r = cursor.fetchone()
-        assert len(r) == 1
+        assert ['kd', None, None] == r, r
 
     def test_delete_columns_multi_rows(self):
         "delete columns from multiple rows"
@@ -325,22 +327,22 @@ class TestCql(ThriftTester):
 
         cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY = 'kc'")
         r = cursor.fetchone()
-        assert  len(r) == 2
+        assert ['kc', 'val'] == r, r
 
         cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY = 'kd'")
         r = cursor.fetchone()
-        assert  len(r) == 2
+        assert ['kd', 'val'] == r, r
 
         cursor.execute("""
             DELETE 'col' FROM StandardString1 WHERE KEY IN ('kc', 'kd')
         """)
         cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY = 'kc'")
         r = cursor.fetchone()
-        assert  len(r) == 1
+        assert ['kc', None] == r, r
 
         cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY = 'kd'")
         r = cursor.fetchone()
-        assert  len(r) == 1
+        assert ['kd', None] == r, r
 
     def test_delete_rows(self):
         "delete entire rows"
@@ -348,15 +350,13 @@ class TestCql(ThriftTester):
         cursor.execute("""
             SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
         """)
-        colnames = [col_d[0] for col_d in cursor.description]
-        assert "cd1" in colnames
-        assert "col" in colnames
+        assert ['Row Key', 'cd1', 'col'] == [col_d[0] for col_d in cursor.description]
         cursor.execute("DELETE FROM StandardString1 WHERE KEY = 'kd'")
         cursor.execute("""
             SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
         """)
         r = cursor.fetchone()
-        assert len(r) == 1
+        assert ['kd', None, None] == r, r
 
     def test_create_keyspace(self):
         "create a new keyspace"

Modified: cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/client/TestRingCache.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/client/TestRingCache.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/client/TestRingCache.java (original)
+++ cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/client/TestRingCache.java Sun Apr 17 05:10:17 2011
@@ -103,7 +103,7 @@ public class TestRingCache
             // now, read the row back directly from the host owning the row locally
             tester.setup(firstEndpoint.getHostAddress(), DatabaseDescriptor.getRpcPort());
             tester.thriftClient.set_keyspace(keyspace);
-            tester.thriftClient.insert(row, parent, new Column(ByteBufferUtil.bytes("col1"), ByteBufferUtil.bytes("val1"), 1), ConsistencyLevel.ONE);
+            tester.thriftClient.insert(row, parent, new Column(ByteBufferUtil.bytes("col1")).setValue(ByteBufferUtil.bytes("val1")).setTimestamp(1), ConsistencyLevel.ONE);
             Column column = tester.thriftClient.get(row, col, ConsistencyLevel.ONE).column;
             System.out.println("read row " + new String(row.array()) + " " + new String(column.name.array()) + ":" + new String(column.value.array()) + ":" + column.timestamp);
         }

Modified: cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java?rev=1094102&r1=1094101&r2=1094102&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java (original)
+++ cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java Sun Apr 17 05:10:17 2011
@@ -84,8 +84,10 @@ public class EmbeddedCassandraServiceTes
         cp.column = ByteBufferUtil.bytes("name");
 
         // insert
-        client.insert(key_user_id, par, new Column(ByteBufferUtil.bytes("name"),
-                      ByteBufferUtil.bytes("Ran"), timestamp), ConsistencyLevel.ONE);
+        client.insert(key_user_id,
+                      par,
+                      new Column(ByteBufferUtil.bytes("name")).setValue(ByteBufferUtil.bytes("Ran")).setTimestamp(timestamp),
+                      ConsistencyLevel.ONE);
 
         // read
         ColumnOrSuperColumn got = client.get(key_user_id, cp, ConsistencyLevel.ONE);