Author: jbellis
Date: Mon May 9 21:40:27 2011
New Revision: 1101234
URL: http://svn.apache.org/viewvc?rev=1101234&view=rev
Log:
add CQL TTL support
patch by pyaskevich; reviewed by jbellis for CASSANDRA-2476
Added:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Attributes.java
Modified:
cassandra/branches/cassandra-0.8.1/CHANGES.txt
cassandra/branches/cassandra-0.8.1/doc/cql/CQL.textile
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/AbstractModification.java
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/BatchStatement.java
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Cql.g
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/DeleteStatement.java
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/QueryProcessor.java
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/UpdateStatement.java
cassandra/branches/cassandra-0.8.1/test/system/test_cql.py
Modified: cassandra/branches/cassandra-0.8.1/CHANGES.txt
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/CHANGES.txt?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8.1/CHANGES.txt Mon May 9 21:40:27 2011
@@ -1,12 +1,15 @@
1.0-dev
+
+
+0.8.1
* add support for insert, delete in cql BATCH (CASSANDRA-2537)
* add support for IN to cql SELECT, UPDATE (CASSANDRA-2553)
* add timestamp support to cql INSERT, UPDATE, and BATCH (CASSANDRA-2555)
-
-0.8.1
* add support for comparator parameters and a generic ReverseType
(CASSANDRA-2355)
* add CompositeType and DynamicCompositeType (CASSANDRA-2231)
+ * add CQL TTL support (CASSANDRA-2476)
+
0.8.0-?
* faster flushes and compaction from fixing excessively pessimistic
Modified: cassandra/branches/cassandra-0.8.1/doc/cql/CQL.textile
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/doc/cql/CQL.textile?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/doc/cql/CQL.textile (original)
+++ cassandra/branches/cassandra-0.8.1/doc/cql/CQL.textile Mon May 9 21:40:27
2011
@@ -74,7 +74,7 @@ h2. INSERT
_Synopsis:_
bc.
-INSERT INTO <COLUMN FAMILY> (KEY, <col>, <col>, ...) VALUES (<key>, <val>,
<val>, ...) [USING CONSISTENCY <LEVEL> [AND TIMESTAMP <timestamp>]];
+INSERT INTO <COLUMN FAMILY> (KEY, <col>, <col>, ...) VALUES (<key>, <val>,
<val>, ...) [USING CONSISTENCY <LEVEL> [AND TIMESTAMP <timestamp>] [AND TTL
<timeToLive>]];
An @INSERT@ is used to write one or more columns to a record in a Cassandra
column family. No results are returned.
@@ -85,7 +85,7 @@ h2. UPDATE
_Synopsis:_
bc.
-UPDATE <COLUMN FAMILY> [USING <CONSISTENCY> [AND TIMESTAMP <timestamp>]]
+UPDATE <COLUMN FAMILY> [USING <CONSISTENCY> [AND TIMESTAMP <timestamp>] [AND
TTL <timeToLive>]]
SET name1 = value1, name2 = value2 WHERE KEY = keyname;
An @UPDATE@ is used to write one or more columns to a record in a Cassandra
column family. No results are returned.
@@ -111,6 +111,13 @@ UPDATE ... [USING TIMESTAMP <timestamp>]
@UPDATE@ supports setting client-supplied optional timestamp for modification.
+h3. TTL
+
+bc.
+UPDATE ... [USING TTL <timeToLive>] ...
+
+@UPDATE@ supports setting time to live (TTL) for each of the columns in
@UPDATE@ statement.
+
h3. Specifying Columns and Row
bc.
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/AbstractModification.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/AbstractModification.java?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/AbstractModification.java
(original)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/AbstractModification.java
Mon May 9 21:40:27 2011
@@ -33,17 +33,19 @@ public abstract class AbstractModificati
protected final String columnFamily;
protected final ConsistencyLevel cLevel;
protected final Long timestamp;
+ protected final int timeToLive;
- public AbstractModification(String columnFamily, ConsistencyLevel cLevel)
+ public AbstractModification(String columnFamily, Attributes attrs)
{
- this(columnFamily, cLevel, null);
+ this(columnFamily, attrs.getConsistencyLevel(), attrs.getTimestamp(),
attrs.getTimeToLive());
}
- public AbstractModification(String columnFamily, ConsistencyLevel cLevel,
Long timestamp)
+ public AbstractModification(String columnFamily, ConsistencyLevel cLevel,
Long timestamp, int timeToLive)
{
this.columnFamily = columnFamily;
this.cLevel = cLevel;
this.timestamp = timestamp;
+ this.timeToLive = timeToLive;
}
public String getColumnFamily()
@@ -76,6 +78,11 @@ public abstract class AbstractModificati
return timestamp != null;
}
+ public int getTimeToLive()
+ {
+ return timeToLive;
+ }
+
/**
* Convert statement into a list of mutations to apply on the server
*
Added:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Attributes.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Attributes.java?rev=1101234&view=auto
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Attributes.java
(added)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Attributes.java
Mon May 9 21:40:27 2011
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.cql;
+
+import org.apache.cassandra.thrift.ConsistencyLevel;
+
+/**
+ * Class to contain attributes for statements
+ */
+public class Attributes
+{
+ private ConsistencyLevel cLevel;
+ private Long timestamp;
+ private int timeToLive;
+
+ public Attributes()
+ {}
+
+ public Attributes(ConsistencyLevel cLevel, Long timestamp, int timeToLive)
+ {
+ this.cLevel = cLevel;
+ this.timestamp = timestamp;
+ this.timeToLive = timeToLive;
+ }
+
+ public ConsistencyLevel getConsistencyLevel()
+ {
+ return cLevel;
+ }
+
+ public void setConsistencyLevel(ConsistencyLevel cLevel)
+ {
+ this.cLevel = cLevel;
+ }
+
+ public Long getTimestamp()
+ {
+ return timestamp;
+ }
+
+ public void setTimestamp(Long timestamp)
+ {
+ this.timestamp = timestamp;
+ }
+
+ public int getTimeToLive()
+ {
+ return timeToLive;
+ }
+
+ public void setTimeToLive(int timeToLive)
+ {
+ this.timeToLive = timeToLive;
+ }
+
+ public String toString()
+ {
+ return String.format("Attributes(consistency=%s, timestamp=%s,
timeToLive=%s)", cLevel, timestamp, timeToLive);
+ }
+
+}
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/BatchStatement.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/BatchStatement.java?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/BatchStatement.java
(original)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/BatchStatement.java
Mon May 9 21:40:27 2011
@@ -43,18 +43,22 @@ public class BatchStatement
// global timestamp to apply for each mutation
protected final Long timestamp;
+ // global time to live
+ protected final int timeToLive;
+
/**
* Creates a new BatchStatement from a list of statements and a
* Thrift consistency level.
*
* @param statements a list of UpdateStatements
- * @param level Thrift consistency level enum
+ * @param attrs additional attributes for statement (CL, timestamp,
timeToLive)
*/
- public BatchStatement(List<AbstractModification> statements,
ConsistencyLevel level, Long timestamp)
+ public BatchStatement(List<AbstractModification> statements, Attributes
attrs)
{
this.statements = statements;
- consistency = level;
- this.timestamp = timestamp;
+ this.consistency = attrs.getConsistencyLevel();
+ this.timestamp = attrs.getTimestamp();
+ this.timeToLive = attrs.getTimeToLive();
}
public List<AbstractModification> getStatements()
@@ -67,6 +71,11 @@ public class BatchStatement
return consistency;
}
+ public int getTimeToLive()
+ {
+ return timeToLive;
+ }
+
public List<RowMutation> getMutations(String keyspace, ClientState
clientState) throws InvalidRequestException
{
List<RowMutation> batch = new LinkedList<RowMutation>();
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Cql.g
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Cql.g?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Cql.g
(original)
+++ cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/Cql.g
Mon May 9 21:40:27 2011
@@ -201,9 +201,7 @@ whereClause returns [WhereClause clause]
*/
insertStatement returns [UpdateStatement expr]
: {
- Long timestamp = null;
- ConsistencyLevel cLevel = null;
-
+ Attributes attrs = new Attributes();
Map<Term, Term> columns = new HashMap<Term, Term>();
List<Term> columnNames = new ArrayList<Term>();
@@ -213,19 +211,20 @@ insertStatement returns [UpdateStatement
'(' K_KEY ( ',' column_name=term {
columnNames.add($column_name.item); } )+ ')'
K_VALUES
'(' key=term ( ',' column_value=term {
columnValues.add($column_value.item); })+ ')'
- ( usingClause[cLevel, timestamp] )?
+ ( usingClause[attrs] )?
{
- return new UpdateStatement($columnFamily.text, cLevel, columnNames,
columnValues, Collections.singletonList(key), timestamp);
+ return new UpdateStatement($columnFamily.text, columnNames,
columnValues, Collections.singletonList(key), attrs);
}
;
-usingClause[ConsistencyLevel cLevel, Long timestamp]
- : K_USING usingClauseObjective[cLevel, timestamp] ( K_AND?
usingClauseObjective[cLevel, timestamp] )?
+usingClause[Attributes attrs]
+ : K_USING usingClauseObjective[attrs] ( K_AND? usingClauseObjective[attrs]
)*
;
-usingClauseObjective[ConsistencyLevel cLevel, Long timestamp]
- : K_CONSISTENCY K_LEVEL { cLevel =
ConsistencyLevel.valueOf($K_LEVEL.text); }
- | K_TIMESTAMP ts=INTEGER { timestamp = Long.valueOf($ts.text); }
+usingClauseObjective[Attributes attrs]
+ : K_CONSISTENCY K_LEVEL {
attrs.setConsistencyLevel(ConsistencyLevel.valueOf($K_LEVEL.text)); }
+ | K_TIMESTAMP ts=INTEGER { attrs.setTimestamp(Long.valueOf($ts.text)); }
+ | K_TTL t=INTEGER { attrs.setTimeToLive(Integer.parseInt($t.text));
}
;
/**
@@ -254,15 +253,16 @@ usingClauseObjective[ConsistencyLevel cL
*/
batchStatement returns [BatchStatement expr]
: {
- Long timestamp = null;
- ConsistencyLevel cLevel = ConsistencyLevel.ONE;
+ Attributes attrs = new Attributes();
+ attrs.setConsistencyLevel(ConsistencyLevel.ONE);
+
List<AbstractModification> statements = new
ArrayList<AbstractModification>();
}
- K_BEGIN K_BATCH ( usingClause[cLevel, timestamp] )?
+ K_BEGIN K_BATCH ( usingClause[attrs] )?
s1=batchStatementObjective ';'? { statements.add(s1); } (
sN=batchStatementObjective ';'? { statements.add(sN); } )*
K_APPLY K_BATCH endStmnt
{
- return new BatchStatement(statements, cLevel, timestamp);
+ return new BatchStatement(statements, attrs);
}
;
@@ -287,19 +287,18 @@ batchStatementObjective returns [Abstrac
*/
updateStatement returns [UpdateStatement expr]
: {
- Long timestamp = null;
- ConsistencyLevel cLevel = null;
+ Attributes attrs = new Attributes();
Map<Term, Term> columns = new HashMap<Term, Term>();
List<Term> keyList = null;
}
K_UPDATE columnFamily=( IDENT | STRING_LITERAL | INTEGER )
- ( usingClause[cLevel, timestamp] )?
+ ( usingClause[attrs] )?
K_SET termPair[columns] (',' termPair[columns])*
K_WHERE ( K_KEY '=' key=term { keyList =
Collections.singletonList(key); }
|
K_KEY K_IN '(' keys=termList { keyList = $keys.items; }
')' )
{
- return new UpdateStatement($columnFamily.text, cLevel, columns,
keyList, timestamp);
+ return new UpdateStatement($columnFamily.text, columns, keyList,
attrs);
}
;
@@ -321,7 +320,8 @@ deleteStatement returns [DeleteStatement
}
K_DELETE
( cols=termList { columnsList = $cols.items; })?
- K_FROM columnFamily=( IDENT | STRING_LITERAL | INTEGER ) ( K_USING
K_CONSISTENCY K_LEVEL )?
+ K_FROM columnFamily=( IDENT | STRING_LITERAL | INTEGER )
+ ( K_USING K_CONSISTENCY K_LEVEL { cLevel =
ConsistencyLevel.valueOf($K_LEVEL.text); } )?
K_WHERE ( K_KEY '=' key=term { keyList =
Collections.singletonList(key); }
| K_KEY K_IN '(' keys=termList { keyList = $keys.items; } ')'
)?
@@ -466,6 +466,7 @@ K_PRIMARY: P R I M A R Y;
K_INTO: I N T O;
K_VALUES: V A L U E S;
K_TIMESTAMP: T I M E S T A M P;
+K_TTL: T T L;
// Case-insensitive alpha characters
fragment A: ('a'|'A');
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/DeleteStatement.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/DeleteStatement.java?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/DeleteStatement.java
(original)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/DeleteStatement.java
Mon May 9 21:40:27 2011
@@ -48,7 +48,7 @@ public class DeleteStatement extends Abs
public DeleteStatement(List<Term> columns, String columnFamily,
ConsistencyLevel cLevel, List<Term> keys)
{
- super(columnFamily, cLevel, null);
+ super(columnFamily, cLevel, null, 0);
this.columns = columns;
this.keys = keys;
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/QueryProcessor.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/QueryProcessor.java?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/QueryProcessor.java
(original)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/QueryProcessor.java
Mon May 9 21:40:27 2011
@@ -559,6 +559,9 @@ public class QueryProcessor
case BATCH:
BatchStatement batch = (BatchStatement) statement.statement;
+ if (batch.getTimeToLive() != 0)
+ throw new InvalidRequestException("Global TTL on the BATCH
statement is not supported.");
+
for (AbstractModification up : batch.getStatements())
{
if (up.isSetConsistencyLevel())
Modified:
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/UpdateStatement.java
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/UpdateStatement.java?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
---
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/UpdateStatement.java
(original)
+++
cassandra/branches/cassandra-0.8.1/src/java/org/apache/cassandra/cql/UpdateStatement.java
Mon May 9 21:40:27 2011
@@ -53,32 +53,20 @@ public class UpdateStatement extends Abs
* level, and key term.
*
* @param columnFamily column family name
- * @param cLevel the thrift consistency level
* @param columns a map of column name/values pairs
* @param keys the keys to update
- * @param timestamp timestamp to use for mutation, if set to null then
System.currentTimeMillis()
+ * @param attrs additional attributes for statement (CL, timestamp,
timeToLive)
*/
- public UpdateStatement(String columnFamily, ConsistencyLevel cLevel,
Map<Term, Term> columns, List<Term> keys, Long timestamp)
+ public UpdateStatement(String columnFamily,
+ Map<Term, Term> columns,
+ List<Term> keys,
+ Attributes attrs)
{
- super(columnFamily, cLevel, timestamp);
+ super(columnFamily, attrs);
this.columns = columns;
this.keys = keys;
}
-
- /**
- * Creates a new UpdateStatement from a column family name, columns map,
- * and key term.
- *
- * @param columnFamily column family name
- * @param columns a map of column name/values pairs
- * @param keys the keys to update
- * @param timestamp timestamp to use for mutation, if set to null then
System.currentTimeMillis()
- */
- public UpdateStatement(String columnFamily, Map<Term, Term> columns,
List<Term> keys, Long timestamp)
- {
- this(columnFamily, null, columns, keys, timestamp);
- }
/**
* Creates a new UpdateStatement from a column family name, a consistency
level,
@@ -86,20 +74,18 @@ public class UpdateStatement extends Abs
* alternate update format, <code>INSERT</code>.
*
* @param columnFamily column family name
- * @param cLevel the thrift consistency level
* @param columnNames list of column names
* @param columnValues list of column values (corresponds to names)
* @param keys the keys to update
- * @param timestamp timestamp to use for mutation, if set to null then
System.currentTimeMillis()
+ * @param attrs additional attributes for statement (CL, timestamp,
timeToLive)
*/
public UpdateStatement(String columnFamily,
- ConsistencyLevel cLevel,
List<Term> columnNames,
List<Term> columnValues,
List<Term> keys,
- Long timestamp)
+ Attributes attrs)
{
- super(columnFamily, cLevel, timestamp);
+ super(columnFamily, attrs);
this.columnNames = columnNames;
this.columnValues = columnValues;
@@ -184,7 +170,8 @@ public class UpdateStatement extends Abs
validateColumn(metadata, colName, colValue);
rm.add(new QueryPath(columnFamily, null, colName),
colValue,
- (timestamp == null) ? getTimestamp() : timestamp);
+ (timestamp == null) ? getTimestamp() : timestamp,
+ getTimeToLive());
}
return rm;
@@ -224,11 +211,13 @@ public class UpdateStatement extends Abs
public String toString()
{
- return String.format("UpdateStatement(columnFamily=%s, keys=%s,
columns=%s, consistency=%s)",
+ return String.format("UpdateStatement(columnFamily=%s, keys=%s,
columns=%s, consistency=%s, timestamp=%s, timeToLive=%s)",
columnFamily,
keys,
columns,
- cLevel);
+ getConsistencyLevel(),
+ timestamp,
+ timeToLive);
}
public AbstractType<?> getKeyType(String keyspace)
Modified: cassandra/branches/cassandra-0.8.1/test/system/test_cql.py
URL:
http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8.1/test/system/test_cql.py?rev=1101234&r1=1101233&r2=1101234&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8.1/test/system/test_cql.py (original)
+++ cassandra/branches/cassandra-0.8.1/test/system/test_cql.py Mon May 9
21:40:27 2011
@@ -807,6 +807,15 @@ class TestCql(ThriftTester):
APPLY BATCH
""")
+ # BATCH should not allow setting global TTL
+ assert_raises(cql.ProgrammingError,
+ cursor.execute,
+ """
+ BEGIN BATCH USING TTL 130374
+ UPDATE StandardString1 SET name = 'name here' WHERE
KEY = 'TimestampedUser4'
+ APPLY BATCH
+ """)
+
assert_raises(cql.ProgrammingError,
cursor.execute,
"""
@@ -842,7 +851,7 @@ class TestCql(ThriftTester):
assert r[2] == "p4ssw0rd", \
"unrecognized value '%s'" % r[1]
- def test_insert_with_timestamp(self):
+ def test_insert_with_timestamp_and_ttl(self):
"insert statement should support setting timestamp"
cursor = init()
cursor.compression = 'NONE'
@@ -877,7 +886,50 @@ class TestCql(ThriftTester):
assert r[1] == "name here", \
"unrecognized value '%s'" % r[1]
- def test_update_with_timestamp(self):
+ # and INSERT with TTL
+ cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES
('TimestampedUser2', 'name here') USING TTL 5678")
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser2'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+ colnames = [col_d[0] for col_d in cursor.description]
+
+ assert colnames[1] == "name", \
+ "unrecognized name '%s'" % colnames[1]
+
+ r = cursor.fetchone()
+ assert r[1] == "name here", \
+ "unrecognized value '%s'" % r[1]
+
+ # and INSERT with CONSISTENCY, TIMESTAMP and TTL together
+ cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES
('TimestampedUser3', 'name here') USING TTL 4587 AND TIMESTAMP 1303743619771318
AND CONSISTENCY ONE")
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser3'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+ colnames = [col_d[0] for col_d in cursor.description]
+
+ assert colnames[1] == "name", \
+ "unrecognized name '%s'" % colnames[1]
+
+ r = cursor.fetchone()
+ assert r[1] == "name here", \
+ "unrecognized value '%s'" % r[1]
+
+ # and INSERT with TTL
+ cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES
('TimestampedUser14', 'name here') USING TTL 1 AND CONSISTENCY ONE")
+
+ # wait for column to expire
+ time.sleep(5)
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser14'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+
+ r = cursor.fetchone()
+ assert len(r) == 1, "expected 0 results, got %d" % len(r)
+
+ def test_update_with_timestamp_and_ttl(self):
"update statement should support setting timestamp"
cursor = init()
cursor.compression = 'NONE'
@@ -911,3 +963,46 @@ class TestCql(ThriftTester):
r = cursor.fetchone()
assert r[1] == "name here", \
"unrecognized value '%s'" % r[1]
+
+ # UPDATE with TTL
+ cursor.execute("UPDATE StandardString1 USING TTL 13030 SET name =
'name here' WHERE KEY = 'TimestampedUser4'")
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser4'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+ colnames = [col_d[0] for col_d in cursor.description]
+
+ assert colnames[1] == "name", \
+ "unrecognized name '%s'" % colnames[1]
+
+ r = cursor.fetchone()
+ assert r[1] == "name here", \
+ "unrecognized value '%s'" % r[1]
+
+ # UPDATE with CONSISTENCY, TIMESTAMP and TTL together
+ cursor.execute("UPDATE StandardString1 USING CONSISTENCY ONE AND
TIMESTAMP 1303743619771318 AND TTL 13037 SET name = 'name here' WHERE KEY =
'TimestampedUser5'")
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser5'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+ colnames = [col_d[0] for col_d in cursor.description]
+
+ assert colnames[1] == "name", \
+ "unrecognized name '%s'" % colnames[1]
+
+ r = cursor.fetchone()
+ assert r[1] == "name here", \
+ "unrecognized value '%s'" % r[1]
+
+ # UPDATE with TTL
+ cursor.execute("UPDATE StandardString1 USING CONSISTENCY ONE TTL 1 SET
name = 'name here' WHERE KEY = 'TimestampedUser6'")
+
+ # wait for column to expire
+ time.sleep(5)
+
+ # try to read it
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY =
'TimestampedUser6'")
+ assert cursor.rowcount == 1, "expected 1 results, got %d" %
cursor.rowcount
+
+ r = cursor.fetchone()
+ assert len(r) == 1, "expected 0 results, got %d" % len(r)