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/07/19 18:14:45 UTC
svn commit: r1148425 - in /cassandra/branches/cassandra-0.8: ./
src/java/org/apache/cassandra/cql/ test/system/
Author: jbellis
Date: Tue Jul 19 16:14:44 2011
New Revision: 1148425
URL: http://svn.apache.org/viewvc?rev=1148425&view=rev
Log:
CQL: include only one row per unique keyfor IN queries
patch by Jim Ancona; reviewed by pyaskevich for CASSANDRA-2717
Modified:
cassandra/branches/cassandra-0.8/CHANGES.txt
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/cql/SelectStatement.java
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Term.java
cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java
cassandra/branches/cassandra-0.8/test/system/test_cql.py
Modified: cassandra/branches/cassandra-0.8/CHANGES.txt
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/CHANGES.txt?rev=1148425&r1=1148424&r2=1148425&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/CHANGES.txt (original)
+++ cassandra/branches/cassandra-0.8/CHANGES.txt Tue Jul 19 16:14:44 2011
@@ -32,6 +32,8 @@
* fix updating KS with durable_writes=false (CASSANDRA-2907)
* add simplified facade to SSTableWriter for bulk loading use
(CASSANDRA-2911)
+ * CQL: include only one row per unique key for IN queries
+ (CASSANDRA-2717)
0.8.1
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=1148425&r1=1148424&r2=1148425&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 Tue Jul 19 16:14:44 2011
@@ -188,7 +188,7 @@ whereClause returns [WhereClause clause]
| key_alias=term { inClause.setKeyAlias(key_alias.getText()); }
K_IN '(' f1=term { inClause.andKeyEquals(f1); }
(',' fN=term { inClause.andKeyEquals(fN); } )* ')'
- { $clause = inClause; }
+ { inClause.setMultiKey(true); $clause = inClause; }
;
/**
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=1148425&r1=1148424&r2=1148425&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 Tue Jul 19 16:14:44 2011
@@ -334,6 +334,10 @@ public class QueryProcessor
if (select.isKeyRange() && (select.getKeyFinish() != null) && (select.getColumnRelations().size() > 0))
throw new InvalidRequestException("You cannot combine key range and by-column clauses in a SELECT");
+ // Can't use more than one KEY =
+ if (!select.isMultiKey() && select.getKeys().size() > 1)
+ throw new InvalidRequestException("You cannot use more than one KEY = in a SELECT");
+
AbstractType<?> comparator = select.getComparator(keyspace);
if (select.getColumnRelations().size() > 0)
Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java?rev=1148425&r1=1148424&r2=1148425&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/SelectStatement.java Tue Jul 19 16:14:44 2011
@@ -22,6 +22,7 @@ package org.apache.cassandra.cql;
import java.nio.ByteBuffer;
import java.util.List;
+import java.util.Set;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.DatabaseDescriptor;
@@ -58,7 +59,7 @@ public class SelectStatement
return clause.isKeyRange();
}
- public List<Term> getKeys()
+ public Set<Term> getKeys()
{
return clause.getKeys();
}
@@ -148,6 +149,11 @@ public class SelectStatement
return clause.getKeyAlias();
}
+ public boolean isMultiKey()
+ {
+ return clause.isMultiKey();
+ }
+
public void extractKeyAliasFromColumns(CFMetaData cfm)
{
clause.extractKeysFromColumns(cfm);
@@ -162,4 +168,5 @@ public class SelectStatement
{
return DatabaseDescriptor.getValueValidator(keyspace, columnFamily, column);
}
+
}
Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Term.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Term.java?rev=1148425&r1=1148424&r2=1148425&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Term.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/Term.java Tue Jul 19 16:14:44 2011
@@ -130,6 +130,38 @@ public class Term
{
return String.format("Term(%s, type=%s)", getText(), type);
}
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((text == null) ? 0 : text.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Term other = (Term) obj;
+ if (text == null)
+ {
+ if (other.text != null)
+ return false;
+ } else if (!text.equals(other.text))
+ return false;
+ if (type != other.type)
+ return false;
+ return true;
+ }
+
}
Modified: cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java?rev=1148425&r1=1148424&r2=1148425&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java (original)
+++ cassandra/branches/cassandra-0.8/src/java/org/apache/cassandra/cql/WhereClause.java Tue Jul 19 16:14:44 2011
@@ -22,15 +22,14 @@ package org.apache.cassandra.cql;
import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.thrift.InvalidRequestException;
-import org.apache.cassandra.thrift.ThriftValidation;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
/**
* WhereClauses encapsulate all of the predicates of a SELECT query.
@@ -39,10 +38,10 @@ import java.util.List;
public class WhereClause
{
// added to either by the parser, e.g. from an IN clause, or by extractKeysFromColumns
- private List<Term> keys = new ArrayList<Term>();
+ private Set<Term> keys = new LinkedHashSet<Term>();
private Term startKey, finishKey;
private List<Relation> columns = new ArrayList<Relation>();
- private boolean includeStartKey = false, includeFinishKey = false;
+ private boolean includeStartKey = false, includeFinishKey = false, multiKey = false;
// set by extractKeysFromColumns
private String keyAlias = null;
@@ -117,7 +116,7 @@ public class WhereClause
return finishKey;
}
- public List<Term> getKeys()
+ public Set<Term> getKeys()
{
return keys;
}
@@ -137,6 +136,15 @@ public class WhereClause
keyAlias = alias.toUpperCase();
}
+ public boolean isMultiKey() {
+ return multiKey;
+ }
+
+ public void setMultiKey(boolean multiKey)
+ {
+ this.multiKey = multiKey;
+ }
+
public String getKeyAlias()
{
// TODO fix special casing here, key alias should always be set post-extract
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=1148425&r1=1148424&r2=1148425&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/system/test_cql.py (original)
+++ cassandra/branches/cassandra-0.8/test/system/test_cql.py Tue Jul 19 16:14:44 2011
@@ -881,6 +881,19 @@ class TestCql(ThriftTester):
assert r[2] == "p4ssw0rd", \
"unrecognized value '%s'" % r[1]
+ # select with same KEY AND'ed (see CASSANDRA-2717)
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'mUser1' AND KEY = 'mUser1'")
+ assert cursor.rowcount == 1, "expected 1 result, got %d" % cursor.rowcount
+
+ # select with different KEYs AND'ed
+ assert_raises(cql.ProgrammingError,
+ cursor.execute,
+ "SELECT * FROM StandardString1 WHERE KEY = 'mUser1' AND KEY = 'mUser2'")
+
+ # select with same KEY repeated in IN
+ cursor.execute("SELECT * FROM StandardString1 WHERE KEY IN ('mUser1', 'mUser1')")
+ assert cursor.rowcount == 1, "expected 1 result, got %d" % cursor.rowcount
+
def test_insert_with_timestamp_and_ttl(self):
"insert statement should support setting timestamp"
cursor = init()