adelapena commented on code in PR #2556:
URL: https://github.com/apache/cassandra/pull/2556#discussion_r1289970266


##########
src/java/org/apache/cassandra/cql3/restrictions/ClusteringColumnRestrictions.java:
##########
@@ -92,61 +92,46 @@ public ClusteringColumnRestrictions mergeWith(Restriction 
restriction, @Nullable
         return new ClusteringColumnRestrictions(this.comparator, 
newRestrictionSet, allowFiltering);
     }
 
-    private boolean hasMultiColumnSlice()
-    {
-        for (SingleRestriction restriction : restrictions)
-        {
-            if (restriction.isMultiColumn() && restriction.isSlice())
-                return true;
-        }
-        return false;
-    }
-
     public NavigableSet<Clustering<?>> valuesAsClustering(QueryOptions 
options, ClientState state) throws InvalidRequestException
     {
-        MultiCBuilder builder = MultiCBuilder.create(comparator, hasIN());
+        MultiCBuilder builder = MultiCBuilder.create(comparator);
         for (SingleRestriction r : restrictions)
         {
             r.appendTo(builder, options);
 
             if (hasIN() && Guardrails.inSelectCartesianProduct.enabled(state))

Review Comment:
   I understand that the guardrails `partitionKeysInSelect` and 
`inSelectCartesianProduct` shouldn't consider the new `NOT IN` restrictions. 
That operator uses filtering and as such doesn't have the same performance 
issues the guardrails try to protect us from.



##########
src/java/org/apache/cassandra/cql3/restrictions/ClusteringColumnRestrictions.java:
##########
@@ -92,61 +92,46 @@ public ClusteringColumnRestrictions mergeWith(Restriction 
restriction, @Nullable
         return new ClusteringColumnRestrictions(this.comparator, 
newRestrictionSet, allowFiltering);
     }
 
-    private boolean hasMultiColumnSlice()
-    {
-        for (SingleRestriction restriction : restrictions)
-        {
-            if (restriction.isMultiColumn() && restriction.isSlice())
-                return true;
-        }
-        return false;
-    }
-
     public NavigableSet<Clustering<?>> valuesAsClustering(QueryOptions 
options, ClientState state) throws InvalidRequestException
     {
-        MultiCBuilder builder = MultiCBuilder.create(comparator, hasIN());
+        MultiCBuilder builder = MultiCBuilder.create(comparator);
         for (SingleRestriction r : restrictions)
         {
             r.appendTo(builder, options);
 
             if (hasIN() && Guardrails.inSelectCartesianProduct.enabled(state))
                 Guardrails.inSelectCartesianProduct.guard(builder.buildSize(), 
"clustering key", false, state);
 
-            if (builder.hasMissingElements())
+            if (builder.buildSize() == 0)

Review Comment:
   There are four calls to `builder.buildSize() == 0`, maybe we could add an 
`MultiCBuilder#isEmpty()` method?



##########
src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java:
##########
@@ -414,38 +398,56 @@ protected boolean isSupportedBy(Index index)
         @Override
         public String toString()
         {
-            return String.format("SLICE%s", slice);
+            return String.format("SLICE{%s, NOT IN %s}", slice, skippedValues);
         }
 
-        private SliceRestriction(ColumnMetadata columnDef, TermSlice slice)
-        {
-            super(columnDef);
-            this.slice = slice;
-        }
     }
 
-    // This holds CONTAINS, CONTAINS_KEY, and map[key] = value restrictions 
because we might want to have any combination of them.
+
+    // This holds CONTAINS, CONTAINS_KEY, NOT CONTAINS, NOT CONTAINS KEY and 
map[key] = value restrictions because we might want to have any combination of 
them.
     public static final class ContainsRestriction extends 
SingleColumnRestriction
     {
         private final List<Term> values = new ArrayList<>(); // for CONTAINS
-        private final List<Term> keys = new ArrayList<>(); // for CONTAINS_KEY
-        private final List<Term> entryKeys = new ArrayList<>(); // for 
map[key] = value
+        private final List<Term> negativeValues = new ArrayList<>(); // for 
NOT_CONTAINS

Review Comment:
   Nit: can we move the private constructor at the bottom of the class to the 
top, so it's together with the other constructors? That way I think it would be 
easier to understand that there can be instances with both positive and 
negative term lists (from `doMergeWith`).



##########
src/java/org/apache/cassandra/cql3/restrictions/SingleColumnRestriction.java:
##########
@@ -414,38 +398,56 @@ protected boolean isSupportedBy(Index index)
         @Override
         public String toString()
         {
-            return String.format("SLICE%s", slice);
+            return String.format("SLICE{%s, NOT IN %s}", slice, skippedValues);
         }
 
-        private SliceRestriction(ColumnMetadata columnDef, TermSlice slice)
-        {
-            super(columnDef);
-            this.slice = slice;
-        }
     }
 
-    // This holds CONTAINS, CONTAINS_KEY, and map[key] = value restrictions 
because we might want to have any combination of them.
+
+    // This holds CONTAINS, CONTAINS_KEY, NOT CONTAINS, NOT CONTAINS KEY and 
map[key] = value restrictions because we might want to have any combination of 
them.
     public static final class ContainsRestriction extends 
SingleColumnRestriction
     {
         private final List<Term> values = new ArrayList<>(); // for CONTAINS
-        private final List<Term> keys = new ArrayList<>(); // for CONTAINS_KEY
-        private final List<Term> entryKeys = new ArrayList<>(); // for 
map[key] = value
+        private final List<Term> negativeValues = new ArrayList<>(); // for 
NOT_CONTAINS
+        private List<Term> keys = new ArrayList<>(); // for CONTAINS_KEY
+        private final List<Term> negativeKeys = new ArrayList<>(); // for 
NOT_CONTAINS_KEY
+        private List<Term> entryKeys = new ArrayList<>(); // for map[key] = 
value
         private final List<Term> entryValues = new ArrayList<>(); // for 
map[key] = value
+        private List<Term> negativeEntryKeys = new ArrayList<>(); // for 
map[key] != value
+        private List<Term> negativeEntryValues = new ArrayList<>(); // for 
map[key] != value

Review Comment:
   All can be `final`.



##########
src/java/org/apache/cassandra/db/MultiCBuilder.java:
##########
@@ -19,104 +19,155 @@
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.NavigableSet;
 
+import org.apache.cassandra.cql3.statements.Bound;
+import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.schema.ColumnMetadata;
 import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.UniqueComparator;
 import org.apache.cassandra.utils.btree.BTreeSet;
 
 /**
  * Builder that allow to build multiple Clustering/ClusteringBound at the same 
time.
  */
-public abstract class MultiCBuilder
+public class MultiCBuilder
 {
+    /**
+     * Represents a building block of a clustering.
+     * Either a point (single value) or a bound.
+     * Knowing the kind of elements greatly simplifies the process of building 
clustering bounds.
+     */
+    public static class Element

Review Comment:
   Nice utility class! It's not related to the patch but, since we are here, I 
wonder if we could/should rename the class to something more explicit, like 
`MultiClusteringBuilder`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to