diff --git a/CHANGES.txt b/CHANGES.txt
index 8f718e4e89..549dd7eba8 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -3,6 +3,7 @@
* Do not go to disk for reading hints file sizes (CASSANDRA-19477)
* Fix system_views.settings to handle array types (CASSANDRA-19475)
Merged from 4.0:
+ * Fix few types issues and implement types compatibility tests (CASSANDRA-19479)
* Optionally avoid hint transfer during decommission (CASSANDRA-19525)
* Change logging to TRACE when failing to get peer certificate (CASSANDRA-19508)
* Push LocalSessions info logs to debug (CASSANDRA-18335)
diff --git a/build.xml b/build.xml
index 6ab59d579e..b81126b69a 100644
--- a/build.xml
+++ b/build.xml
@@ -737,9 +737,9 @@
-
+
-
+
diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
index 18007fb711..0993832c8f 100644
--- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java
@@ -59,7 +59,7 @@ public abstract class AbstractCompositeType extends AbstractType
int offsetL = startingOffset(isStaticL);
int offsetR = startingOffset(isStaticR);
- while (!accessorL.isEmptyFromOffset(left, offsetL) && !accessorR.isEmptyFromOffset(right, offsetL))
+ while (!accessorL.isEmptyFromOffset(left, offsetL) && !accessorR.isEmptyFromOffset(right, offsetR))
{
AbstractType> comparator = getComparator(i, left, accessorL, right, accessorR, offsetL, offsetR);
offsetL += getComparatorSize(i, left, accessorL, offsetL);
diff --git a/src/java/org/apache/cassandra/db/marshal/ByteArrayAccessor.java b/src/java/org/apache/cassandra/db/marshal/ByteArrayAccessor.java
index df24a627a4..d7108992da 100644
--- a/src/java/org/apache/cassandra/db/marshal/ByteArrayAccessor.java
+++ b/src/java/org/apache/cassandra/db/marshal/ByteArrayAccessor.java
@@ -248,6 +248,13 @@ public class ByteArrayAccessor implements ValueAccessor
return Ballot.deserialize(value);
}
+ @Override
+ public int putByte(byte[] dst, int offset, byte value)
+ {
+ dst[offset] = value;
+ return TypeSizes.BYTE_SIZE;
+ }
+
@Override
public int putShort(byte[] dst, int offset, short value)
{
diff --git a/src/java/org/apache/cassandra/db/marshal/ByteBufferAccessor.java b/src/java/org/apache/cassandra/db/marshal/ByteBufferAccessor.java
index 40a3bf4b34..0712930c3a 100644
--- a/src/java/org/apache/cassandra/db/marshal/ByteBufferAccessor.java
+++ b/src/java/org/apache/cassandra/db/marshal/ByteBufferAccessor.java
@@ -252,6 +252,13 @@ public class ByteBufferAccessor implements ValueAccessor
return Ballot.deserialize(value);
}
+ @Override
+ public int putByte(ByteBuffer dst, int offset, byte value)
+ {
+ dst.put(dst.position() + offset, value);
+ return TypeSizes.BYTE_SIZE;
+ }
+
@Override
public int putShort(ByteBuffer dst, int offset, short value)
{
diff --git a/src/java/org/apache/cassandra/db/marshal/CompositeType.java b/src/java/org/apache/cassandra/db/marshal/CompositeType.java
index bf5e914a9d..2d77dc5334 100644
--- a/src/java/org/apache/cassandra/db/marshal/CompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/CompositeType.java
@@ -21,6 +21,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -29,7 +30,9 @@ import com.google.common.collect.Lists;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.serializers.BytesSerializer;
import org.apache.cassandra.serializers.MarshalException;
+import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import static com.google.common.collect.Iterables.any;
@@ -62,9 +65,37 @@ import static com.google.common.collect.Iterables.transform;
*/
public class CompositeType extends AbstractCompositeType
{
+ private static class Serializer extends BytesSerializer
+ {
+ // types are held to make sure the serializer is unique for each collection of types, this is to make sure it's
+ // safe to cache in all cases
+ public final List> types;
+
+ public Serializer(List> types)
+ {
+ this.types = types;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Serializer that = (Serializer) o;
+ return types.equals(that.types);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(types);
+ }
+ }
+
private static final int STATIC_MARKER = 0xFFFF;
public final List> types;
+ private final Serializer serializer;
// interning instances
private static final ConcurrentMap>, CompositeType> instances = new ConcurrentHashMap<>();
@@ -136,8 +167,16 @@ public class CompositeType extends AbstractCompositeType
protected CompositeType(List> types)
{
this.types = ImmutableList.copyOf(types);
+ this.serializer = new Serializer(this.types);
}
+ @Override
+ public TypeSerializer getSerializer()
+ {
+ return serializer;
+ }
+
+
protected AbstractType> getComparator(int i, V value, ValueAccessor accessor, int offset)
{
try
diff --git a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
index 5df3600995..541b7bba5d 100644
--- a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
+++ b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java
@@ -20,8 +20,11 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,6 +33,7 @@ import org.apache.cassandra.cql3.Term;
import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
+import org.apache.cassandra.serializers.BytesSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.serializers.TypeSerializer;
import org.apache.cassandra.transport.ProtocolVersion;
@@ -60,7 +64,36 @@ public class DynamicCompositeType extends AbstractCompositeType
{
private static final Logger logger = LoggerFactory.getLogger(DynamicCompositeType.class);
- private final Map> aliases;
+ public static class Serializer extends BytesSerializer
+ {
+ // aliases are held to make sure the serializer is unique for each collection of types, this is to make sure it's
+ // safe to cache in all cases
+ private final Map> aliases;
+
+ public Serializer(Map> aliases)
+ {
+ this.aliases = aliases;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Serializer that = (Serializer) o;
+ return aliases.equals(that.aliases);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(aliases);
+ }
+ }
+
+ @VisibleForTesting
+ public final Map> aliases;
+ private final Serializer serializer;
// interning instances
private static final ConcurrentHashMap