You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by sl...@apache.org on 2012/04/11 17:24:18 UTC

[2/3] git commit: CQL3: Support slice with exclusive start and stop

CQL3: Support slice with exclusive start and stop

patch by slebresne; reviewed by jbellis for CASSANDRA-3785


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

Branch: refs/heads/cassandra-1.1
Commit: d49113fad1bf7a15ca052156b872b9bdc01b6d73
Parents: fc7e864
Author: Sylvain Lebresne <sy...@datastax.com>
Authored: Thu Jan 26 10:49:56 2012 +0100
Committer: Sylvain Lebresne <sy...@datastax.com>
Committed: Wed Apr 11 17:17:59 2012 +0200

----------------------------------------------------------------------
 CHANGES.txt                                        |    1 +
 .../cassandra/cql3/statements/SelectStatement.java |   61 ++++++++++++--
 2 files changed, 53 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/d49113fa/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index df030b9..4ef47c5 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -13,6 +13,7 @@
    (CASSANDRA-4128)
  * Move CfDef and KsDef validation out of thrift (CASSANDRA-4037)
  * Fix get_paged_slice (CASSANDRA-4136)
+ * CQL3: Support slice with exclusive start and stop (CASSANDRA-3785)
 Merged from 1.0:
  * add auto_snapshot option allowing disabling snapshot before drop/truncate
    (CASSANDRA-3710)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/d49113fa/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 5bcd37a..0485857 100644
--- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java
@@ -91,6 +91,7 @@ public class SelectStatement implements CQLStatement
     private Restriction keyRestriction;
     private final Restriction[] columnRestrictions;
     private final Map<CFDefinition.Name, Restriction> metadataRestrictions = new HashMap<CFDefinition.Name, Restriction>();
+    private Restriction sliceRestriction;
 
     private static enum Bound
     {
@@ -323,10 +324,13 @@ public class SelectStatement implements CQLStatement
 
     private int getLimit()
     {
+        // Internally, we don't support exclusive bounds for slices. Instead,
+        // we query one more element if necessary and exclude
+        int limit = sliceRestriction != null && !sliceRestriction.isInclusive(Bound.START) ? parameters.limit + 1 : parameters.limit;
         // For sparse, we'll end up merging all defined colums into the same CqlRow. Thus we should query up
         // to 'defined columns' * 'asked limit' to be sure to have enough columns. We'll trim after query if
         // this end being too much.
-        return cfDef.isCompact ? parameters.limit : cfDef.metadata.size() * parameters.limit;
+        return cfDef.isCompact ? limit : cfDef.metadata.size() * limit;
     }
 
     private boolean isKeyRange()
@@ -602,9 +606,20 @@ public class SelectStatement implements CQLStatement
 
                     thriftColumns = new ArrayList<Column>();
 
-                    ByteBuffer[] components = cfDef.isComposite
-                                            ? ((CompositeType)cfDef.cfm.comparator).split(c.name())
-                                            : null;
+                    ByteBuffer[] components = null;
+
+                    if (cfDef.isComposite)
+                    {
+                        components = ((CompositeType)cfDef.cfm.comparator).split(c.name());
+                    }
+                    else if (sliceRestriction != null)
+                    {
+                        // For dynamic CF, the column could be out of the requested bounds, filter here
+                        if (!sliceRestriction.isInclusive(Bound.START) && c.name().equals(sliceRestriction.bound(Bound.START).getByteBuffer(cfDef.cfm.comparator, variables)))
+                            continue;
+                        if (!sliceRestriction.isInclusive(Bound.END) && c.name().equals(sliceRestriction.bound(Bound.END).getByteBuffer(cfDef.cfm.comparator, variables)))
+                            continue;
+                    }
 
                     // Respect selection order
                     for (Pair<CFDefinition.Name, ColumnIdentifier> p : selection)
@@ -711,9 +726,9 @@ public class SelectStatement implements CQLStatement
         if (parameters.isColumnsReversed)
             Collections.reverse(cqlRows);
 
+        // Trim result if needed to respect the limit
         cqlRows = cqlRows.size() > parameters.limit ? cqlRows.subList(0, parameters.limit) : cqlRows;
 
-        // Trim result if needed to respect the limit
         return cqlRows;
     }
 
@@ -880,14 +895,26 @@ public class SelectStatement implements CQLStatement
                 CFDefinition.Name cname = iter.next();
                 Restriction restriction = stmt.columnRestrictions[i];
                 if (restriction == null)
+                {
                     shouldBeDone = true;
+                }
                 else if (shouldBeDone)
+                {
                     throw new InvalidRequestException(String.format("PRIMARY KEY part %s cannot be restricted (preceding part %s is either not restricted or by a non-EQ relation)", cname, previous));
+                }
                 else if (!restriction.isEquality())
+                {
                     shouldBeDone = true;
+                    // For non-composite slices, we don't support internally the difference between exclusive and
+                    // inclusive bounds, so we deal with it manually.
+                    if (!cfDef.isComposite && (!restriction.isInclusive(Bound.START) || !restriction.isInclusive(Bound.END)))
+                        stmt.sliceRestriction = restriction;
+                }
                 // We only support IN for the last name so far
                 else if (restriction.eqValues.size() > 1 && i != stmt.columnRestrictions.length - 1)
+                {
                     throw new InvalidRequestException(String.format("PRIMARY KEY part %s cannot be restricted by IN relation (only the first and last parts can)", cname));
+                }
 
                 previous = cname;
             }
@@ -1039,7 +1066,7 @@ public class SelectStatement implements CQLStatement
 
         public boolean isInclusive(Bound b)
         {
-            return boundInclusive[b.idx];
+            return bounds[b.idx] == null || boundInclusive[b.idx];
         }
 
         public Relation.Type getRelation(Bound b)
@@ -1080,11 +1107,11 @@ public class SelectStatement implements CQLStatement
                     b = Bound.START;
                     inclusive = true;
                     break;
-                case LTE:
+                case LT:
                     b = Bound.END;
-                    inclusive = true;
+                    inclusive = false;
                     break;
-                case LT:
+                case LTE:
                     b = Bound.END;
                     inclusive = true;
                     break;
@@ -1095,6 +1122,22 @@ public class SelectStatement implements CQLStatement
             bounds[b.idx] = t;
             boundInclusive[b.idx] = inclusive;
         }
+
+        @Override
+        public String toString()
+        {
+            if (eqValues == null)
+            {
+                return String.format("SLICE(%s %s, %s %s)", boundInclusive[0] ? ">=" : ">",
+                                                            bounds[0],
+                                                            boundInclusive[1] ? "<=" : "<",
+                                                            bounds[1]);
+            }
+            else
+            {
+                return String.format("EQ(%s)", eqValues);
+            }
+        }
     }
 
     public static class Parameters