Skip to content

Commit

Permalink
add CQL TTL support
Browse files Browse the repository at this point in the history
patch by pyaskevich; reviewed by jbellis for CASSANDRA-2476

git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.8.1@1101234 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jbellis committed May 9, 2011
1 parent 0427c83 commit fcd02e3
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 59 deletions.
7 changes: 5 additions & 2 deletions CHANGES.txt
@@ -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
Expand Down
11 changes: 9 additions & 2 deletions doc/cql/CQL.textile
Expand Up @@ -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.

Expand All @@ -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.
Expand All @@ -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.
Expand Down
13 changes: 10 additions & 3 deletions src/java/org/apache/cassandra/cql/AbstractModification.java
Expand Up @@ -33,17 +33,19 @@ public abstract class AbstractModification
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()
Expand Down Expand Up @@ -76,6 +78,11 @@ public boolean isSetTimestamp()
return timestamp != null;
}

public int getTimeToLive()
{
return timeToLive;
}

/**
* Convert statement into a list of mutations to apply on the server
*
Expand Down
79 changes: 79 additions & 0 deletions src/java/org/apache/cassandra/cql/Attributes.java
@@ -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);
}

}
17 changes: 13 additions & 4 deletions src/java/org/apache/cassandra/cql/BatchStatement.java
Expand Up @@ -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()
Expand All @@ -67,6 +71,11 @@ public ConsistencyLevel getConsistencyLevel()
return consistency;
}

public int getTimeToLive()
{
return timeToLive;
}

public List<RowMutation> getMutations(String keyspace, ClientState clientState) throws InvalidRequestException
{
List<RowMutation> batch = new LinkedList<RowMutation>();
Expand Down
39 changes: 20 additions & 19 deletions src/java/org/apache/cassandra/cql/Cql.g
Expand Up @@ -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>();
Expand All @@ -213,19 +211,20 @@ insertStatement returns [UpdateStatement expr]
'(' 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)); }
;

/**
Expand Down Expand Up @@ -254,15 +253,16 @@ usingClauseObjective[ConsistencyLevel cLevel, Long timestamp]
*/
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);
}
;

Expand All @@ -287,19 +287,18 @@ batchStatementObjective returns [AbstractModification statement]
*/
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);
}
;

Expand All @@ -321,7 +320,8 @@ deleteStatement returns [DeleteStatement expr]
}
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; } ')'
)?
Expand Down Expand Up @@ -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');
Expand Down
2 changes: 1 addition & 1 deletion src/java/org/apache/cassandra/cql/DeleteStatement.java
Expand Up @@ -48,7 +48,7 @@ public class DeleteStatement extends AbstractModification

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;
Expand Down
3 changes: 3 additions & 0 deletions src/java/org/apache/cassandra/cql/QueryProcessor.java
Expand Up @@ -559,6 +559,9 @@ public static CqlResult process(String queryString, ClientState clientState)
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())
Expand Down

0 comments on commit fcd02e3

Please sign in to comment.