This is an automated email from the ASF dual-hosted git repository.

adelapena pushed a commit to branch cassandra-4.0
in repository https://gitbox.apache.org/repos/asf/cassandra.git

commit 5cf6db30f6b907e573c20b4f7b2958fb7e8995e1
Merge: af24242af9 0e1d068d92
Author: Andrés de la Peña <a.penya.gar...@gmail.com>
AuthorDate: Fri May 20 11:47:06 2022 +0100

    Merge branch 'cassandra-3.11' into cassandra-4.0

 CHANGES.txt                                        |   1 +
 src/java/org/apache/cassandra/cql3/Maps.java       |  11 +-
 src/java/org/apache/cassandra/cql3/Sets.java       |   2 +-
 test/unit/org/apache/cassandra/cql3/CQLTester.java |  31 +++-
 .../cql3/conditions/ColumnConditionTest.java       |   6 +-
 .../cql3/validation/entities/CollectionsTest.java  |  99 ++++++++++++
 .../cassandra/io/sstable/CQLSSTableWriterTest.java | 171 ++++++++++++++++++++-
 7 files changed, 307 insertions(+), 14 deletions(-)

diff --cc CHANGES.txt
index bf7f8137c6,d796eb9449..6c31e17981
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,6 -1,6 +1,7 @@@
 -3.11.14
 +4.0.5
 +Merged from 3.11:
  Merged from 3.0:
+  * Fix issue where frozen maps may not be serialized in the correct order 
(CASSANDRA-17623)
   * Suppress CVE-2022-24823 (CASSANDRA-17633)
   * fsync TOC and digest files (CASSANDRA-10709)
  
diff --cc src/java/org/apache/cassandra/cql3/Maps.java
index 6e7e07b576,e21fc6c5c2..3a9575c833
--- a/src/java/org/apache/cassandra/cql3/Maps.java
+++ b/src/java/org/apache/cassandra/cql3/Maps.java
@@@ -228,8 -184,9 +228,9 @@@ public abstract class Map
              {
                  // Collections have this small hack that validate cannot be 
called on a serialized object,
                  // but compose does the validation (so we're fine).
 -                Map<?, ?> m = 
type.getSerializer().deserializeForNativeProtocol(value, version);
 +                Map<?, ?> m = 
type.getSerializer().deserializeForNativeProtocol(value, 
ByteBufferAccessor.instance, version);
-                 Map<ByteBuffer, ByteBuffer> map = new 
LinkedHashMap<>(m.size());
+                 // We depend on Maps to be properly sorted by their keys, so 
use a sorted map implementation here.
+                 SortedMap<ByteBuffer, ByteBuffer> map = new 
TreeMap<>(type.getKeysType());
                  for (Map.Entry<?, ?> entry : m.entrySet())
                      map.put(type.getKeysType().decompose(entry.getKey()), 
type.getValuesType().decompose(entry.getValue()));
                  return new Value(map);
diff --cc test/unit/org/apache/cassandra/cql3/CQLTester.java
index 8d0adbfe7c,996cfc8d5e..a8ca1e5d24
--- a/test/unit/org/apache/cassandra/cql3/CQLTester.java
+++ b/test/unit/org/apache/cassandra/cql3/CQLTester.java
@@@ -31,21 -28,12 +31,23 @@@ import java.util.*
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.atomic.AtomicInteger;
 +import java.util.function.Consumer;
 +import java.util.regex.Matcher;
 +import java.util.regex.Pattern;
  import java.util.stream.Collectors;
  
 +import javax.management.MBeanServerConnection;
 +import javax.management.remote.JMXConnector;
 +import javax.management.remote.JMXConnectorFactory;
 +import javax.management.remote.JMXConnectorServer;
 +import javax.management.remote.JMXServiceURL;
 +import javax.management.remote.rmi.RMIConnectorServer;
 +
  import com.google.common.base.Objects;
 +import com.google.common.base.Strings;
  import com.google.common.collect.ImmutableSet;
+ import com.google.common.collect.Iterables;
+ 
  import org.junit.*;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
@@@ -218,39 -205,45 +220,39 @@@ public abstract class CQLTeste
  
      public static void cleanup()
      {
 -        // clean up commitlog
 -        String[] directoryNames = { 
DatabaseDescriptor.getCommitLogLocation(), };
 -        for (String dirName : directoryNames)
 -        {
 -            File dir = new File(dirName);
 -            if (!dir.exists())
 -                throw new RuntimeException("No such directory: " + 
dir.getAbsolutePath());
 -            FileUtils.deleteRecursive(dir);
 -        }
 -
 -        File cdcDir = new File(DatabaseDescriptor.getCDCLogLocation());
 -        if (cdcDir.exists())
 -            FileUtils.deleteRecursive(cdcDir);
 +        ServerTestUtils.cleanup();
 +    }
  
 -        cleanupSavedCaches();
 +    /**
 +     * Starts the JMX server. It's safe to call this method multiple times.
 +     */
 +    public static void startJMXServer() throws Exception
 +    {
 +        if (jmxServer != null)
 +            return;
  
 -        // clean up data directory which are stored as data 
directory/keyspace/data files
 -        for (String dirName : DatabaseDescriptor.getAllDataFileLocations())
 -        {
 -            File dir = new File(dirName);
 -            if (!dir.exists())
 -                throw new RuntimeException("No such directory: " + 
dir.getAbsolutePath());
 -            FileUtils.deleteRecursive(dir);
 -        }
 +        InetAddress loopback = InetAddress.getLoopbackAddress();
 +        jmxHost = loopback.getHostAddress();
 +        jmxPort = getAutomaticallyAllocatedPort(loopback);
 +        jmxServer = JMXServerUtils.createJMXServer(jmxPort, true);
 +        jmxServer.start();
      }
-     
+ 
 -    public static void mkdirs()
 +    public static void createMBeanServerConnection() throws Exception
      {
 -        DatabaseDescriptor.createAllDirectories();
 +        assert jmxServer != null : "jmxServer not started";
 +
 +        Map<String, Object> env = new HashMap<>();
 +        env.put("com.sun.jndi.rmi.factory.socket", 
RMISocketFactory.getDefaultSocketFactory());
 +        JMXConnector jmxc = JMXConnectorFactory.connect(getJMXServiceURL(), 
env);
 +        jmxConnection =  jmxc.getMBeanServerConnection();
      }
  
 -    public static void cleanupSavedCaches()
 +    public static JMXServiceURL getJMXServiceURL() throws 
MalformedURLException
      {
 -        File cachesDir = new 
File(DatabaseDescriptor.getSavedCachesLocation());
 +        assert jmxServer != null : "jmxServer not started";
  
 -        if (!cachesDir.exists() || !cachesDir.isDirectory())
 -            return;
 -
 -        FileUtils.delete(cachesDir.listFiles());
 +        return new 
JMXServiceURL(String.format("service:jmx:rmi:///jndi/rmi://%s:%d/jmxrmi", 
jmxHost, jmxPort));
      }
  
      @BeforeClass
@@@ -731,23 -643,9 +733,23 @@@
          return currentKeyspace;
      }
  
 +    protected void alterKeyspace(String query)
 +    {
 +        String fullQuery = String.format(query, currentKeyspace());
 +        logger.info(fullQuery);
 +        schemaChange(fullQuery);
 +    }
-  
++
 +    protected void alterKeyspaceMayThrow(String query) throws Throwable
 +    {
 +        String fullQuery = String.format(query, currentKeyspace());
 +        logger.info(fullQuery);
 +        QueryProcessor.executeOnceInternal(fullQuery);
 +    }
-     
++
      protected String createKeyspaceName()
      {
 -        String currentKeyspace = "keyspace_" + seqNumber.getAndIncrement();
 +        String currentKeyspace = String.format("keyspace_%02d", 
seqNumber.getAndIncrement());
          keyspaces.add(currentKeyspace);
          return currentKeyspace;
      }
@@@ -1788,13 -1612,27 +1797,27 @@@
          return ImmutableSet.copyOf(values);
      }
  
+     // LinkedHashSets are iterable in insertion order, which is important for 
some tests
+     protected LinkedHashSet<Object> linkedHashSet(Object...values)
+     {
+         LinkedHashSet<Object> s = new LinkedHashSet<>(values.length);
+         s.addAll(Arrays.asList(values));
+         return s;
+     }
+ 
      protected Object map(Object...values)
+     {
+         return linkedHashMap(values);
+     }
+ 
+     // LinkedHashMaps are iterable in insertion order, which is important for 
some tests
+     protected static LinkedHashMap<Object, Object> 
linkedHashMap(Object...values)
      {
          if (values.length % 2 != 0)
 -            throw new IllegalArgumentException();
 +            throw new IllegalArgumentException("Invalid number of arguments, 
got " + values.length);
  
          int size = values.length / 2;
-         Map<Object, Object> m = new LinkedHashMap<>(size);
+         LinkedHashMap<Object, Object> m = new LinkedHashMap<>(size);
          for (int i = 0; i < size; i++)
              m.put(values[2 * i], values[(2 * i) + 1]);
          return m;
diff --cc 
test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java
index 0035fa161d,0000000000..f62119d4e6
mode 100644,000000..100644
--- a/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/conditions/ColumnConditionTest.java
@@@ -1,555 -1,0 +1,555 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *     http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package org.apache.cassandra.cql3.conditions;
 +
 +import java.nio.ByteBuffer;
 +import java.util.*;
 +
 +import org.junit.Assert;
 +import org.junit.Test;
 +
 +import org.apache.cassandra.cql3.*;
 +import org.apache.cassandra.db.Clustering;
 +import org.apache.cassandra.db.marshal.Int32Type;
 +import org.apache.cassandra.db.marshal.ListType;
 +import org.apache.cassandra.db.marshal.MapType;
 +import org.apache.cassandra.db.marshal.SetType;
 +import org.apache.cassandra.db.rows.*;
 +import org.apache.cassandra.exceptions.InvalidRequestException;
 +import org.apache.cassandra.schema.ColumnMetadata;
 +import org.apache.cassandra.serializers.TimeUUIDSerializer;
 +import org.apache.cassandra.utils.ByteBufferUtil;
 +import org.apache.cassandra.utils.UUIDGen;
 +
 +import static org.junit.Assert.assertFalse;
 +import static org.junit.Assert.assertTrue;
 +import static org.junit.Assert.fail;
 +
 +import static org.apache.cassandra.cql3.Operator.*;
 +import static org.apache.cassandra.utils.ByteBufferUtil.EMPTY_BYTE_BUFFER;
 +
 +
 +public class ColumnConditionTest
 +{
 +    public static final ByteBuffer ZERO = Int32Type.instance.fromString("0");
 +    public static final ByteBuffer ONE = Int32Type.instance.fromString("1");
 +    public static final ByteBuffer TWO = Int32Type.instance.fromString("2");
 +
 +    private static Row newRow(ColumnMetadata definition, ByteBuffer value)
 +    {
 +        BufferCell cell = new BufferCell(definition, 0L, Cell.NO_TTL, 
Cell.NO_DELETION_TIME, value, null);
 +        return BTreeRow.singleCellRow(Clustering.EMPTY, cell);
 +    }
 +
 +    private static Row newRow(ColumnMetadata definition, List<ByteBuffer> 
values)
 +    {
 +        Row.Builder builder = BTreeRow.sortedBuilder();
 +        builder.newRow(Clustering.EMPTY);
 +        long now = System.currentTimeMillis();
 +        if (values != null)
 +        {
 +            for (int i = 0, m = values.size(); i < m; i++)
 +            {
 +                UUID uuid = UUIDGen.getTimeUUID(now, i);
 +                ByteBuffer key = TimeUUIDSerializer.instance.serialize(uuid);
 +                ByteBuffer value = values.get(i);
 +                BufferCell cell = new BufferCell(definition,
 +                                                 0L,
 +                                                 Cell.NO_TTL,
 +                                                 Cell.NO_DELETION_TIME,
 +                                                 value,
 +                                                 CellPath.create(key));
 +                builder.addCell(cell);
 +            }
 +        }
 +        return builder.build();
 +    }
 +
 +    private static Row newRow(ColumnMetadata definition, 
SortedSet<ByteBuffer> values)
 +    {
 +        Row.Builder builder = BTreeRow.sortedBuilder();
 +        builder.newRow(Clustering.EMPTY);
 +        if (values != null)
 +        {
 +            for (ByteBuffer value : values)
 +            {
 +                BufferCell cell = new BufferCell(definition,
 +                                                 0L,
 +                                                 Cell.NO_TTL,
 +                                                 Cell.NO_DELETION_TIME,
 +                                                 
ByteBufferUtil.EMPTY_BYTE_BUFFER,
 +                                                 CellPath.create(value));
 +                builder.addCell(cell);
 +            }
 +        }
 +        return builder.build();
 +    }
 +
 +    private static Row newRow(ColumnMetadata definition, Map<ByteBuffer, 
ByteBuffer> values)
 +    {
 +        Row.Builder builder = BTreeRow.sortedBuilder();
 +        builder.newRow(Clustering.EMPTY);
 +        if (values != null)
 +        {
 +            for (Map.Entry<ByteBuffer, ByteBuffer> entry : values.entrySet())
 +            {
 +                BufferCell cell = new BufferCell(definition,
 +                                                 0L,
 +                                                 Cell.NO_TTL,
 +                                                 Cell.NO_DELETION_TIME,
 +                                                 entry.getValue(),
 +                                                 
CellPath.create(entry.getKey()));
 +                builder.addCell(cell);
 +            }
 +        }
 +        return builder.build();
 +    }
 +
 +    private static boolean conditionApplies(ByteBuffer rowValue, Operator op, 
ByteBuffer conditionValue)
 +    {
 +        ColumnMetadata definition = ColumnMetadata.regularColumn("ks", "cf", 
"c", Int32Type.instance);
 +        ColumnCondition condition = ColumnCondition.condition(definition, op, 
Terms.of(new Constants.Value(conditionValue)));
 +        ColumnCondition.Bound bound = condition.bind(QueryOptions.DEFAULT);
 +        return bound.appliesTo(newRow(definition, rowValue));
 +    }
 +
 +    private static boolean conditionApplies(List<ByteBuffer> rowValue, 
Operator op, List<ByteBuffer> conditionValue)
 +    {
 +        ColumnMetadata definition = ColumnMetadata.regularColumn("ks", "cf", 
"c", ListType.getInstance(Int32Type.instance, true));
 +        ColumnCondition condition = ColumnCondition.condition(definition, op, 
Terms.of(new Lists.Value(conditionValue)));
 +        ColumnCondition.Bound bound = condition.bind(QueryOptions.DEFAULT);
 +        return bound.appliesTo(newRow(definition, rowValue));
 +    }
 +
 +    private static boolean conditionApplies(SortedSet<ByteBuffer> rowValue, 
Operator op, SortedSet<ByteBuffer> conditionValue)
 +    {
 +        ColumnMetadata definition = ColumnMetadata.regularColumn("ks", "cf", 
"c", SetType.getInstance(Int32Type.instance, true));
 +        ColumnCondition condition = ColumnCondition.condition(definition, op, 
Terms.of(new Sets.Value(conditionValue)));
 +        ColumnCondition.Bound bound = condition.bind(QueryOptions.DEFAULT);
 +        return bound.appliesTo(newRow(definition, rowValue));
 +    }
 +
-     private static boolean conditionApplies(Map<ByteBuffer, ByteBuffer> 
rowValue, Operator op, Map<ByteBuffer, ByteBuffer> conditionValue)
++    private static boolean conditionApplies(Map<ByteBuffer, ByteBuffer> 
rowValue, Operator op, SortedMap<ByteBuffer, ByteBuffer> conditionValue)
 +    {
 +        ColumnMetadata definition = ColumnMetadata.regularColumn("ks", "cf", 
"c", MapType.getInstance(Int32Type.instance, Int32Type.instance, true));
 +        ColumnCondition condition = ColumnCondition.condition(definition, op, 
Terms.of(new Maps.Value(conditionValue)));
 +        ColumnCondition.Bound bound = condition.bind(QueryOptions.DEFAULT);
 +        return bound.appliesTo(newRow(definition, rowValue));
 +    }
 +
 +    @FunctionalInterface
 +    public interface CheckedFunction {
 +        void apply();
 +    }
 +
 +    private static void assertThrowsIRE(CheckedFunction runnable, String 
errorMessage)
 +    {
 +        try
 +        {
 +            runnable.apply();
 +            fail("Expected InvalidRequestException was not thrown");
 +        } catch (InvalidRequestException e)
 +        {
 +            Assert.assertTrue("Expected error message to contain '" + 
errorMessage + "', but got '" + e.getMessage() + "'",
 +                              e.getMessage().contains(errorMessage));
 +        }
 +    }
 +
 +    @Test
 +    public void testSimpleBoundIsSatisfiedByValue() throws 
InvalidRequestException
 +    {
 +        // EQ
 +        assertTrue(conditionApplies(ONE, EQ, ONE));
 +        assertFalse(conditionApplies(TWO, EQ, ONE));
 +        assertFalse(conditionApplies(ONE, EQ, TWO));
 +        assertFalse(conditionApplies(ONE, EQ, EMPTY_BYTE_BUFFER));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, EQ, ONE));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, EQ, 
EMPTY_BYTE_BUFFER));
 +        assertFalse(conditionApplies(ONE, EQ, null));
 +        assertFalse(conditionApplies(null, EQ, ONE));
 +        assertTrue(conditionApplies((ByteBuffer) null, EQ, (ByteBuffer) 
null));
 +
 +        // NEQ
 +        assertFalse(conditionApplies(ONE, NEQ, ONE));
 +        assertTrue(conditionApplies(TWO, NEQ, ONE));
 +        assertTrue(conditionApplies(ONE, NEQ, TWO));
 +        assertTrue(conditionApplies(ONE, NEQ, EMPTY_BYTE_BUFFER));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, NEQ, ONE));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, NEQ, 
EMPTY_BYTE_BUFFER));
 +        assertTrue(conditionApplies(ONE, NEQ, null));
 +        assertTrue(conditionApplies(null, NEQ, ONE));
 +        assertFalse(conditionApplies((ByteBuffer) null, NEQ, (ByteBuffer) 
null));
 +
 +        // LT
 +        assertFalse(conditionApplies(ONE, LT, ONE));
 +        assertFalse(conditionApplies(TWO, LT, ONE));
 +        assertTrue(conditionApplies(ONE, LT, TWO));
 +        assertFalse(conditionApplies(ONE, LT, EMPTY_BYTE_BUFFER));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, LT, ONE));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, LT, 
EMPTY_BYTE_BUFFER));
 +        assertThrowsIRE(() -> conditionApplies(ONE, LT, null), "Invalid 
comparison with null for operator \"<\"");
 +        assertFalse(conditionApplies(null, LT, ONE));
 +
 +        // LTE
 +        assertTrue(conditionApplies(ONE, LTE, ONE));
 +        assertFalse(conditionApplies(TWO, LTE, ONE));
 +        assertTrue(conditionApplies(ONE, LTE, TWO));
 +        assertFalse(conditionApplies(ONE, LTE, EMPTY_BYTE_BUFFER));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, LTE, ONE));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, LTE, 
EMPTY_BYTE_BUFFER));
 +        assertThrowsIRE(() -> conditionApplies(ONE, LTE, null), "Invalid 
comparison with null for operator \"<=\"");
 +        assertFalse(conditionApplies(null, LTE, ONE));
 +
 +        // GT
 +        assertFalse(conditionApplies(ONE, GT, ONE));
 +        assertTrue(conditionApplies(TWO, GT, ONE));
 +        assertFalse(conditionApplies(ONE, GT, TWO));
 +        assertTrue(conditionApplies(ONE, GT, EMPTY_BYTE_BUFFER));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, GT, ONE));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, GT, 
EMPTY_BYTE_BUFFER));
 +        assertThrowsIRE(() -> conditionApplies(ONE, GT, null), "Invalid 
comparison with null for operator \">\"");
 +        assertFalse(conditionApplies(null, GT, ONE));
 +
 +        // GTE
 +        assertTrue(conditionApplies(ONE, GTE, ONE));
 +        assertTrue(conditionApplies(TWO, GTE, ONE));
 +        assertFalse(conditionApplies(ONE, GTE, TWO));
 +        assertTrue(conditionApplies(ONE, GTE, EMPTY_BYTE_BUFFER));
 +        assertFalse(conditionApplies(EMPTY_BYTE_BUFFER, GTE, ONE));
 +        assertTrue(conditionApplies(EMPTY_BYTE_BUFFER, GTE, 
EMPTY_BYTE_BUFFER));
 +        assertThrowsIRE(() -> conditionApplies(ONE, GTE, null), "Invalid 
comparison with null for operator \">=\"");
 +        assertFalse(conditionApplies(null, GTE, ONE));
 +    }
 +
 +    private static List<ByteBuffer> list(ByteBuffer... values)
 +    {
 +        return Arrays.asList(values);
 +    }
 +
 +    @Test
 +    // sets use the same check as lists
 +    public void testListCollectionBoundAppliesTo() throws 
InvalidRequestException
 +    {
 +        // EQ
 +        assertTrue(conditionApplies(list(ONE), EQ, list(ONE)));
 +        assertTrue(conditionApplies(list(), EQ, list()));
 +        assertFalse(conditionApplies(list(ONE), EQ, list(ZERO)));
 +        assertFalse(conditionApplies(list(ZERO), EQ, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE, ONE), EQ, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE), EQ, list(ONE, ONE)));
 +        assertFalse(conditionApplies(list(ONE), EQ, list()));
 +        assertFalse(conditionApplies(list(), EQ, list(ONE)));
 +
 +        assertFalse(conditionApplies(list(ONE), EQ, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
EQ, list(ONE)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
EQ, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // NEQ
 +        assertFalse(conditionApplies(list(ONE), NEQ, list(ONE)));
 +        assertFalse(conditionApplies(list(), NEQ, list()));
 +        assertTrue(conditionApplies(list(ONE), NEQ, list(ZERO)));
 +        assertTrue(conditionApplies(list(ZERO), NEQ, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE, ONE), NEQ, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE), NEQ, list(ONE, ONE)));
 +        assertTrue(conditionApplies(list(ONE), NEQ, list()));
 +        assertTrue(conditionApplies(list(), NEQ, list(ONE)));
 +
 +        assertTrue(conditionApplies(list(ONE), NEQ, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
NEQ, list(ONE)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
NEQ, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LT
 +        assertFalse(conditionApplies(list(ONE), LT, list(ONE)));
 +        assertFalse(conditionApplies(list(), LT, list()));
 +        assertFalse(conditionApplies(list(ONE), LT, list(ZERO)));
 +        assertTrue(conditionApplies(list(ZERO), LT, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE, ONE), LT, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE), LT, list(ONE, ONE)));
 +        assertFalse(conditionApplies(list(ONE), LT, list()));
 +        assertTrue(conditionApplies(list(), LT, list(ONE)));
 +
 +        assertFalse(conditionApplies(list(ONE), LT, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LT, list(ONE)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LT, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LTE
 +        assertTrue(conditionApplies(list(ONE), LTE, list(ONE)));
 +        assertTrue(conditionApplies(list(), LTE, list()));
 +        assertFalse(conditionApplies(list(ONE), LTE, list(ZERO)));
 +        assertTrue(conditionApplies(list(ZERO), LTE, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE, ONE), LTE, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE), LTE, list(ONE, ONE)));
 +        assertFalse(conditionApplies(list(ONE), LTE, list()));
 +        assertTrue(conditionApplies(list(), LTE, list(ONE)));
 +
 +        assertFalse(conditionApplies(list(ONE), LTE, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LTE, list(ONE)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LTE, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GT
 +        assertFalse(conditionApplies(list(ONE), GT, list(ONE)));
 +        assertFalse(conditionApplies(list(), GT, list()));
 +        assertTrue(conditionApplies(list(ONE), GT, list(ZERO)));
 +        assertFalse(conditionApplies(list(ZERO), GT, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE, ONE), GT, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE), GT, list(ONE, ONE)));
 +        assertTrue(conditionApplies(list(ONE), GT, list()));
 +        assertFalse(conditionApplies(list(), GT, list(ONE)));
 +
 +        assertTrue(conditionApplies(list(ONE), GT, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GT, list(ONE)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GT, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GTE
 +        assertTrue(conditionApplies(list(ONE), GTE, list(ONE)));
 +        assertTrue(conditionApplies(list(), GTE, list()));
 +        assertTrue(conditionApplies(list(ONE), GTE, list(ZERO)));
 +        assertFalse(conditionApplies(list(ZERO), GTE, list(ONE)));
 +        assertTrue(conditionApplies(list(ONE, ONE), GTE, list(ONE)));
 +        assertFalse(conditionApplies(list(ONE), GTE, list(ONE, ONE)));
 +        assertTrue(conditionApplies(list(ONE), GTE, list()));
 +        assertFalse(conditionApplies(list(), GTE, list(ONE)));
 +
 +        assertTrue(conditionApplies(list(ONE), GTE, 
list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GTE, list(ONE)));
 +        assertTrue(conditionApplies(list(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GTE, list(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +    }
 +
 +    private static SortedSet<ByteBuffer> set(ByteBuffer... values)
 +    {
 +        SortedSet<ByteBuffer> results = new TreeSet<>(Int32Type.instance);
 +        results.addAll(Arrays.asList(values));
 +        return results;
 +    }
 +
 +    @Test
 +    public void testSetCollectionBoundAppliesTo() throws 
InvalidRequestException
 +    {
 +        // EQ
 +        assertTrue(conditionApplies(set(ONE), EQ, set(ONE)));
 +        assertTrue(conditionApplies(set(), EQ, set()));
 +        assertFalse(conditionApplies(set(ONE), EQ, set(ZERO)));
 +        assertFalse(conditionApplies(set(ZERO), EQ, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE, TWO), EQ, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE), EQ, set(ONE, TWO)));
 +        assertFalse(conditionApplies(set(ONE), EQ, set()));
 +        assertFalse(conditionApplies(set(), EQ, set(ONE)));
 +
 +        assertFalse(conditionApplies(set(ONE), EQ, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
EQ, set(ONE)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
EQ, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // NEQ
 +        assertFalse(conditionApplies(set(ONE), NEQ, set(ONE)));
 +        assertFalse(conditionApplies(set(), NEQ, set()));
 +        assertTrue(conditionApplies(set(ONE), NEQ, set(ZERO)));
 +        assertTrue(conditionApplies(set(ZERO), NEQ, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE, TWO), NEQ, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE), NEQ, set(ONE, TWO)));
 +        assertTrue(conditionApplies(set(ONE), NEQ, set()));
 +        assertTrue(conditionApplies(set(), NEQ, set(ONE)));
 +
 +        assertTrue(conditionApplies(set(ONE), NEQ, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
NEQ, set(ONE)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
NEQ, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LT
 +        assertFalse(conditionApplies(set(ONE), LT, set(ONE)));
 +        assertFalse(conditionApplies(set(), LT, set()));
 +        assertFalse(conditionApplies(set(ONE), LT, set(ZERO)));
 +        assertTrue(conditionApplies(set(ZERO), LT, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE, TWO), LT, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE), LT, set(ONE, TWO)));
 +        assertFalse(conditionApplies(set(ONE), LT, set()));
 +        assertTrue(conditionApplies(set(), LT, set(ONE)));
 +
 +        assertFalse(conditionApplies(set(ONE), LT, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LT, set(ONE)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LT, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LTE
 +        assertTrue(conditionApplies(set(ONE), LTE, set(ONE)));
 +        assertTrue(conditionApplies(set(), LTE, set()));
 +        assertFalse(conditionApplies(set(ONE), LTE, set(ZERO)));
 +        assertTrue(conditionApplies(set(ZERO), LTE, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE, TWO), LTE, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE), LTE, set(ONE, TWO)));
 +        assertFalse(conditionApplies(set(ONE), LTE, set()));
 +        assertTrue(conditionApplies(set(), LTE, set(ONE)));
 +
 +        assertFalse(conditionApplies(set(ONE), LTE, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LTE, set(ONE)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
LTE, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GT
 +        assertFalse(conditionApplies(set(ONE), GT, set(ONE)));
 +        assertFalse(conditionApplies(set(), GT, set()));
 +        assertTrue(conditionApplies(set(ONE), GT, set(ZERO)));
 +        assertFalse(conditionApplies(set(ZERO), GT, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE, TWO), GT, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE), GT, set(ONE, TWO)));
 +        assertTrue(conditionApplies(set(ONE), GT, set()));
 +        assertFalse(conditionApplies(set(), GT, set(ONE)));
 +
 +        assertTrue(conditionApplies(set(ONE), GT, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GT, set(ONE)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GT, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GTE
 +        assertTrue(conditionApplies(set(ONE), GTE, set(ONE)));
 +        assertTrue(conditionApplies(set(), GTE, set()));
 +        assertTrue(conditionApplies(set(ONE), GTE, set(ZERO)));
 +        assertFalse(conditionApplies(set(ZERO), GTE, set(ONE)));
 +        assertTrue(conditionApplies(set(ONE, TWO), GTE, set(ONE)));
 +        assertFalse(conditionApplies(set(ONE), GTE, set(ONE, TWO)));
 +        assertTrue(conditionApplies(set(ONE), GTE, set()));
 +        assertFalse(conditionApplies(set(), GTE, set(ONE)));
 +
 +        assertTrue(conditionApplies(set(ONE), GTE, 
set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GTE, set(ONE)));
 +        assertTrue(conditionApplies(set(ByteBufferUtil.EMPTY_BYTE_BUFFER), 
GTE, set(ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +    }
 +
 +    // values should be a list of key, value, key, value, ...
-     private static Map<ByteBuffer, ByteBuffer> map(ByteBuffer... values)
++    private static SortedMap<ByteBuffer, ByteBuffer> map(ByteBuffer... values)
 +    {
-         Map<ByteBuffer, ByteBuffer> map = new TreeMap<>();
++        SortedMap<ByteBuffer, ByteBuffer> map = new TreeMap<>();
 +        for (int i = 0; i < values.length; i += 2)
 +            map.put(values[i], values[i + 1]);
 +
 +        return map;
 +    }
 +
 +    @Test
 +    public void testMapCollectionBoundIsSatisfiedByValue() throws 
InvalidRequestException
 +    {
 +        // EQ
 +        assertTrue(conditionApplies(map(ONE, ONE), EQ, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(), EQ, map()));
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, map(ZERO, ONE)));
 +        assertFalse(conditionApplies(map(ZERO, ONE), EQ, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, map(ONE, ZERO)));
 +        assertFalse(conditionApplies(map(ONE, ZERO), EQ, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE, TWO, ONE), EQ, map(ONE, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, map(ONE, ONE, TWO, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, map()));
 +        assertFalse(conditionApplies(map(), EQ, map(ONE, ONE)));
 +
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), EQ, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), EQ, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), EQ, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), EQ, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), EQ, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // NEQ
 +        assertFalse(conditionApplies(map(ONE, ONE), NEQ, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(), NEQ, map()));
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, map(ZERO, ONE)));
 +        assertTrue(conditionApplies(map(ZERO, ONE), NEQ, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, map(ONE, ZERO)));
 +        assertTrue(conditionApplies(map(ONE, ZERO), NEQ, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE, TWO, ONE), NEQ, map(ONE, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, map(ONE, ONE, TWO, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, map()));
 +        assertTrue(conditionApplies(map(), NEQ, map(ONE, ONE)));
 +
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), NEQ, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), NEQ, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), NEQ, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), NEQ, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), NEQ, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LT
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(), LT, map()));
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, map(ZERO, ONE)));
 +        assertTrue(conditionApplies(map(ZERO, ONE), LT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, map(ONE, ZERO)));
 +        assertTrue(conditionApplies(map(ONE, ZERO), LT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE, TWO, ONE), LT, map(ONE, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), LT, map(ONE, ONE, TWO, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, map()));
 +        assertTrue(conditionApplies(map(), LT, map(ONE, ONE)));
 +
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), LT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LT, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), LT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), LT, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), LT, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // LTE
 +        assertTrue(conditionApplies(map(ONE, ONE), LTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(), LTE, map()));
 +        assertFalse(conditionApplies(map(ONE, ONE), LTE, map(ZERO, ONE)));
 +        assertTrue(conditionApplies(map(ZERO, ONE), LTE, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LTE, map(ONE, ZERO)));
 +        assertTrue(conditionApplies(map(ONE, ZERO), LTE, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE, TWO, ONE), LTE, map(ONE, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), LTE, map(ONE, ONE, TWO, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LTE, map()));
 +        assertTrue(conditionApplies(map(), LTE, map(ONE, ONE)));
 +
 +        assertFalse(conditionApplies(map(ONE, ONE), LTE, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), LTE, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), LTE, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), LTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), LTE, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), LTE, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GT
 +        assertFalse(conditionApplies(map(ONE, ONE), GT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(), GT, map()));
 +        assertTrue(conditionApplies(map(ONE, ONE), GT, map(ZERO, ONE)));
 +        assertFalse(conditionApplies(map(ZERO, ONE), GT, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GT, map(ONE, ZERO)));
 +        assertFalse(conditionApplies(map(ONE, ZERO), GT, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE, TWO, ONE), GT, map(ONE, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), GT, map(ONE, ONE, TWO, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GT, map()));
 +        assertFalse(conditionApplies(map(), GT, map(ONE, ONE)));
 +
 +        assertTrue(conditionApplies(map(ONE, ONE), GT, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), GT, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GT, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), GT, map(ONE, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), GT, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), GT, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +
 +        // GTE
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(), GTE, map()));
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, map(ZERO, ONE)));
 +        assertFalse(conditionApplies(map(ZERO, ONE), GTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, map(ONE, ZERO)));
 +        assertFalse(conditionApplies(map(ONE, ZERO), GTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE, TWO, ONE), GTE, map(ONE, 
ONE)));
 +        assertFalse(conditionApplies(map(ONE, ONE), GTE, map(ONE, ONE, TWO, 
ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, map()));
 +        assertFalse(conditionApplies(map(), GTE, map(ONE, ONE)));
 +
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, 
map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertFalse(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), GTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ONE, ONE), GTE, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +        assertFalse(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), GTE, map(ONE, ONE)));
 +        assertTrue(conditionApplies(map(ByteBufferUtil.EMPTY_BYTE_BUFFER, 
ONE), GTE, map(ByteBufferUtil.EMPTY_BYTE_BUFFER, ONE)));
 +        assertTrue(conditionApplies(map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER), GTE, map(ONE, 
ByteBufferUtil.EMPTY_BYTE_BUFFER)));
 +    }
 +}
diff --cc 
test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java
index 54dd0c4c99,7424469b4c..f7848a3d03
--- 
a/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java
+++ 
b/test/unit/org/apache/cassandra/cql3/validation/entities/CollectionsTest.java
@@@ -21,14 -21,8 +21,15 @@@ import java.util.*
  
  import org.junit.Test;
  
 +import com.datastax.driver.core.ColumnDefinitions;
 +import com.datastax.driver.core.DataType;
 +import com.datastax.driver.core.ResultSet;
 +import com.datastax.driver.core.Session;
+ import com.datastax.driver.core.utils.UUIDs;
  import org.apache.cassandra.cql3.CQLTester;
 +import org.apache.cassandra.cql3.ColumnSpecification;
 +import org.apache.cassandra.cql3.UntypedResultSet;
 +import org.apache.cassandra.db.marshal.UTF8Type;
  import org.apache.cassandra.utils.FBUtilities;
  
  import static org.junit.Assert.assertEquals;
@@@ -1916,67 -1073,76 +1917,165 @@@ public class CollectionsTest extends CQ
                               "INSERT INTO %s (k, m) VALUES (0, {1 : (1, '1', 
1.0, 1)})");
      }
  
 +    @Test
 +    public void testSelectionOfEmptyCollections() throws Throwable
 +    {
 +        createTable("CREATE TABLE %s (k int PRIMARY KEY, m frozen<map<text, 
int>>, s frozen<set<int>>)");
 +
 +        execute("INSERT INTO %s(k) VALUES (0)");
 +        execute("INSERT INTO %s(k, m, s) VALUES (1, {}, {})");
 +        execute("INSERT INTO %s(k, m, s) VALUES (2, ?, ?)", map(), set());
 +        execute("INSERT INTO %s(k, m, s) VALUES (3, {'2':2}, {2})");
 +
 +        beforeAndAfterFlush(() ->
 +        {
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 0"), row(null, 
null));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 0"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
0"), row(null, null));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 0"), row(null, null));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 1"), row(map(), 
set()));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 1"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
1"), row(map(), set()));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 1"), row(map(), set()));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 2"), row(map(), 
set()));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 2"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
2"), row(map(), set()));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 2"), row(map(), set()));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 3"), 
row(map("2", 2), set(2)));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 3"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
3"), row(map(), set()));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 3"), row(map(), set()));
 +        });
 +
 +        createTable("CREATE TABLE %s (k int PRIMARY KEY, m map<text, int>, s 
set<int>)");
 +
 +        execute("INSERT INTO %s(k) VALUES (0)");
 +        execute("INSERT INTO %s(k, m, s) VALUES (1, {}, {})");
 +        execute("INSERT INTO %s(k, m, s) VALUES (2, ?, ?)", map(), set());
 +        execute("INSERT INTO %s(k, m, s) VALUES (3, {'2':2}, {2})");
 +
 +        beforeAndAfterFlush(() ->
 +        {
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 0"), row(null, 
null));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 0"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
0"), row(null, null));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 0"), row(null, null));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 1"), row(null, 
null));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 1"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
1"), row(null, null));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 1"), row(null, null));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 2"), row(null, 
null));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 2"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
2"), row(null, null));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 2"), row(null, null));
 +
 +            assertRows(execute("SELECT m, s FROM %s WHERE k = 3"), 
row(map("2", 2), set(2)));
 +            assertRows(execute("SELECT m['0'], s[0] FROM %s WHERE k = 3"), 
row(null, null));
 +            assertRows(execute("SELECT m['0'..'1'], s[0..1] FROM %s WHERE k = 
3"), row(null, null));
 +            assertRows(execute("SELECT m['0'..'1']['3'..'5'], s[0..1][3..5] 
FROM %s WHERE k = 3"), row(null, null));
 +        });
 +    }
++
+     /*
+      Tests for CASSANDRA-17623
+      Before CASSANDRA-17623, parameterized queries with maps as values would 
fail because frozen maps were
+      required to be sorted by the sort order of their key type, but weren't 
always sorted correctly.
+      Also adding tests for Sets, which did work because they always used 
SortedSet, to make sure this behavior is maintained.
+      We use `executeNet` in these tests because `execute` passes parameters 
through CqlTester#transformValues(), which calls
+      AbstractType#decompose() on the value, which "fixes" the map order, but 
wouldn't happen normally.
+      */
+ 
+     @Test
+     public void 
testInsertingMapDataWithParameterizedQueriesIsKeyOrderIndependent() throws 
Throwable
+     {
+         UUID uuid1 = UUIDs.timeBased();
+         UUID uuid2 = UUIDs.timeBased();
+         createTable("CREATE TABLE %s (k text, c frozen<map<timeuuid, text>>, 
PRIMARY KEY (k, c));");
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashMap(uuid1, "0", uuid2, "1"));
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashMap(uuid2, "3", uuid1, "4"));
+         beforeAndAfterFlush(() -> {
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid1 + ": '0', " + uuid2 + ": '1'}"), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid2 + ": '1', " + uuid1 + ": '0'}"), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid1 + ": '4', " + uuid2 + ": '3'}"), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid2 + ": '3', " + uuid1 + ": '4'}"), 1);
+         });
+     }
+ 
++    @Test
++    public void 
testInsertingMapDataWithParameterizedQueriesIsKeyOrderIndependentWithSelectSlice()
 throws Throwable
++    {
++        UUID uuid1 = UUIDs.timeBased();
++        UUID uuid2 = UUIDs.timeBased();
++        createTable("CREATE TABLE %s (k text, c frozen<map<timeuuid, text>>, 
PRIMARY KEY (k, c));");
++        beforeAndAfterFlush(() -> {
++            executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashMap(uuid2, "2", uuid1, "1"));
++            // Make sure that we can slice either value out of the map
++            assertRowsNet(executeNet("SELECT k, c[" + uuid2 + "] from %s"), 
row("0", "2"));
++            assertRowsNet(executeNet("SELECT k, c[" + uuid1 + "] from %s"), 
row("0", "1"));
++        });
++    }
+ 
+     @Test
+     public void 
testSelectingMapDataWithParameterizedQueriesIsKeyOrderIndependent() throws 
Throwable
+     {
+         UUID uuid1 = UUIDs.timeBased();
+         UUID uuid2 = UUIDs.timeBased();
+         createTable("CREATE TABLE %s (k text, c frozen<map<timeuuid, text>>, 
PRIMARY KEY (k, c));");
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', {" + uuid1 + ": '0', " 
+ uuid2 + ": '1'})");
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', {" + uuid2 + ": '3', " 
+ uuid1 + ": '4'})");
+         beforeAndAfterFlush(() -> {
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k=? AND 
c=?", "0", linkedHashMap(uuid1, "0", uuid2, "1")), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k=? AND 
c=?", "0", linkedHashMap(uuid2, "1", uuid1, "0")), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k=? AND 
c=?", "0", linkedHashMap(uuid1, "4", uuid2, "3")), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k=? AND 
c=?", "0", linkedHashMap(uuid2, "3", uuid1, "4")), 1);
+         });
+     }
+ 
+     @Test
+     public void 
testInsertingSetDataWithParameterizedQueriesIsKeyOrderIndependent() throws 
Throwable
+     {
+         UUID uuid1 = UUIDs.timeBased();
+         UUID uuid2 = UUIDs.timeBased();
+         createTable("CREATE TABLE %s (k text, c frozen<set<timeuuid>>, 
PRIMARY KEY (k, c));");
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashSet(uuid1, uuid2));
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashSet(uuid2, uuid1));
+         beforeAndAfterFlush(() -> {
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid1 + ", " + uuid2 + '}'), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid2 + ", " + uuid1 + '}'), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid1 + ", " + uuid2 + '}'), 1);
+             assertRowCountNet(executeNet("SELECT * FROM %s WHERE k='0' AND 
c={" + uuid2 + ", " + uuid1 + '}'), 1);
+         });
+     }
+ 
++    @Test
++    public void 
testInsertingSetDataWithParameterizedQueriesIsKeyOrderIndependentWithSelectSlice()
 throws Throwable
++    {
++        UUID uuid1 = UUIDs.timeBased();
++        UUID uuid2 = UUIDs.timeBased();
++        createTable("CREATE TABLE %s (k text, c frozen<set<timeuuid>>, 
PRIMARY KEY (k, c));");
++        beforeAndAfterFlush(() -> {
++            executeNet("INSERT INTO %s (k, c) VALUES ('0', ?)", 
linkedHashSet(uuid2, uuid1));
++            assertRowsNet(executeNet("SELECT k, c[" + uuid2 + "] from %s"), 
row("0", uuid2));
++            assertRowsNet(executeNet("SELECT k, c[" + uuid1 + "] from %s"), 
row("0", uuid1));
++        });
++    }
+ 
+     @Test
+     public void 
testSelectingSetDataWithParameterizedQueriesIsKeyOrderIndependent() throws 
Throwable
+     {
+         UUID uuid1 = UUIDs.timeBased();
+         UUID uuid2 = UUIDs.timeBased();
+         createTable("CREATE TABLE %s (k text, c frozen<set<timeuuid>>, 
PRIMARY KEY (k, c));");
+         executeNet("INSERT INTO %s (k, c) VALUES ('0', {" + uuid1 + ", " + 
uuid2 + "})");
+         beforeAndAfterFlush(() -> {
+             assertRowsNet(executeNet("SELECT k, c from %s where k='0' and 
c=?", linkedHashSet(uuid1, uuid2)), row("0", list(uuid1, uuid2)));
+             assertRowsNet(executeNet("SELECT k, c from %s where k='0' and 
c=?", linkedHashSet(uuid2, uuid1)), row("0", list(uuid1, uuid2)));
+         });
+     }
+     // End tests for CASSANDRA-17623
  }
diff --cc test/unit/org/apache/cassandra/io/sstable/CQLSSTableWriterTest.java
index dd7085ab76,57910fbf6f..f43294c8ec
--- a/test/unit/org/apache/cassandra/io/sstable/CQLSSTableWriterTest.java
+++ b/test/unit/org/apache/cassandra/io/sstable/CQLSSTableWriterTest.java
@@@ -32,29 -31,29 +32,31 @@@ import com.google.common.collect.Immuta
  import com.google.common.collect.ImmutableMap;
  import com.google.common.io.Files;
  
 -import org.apache.commons.io.FileUtils;
 -import org.junit.After;
  import org.junit.Before;
  import org.junit.BeforeClass;
 +import org.junit.Rule;
  import org.junit.Test;
 +import org.junit.rules.TemporaryFolder;
  
+ import com.datastax.driver.core.utils.UUIDs;
  import org.apache.cassandra.SchemaLoader;
  import org.apache.cassandra.Util;
  import org.apache.cassandra.config.*;
  import org.apache.cassandra.cql3.*;
  import org.apache.cassandra.cql3.functions.UDHelper;
 +import org.apache.cassandra.cql3.functions.types.*;
  import org.apache.cassandra.db.Keyspace;
 +import org.apache.cassandra.db.commitlog.CommitLog;
 +import org.apache.cassandra.db.rows.Row;
+ import org.apache.cassandra.db.marshal.UTF8Type;
  import org.apache.cassandra.dht.*;
  import org.apache.cassandra.exceptions.*;
 +import org.apache.cassandra.schema.Schema;
 +import org.apache.cassandra.schema.TableMetadataRef;
 +import org.apache.cassandra.serializers.SimpleDateSerializer;
  import org.apache.cassandra.service.StorageService;
 +import org.apache.cassandra.transport.ProtocolVersion;
  import org.apache.cassandra.utils.*;
 -import com.datastax.driver.core.DataType;
 -import com.datastax.driver.core.ProtocolVersion;
 -import com.datastax.driver.core.TypeCodec;
 -import com.datastax.driver.core.UDTValue;
 -import com.datastax.driver.core.UserType;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
@@@ -120,7 -125,7 +123,7 @@@ public class CQLSSTableWriterTes
  
              loadSSTables(dataDir, keyspace);
  
--            UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * 
FROM " + qualifiedTable + ";");
++            UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * 
FROM " + qualifiedTable);
              assertEquals(4, rs.size());
  
              Iterator<UntypedResultSet.Row> iter = rs.iterator();
@@@ -639,44 -644,172 +642,210 @@@
          assertEquals(100, resultSet.size());
      }
  
 +    @Test
 +    public void testDateType() throws Exception
 +    {
 +        // Test to make sure we can write to `date` fields in both old and 
new formats
 +        String schema = "CREATE TABLE " + qualifiedTable + " ("
 +                        + "  k int,"
 +                        + "  c date,"
 +                        + "  PRIMARY KEY (k)"
 +                        + ")";
 +        String insert = "INSERT INTO " + qualifiedTable + " (k, c) VALUES (?, 
?)";
 +        CQLSSTableWriter writer = CQLSSTableWriter.builder()
 +                                                  .inDirectory(dataDir)
 +                                                  .forTable(schema)
 +                                                  .using(insert)
 +                                                  .withBufferSizeInMB(1)
 +                                                  .build();
 +
 +        final int ID_OFFSET = 1000;
 +        for (int i = 0; i < 100 ; i++) {
 +            // Use old-style integer as date to test backwards-compatibility
 +            writer.addRow(i, i - Integer.MIN_VALUE); // old-style raw integer 
needs to be offset
 +            // Use new-style `LocalDate` for date value.
 +            writer.addRow(i + ID_OFFSET, LocalDate.fromDaysSinceEpoch(i));
 +        }
 +        writer.close();
 +        loadSSTables(dataDir, keyspace);
 +
 +        UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * FROM " 
+ qualifiedTable + ";");
 +        assertEquals(200, rs.size());
 +        Map<Integer, LocalDate> map = StreamSupport.stream(rs.spliterator(), 
false)
 +                                                   .collect(Collectors.toMap( 
r -> r.getInt("k"), r -> r.getDate("c")));
 +        for (int i = 0; i < 100; i++) {
 +            final LocalDate expected = LocalDate.fromDaysSinceEpoch(i);
 +            assertEquals(expected, map.get(i + ID_OFFSET));
 +            assertEquals(expected, map.get(i));
 +        }
 +    }
 +
+     @Test
+     public void testFrozenMapType() throws Exception
+     {
+         // Test to make sure we can write to `date` fields in both old and 
new formats
+         String schema = "CREATE TABLE " + qualifiedTable + " ("
+                         + "  k text,"
+                         + "  c frozen<map<text, text>>,"
+                         + "  PRIMARY KEY (k, c)"
+                         + ")";
+         String insert = "INSERT INTO " + qualifiedTable + " (k, c) VALUES (?, 
?)";
+         CQLSSTableWriter writer = CQLSSTableWriter.builder()
+                                                   .inDirectory(dataDir)
+                                                   .forTable(schema)
+                                                   .using(insert)
+                                                   .withBufferSizeInMB(1)
+                                                   .build();
+         for (int i = 0; i < 100; i++)
+         {
+             LinkedHashMap<String, String> map = new LinkedHashMap<>();
+             map.put("a_key", "av" + i);
+             map.put("b_key", "zv" + i);
+             writer.addRow(String.valueOf(i), map);
+         }
+         for (int i = 100; i < 200; i++)
+         {
+             LinkedHashMap<String, String> map = new LinkedHashMap<>();
+             map.put("b_key", "zv" + i);
+             map.put("a_key", "av" + i);
+             writer.addRow(String.valueOf(i), map);
+         }
+         writer.close();
+         loadSSTables(dataDir, keyspace);
+ 
+         UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * FROM " 
+ qualifiedTable + ";");
+         assertEquals(200, rs.size());
+         Map<String, Map<String, String>> map = 
StreamSupport.stream(rs.spliterator(), false)
+                                                             
.collect(Collectors.toMap(r -> r.getString("k"), r -> r.getFrozenMap("c", 
UTF8Type.instance, UTF8Type.instance)));
+         for (int i = 0; i < 200; i++)
+         {
+             final String expectedKey = String.valueOf(i);
+             assertTrue(map.containsKey(expectedKey));
+             Map<String, String> innerMap = map.get(expectedKey);
+             assertTrue(innerMap.containsKey("a_key"));
+             assertEquals(innerMap.get("a_key"), "av" + i);
+             assertTrue(innerMap.containsKey("b_key"));
+             assertEquals(innerMap.get("b_key"), "zv" + i);
+         }
+ 
+         // Make sure we can filter with map values regardless of which order 
we put the keys in
+         UntypedResultSet filtered;
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='0' and c={'a_key': 'av0', 'b_key': 'zv0'};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='0' and c={'b_key': 'zv0', 'a_key': 'av0'};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='100' and c={'b_key': 'zv100', 'a_key': 'av100'};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='100' and c={'a_key': 'av100', 'b_key': 'zv100'};");
+         assertEquals(1, filtered.size());
+     }
+ 
+     @Test
+     public void testFrozenMapTypeCustomOrdered() throws Exception
+     {
+         // Test to make sure we can write to `date` fields in both old and 
new formats
+         String schema = "CREATE TABLE " + qualifiedTable + " ("
+                         + "  k text,"
+                         + "  c frozen<map<timeuuid, int>>,"
+                         + "  PRIMARY KEY (k, c)"
+                         + ")";
+         String insert = "INSERT INTO " + qualifiedTable + " (k, c) VALUES (?, 
?)";
+         CQLSSTableWriter writer = CQLSSTableWriter.builder()
+                                                   .inDirectory(dataDir)
+                                                   .forTable(schema)
+                                                   .using(insert)
+                                                   .withBufferSizeInMB(1)
+                                                   .build();
+         UUID uuid1 = UUIDs.timeBased();
+         UUID uuid2 = UUIDs.timeBased();
+         UUID uuid3 = UUIDs.timeBased();
+         UUID uuid4 = UUIDs.timeBased();
+         Map<UUID, Integer> map = new LinkedHashMap<>();
+         // NOTE: if these two `put` calls are switched, the test passes
+         map.put(uuid2, 2);
+         map.put(uuid1, 1);
+         writer.addRow(String.valueOf(1), map);
+ 
+         Map<UUID, Integer> map2 = new LinkedHashMap<>();
+         map2.put(uuid3, 1);
+         map2.put(uuid4, 2);
+         writer.addRow(String.valueOf(2), map2);
+ 
+         writer.close();
+         loadSSTables(dataDir, keyspace);
+ 
+         UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * FROM " 
+ qualifiedTable + ";");
+         assertEquals(2, rs.size());
+ 
+         // Make sure we can filter with map values regardless of which order 
we put the keys in
+         UntypedResultSet filtered;
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='1' and c={" + uuid1 + ": 1, " + uuid2 + ": 2};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='1' and c={" + uuid2 + ": 2, " + uuid1 + ": 1};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid3 + ": 1, " + uuid4 + ": 2};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid4 + ": 2, " + uuid3 + ": 1};");
+         assertEquals(1, filtered.size());
+         UUID other = UUIDs.startOf(1234L); // Just some other TimeUUID
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid3 + ": 1, " + other + ": 2};");
+         assertEquals(0, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid4 + ": 2, " + other + ": 1};");
+         assertEquals(0, filtered.size());
+     }
+ 
+     @Test
+     public void testFrozenSetTypeCustomOrdered() throws Exception
+     {
+         // Test to make sure we can write to `date` fields in both old and 
new formats
+         String schema = "CREATE TABLE " + qualifiedTable + " ("
+                         + "  k text,"
+                         + "  c frozen<set<timeuuid>>,"
+                         + "  PRIMARY KEY (k, c)"
+                         + ")";
+         String insert = "INSERT INTO " + qualifiedTable + " (k, c) VALUES (?, 
?)";
+         CQLSSTableWriter writer = CQLSSTableWriter.builder()
+                                                   .inDirectory(dataDir)
+                                                   .forTable(schema)
+                                                   .using(insert)
+                                                   .withBufferSizeInMB(1)
+                                                   .build();
+         UUID uuid1 = UUIDs.startOf(0L);
+         UUID uuid2 = UUIDs.startOf(10000000L);
+ 
+         LinkedHashSet<UUID> set = new LinkedHashSet<>();
+         set.add(uuid1);
+         set.add(uuid2);
+         writer.addRow(String.valueOf(1), set);
+ 
+         LinkedHashSet<UUID> set2 = new LinkedHashSet<>();
+         set2.add(uuid2);
+         set2.add(uuid1);
+         writer.addRow(String.valueOf(2), set2);
+ 
+         writer.close();
+         loadSSTables(dataDir, keyspace);
+ 
+         UntypedResultSet rs = QueryProcessor.executeInternal("SELECT * FROM " 
+ qualifiedTable + ";");
+         assertEquals(2, rs.size());
+ 
+         // Make sure we can filter with map values regardless of which order 
we put the keys in
+         UntypedResultSet filtered;
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='1' and c={" + uuid1 + ", " + uuid2 + "};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='1' and c={" + uuid2 + ", " + uuid1 + "};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid1 + ", " + uuid2 + "};");
+         assertEquals(1, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid2 + ", " + uuid1 + "};");
+         assertEquals(1, filtered.size());
+         UUID other = UUIDs.startOf(10000000L + 1L); // Pick one that's really 
close just to make sure clustering filters are working
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + uuid1 + ", " + other + "};");
+         assertEquals(0, filtered.size());
+         filtered = QueryProcessor.executeInternal("SELECT * FROM " + 
qualifiedTable + " where k='2' and c={" + other + ", " + uuid1 + "};");
+         assertEquals(0, filtered.size());
+     }
+ 
      private static void loadSSTables(File dataDir, String ks) throws 
ExecutionException, InterruptedException
      {
          SSTableLoader loader = new SSTableLoader(dataDir, new 
SSTableLoader.Client()


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org
For additional commands, e-mail: commits-h...@cassandra.apache.org

Reply via email to