fix for SelectStatement start/end key are not set correctly when a key alias is involved patch by Pavel Yaskevich; reviewed by Jonathan Ellis for CASSANDRA-3700
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/621bc0cc Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/621bc0cc Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/621bc0cc Branch: refs/heads/trunk Commit: 621bc0cc7939efdc00d32826f138701349191fe0 Parents: 7ab6cb1 Author: Pavel Yaskevich <[email protected]> Authored: Fri Jan 6 15:59:40 2012 +0200 Committer: Pavel Yaskevich <[email protected]> Committed: Sat Jan 7 17:34:54 2012 +0200 ---------------------------------------------------------------------- CHANGES.txt | 2 + .../org/apache/cassandra/cql/QueryProcessor.java | 2 +- src/java/org/apache/cassandra/cql/Relation.java | 23 +---- src/java/org/apache/cassandra/cql/WhereClause.java | 76 +++++++-------- 4 files changed, 41 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/621bc0cc/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index e17def1..859401a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -24,6 +24,8 @@ Merged from 0.8: * Secondary Indexes should report memory consumption (CASSANDRA-3155) * use correct list of replicas for LOCAL_QUORUM reads when read repair is disabled (CASSANDRA-3696) + * fix for SelectStatement start/end key are not set correctly + when a key alias is involved (CASSANDRA-3700) 1.0.6 http://git-wip-us.apache.org/repos/asf/cassandra/blob/621bc0cc/src/java/org/apache/cassandra/cql/QueryProcessor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql/QueryProcessor.java b/src/java/org/apache/cassandra/cql/QueryProcessor.java index f2038ea..8e90e06 100644 --- a/src/java/org/apache/cassandra/cql/QueryProcessor.java +++ b/src/java/org/apache/cassandra/cql/QueryProcessor.java @@ -412,7 +412,7 @@ public class QueryProcessor assert key.toUpperCase().equals(key); // should always be uppercased by caller String realKeyAlias = bufferToString(cfm.getKeyName()).toUpperCase(); if (!realKeyAlias.equals(key)) - throw new InvalidRequestException(String.format("Expected key '%s' to be present in WHERE clause for '%s'", key, cfm.cfName)); + throw new InvalidRequestException(String.format("Expected key '%s' to be present in WHERE clause for '%s'", realKeyAlias, cfm.cfName)); } private static void validateColumnNames(Iterable<ByteBuffer> columns) http://git-wip-us.apache.org/repos/asf/cassandra/blob/621bc0cc/src/java/org/apache/cassandra/cql/Relation.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql/Relation.java b/src/java/org/apache/cassandra/cql/Relation.java index 1e3aecf..eb34080 100644 --- a/src/java/org/apache/cassandra/cql/Relation.java +++ b/src/java/org/apache/cassandra/cql/Relation.java @@ -22,12 +22,11 @@ package org.apache.cassandra.cql; /** * Relations encapsulate the relationship between an entity of some kind, and - * a value (term). For example, KEY > "start" or "colname1" = "somevalue". + * a value (term). For example, <key> > "start" or "colname1" = "somevalue". * */ public class Relation { - private EntityType entityType = EntityType.COLUMN; private Term entity; private RelationType relationType; private Term value; @@ -41,24 +40,11 @@ public class Relation */ public Relation(Term entity, String type, Term value) { - if (entity.getText().toUpperCase().equals("KEY")) - this.entityType = EntityType.KEY; - this.entity = entity; this.relationType = RelationType.forString(type); this.value = value; } - public boolean isKey() - { - return entityType == EntityType.KEY; - } - - public boolean isColumn() - { - return entityType == EntityType.COLUMN; - } - public RelationType operator() { return relationType; @@ -77,15 +63,10 @@ public class Relation @Override public String toString() { - return String.format("Relation(%s, %s,nnn %s)", entity, relationType, value); + return String.format("Relation(%s, %s, %s)", entity, relationType, value); } } -enum EntityType -{ - KEY, COLUMN; -} - enum RelationType { EQ, LT, LTE, GTE, GT; http://git-wip-us.apache.org/repos/asf/cassandra/blob/621bc0cc/src/java/org/apache/cassandra/cql/WhereClause.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql/WhereClause.java b/src/java/org/apache/cassandra/cql/WhereClause.java index 5df4512..964aad8 100644 --- a/src/java/org/apache/cassandra/cql/WhereClause.java +++ b/src/java/org/apache/cassandra/cql/WhereClause.java @@ -20,27 +20,29 @@ package org.apache.cassandra.cql; * */ - -import org.apache.cassandra.config.CFMetaData; -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; +import org.apache.cassandra.config.CFMetaData; +import org.apache.cassandra.utils.ByteBufferUtil; + /** * WhereClauses encapsulate all of the predicates of a SELECT query. * */ public class WhereClause { - // added to either by the parser, e.g. from an IN clause, or by extractKeysFromColumns + // all relations (except for `<key> IN (.., .., ..)` which can be directly interpreted) from parser + // are stored into this array and are filtered to the keys/columns by extractKeysFromColumns(...) + private List<Relation> clauseRelations = new ArrayList<Relation>(); + private List<Relation> columns = new ArrayList<Relation>(); + + // added to either by the parser from an IN clause or by extractKeysFromColumns private Set<Term> keys = new LinkedHashSet<Term>(); private Term startKey, finishKey; - private List<Relation> columns = new ArrayList<Relation>(); private boolean includeStartKey = false, includeFinishKey = false, multiKey = false; // set by extractKeysFromColumns private String keyAlias = null; @@ -56,9 +58,7 @@ public class WhereClause } public WhereClause() - { - - } + {} /** * Add an additional relation to this WHERE clause. @@ -67,24 +67,7 @@ public class WhereClause */ public void and(Relation relation) { - if ((relation != null) && relation.isKey()) - { - if (relation.operator() == RelationType.EQ) - keys.add(relation.getValue()); - else if ((relation.operator() == RelationType.GT) || (relation.operator() == RelationType.GTE)) - { - startKey = relation.getValue(); - includeStartKey = relation.operator() == RelationType.GTE; - } - else if ((relation.operator() == RelationType.LT) || (relation.operator() == RelationType.LTE)) - { - finishKey = relation.getValue(); - includeFinishKey = relation.operator() == RelationType.LTE; - } - - } - else - columns.add(relation); + clauseRelations.add(relation); } /** @@ -162,23 +145,36 @@ public class WhereClause ByteBuffer realKeyAlias = cfm.getKeyName(); if (!keys.isEmpty()) - return; // we already have key(s) set - - Iterator<Relation> iter = columns.iterator(); + return; // we already have key(s) set (<key> IN (.., ...) construction used) - while (iter.hasNext()) + for (Relation relation : clauseRelations) { - Relation relation = iter.next(); - - ByteBuffer name = ByteBufferUtil.bytes(relation.getEntity().getText()); + String nameText = relation.getEntity().getText(); + ByteBuffer name = ByteBufferUtil.bytes(nameText); if (name.equals(realKeyAlias)) { - // setting found key as an alias - keyAlias = relation.getEntity().getText().toUpperCase(); - keys.add(relation.getValue()); // add a key value to the keys list - iter.remove(); // removing it from the columns - break; + if (keyAlias == null) // setting found key as an alias + keyAlias = nameText.toUpperCase(); + + if (relation.operator() == RelationType.EQ) + { + keys.add(relation.getValue()); + } + else if ((relation.operator() == RelationType.GT) || (relation.operator() == RelationType.GTE)) + { + startKey = relation.getValue(); + includeStartKey = relation.operator() == RelationType.GTE; + } + else if ((relation.operator() == RelationType.LT) || (relation.operator() == RelationType.LTE)) + { + finishKey = relation.getValue(); + includeFinishKey = relation.operator() == RelationType.LTE; + } + } + else + { + columns.add(relation); } } }
