cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From slebre...@apache.org
Subject [1/3] git commit: Queries on compact tables can return more results than requested
Date Mon, 21 Apr 2014 10:03:50 GMT
Repository: cassandra
Updated Branches:
  refs/heads/trunk e5ace5b42 -> 8a788e76a


Queries on compact tables can return more results than requested

patch by slebresne; reviewed by thobbs for CASSANDRA-7052


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/54bf92f3
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/54bf92f3
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/54bf92f3

Branch: refs/heads/trunk
Commit: 54bf92f37d4ad1a65f106b8b2a3212e8f2516282
Parents: 4596a07
Author: Sylvain Lebresne <sylvain@datastax.com>
Authored: Mon Apr 21 12:00:19 2014 +0200
Committer: Sylvain Lebresne <sylvain@datastax.com>
Committed: Mon Apr 21 12:00:19 2014 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  1 +
 .../cql3/statements/SelectStatement.java        | 34 ++++++++++++--------
 .../cassandra/service/pager/QueryPager.java     |  2 +-
 3 files changed, 23 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/54bf92f3/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 972f65a..b976d64 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 2.0.8
+ * Queries on compact tables can return more rows that requested (CASSANDRA-7052)
 Merged from 1.2:
  * Fix batchlog to account for CF truncation records (CASSANDRA-6999)
  * Fix CQLSH parsing of functions and BLOB literals (CASSANDRA-7018)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/54bf92f3/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 56e87e8..2652b29 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -194,15 +194,16 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
         cl.validateForRead(keyspace());
 
         int limit = getLimit(variables);
+        int limitForQuery = updateLimitForQuery(limit);
         long now = System.currentTimeMillis();
         Pageable command;
         if (isKeyRange || usesSecondaryIndexing)
         {
-            command = getRangeCommand(variables, limit, now);
+            command = getRangeCommand(variables, limitForQuery, now);
         }
         else
         {
-            List<ReadCommand> commands = getSliceCommands(variables, limit, now);
+            List<ReadCommand> commands = getSliceCommands(variables, limitForQuery,
now);
             command = commands == null ? null : new Pageable.ReadCommands(commands);
         }
 
@@ -221,7 +222,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
         {
             QueryPager pager = QueryPagers.pager(command, cl, options.getPagingState());
             if (parameters.isCount)
-                return pageCountQuery(pager, variables, pageSize, now);
+                return pageCountQuery(pager, variables, pageSize, now, limit);
 
             // We can't properly do post-query ordering if we page (see #6722)
             if (needsPostQueryOrdering())
@@ -253,7 +254,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
         return processResults(rows, variables, limit, now);
     }
 
-    private ResultMessage.Rows pageCountQuery(QueryPager pager, List<ByteBuffer> variables,
int pageSize, long now) throws RequestValidationException, RequestExecutionException
+    private ResultMessage.Rows pageCountQuery(QueryPager pager, List<ByteBuffer> variables,
int pageSize, long now, int limit) throws RequestValidationException, RequestExecutionException
     {
         int count = 0;
         while (!pager.isExhausted())
@@ -264,7 +265,9 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
             count += rset.rows.size();
         }
 
-        ResultSet result = ResultSet.makeCountResult(keyspace(), columnFamily(), count, parameters.countAlias);
+        // We sometimes query one more result than the user limit asks to handle exclusive
bounds with compact tables (see updateLimitForQuery).
+        // So do make sure the count is not greater than what the user asked for.
+        ResultSet result = ResultSet.makeCountResult(keyspace(), columnFamily(), Math.min(count,
limit), parameters.countAlias);
         return new ResultMessage.Rows(result);
     }
 
@@ -289,16 +292,17 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
     {
         List<ByteBuffer> variables = Collections.emptyList();
         int limit = getLimit(variables);
+        int limitForQuery = updateLimitForQuery(limit);
         long now = System.currentTimeMillis();
         List<Row> rows;
         if (isKeyRange || usesSecondaryIndexing)
         {
-            RangeSliceCommand command = getRangeCommand(variables, limit, now);
+            RangeSliceCommand command = getRangeCommand(variables, limitForQuery, now);
             rows = command == null ? Collections.<Row>emptyList() : command.executeLocally();
         }
         else
         {
-            List<ReadCommand> commands = getSliceCommands(variables, limit, now);
+            List<ReadCommand> commands = getSliceCommands(variables, limitForQuery,
now);
             rows = commands == null ? Collections.<Row>emptyList() : readLocally(keyspace(),
commands);
         }
 
@@ -561,14 +565,18 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
         if (l <= 0)
             throw new InvalidRequestException("LIMIT must be strictly positive");
 
-        // Internally, we don't support exclusive bounds for slices. Instead,
-        // we query one more element if necessary and exclude
-        if (sliceRestriction != null && (!sliceRestriction.isInclusive(Bound.START)
|| !sliceRestriction.isInclusive(Bound.END)) && l != Integer.MAX_VALUE)
-            l += 1;
-
         return l;
     }
 
+    private int updateLimitForQuery(int limit)
+    {
+        // Internally, we don't support exclusive bounds for slices. Instead, we query one
more element if necessary
+        // and exclude it later (in processColumnFamily)
+        return sliceRestriction != null && (!sliceRestriction.isInclusive(Bound.START)
|| !sliceRestriction.isInclusive(Bound.END)) && limit != Integer.MAX_VALUE
+             ? limit + 1
+             : limit;
+    }
+
     private Collection<ByteBuffer> getKeys(final List<ByteBuffer> variables)
throws InvalidRequestException
     {
         List<ByteBuffer> keys = new ArrayList<ByteBuffer>();
@@ -961,7 +969,7 @@ public class SelectStatement implements CQLStatement, MeasurableForPreparedCache
         if (isReversed)
             cqlRows.reverse();
 
-        // Trim result if needed to respect the limit
+        // Trim result if needed to respect the user limit
         cqlRows.trim(limit);
         return cqlRows;
     }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/54bf92f3/src/java/org/apache/cassandra/service/pager/QueryPager.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/pager/QueryPager.java b/src/java/org/apache/cassandra/service/pager/QueryPager.java
index 218ade3..ab2dad7 100644
--- a/src/java/org/apache/cassandra/service/pager/QueryPager.java
+++ b/src/java/org/apache/cassandra/service/pager/QueryPager.java
@@ -39,7 +39,7 @@ import org.apache.cassandra.exceptions.RequestValidationException;
  * Also, there is no guarantee that fetchPage() won't return an empty list,
  * even if isExhausted() return false (but it is guaranteed to return an empty
  * list *if* isExhausted() return true). Indeed, isExhausted() does *not*
- * trigger a query so in some (failry rare) case we might not know the paging
+ * trigger a query so in some (fairly rare) case we might not know the paging
  * is done even though it is.
  */
 public interface QueryPager


Mime
View raw message