cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ble...@apache.org
Subject [3/6] cassandra git commit: Merge branch cassandra-2.2 into cassandra-3.0
Date Mon, 04 Jul 2016 12:45:12 GMT
Merge branch cassandra-2.2 into cassandra-3.0


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

Branch: refs/heads/trunk
Commit: 9244531ab7bb0f4d07cf9996a9bb89d5e4370f54
Parents: db61372 e06dae8
Author: Benjamin Lerer <b.lerer@gmail.com>
Authored: Mon Jul 4 14:30:55 2016 +0200
Committer: Benjamin Lerer <b.lerer@gmail.com>
Committed: Mon Jul 4 14:31:46 2016 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |  3 +
 .../restrictions/MultiColumnRestriction.java    |  2 +-
 .../restrictions/PrimaryKeyRestrictionSet.java  | 82 ++++----------------
 .../restrictions/StatementRestrictions.java     | 41 ++++++++--
 .../SelectMultiColumnRelationTest.java          | 33 +++++++-
 .../cql3/validation/operations/SelectTest.java  | 61 +++++++++++++++
 6 files changed, 144 insertions(+), 78 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index f12d704,451575c..2df77e1
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,17 -1,11 +1,20 @@@
 -2.2.8
 +3.0.9
 + * Avoid digest mismatch with empty but static rows (CASSANDRA-12090)
 + * Fix EOF exception when altering column type (CASSANDRA-11820)
 +Merged from 2.2:
   * MemoryUtil.getShort() should return an unsigned short also for architectures not supporting
unaligned memory accesses (CASSANDRA-11973)
+ Merged from 2.1:
+  * Fix filtering on clustering columns when 2i is used (CASSANDRA-11907)
 - * Account for partition deletions in tombstone histogram (CASSANDRA-12112)
+ 
  
 -2.2.7
 +3.0.8
 + * Fix potential race in schema during new table creation (CASSANDRA-12083)
 + * cqlsh: fix error handling in rare COPY FROM failure scenario (CASSANDRA-12070)
 + * Disable autocompaction during drain (CASSANDRA-11878)
 + * Add a metrics timer to MemtablePool and use it to track time spent blocked on memory
in MemtableAllocator (CASSANDRA-11327)
 + * Fix upgrading schema with super columns with non-text subcomparators (CASSANDRA-12023)
 + * Add TimeWindowCompactionStrategy (CASSANDRA-9666)
 +Merged from 2.2:
   * Allow nodetool info to run with readonly JMX access (CASSANDRA-11755)
   * Validate bloom_filter_fp_chance against lowest supported
     value when the table is created (CASSANDRA-11920)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
index 4329b6e,51e2ce4..9d33bb1
--- a/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/MultiColumnRestriction.java
@@@ -473,11 -471,11 +473,11 @@@ public abstract class MultiColumnRestri
          }
  
          @Override
 -        public final void addIndexExpressionTo(List<IndexExpression> expressions,
 -                                               SecondaryIndexManager indexManager,
 -                                               QueryOptions options) throws InvalidRequestException
 +        public final void addRowFilterTo(RowFilter filter,
 +                                         SecondaryIndexManager indexManager,
 +                                         QueryOptions options) throws InvalidRequestException
          {
-             throw invalidRequest("Slice restrictions are not supported on indexed columns");
+             throw invalidRequest("Multi-column slice restrictions cannot be used for filtering.");
          }
  
          @Override

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
index 061284b,e1cbc29..a5f4a24
--- a/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/PrimaryKeyRestrictionSet.java
@@@ -25,14 -26,11 +25,13 @@@ import org.apache.cassandra.config.Colu
  import org.apache.cassandra.cql3.QueryOptions;
  import org.apache.cassandra.cql3.functions.Function;
  import org.apache.cassandra.cql3.statements.Bound;
 -import org.apache.cassandra.db.IndexExpression;
 -import org.apache.cassandra.db.composites.*;
 -import org.apache.cassandra.db.composites.Composite.EOC;
 -import org.apache.cassandra.db.index.SecondaryIndexManager;
 +import org.apache.cassandra.db.*;
 +import org.apache.cassandra.db.filter.RowFilter;
  import org.apache.cassandra.exceptions.InvalidRequestException;
 +import org.apache.cassandra.index.SecondaryIndexManager;
 +import org.apache.cassandra.utils.btree.BTreeSet;
 +
- import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
 +import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
  
  /**
   * A set of single column restrictions on a primary key part (partition key or clustering
key).
@@@ -64,72 -62,18 +63,26 @@@ final class PrimaryKeyRestrictionSet ex
       */
      private boolean contains;
  
 -    public PrimaryKeyRestrictionSet(CType ctype)
 +    /**
 +     * <code>true</code> if the restrictions corresponding to a partition key,
<code>false</code> if it's clustering columns.
 +     */
 +    private boolean isPartitionKey;
 +
-     /**
-      * If restrictions apply to clustering columns, we need to check whether they can be
satisfied by an index lookup
-      * as this affects which other restrictions can legally be specified (if an index is
present, we are more lenient
-      * about what additional filtering can be performed on the results of a lookup - see
CASSANDRA-11510).
-      *
-      * We don't hold a reference to the SecondaryIndexManager itself as this is not strictly
a singleton (although
-      * we often treat is as one), the field would also require annotation with @Unmetered
to avoid blowing up the
-      * object size (used when calculating the size of prepared statements for caching).
Instead, we refer to the
-      * CFMetaData and retrieve the index manager when necessary.
-      *
-      * There are a couple of scenarios where the CFM can be null (and we make sure and test
for null when we use it):
-      *  * where an empty set of restrictions are created for use in processing query results
- see
-      *    SelectStatement.forSelection
-      *  * where the restrictions apply to partition keys and not clustering columns e.g.
-      *    StatementRestrictions.partitionKeyRestrictions
-      *  * in unit tests (in particular PrimaryKeyRestrictionSetTest which is primarily concerned
with the correct
-      *    generation of bounds when secondary indexes are not used).
-      */
-     private final CFMetaData cfm;
- 
 +    public PrimaryKeyRestrictionSet(ClusteringComparator comparator, boolean isPartitionKey)
      {
-        this(comparator, isPartitionKey, null);
-     }
- 
-     public PrimaryKeyRestrictionSet(ClusteringComparator comparator, boolean isPartitionKey,
CFMetaData cfm)
-     {
 -        super(ctype);
 +        super(comparator);
 +
-         if (cfm != null)
-             assert !isPartitionKey;
- 
-         this.cfm = cfm;
          this.restrictions = new RestrictionSet();
          this.eq = true;
 +        this.isPartitionKey = isPartitionKey;
      }
  
      private PrimaryKeyRestrictionSet(PrimaryKeyRestrictionSet primaryKeyRestrictions,
                                       Restriction restriction) throws InvalidRequestException
      {
 -        super(primaryKeyRestrictions.ctype);
 +        super(primaryKeyRestrictions.comparator);
          this.restrictions = primaryKeyRestrictions.restrictions.addRestriction(restriction);
 +        this.isPartitionKey = primaryKeyRestrictions.isPartitionKey;
-         this.cfm = primaryKeyRestrictions.cfm;
- 
-         if (!primaryKeyRestrictions.isEmpty() && !hasSupportingIndex(restriction))
-         {
-             ColumnDefinition lastRestrictionStart = primaryKeyRestrictions.restrictions.lastRestriction().getFirstColumn();
-             ColumnDefinition newRestrictionStart = restriction.getFirstColumn();
- 
-             checkFalse(primaryKeyRestrictions.isSlice() && newRestrictionStart.position()
> lastRestrictionStart.position(),
-                        "Clustering column \"%s\" cannot be restricted (preceding column
\"%s\" is restricted by a non-EQ relation)",
-                        newRestrictionStart.name,
-                        lastRestrictionStart.name);
- 
-             if (newRestrictionStart.position() < lastRestrictionStart.position() &&
restriction.isSlice())
-                 throw invalidRequest("PRIMARY KEY column \"%s\" cannot be restricted (preceding
column \"%s\" is restricted by a non-EQ relation)",
-                                      restrictions.nextColumn(newRestrictionStart).name,
-                                      newRestrictionStart.name);
-         }
  
          if (restriction.isSlice() || primaryKeyRestrictions.isSlice())
              this.slice = true;
@@@ -141,22 -85,6 +94,15 @@@
              this.eq = true;
      }
  
 +    private List<ByteBuffer> toByteBuffers(SortedSet<? extends ClusteringPrefix>
clusterings)
 +    {
 +        // It's currently a tad hard to follow that this is only called for partition key
so we should fix that
 +        List<ByteBuffer> l = new ArrayList<>(clusterings.size());
 +        for (ClusteringPrefix clustering : clusterings)
 +            l.add(CFMetaData.serializePartitionKey(clustering));
 +        return l;
 +    }
 +
-     private boolean hasSupportingIndex(Restriction restriction)
-     {
-         return cfm != null
-                && restriction.hasSupportingIndex(Keyspace.openAndGetStore(cfm).indexManager);
- 
-     }
- 
      @Override
      public boolean isSlice()
      {
@@@ -319,16 -338,22 +265,15 @@@
  
          for (Restriction restriction : restrictions)
          {
--            ColumnDefinition columnDef = restriction.getFirstColumn();
 -
 -            // PrimaryKeyRestrictionSet contains only one kind of column, either partition
key or clustering columns.
 -            // Therefore we only need to check the column kind once. All the other columns
will be of the same kind.
 -            if (clusteringColumns == null)
 -                clusteringColumns = columnDef.isClusteringColumn() ? Boolean.TRUE : Boolean.FALSE;
--
              // We ignore all the clustering columns that can be handled by slices.
-             if (!isPartitionKey && !restriction.isContains()&& position
== columnDef.position())
 -            if (!clusteringColumns || handleInFilter(restriction, position) || restriction.hasSupportingIndex(indexManager))
++            if (isPartitionKey || handleInFilter(restriction, position) || restriction.hasSupportingIndex(indexManager))
              {
-                 position = restriction.getLastColumn().position() + 1;
-                 if (!restriction.hasSupportingIndex(indexManager))
-                     continue;
 -                restriction.addIndexExpressionTo(expressions, indexManager, options);
++                restriction.addRowFilterTo(filter, indexManager, options);
+                 continue;
              }
-             restriction.addRowFilterTo(filter, indexManager, options);
+ 
+             if (!restriction.isSlice())
+                 position = restriction.getLastColumn().position() + 1;
          }
      }
  

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
----------------------------------------------------------------------
diff --cc src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
index ae0c9c4,1547210..647d22f
--- a/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
+++ b/src/java/org/apache/cassandra/cql3/restrictions/StatementRestrictions.java
@@@ -27,22 -28,17 +27,20 @@@ import org.apache.cassandra.config.Colu
  import org.apache.cassandra.cql3.*;
  import org.apache.cassandra.cql3.functions.Function;
  import org.apache.cassandra.cql3.statements.Bound;
 +import org.apache.cassandra.cql3.statements.StatementType;
  import org.apache.cassandra.db.*;
 -import org.apache.cassandra.db.composites.Composite;
 -import org.apache.cassandra.db.index.SecondaryIndexManager;
 +import org.apache.cassandra.db.filter.RowFilter;
 +import org.apache.cassandra.db.marshal.AbstractType;
  import org.apache.cassandra.dht.*;
  import org.apache.cassandra.exceptions.InvalidRequestException;
 -import org.apache.cassandra.service.StorageService;
 +import org.apache.cassandra.index.Index;
 +import org.apache.cassandra.index.SecondaryIndexManager;
 +import org.apache.cassandra.net.MessagingService;
  import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.btree.BTreeSet;
  
 -import static org.apache.cassandra.config.ColumnDefinition.toIdentifiers;
  import static org.apache.cassandra.cql3.statements.RequestValidations.checkFalse;
  import static org.apache.cassandra.cql3.statements.RequestValidations.checkNotNull;
- import static org.apache.cassandra.cql3.statements.RequestValidations.checkTrue;
  import static org.apache.cassandra.cql3.statements.RequestValidations.invalidRequest;
  
  /**
@@@ -125,58 -110,28 +123,58 @@@ public final class StatementRestriction
                                   VariableSpecifications boundNames,
                                   boolean selectsOnlyStaticColumns,
                                   boolean selectACollection,
-                                  boolean useFiltering,
 -                                 boolean allowFiltering)
++                                 boolean allowFiltering,
 +                                 boolean forView) throws InvalidRequestException
      {
 +        this.type = type;
          this.cfm = cfm;
 -        this.partitionKeyRestrictions = new PrimaryKeyRestrictionSet(cfm.getKeyValidatorAsCType());
 -        this.clusteringColumnsRestrictions = new PrimaryKeyRestrictionSet(cfm.comparator);
 +        this.partitionKeyRestrictions = new PrimaryKeyRestrictionSet(cfm.getKeyValidatorAsClusteringComparator(),
true);
-         this.clusteringColumnsRestrictions = new PrimaryKeyRestrictionSet(cfm.comparator,
false, cfm);
++        this.clusteringColumnsRestrictions = new PrimaryKeyRestrictionSet(cfm.comparator,
false);
          this.nonPrimaryKeyRestrictions = new RestrictionSet();
 +        this.notNullColumns = new HashSet<>();
  
          /*
 -         * WHERE clause. For a given entity, rules are: - EQ relation conflicts with anything
else (including a 2nd EQ)
 -         * - Can't have more than one LT(E) relation (resp. GT(E) relation) - IN relation
are restricted to row keys
 -         * (for now) and conflicts with anything else (we could allow two IN for the same
entity but that doesn't seem
 -         * very useful) - The value_alias cannot be restricted in any way (we don't support
wide rows with indexed value
 -         * in CQL so far)
 +         * WHERE clause. For a given entity, rules are:
 +         *   - EQ relation conflicts with anything else (including a 2nd EQ)
 +         *   - Can't have more than one LT(E) relation (resp. GT(E) relation)
 +         *   - IN relation are restricted to row keys (for now) and conflicts with anything
else (we could
 +         *     allow two IN for the same entity but that doesn't seem very useful)
 +         *   - The value_alias cannot be restricted in any way (we don't support wide rows
with indexed value
 +         *     in CQL so far)
           */
 -        for (Relation relation : whereClause)
 -            addRestriction(relation.toRestriction(cfm, boundNames));
 +        for (Relation relation : whereClause.relations)
 +        {
 +            if (relation.operator() == Operator.IS_NOT)
 +            {
 +                if (!forView)
 +                    throw new InvalidRequestException("Unsupported restriction: " + relation);
 +
 +                for (ColumnDefinition def : relation.toRestriction(cfm, boundNames).getColumnDefs())
 +                    this.notNullColumns.add(def);
 +            }
 +            else
 +            {
 +                addRestriction(relation.toRestriction(cfm, boundNames));
 +            }
 +        }
 +
 +        boolean hasQueriableClusteringColumnIndex = false;
 +        boolean hasQueriableIndex = false;
  
 -        SecondaryIndexManager secondaryIndexManager = Keyspace.open(cfm.ksName).getColumnFamilyStore(cfm.cfName).indexManager;
 -        boolean hasQueriableClusteringColumnIndex = clusteringColumnsRestrictions.hasSupportingIndex(secondaryIndexManager);
 -        boolean hasQueriableIndex = hasQueriableClusteringColumnIndex
 -                || partitionKeyRestrictions.hasSupportingIndex(secondaryIndexManager)
 -                || nonPrimaryKeyRestrictions.hasSupportingIndex(secondaryIndexManager);
 +        if (type.allowUseOfSecondaryIndices())
 +        {
 +            ColumnFamilyStore cfs = Keyspace.open(cfm.ksName).getColumnFamilyStore(cfm.cfName);
 +            SecondaryIndexManager secondaryIndexManager = cfs.indexManager;
 +
 +            if (whereClause.containsCustomExpressions())
 +                processCustomIndexExpressions(whereClause.expressions, boundNames, secondaryIndexManager);
 +
 +            hasQueriableClusteringColumnIndex = clusteringColumnsRestrictions.hasSupportingIndex(secondaryIndexManager);
 +            hasQueriableIndex = !indexRestrictions.getCustomIndexExpressions().isEmpty()
 +                    || hasQueriableClusteringColumnIndex
 +                    || partitionKeyRestrictions.hasSupportingIndex(secondaryIndexManager)
 +                    || nonPrimaryKeyRestrictions.hasSupportingIndex(secondaryIndexManager);
 +        }
  
          // At this point, the select statement if fully constructed, but we still have a
few things to validate
          processPartitionKeyRestrictions(hasQueriableIndex);
@@@ -220,19 -159,17 +218,19 @@@
          // there is restrictions not covered by the PK.
          if (!nonPrimaryKeyRestrictions.isEmpty())
          {
 -            if (!hasQueriableIndex)
 +            if (!type.allowNonPrimaryKeyInWhereClause())
              {
 -                // Filtering for non-index query is only supported for thrift static CFs
 -                if (cfm.comparator.isDense() ||  cfm.comparator.isCompound())
 -                    throw invalidRequest("Predicates on non-primary-key columns (%s) are
not yet supported for non secondary index queries",
 -                                         Joiner.on(", ").join(toIdentifiers(nonPrimaryKeyRestrictions.getColumnDefs())));
 +                Collection<ColumnIdentifier> nonPrimaryKeyColumns =
 +                        ColumnDefinition.toIdentifiers(nonPrimaryKeyRestrictions.getColumnDefs());
  
 -                if (!allowFiltering)
 -                    throw invalidRequest(REQUIRES_ALLOW_FILTERING_MESSAGE);
 +                throw invalidRequest("Non PRIMARY KEY columns found in where clause: %s
",
 +                                     Joiner.on(", ").join(nonPrimaryKeyColumns));
              }
 -            usesSecondaryIndexing = true;
 +            if (hasQueriableIndex)
 +                usesSecondaryIndexing = true;
-             else if (!useFiltering)
++            else if (!allowFiltering)
 +                throw invalidRequest(StatementRestrictions.REQUIRES_ALLOW_FILTERING_MESSAGE);
 +
              indexRestrictions.add(nonPrimaryKeyRestrictions);
          }
  
@@@ -435,60 -299,78 +433,93 @@@
       * Processes the clustering column restrictions.
       *
       * @param hasQueriableIndex <code>true</code> if some of the queried data
are indexed, <code>false</code> otherwise
 +     * @param selectsOnlyStaticColumns <code>true</code> if the selected or
modified columns are all statics,
 +     * <code>false</code> otherwise.
       * @param selectACollection <code>true</code> if the query should return
a collection column
 -     * @throws InvalidRequestException if the request is invalid
       */
      private void processClusteringColumnsRestrictions(boolean hasQueriableIndex,
 -                                                      boolean selectACollection) throws
InvalidRequestException
 +                                                      boolean selectsOnlyStaticColumns,
 +                                                      boolean selectACollection,
 +                                                      boolean forView) throws InvalidRequestException
      {
+         validateClusteringRestrictions(hasQueriableIndex);
+ 
 -        checkFalse(clusteringColumnsRestrictions.isIN() && selectACollection,
 -                   "Cannot restrict clustering columns by IN relations when a collection
is selected by the query");
 -        checkFalse(clusteringColumnsRestrictions.isContains() && !hasQueriableIndex,
 -                   "Cannot restrict clustering columns by a CONTAINS relation without a
secondary index");
 +        checkFalse(!type.allowClusteringColumnSlices() && clusteringColumnsRestrictions.isSlice(),
 +                   "Slice restrictions are not supported on the clustering columns in %s
statements", type);
  
 -        if (hasClusteringColumnsRestriction() && clusteringRestrictionsNeedFiltering())
 +        if (!type.allowClusteringColumnSlices()
 +               && (!cfm.isCompactTable() || (cfm.isCompactTable() && !hasClusteringColumnsRestriction())))
          {
 -            if (hasQueriableIndex)
 -            {
 -                usesSecondaryIndexing = true;
 -                return;
 -            }
 -
 -            List<ColumnDefinition> clusteringColumns = cfm.clusteringColumns();
 -            List<ColumnDefinition> restrictedColumns = new LinkedList<>(clusteringColumnsRestrictions.getColumnDefs());
 +            if (!selectsOnlyStaticColumns && hasUnrestrictedClusteringColumns())
 +                throw invalidRequest("Some clustering keys are missing: %s",
 +                                     Joiner.on(", ").join(getUnrestrictedClusteringColumns()));
 +        }
 +        else
 +        {
 +            checkFalse(clusteringColumnsRestrictions.isIN() && selectACollection,
 +                       "Cannot restrict clustering columns by IN relations when a collection
is selected by the query");
 +            checkFalse(clusteringColumnsRestrictions.isContains() && !hasQueriableIndex,
 +                       "Cannot restrict clustering columns by a CONTAINS relation without
a secondary index");
  
 -            for (int i = 0, m = restrictedColumns.size(); i < m; i++)
 +            if (hasClusteringColumnsRestriction() && clusteringRestrictionsNeedFiltering())
              {
 -                ColumnDefinition clusteringColumn = clusteringColumns.get(i);
 -                ColumnDefinition restrictedColumn = restrictedColumns.get(i);
 +                if (hasQueriableIndex || forView)
 +                {
 +                    usesSecondaryIndexing = true;
 +                    return;
 +                }
  
 -                if (!clusteringColumn.equals(restrictedColumn))
 +                List<ColumnDefinition> clusteringColumns = cfm.clusteringColumns();
 +                List<ColumnDefinition> restrictedColumns = new LinkedList<>(clusteringColumnsRestrictions.getColumnDefs());
 +
 +                for (int i = 0, m = restrictedColumns.size(); i < m; i++)
                  {
 -                    throw invalidRequest(
 -                              "PRIMARY KEY column \"%s\" cannot be restricted as preceding
column \"%s\" is not restricted",
 -                              restrictedColumn.name,
 -                              clusteringColumn.name);
 +                    ColumnDefinition clusteringColumn = clusteringColumns.get(i);
 +                    ColumnDefinition restrictedColumn = restrictedColumns.get(i);
 +
 +                    if (!clusteringColumn.equals(restrictedColumn))
 +                    {
 +                        throw invalidRequest(
 +                           "PRIMARY KEY column \"%s\" cannot be restricted as preceding
column \"%s\" is not restricted",
 +                            restrictedColumn.name,
 +                            clusteringColumn.name);
 +                    }
                  }
              }
          }
      }
  
+     /**
+      * Validates whether or not restrictions are allowed for execution when secondary index
is not used.
+      */
+     public final void validateClusteringRestrictions(boolean hasQueriableIndex)
+     {
+         assert clusteringColumnsRestrictions instanceof PrimaryKeyRestrictionSet;
+ 
+         // If there's a queriable index, filtering will take care of clustering restrictions
+         if (hasQueriableIndex)
+             return;
+ 
 -        Iterator<Restriction> iter = ((PrimaryKeyRestrictionSet)clusteringColumnsRestrictions).iterator();
++        Iterator<Restriction> iter = ((PrimaryKeyRestrictionSet) clusteringColumnsRestrictions).iterator();
+         Restriction previousRestriction = null;
 -
+         while (iter.hasNext())
+         {
+             Restriction restriction = iter.next();
+ 
+             if (previousRestriction != null)
+             {
+                 ColumnDefinition lastRestrictionStart = previousRestriction.getFirstColumn();
+                 ColumnDefinition newRestrictionStart = restriction.getFirstColumn();
+ 
+                 if (previousRestriction.isSlice() && newRestrictionStart.position()
> lastRestrictionStart.position())
+                     throw invalidRequest("Clustering column \"%s\" cannot be restricted
(preceding column \"%s\" is restricted by a non-EQ relation)",
+                                          newRestrictionStart.name,
+                                          lastRestrictionStart.name);
+             }
+             previousRestriction = restriction;
+         }
+     }
+ 
      public final boolean clusteringRestrictionsNeedFiltering()
      {
          assert clusteringColumnsRestrictions instanceof PrimaryKeyRestrictionSet;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
index 0db0039,0975662..ce74fe2
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectMultiColumnRelationTest.java
@@@ -885,19 -874,33 +885,46 @@@ public class SelectMultiColumnRelationT
      }
  
      @Test
+     public void testMultiColumnRestrictionsWithIndex() throws Throwable
+     {
+         createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, v int, PRIMARY
KEY (a, b, c, d, e))");
+         createIndex("CREATE INDEX ON %s (v)");
+         for (int i = 1; i <= 5; i++)
+         {
+             execute("INSERT INTO %s (a,b,c,d,e,v) VALUES (?,?,?,?,?,?)", 0, i, 0, 0, 0,
0);
+             execute("INSERT INTO %s (a,b,c,d,e,v) VALUES (?,?,?,?,?,?)", 0, i, i, 0, 0,
0);
+             execute("INSERT INTO %s (a,b,c,d,e,v) VALUES (?,?,?,?,?,?)", 0, i, i, i, 0,
0);
+             execute("INSERT INTO %s (a,b,c,d,e,v) VALUES (?,?,?,?,?,?)", 0, i, i, i, i,
0);
+             execute("INSERT INTO %s (a,b,c,d,e,v) VALUES (?,?,?,?,?,?)", 0, i, i, i, i,
i);
+         }
+ 
+         String errorMsg = "Multi-column slice restrictions cannot be used for filtering.";
+         assertInvalidMessage(errorMsg,
+                              "SELECT * FROM %s WHERE a = 0 AND (c,d) < (2,2) AND v =
0 ALLOW FILTERING");
+         assertInvalidMessage(errorMsg,
+                              "SELECT * FROM %s WHERE a = 0 AND (d,e) < (2,2) AND b =
1 AND v = 0 ALLOW FILTERING");
+         assertInvalidMessage(errorMsg,
+                              "SELECT * FROM %s WHERE a = 0 AND b = 1 AND (d,e) < (2,2)
AND v = 0 ALLOW FILTERING");
+         assertInvalidMessage(errorMsg,
+                              "SELECT * FROM %s WHERE a = 0 AND b > 1 AND (d,e) < (2,2)
AND v = 0 ALLOW FILTERING");
+         assertInvalidMessage(errorMsg,
+                              "SELECT * FROM %s WHERE a = 0 AND (b,c) > (1,0) AND (d,e)
< (2,2) AND v = 0 ALLOW FILTERING");
+     }
+ 
+     @Test
 +    public void testMultipleClusteringWithIndexAndValueOver64K() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (a int, b blob, c int, d int, PRIMARY KEY (a, b, c))");
 +        createIndex("CREATE INDEX ON %s (b)");
 +
 +        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, ByteBufferUtil.bytes(1),
0, 0);
 +        execute("INSERT INTO %s (a, b, c, d) VALUES (?, ?, ?, ?)", 0, ByteBufferUtil.bytes(2),
1, 0);
 +
 +        assertInvalidMessage("Index expression values may not be larger than 64K",
 +                             "SELECT * FROM %s WHERE (b, c) = (?, ?) AND d = ?  ALLOW FILTERING",
TOO_BIG, 1, 2);
 +    }
 +
 +    @Test
      public void testMultiplePartitionKeyAndMultiClusteringWithIndex() throws Throwable
      {
          createTable("CREATE TABLE %s (a int, b int, c int, d int, e int, f int, PRIMARY
KEY ((a, b), c, d, e))");

http://git-wip-us.apache.org/repos/asf/cassandra/blob/9244531a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
----------------------------------------------------------------------
diff --cc test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
index 65bfb32,c8df4c3..1b6fe9b
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/SelectTest.java
@@@ -1534,6 -1450,32 +1534,24 @@@ public class SelectTest extends CQLTest
      }
  
      @Test
 -    public void testFilteringOnStaticColumnWithoutIndices() throws Throwable
++    public void testIndexQueryWithCompositePartitionKey() throws Throwable
+     {
 -        createTable("CREATE TABLE %s (a int, b int, s int static, c int, PRIMARY KEY (a,
b))");
++        createTable("CREATE TABLE %s (p1 int, p2 int, v int, PRIMARY KEY ((p1, p2)))");
++        assertInvalidMessage("Partition key parts: p2 must be restricted as other parts
are",
++                             "SELECT * FROM %s WHERE p1 = 1 AND v = 3 ALLOW FILTERING");
+ 
 -        // Checks filtering
 -        assertInvalidMessage("Predicates on non-primary-key columns (c, s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE c = 1 AND s = 2 ALLOW FILTERING");
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE a = 1 AND b = 1 AND s = 2 ALLOW FILTERING");
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE s > 2 ALLOW FILTERING");
++        createIndex("CREATE INDEX ON %s(v)");
+ 
 -        // Checks filtering with null
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE s = null ALLOW FILTERING");
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE s > null ALLOW FILTERING");
++        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 1, 1, 3);
++        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 1, 2, 3);
++        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 2, 1, 3);
+ 
 -        // Checks filtering with unset
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE s = ? ALLOW FILTERING", unset());
 -        assertInvalidMessage("Predicates on non-primary-key columns (s) are not yet supported
for non secondary index queries",
 -                             "SELECT * FROM %s WHERE s > ? ALLOW FILTERING", unset());
++        assertRows(execute("SELECT * FROM %s WHERE p1 = 1 AND v = 3 ALLOW FILTERING"),
++                   row(1, 2, 3),
++                   row(1, 1, 3));
+     }
+ 
+     @Test
      public void testFilteringOnCompactTablesWithoutIndices() throws Throwable
      {
          //----------------------------------------------
@@@ -2515,4 -2250,93 +2533,47 @@@
                         row("a", 3, 5));
          }
      }
+ 
+     @Test
 -    public void testOverlyLargeSelectPK() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a text, b text, PRIMARY KEY ((a), b))");
 -
 -        assertInvalidThrow(InvalidRequestException.class,
 -                           "SELECT * FROM %s WHERE a = ?", new String(TOO_BIG.array()));
 -    }
 -
 -    @Test
 -    public void testOverlyLargeSelectCK() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a text, b text, PRIMARY KEY ((a), b))");
 -
 -        assertInvalidThrow(InvalidRequestException.class,
 -                           "SELECT * FROM %s WHERE a = 'foo' AND b = ?", new String(TOO_BIG.array()));
 -    }
 -
 -    @Test
 -    public void testOverlyLargeSelectKeyIn() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (a text, b text, c text, d text, PRIMARY KEY ((a, b,
c), d))");
 -
 -        assertInvalidThrow(InvalidRequestException.class,
 -                           "SELECT * FROM %s WHERE a = 'foo' AND b= 'bar' AND c IN (?, ?)",
 -                           new String(TOO_BIG.array()), new String(TOO_BIG.array()));
 -    }
 -
 -    @Test
+     public void testFilteringWithSecondaryIndex() throws Throwable
+     {
+         createTable("CREATE TABLE %s (pk int, " +
+                     "c1 int, " +
+                     "c2 int, " +
+                     "c3 int, " +
+                     "v int, " +
+                     "PRIMARY KEY (pk, c1, c2, c3))");
+         createIndex("CREATE INDEX v_idx_1 ON %s (v);");
+ 
+         for (int i = 1; i <= 5; i++)
+         {
+             execute("INSERT INTO %s (pk, c1, c2, c3, v) VALUES (?, ?, ?, ?, ?)", 1, 1, 1,
1, i);
+             execute("INSERT INTO %s (pk, c1, c2, c3, v) VALUES (?, ?, ?, ?, ?)", 1, 1, 1,
i, i);
+             execute("INSERT INTO %s (pk, c1, c2, c3, v) VALUES (?, ?, ?, ?, ?)", 1, 1, i,
i, i);
+             execute("INSERT INTO %s (pk, c1, c2, c3, v) VALUES (?, ?, ?, ?, ?)", 1, i, i,
i, i);
+         }
+ 
+         assertRows(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 > 0 AND c1 < 5 AND
c2 = 1 AND v = 3 ALLOW FILTERING;"),
+                    row(1, 1, 1, 3, 3));
+ 
+         assertEmpty(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 > 1 AND c1 < 5
AND c2 = 1 AND v = 3 ALLOW FILTERING;"));
+ 
+         assertRows(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 > 1 AND c2 > 2 AND
c3 > 2 AND v = 3 ALLOW FILTERING;"),
+                    row(1, 3, 3, 3, 3));
+ 
+         assertRows(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 > 1 AND c2 > 2 AND
c3 = 3 AND v = 3 ALLOW FILTERING;"),
+                    row(1, 3, 3, 3, 3));
+ 
+         assertRows(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 IN(0,1,2) AND c2 = 1 AND
v = 3 ALLOW FILTERING;"),
+                    row(1, 1, 1, 3, 3));
+ 
+         assertRows(execute("SELECT * FROM %s WHERE pk = 1 AND  c1 IN(0,1,2) AND c2 = 1 AND
v = 3"),
+                    row(1, 1, 1, 3, 3));
+ 
+         assertInvalidMessage("Clustering column \"c2\" cannot be restricted (preceding column
\"c1\" is restricted by a non-EQ relation)",
+                              "SELECT * FROM %s WHERE pk = 1 AND  c1 > 0 AND c1 < 5
AND c2 = 1 ALLOW FILTERING;");
+ 
+         assertInvalidMessage("PRIMARY KEY column \"c2\" cannot be restricted as preceding
column \"c1\" is not restricted",
+                              "SELECT * FROM %s WHERE pk = 1 AND  c2 = 1 ALLOW FILTERING;");
+     }
 -
 -    @Test
 -    public void testIndexQueryWithCompositePartitionKey() throws Throwable
 -    {
 -        createTable("CREATE TABLE %s (p1 int, p2 int, v int, PRIMARY KEY ((p1, p2)))");
 -        assertInvalidMessage("Partition key parts: p2 must be restricted as other parts
are",
 -                             "SELECT * FROM %s WHERE p1 = 1 AND v = 3 ALLOW FILTERING");
 -
 -        createIndex("CREATE INDEX ON %s(v)");
 -
 -        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 1, 1, 3);
 -        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 1, 2, 3);
 -        execute("INSERT INTO %s(p1, p2, v) values (?, ?, ?)", 2, 1, 3);
 -
 -        assertRows(execute("SELECT * FROM %s WHERE p1 = 1 AND v = 3 ALLOW FILTERING"),
 -                   row(1, 2, 3),
 -                   row(1, 1, 3));
 -    }
  }


Mime
View raw message