Duplicate rows returned when in clause has repeated values Patch by Benjamin Lerer, reviewed by Robert Stupp for CASSANDRA-6706
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/0c2eaa9c Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/0c2eaa9c Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/0c2eaa9c Branch: refs/heads/trunk Commit: 0c2eaa9cbb51f064b439c4d098adb5aa76b65b0f Parents: faf9181 Author: Benjamin Lerer <[email protected]> Authored: Wed Jan 21 20:12:55 2015 +0100 Committer: Robert Stupp <[email protected]> Committed: Wed Jan 21 20:12:55 2015 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cql3/statements/SelectStatement.java | 25 ++++++++++++++++++++ 2 files changed, 26 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/0c2eaa9c/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index f1eaa77..9cd8189 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 2.1.3 + * Duplicate rows returned when in clause has repeated values (CASSANDRA-6707) * Add tooling to detect hot partitions (CASSANDRA-7974) * Fix cassandra-stress user-mode truncation of partition generation (CASSANDRA-8608) * Only stream from unrepaired sstables during inc repair (CASSANDRA-8267) http://git-wip-us.apache.org/repos/asf/cassandra/blob/0c2eaa9c/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java index 30259dd..633d43c 100644 --- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java @@ -65,6 +65,13 @@ public class SelectStatement implements CQLStatement private static final int DEFAULT_COUNT_PAGE_SIZE = 10000; + /** + * In the current version a query containing duplicate values in an IN restriction on the partition key will + * cause the same record to be returned multiple time. This behavior will be changed in 3.0 but until then + * we will log a warning the first time this problem occurs. + */ + private static volatile boolean HAS_LOGGED_WARNING_FOR_IN_RESTRICTION_WITH_DUPLICATES; + private final int boundTerms; public final CFMetaData cfm; public final Parameters parameters; @@ -588,6 +595,13 @@ public class SelectStatement implements CQLStatement if (builder.remainingCount() == 1) { + if (values.size() > 1 && !HAS_LOGGED_WARNING_FOR_IN_RESTRICTION_WITH_DUPLICATES && containsDuplicates(values)) + { + // This approach does not fully prevent race conditions but it is not a big deal. + HAS_LOGGED_WARNING_FOR_IN_RESTRICTION_WITH_DUPLICATES = true; + logger.warn("SELECT queries with IN restrictions on the partition key containing duplicate values will return duplicate rows."); + } + for (ByteBuffer val : values) { if (val == null) @@ -609,6 +623,17 @@ public class SelectStatement implements CQLStatement return keys; } + /** + * Checks if the specified list contains duplicate values. + * + * @param values the values to check + * @return <code>true</code> if the specified list contains duplicate values, <code>false</code> otherwise. + */ + private static boolean containsDuplicates(List<ByteBuffer> values) + { + return new HashSet<>(values).size() < values.size(); + } + private ByteBuffer getKeyBound(Bound b, QueryOptions options) throws InvalidRequestException { // Deal with unrestricted partition key components (special-casing is required to deal with 2i queries on the first
