Fix prepared marker for collections inside UDT

patch by slebresne; reviewed by thobbs for CASSANDRA-7472
This commit is contained in:
Jonathan Ellis 2014-07-06 23:55:32 -05:00
parent 92cb551ae3
commit 9b539f966f
6 changed files with 34 additions and 23 deletions

View File

@ -1,4 +1,5 @@
2.1.0
* Fix prepared marker for collections inside UDT (CASSANDRA-7472)
* Remove left-over populate_io_cache_on_flush and replicate_on_write
uses (CASSANDRA-7493)
* (Windows) handle spaces in path names (CASSANDRA-7451)

View File

@ -110,8 +110,6 @@ public abstract class QueryOptions
*/
public abstract int getProtocolVersion();
public abstract QueryOptions withProtocolVersion(int version);
// Mainly for the sake of BatchQueryOptions
abstract SpecificOptions getSpecificOptions();
@ -139,11 +137,6 @@ public abstract class QueryOptions
this.protocolVersion = protocolVersion;
}
public QueryOptions withProtocolVersion(int version)
{
return new DefaultQueryOptions(consistency, values, skipMetadata, options, version);
}
public ConsistencyLevel getConsistency()
{
return consistency;
@ -205,11 +198,6 @@ public abstract class QueryOptions
wrapped.prepare(specs);
return this;
}
public QueryOptions withProtocolVersion(int version)
{
return new DefaultQueryOptions(getConsistency(), getValues(), skipMetadata(), getSpecificOptions(), version);
}
}
static class OptionsWithNames extends QueryOptionsWrapper

View File

@ -71,7 +71,7 @@ public class Tuples
values.add(value);
}
DelayedValue value = new DelayedValue(values);
DelayedValue value = new DelayedValue((TupleType)receiver.type, values);
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
}
@ -81,6 +81,7 @@ public class Tuples
throw new InvalidRequestException(String.format("Expected %d elements in value tuple, but got %d: %s", receivers.size(), elements.size(), this));
List<Term> values = new ArrayList<>(elements.size());
List<AbstractType<?>> types = new ArrayList<>(elements.size());
boolean allTerminal = true;
for (int i = 0; i < elements.size(); i++)
{
@ -89,8 +90,9 @@ public class Tuples
allTerminal = false;
values.add(t);
types.add(receivers.get(i).type);
}
DelayedValue value = new DelayedValue(values);
DelayedValue value = new DelayedValue(new TupleType(types), values);
return allTerminal ? value.bind(QueryOptions.DEFAULT) : value;
}
@ -166,10 +168,12 @@ public class Tuples
*/
public static class DelayedValue extends Term.NonTerminal
{
public final TupleType type;
public final List<Term> elements;
public DelayedValue(List<Term> elements)
public DelayedValue(TupleType type, List<Term> elements)
{
this.type = type;
this.elements = elements;
}
@ -190,13 +194,17 @@ public class Tuples
private ByteBuffer[] bindInternal(QueryOptions options) throws InvalidRequestException
{
// Inside tuples, we must force the serialization of collections whatever the protocol version is in
// use since we're going to store directly that serialized value.
options = options.withProtocolVersion(3);
int version = options.getProtocolVersion();
ByteBuffer[] buffers = new ByteBuffer[elements.size()];
for (int i = 0; i < elements.size(); i++)
{
buffers[i] = elements.get(i).bindAndGet(options);
// Inside tuples, we must force the serialization of collections to v3 whatever protocol
// version is in use since we're going to store directly that serialized value.
if (version < 3 && type.type(i).isCollection())
buffers[i] = ((CollectionType)type.type(i)).getSerializer().reserializeToV3(buffers[i]);
}
return buffers;
}

View File

@ -20,6 +20,7 @@ package org.apache.cassandra.cql3;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.UserType;
import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.exceptions.InvalidRequestException;
@ -33,10 +34,11 @@ public abstract class UserTypes
public static ColumnSpecification fieldSpecOf(ColumnSpecification column, int field)
{
UserType ut = (UserType)column.type;
return new ColumnSpecification(column.ksName,
column.cfName,
new ColumnIdentifier(column.name + "." + field, true),
((UserType)column.type).fieldType(field));
new ColumnIdentifier(column.name + "." + UTF8Type.instance.compose(ut.fieldName(field)), true),
ut.fieldType(field));
}
public static class Literal implements Term.Raw
@ -150,13 +152,17 @@ public abstract class UserTypes
private ByteBuffer[] bindInternal(QueryOptions options) throws InvalidRequestException
{
// Inside UDT values, we must force the serialization of collections whatever the protocol version is in
// use since we're going to store directly that serialized value.
options = options.withProtocolVersion(3);
int version = options.getProtocolVersion();
ByteBuffer[] buffers = new ByteBuffer[values.size()];
for (int i = 0; i < type.size(); i++)
{
buffers[i] = values.get(i).bindAndGet(options);
// Inside UDT values, we must force the serialization of collections to v3 whatever protocol
// version is in use since we're going to store directly that serialized value.
if (version < 3 && type.fieldType(i).isCollection())
buffers[i] = ((CollectionType)type.fieldType(i)).getSerializer().reserializeToV3(buffers[i]);
}
return buffers;
}

View File

@ -60,6 +60,9 @@ public abstract class CollectionType<T> extends AbstractType<T>
public abstract List<ByteBuffer> serializedValues(List<Cell> cells);
@Override
public abstract CollectionSerializer<T> getSerializer();
@Override
public String toString()
{

View File

@ -48,6 +48,11 @@ public abstract class CollectionSerializer<T> implements TypeSerializer<T>
return deserializeForNativeProtocol(bytes, 3);
}
public ByteBuffer reserializeToV3(ByteBuffer bytes)
{
return serialize(deserializeForNativeProtocol(bytes, 2));
}
public void validate(ByteBuffer bytes) throws MarshalException
{
// Same thing than above