cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From slebre...@apache.org
Subject [1/2] git commit: Add proper compare function for CollectionType (for UDT sake)
Date Thu, 20 Mar 2014 09:13:05 GMT
Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.1 6e366e3b2 -> e62238e08


Add proper compare function for CollectionType (for UDT sake)

patch by slebresne; reviewed by thobbs for CASSANDRA-6783


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

Branch: refs/heads/cassandra-2.1
Commit: f4b9f16114947e708331899bdb15f8daf5100a3a
Parents: e23e57f
Author: Sylvain Lebresne <sylvain@datastax.com>
Authored: Thu Mar 20 10:10:45 2014 +0100
Committer: Sylvain Lebresne <sylvain@datastax.com>
Committed: Thu Mar 20 10:10:45 2014 +0100

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../cassandra/db/marshal/CollectionType.java    |   5 -
 .../apache/cassandra/db/marshal/ListType.java   |  33 ++++++
 .../apache/cassandra/db/marshal/MapType.java    |  34 ++++++
 .../apache/cassandra/db/marshal/SetType.java    |   6 +
 .../db/marshal/CollectionTypeTest.java          | 116 +++++++++++++++++++
 6 files changed, 190 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 159d242..856ec23 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -23,6 +23,7 @@
  * Add logging levels (minimal, normal or verbose) to stress tool (CASSANDRA-6849)
  * Fix race condition in Batch CLE (CASSANDRA-6860)
  * Improve cleanup/scrub/upgradesstables failure handling (CASSANDRA-6774)
+ * Proper compare function for CollectionType (CASSANDRA-6783)
 Merged from 2.0:
  * Omit tombstones from schema digests (CASSANDRA-6862)
  * Include correct consistencyLevel in LWT timeout (CASSANDRA-6884)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/src/java/org/apache/cassandra/db/marshal/CollectionType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
index 02d01ff..5db4ba0 100644
--- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java
@@ -67,11 +67,6 @@ public abstract class CollectionType<T> extends AbstractType<T>
         return sb.toString();
     }
 
-    public int compare(ByteBuffer o1, ByteBuffer o2)
-    {
-        throw new UnsupportedOperationException("CollectionType should not be use directly
as a comparator");
-    }
-
     public String getString(ByteBuffer bytes)
     {
         return BytesType.instance.getString(bytes);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/src/java/org/apache/cassandra/db/marshal/ListType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/ListType.java b/src/java/org/apache/cassandra/db/marshal/ListType.java
index eabda0b..1cc0425 100644
--- a/src/java/org/apache/cassandra/db/marshal/ListType.java
+++ b/src/java/org/apache/cassandra/db/marshal/ListType.java
@@ -25,6 +25,7 @@ import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.SyntaxException;
 import org.apache.cassandra.serializers.TypeSerializer;
 import org.apache.cassandra.serializers.ListSerializer;
+import org.apache.cassandra.utils.ByteBufferUtil;
 
 public class ListType<T> extends CollectionType<List<T>>
 {
@@ -76,6 +77,38 @@ public class ListType<T> extends CollectionType<List<T>>
         return serializer;
     }
 
+    @Override
+    public int compare(ByteBuffer o1, ByteBuffer o2)
+    {
+        return compareListOrSet(elements, o1, o2);
+    }
+
+    static int compareListOrSet(AbstractType<?> elementsComparator, ByteBuffer o1,
ByteBuffer o2)
+    {
+        // Note that this is only used if the collection is inside an UDT
+        if (o1 == null || !o1.hasRemaining())
+            return o2 == null || !o2.hasRemaining() ? 0 : -1;
+        if (o2 == null || !o2.hasRemaining())
+            return 1;
+
+        ByteBuffer bb1 = o1.duplicate();
+        ByteBuffer bb2 = o2.duplicate();
+
+        int size1 = ByteBufferUtil.readShortLength(bb1);
+        int size2 = ByteBufferUtil.readShortLength(bb2);
+
+        for (int i = 0; i < Math.min(size1, size2); i++)
+        {
+            ByteBuffer v1 = ByteBufferUtil.readBytesWithShortLength(bb1);
+            ByteBuffer v2 = ByteBufferUtil.readBytesWithShortLength(bb2);
+            int cmp = elementsComparator.compare(v1, v2);
+            if (cmp != 0)
+                return cmp;
+        }
+
+        return size1 == size2 ? 0 : (size1 < size2 ? -1 : 1);
+    }
+
     protected void appendToStringBuilder(StringBuilder sb)
     {
         sb.append(getClass().getName()).append(TypeParser.stringifyTypeParameters(Collections.<AbstractType<?>>singletonList(elements)));

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/src/java/org/apache/cassandra/db/marshal/MapType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java b/src/java/org/apache/cassandra/db/marshal/MapType.java
index 4d834e7..2e693d6 100644
--- a/src/java/org/apache/cassandra/db/marshal/MapType.java
+++ b/src/java/org/apache/cassandra/db/marshal/MapType.java
@@ -26,6 +26,7 @@ import org.apache.cassandra.exceptions.SyntaxException;
 import org.apache.cassandra.serializers.TypeSerializer;
 import org.apache.cassandra.serializers.MapSerializer;
 import org.apache.cassandra.utils.Pair;
+import org.apache.cassandra.utils.ByteBufferUtil;
 
 public class MapType<K, V> extends CollectionType<Map<K, V>>
 {
@@ -76,6 +77,39 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
     }
 
     @Override
+    public int compare(ByteBuffer o1, ByteBuffer o2)
+    {
+        // Note that this is only used if the collection is inside an UDT
+        if (o1 == null || !o1.hasRemaining())
+            return o2 == null || !o2.hasRemaining() ? 0 : -1;
+        if (o2 == null || !o2.hasRemaining())
+            return 1;
+
+        ByteBuffer bb1 = o1.duplicate();
+        ByteBuffer bb2 = o2.duplicate();
+
+        int size1 = ByteBufferUtil.readShortLength(bb1);
+        int size2 = ByteBufferUtil.readShortLength(bb2);
+
+        for (int i = 0; i < Math.min(size1, size2); i++)
+        {
+            ByteBuffer k1 = ByteBufferUtil.readBytesWithShortLength(bb1);
+            ByteBuffer k2 = ByteBufferUtil.readBytesWithShortLength(bb2);
+            int cmp = keys.compare(k1, k2);
+            if (cmp != 0)
+                return cmp;
+
+            ByteBuffer v1 = ByteBufferUtil.readBytesWithShortLength(bb1);
+            ByteBuffer v2 = ByteBufferUtil.readBytesWithShortLength(bb2);
+            cmp = values.compare(v1, v2);
+            if (cmp != 0)
+                return cmp;
+        }
+
+        return size1 == size2 ? 0 : (size1 < size2 ? -1 : 1);
+    }
+
+    @Override
     public TypeSerializer<Map<K, V>> getSerializer()
     {
         return serializer;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/src/java/org/apache/cassandra/db/marshal/SetType.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java b/src/java/org/apache/cassandra/db/marshal/SetType.java
index 292b832..5c13c2e 100644
--- a/src/java/org/apache/cassandra/db/marshal/SetType.java
+++ b/src/java/org/apache/cassandra/db/marshal/SetType.java
@@ -71,6 +71,12 @@ public class SetType<T> extends CollectionType<Set<T>>
         return EmptyType.instance;
     }
 
+    @Override
+    public int compare(ByteBuffer o1, ByteBuffer o2)
+    {
+        return ListType.compareListOrSet(elements, o1, o2);
+    }
+
     public TypeSerializer<Set<T>> getSerializer()
     {
         return serializer;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f4b9f161/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
new file mode 100644
index 0000000..fba4742
--- /dev/null
+++ b/test/unit/org/apache/cassandra/db/marshal/CollectionTypeTest.java
@@ -0,0 +1,116 @@
+/**
+ * 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.db.marshal;
+
+import java.nio.ByteBuffer;
+import java.util.*;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.cassandra.utils.ByteBufferUtil;
+
+public class CollectionTypeTest
+{
+    @Test
+    public void testListComparison()
+    {
+        ListType<String> lt = ListType.getInstance(UTF8Type.instance);
+
+        ByteBuffer[] lists = new ByteBuffer[] {
+            ByteBufferUtil.EMPTY_BYTE_BUFFER,
+            lt.decompose(ImmutableList.<String>of()),
+            lt.decompose(ImmutableList.of("aa")),
+            lt.decompose(ImmutableList.of("bb")),
+            lt.decompose(ImmutableList.of("bb", "cc")),
+            lt.decompose(ImmutableList.of("bb", "dd"))
+        };
+
+        for (int i = 0; i < lists.length; i++)
+            assertEquals(lt.compare(lists[i], lists[i]), 0);
+
+        for (int i = 0; i < lists.length-1; i++)
+        {
+            for (int j = i+1; j < lists.length; j++)
+            {
+                assertEquals(lt.compare(lists[i], lists[j]), -1);
+                assertEquals(lt.compare(lists[j], lists[i]), 1);
+            }
+        }
+    }
+
+    @Test
+    public void testSetComparison()
+    {
+        SetType<String> st = SetType.getInstance(UTF8Type.instance);
+
+        ByteBuffer[] sets = new ByteBuffer[] {
+            ByteBufferUtil.EMPTY_BYTE_BUFFER,
+            st.decompose(ImmutableSet.<String>of()),
+            st.decompose(ImmutableSet.of("aa")),
+            st.decompose(ImmutableSet.of("bb")),
+            st.decompose(ImmutableSet.of("bb", "cc")),
+            st.decompose(ImmutableSet.of("bb", "dd"))
+        };
+
+        for (int i = 0; i < sets.length; i++)
+            assertEquals(st.compare(sets[i], sets[i]), 0);
+
+        for (int i = 0; i < sets.length-1; i++)
+        {
+            for (int j = i+1; j < sets.length; j++)
+            {
+                assertEquals(st.compare(sets[i], sets[j]), -1);
+                assertEquals(st.compare(sets[j], sets[i]), 1);
+            }
+        }
+    }
+
+    @Test
+    public void testMapComparison()
+    {
+        MapType<String, String> mt = MapType.getInstance(UTF8Type.instance, UTF8Type.instance);
+
+        ByteBuffer[] maps = new ByteBuffer[] {
+            ByteBufferUtil.EMPTY_BYTE_BUFFER,
+            mt.decompose(ImmutableMap.<String, String>of()),
+            mt.decompose(ImmutableMap.of("aa", "val1")),
+            mt.decompose(ImmutableMap.of("aa", "val2")),
+            mt.decompose(ImmutableMap.of("bb", "val1")),
+            mt.decompose(ImmutableMap.of("bb", "val1", "cc", "val3")),
+            mt.decompose(ImmutableMap.of("bb", "val1", "dd", "val3")),
+            mt.decompose(ImmutableMap.of("bb", "val1", "dd", "val4"))
+        };
+
+        for (int i = 0; i < maps.length; i++)
+            assertEquals(mt.compare(maps[i], maps[i]), 0);
+
+        for (int i = 0; i < maps.length-1; i++)
+        {
+            for (int j = i+1; j < maps.length; j++)
+            {
+                assertEquals(mt.compare(maps[i], maps[j]), -1);
+                assertEquals(mt.compare(maps[j], maps[i]), 1);
+            }
+        }
+    }
+}


Mime
View raw message