Don't tie client side use of AbstractType to JDBC

patch by carlyeks; reviewed by ardot for CASSANDRA-4495
This commit is contained in:
Sylvain Lebresne 2013-07-08 18:34:34 +02:00
parent a90e8b77c5
commit e9c674242b
88 changed files with 1456 additions and 1414 deletions

View File

@ -71,6 +71,7 @@
sstable (CASSANDRA-5454)
* Move resultset type information into prepare, not execute (CASSANDRA-5649)
* Auto paging in binary protocol (CASSANDRA-4415, 5714)
* Don't tie client side use of AbstractType to JDBC (CASSANDRA-4495)
1.2.7

View File

@ -736,7 +736,7 @@
<!-- TODO: write maven pom here -->
<jar jarfile="${build.dir}/${ant.project.name}-clientutil-${version}.jar">
<fileset dir="${build.classes.main}">
<include name="org/apache/cassandra/cql/jdbc/*" />
<include name="org/apache/cassandra/type/*" />
<include name="org/apache/cassandra/utils/ByteBufferUtil*.class" />
<include name="org/apache/cassandra/utils/Hex.class" />
<include name="org/apache/cassandra/utils/UUIDGen*.class" />
@ -794,7 +794,7 @@
<create-javadoc destdir="${javadoc.jars.dir}/clientutil">
<filesets>
<fileset dir="${build.src.java}" defaultexcludes="yes">
<include name="org/apache/cassandra/cql/jdbc/*" />
<include name="org/apache/cassandra/type/*" />
<include name="org/apache/cassandra/utils/ByteBufferUtil*.java" />
<include name="org/apache/cassandra/utils/Hex.java" />
<include name="org/apache/cassandra/utils/UUIDGen*.java" />
@ -827,7 +827,7 @@
</jar>
<jar jarfile="${build.dir}/${ant.project.name}-clientutil-${version}-sources.jar">
<fileset dir="${build.src.java}" defaultexcludes="yes">
<include name="org/apache/cassandra/cql/jdbc/*" />
<include name="org/apache/cassandra/type/*" />
<include name="org/apache/cassandra/utils/ByteBufferUtil*.java" />
<include name="org/apache/cassandra/utils/Hex.java" />
<include name="org/apache/cassandra/utils/UUIDGen*.java" />
@ -1045,7 +1045,7 @@
-->
<target name="test-clientutil-jar" depends="build-test,jar" description="Test clientutil jar">
<junit>
<test name="org.apache.cassandra.cql.jdbc.ClientUtilsTest" />
<test name="org.apache.cassandra.type.ClientUtilsTest" />
<formatter type="brief" usefile="false" />
<classpath>
<pathelement location="${test.classes}" />

View File

@ -32,6 +32,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import org.apache.cassandra.type.MarshalException;
import org.apache.commons.lang.StringUtils;
import org.antlr.runtime.tree.Tree;

View File

@ -31,6 +31,7 @@ import com.google.common.base.Objects;
import com.google.common.collect.MapDifference;
import com.google.common.collect.Maps;
import org.apache.cassandra.type.MarshalException;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;

View File

@ -23,6 +23,7 @@ import java.nio.charset.CharacterCodingException;
import java.util.*;
import java.util.concurrent.TimeoutException;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -36,7 +37,6 @@ import org.apache.cassandra.db.filter.*;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.db.marshal.TypeParser;
import org.apache.cassandra.dht.*;
import org.apache.cassandra.exceptions.*;

View File

@ -25,8 +25,8 @@ import org.apache.cassandra.db.marshal.AsciiType;
import org.apache.cassandra.db.marshal.FloatType;
import org.apache.cassandra.db.marshal.IntegerType;
import org.apache.cassandra.db.marshal.LexicalUUIDType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.type.MarshalException;
/** A term parsed from a CQL statement. */
public class Term

View File

@ -1,69 +0,0 @@
/*
* 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.cql.jdbc;
import java.sql.Types;
import java.util.UUID;
public abstract class AbstractJdbcUUID extends AbstractJdbcType<UUID>
{
public String toString(UUID obj)
{
return obj.toString();
}
public boolean isCaseSensitive()
{
return false;
}
public int getScale(UUID obj)
{
return -1;
}
public int getPrecision(UUID obj)
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public boolean needsQuotes()
{
return false;
}
public Class<UUID> getType()
{
return UUID.class;
}
public int getJdbcType()
{
return Types.OTHER;
}
}

View File

@ -1,53 +0,0 @@
/*
* 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.cql.jdbc;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.apache.cassandra.utils.UUIDGen;
public class JdbcLexicalUUID extends AbstractJdbcUUID
{
public static final JdbcLexicalUUID instance = new JdbcLexicalUUID();
public JdbcLexicalUUID() {}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 16)
{
throw new MarshalException("UUIDs must be exactly 16 bytes");
}
return UUIDGen.getUUID(bytes).toString();
}
public UUID compose(ByteBuffer bytes)
{
return UUIDGen.getUUID(bytes);
}
public ByteBuffer decompose(UUID value)
{
return ByteBuffer.wrap(UUIDGen.decompose(value));
}
}

View File

@ -1,100 +0,0 @@
/*
* 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.cql.jdbc;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcUTF8 extends AbstractJdbcType<String>
{
private static final Charset UTF_8 = Charset.forName("UTF-8");
public static final JdbcUTF8 instance = new JdbcUTF8();
public JdbcUTF8() {}
public boolean isCaseSensitive()
{
return true;
}
public int getScale(String obj)
{
return -1;
}
public int getPrecision(String obj)
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public String toString(String obj)
{
return obj;
}
public boolean needsQuotes()
{
return true;
}
public String getString(ByteBuffer bytes)
{
try
{
return ByteBufferUtil.string(bytes);
}
catch (CharacterCodingException e)
{
throw new MarshalException("invalid UTF8 bytes " + ByteBufferUtil.bytesToHex(bytes));
}
}
public Class<String> getType()
{
return String.class;
}
public int getJdbcType()
{
return Types.VARCHAR;
}
public String compose(ByteBuffer bytes)
{
return getString(bytes);
}
public ByteBuffer decompose(String value)
{
return ByteBufferUtil.bytes(value, UTF_8);
}
}

View File

@ -1,54 +0,0 @@
/*
* 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.cql.jdbc;
import java.util.HashMap;
import java.util.Map;
public class TypesMap
{
private final static Map<String, AbstractJdbcType<?>> map = new HashMap<String, AbstractJdbcType<?>>();
static
{
map.put("org.apache.cassandra.db.marshal.AsciiType", JdbcAscii.instance);
map.put("org.apache.cassandra.db.marshal.BooleanType", JdbcBoolean.instance);
map.put("org.apache.cassandra.db.marshal.BytesType", JdbcBytes.instance);
map.put("org.apache.cassandra.db.marshal.CounterColumnType", JdbcCounterColumn.instance);
map.put("org.apache.cassandra.db.marshal.DateType", JdbcDate.instance);
map.put("org.apache.cassandra.db.marshal.DecimalType", JdbcDecimal.instance);
map.put("org.apache.cassandra.db.marshal.DoubleType", JdbcDouble.instance);
map.put("org.apache.cassandra.db.marshal.FloatType", JdbcFloat.instance);
map.put("org.apache.cassandra.db.marshal.Int32Type", JdbcInt32.instance);
map.put("org.apache.cassandra.db.marshal.InetAddressType", JdbcInetAddress.instance);
map.put("org.apache.cassandra.db.marshal.IntegerType", JdbcInteger.instance);
map.put("org.apache.cassandra.db.marshal.LexicalUUIDType", JdbcLexicalUUID.instance);
map.put("org.apache.cassandra.db.marshal.LongType", JdbcLong.instance);
map.put("org.apache.cassandra.db.marshal.TimeUUIDType", JdbcTimeUUID.instance);
map.put("org.apache.cassandra.db.marshal.UTF8Type", JdbcUTF8.instance);
map.put("org.apache.cassandra.db.marshal.UUIDType", JdbcUUID.instance);
}
public static AbstractJdbcType<?> getTypeForComparator(String comparator)
{
// If not fully qualified, assume it's the short name for a built-in.
if ((comparator != null) && (!comparator.contains(".")))
return map.get("org.apache.cassandra.db.marshal." + comparator);
return map.get(comparator);
}
}

View File

@ -23,8 +23,8 @@ import java.util.List;
import org.apache.cassandra.db.ExpiringColumn;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.LongType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.type.MarshalException;
/**
* Utility class for the Parser to gather attributes for modification

View File

@ -20,11 +20,17 @@ package org.apache.cassandra.cql3;
import java.nio.ByteBuffer;
import java.util.List;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.CounterColumnType;
import org.apache.cassandra.db.marshal.LongType;
import org.apache.cassandra.db.marshal.ReversedType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.utils.ByteBufferUtil;

View File

@ -27,8 +27,8 @@ import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.db.marshal.ListType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;

View File

@ -27,8 +27,8 @@ import java.util.TreeMap;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;

View File

@ -29,10 +29,10 @@ import com.google.common.base.Joiner;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.marshal.CollectionType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.SetType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;

View File

@ -44,6 +44,7 @@ import org.apache.cassandra.db.ConsistencyLevel;
import org.apache.cassandra.thrift.IndexExpression;
import org.apache.cassandra.thrift.IndexOperator;
import org.apache.cassandra.thrift.ThriftValidation;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
import org.apache.cassandra.utils.Pair;

View File

@ -33,6 +33,7 @@ import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;

View File

@ -25,6 +25,7 @@ import java.util.Set;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -33,7 +34,6 @@ import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.context.CounterContext;
import org.apache.cassandra.db.context.IContext.ContextRelationship;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.exceptions.OverloadedException;
import org.apache.cassandra.exceptions.RequestExecutionException;
import org.apache.cassandra.io.util.DataOutputBuffer;

View File

@ -22,8 +22,8 @@ import java.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.HeapAllocator;

View File

@ -23,8 +23,8 @@ import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.Allocator;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.HeapAllocator;

View File

@ -22,9 +22,9 @@ import java.nio.ByteBuffer;
import java.security.MessageDigest;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.ISSTableSerializer;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public interface OnDiskAtom

View File

@ -25,10 +25,10 @@ import java.security.MessageDigest;
import java.util.*;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.ISSTableSerializer;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.Interval;

View File

@ -23,12 +23,12 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.db.compaction.CompactionManager;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.utils.*;
/**

View File

@ -17,6 +17,10 @@
*/
package org.apache.cassandra.db.marshal;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.BytesSerializer;
import org.apache.cassandra.type.MarshalException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
@ -325,6 +329,12 @@ public abstract class AbstractCompositeType extends AbstractType<ByteBuffer>
return value;
}
@Override
public AbstractSerializer<ByteBuffer> asComposer()
{
return BytesSerializer.instance;
}
/**
* @return the comparator for the given component. static CompositeType will consult
* @param i DynamicCompositeType will read the type information from @param bb

View File

@ -31,6 +31,8 @@ import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.db.OnDiskAtom;
import org.apache.cassandra.db.RangeTombstone;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import static org.apache.cassandra.io.sstable.IndexHelper.IndexInfo;
@ -160,6 +162,8 @@ public abstract class AbstractType<T> implements Comparator<ByteBuffer>
return new CQL3Type.Custom(this);
}
public abstract AbstractSerializer<T> asComposer();
/** @deprecated use reverseComparator field instead */
public Comparator<ByteBuffer> getReverseComparator()
{

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcAscii;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.AsciiSerializer;
import org.apache.cassandra.type.MarshalException;
public class AsciiType extends AbstractType<String>
{
@ -30,14 +32,7 @@ public class AsciiType extends AbstractType<String>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcAscii.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return AsciiSerializer.instance.getString(bytes);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -47,12 +42,12 @@ public class AsciiType extends AbstractType<String>
public String compose(ByteBuffer bytes)
{
return JdbcAscii.instance.getString(bytes);
return AsciiSerializer.instance.getString(bytes);
}
public ByteBuffer decompose(String value)
{
return JdbcAscii.instance.decompose(value);
return AsciiSerializer.instance.deserialize(value);
}
public ByteBuffer fromString(String source)
@ -62,17 +57,16 @@ public class AsciiType extends AbstractType<String>
public void validate(ByteBuffer bytes) throws MarshalException
{
// 0-127
for (int i = bytes.position(); i < bytes.limit(); i++)
{
byte b = bytes.get(i);
if (b < 0 || b > 127)
throw new MarshalException("Invalid byte for ascii: " + Byte.toString(b));
}
AsciiSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.ASCII;
}
public AbstractSerializer<String> asComposer()
{
return AsciiSerializer.instance;
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcBoolean;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.BooleanSerializer;
import org.apache.cassandra.type.MarshalException;
public class BooleanType extends AbstractType<Boolean>
{
@ -30,12 +32,12 @@ public class BooleanType extends AbstractType<Boolean>
public Boolean compose(ByteBuffer bytes)
{
return JdbcBoolean.instance.compose(bytes);
return BooleanSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Boolean value)
{
return JdbcBoolean.instance.decompose(value);
return BooleanSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -50,14 +52,7 @@ public class BooleanType extends AbstractType<Boolean>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcBoolean.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return BooleanSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -75,12 +70,17 @@ public class BooleanType extends AbstractType<Boolean>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 1 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 1 or 0 byte value (%d)", bytes.remaining()));
BooleanSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.BOOLEAN;
}
@Override
public AbstractSerializer<Boolean> asComposer()
{
return BooleanSerializer.instance;
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcBytes;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.BytesSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.Hex;
@ -32,12 +34,12 @@ public class BytesType extends AbstractType<ByteBuffer>
public ByteBuffer compose(ByteBuffer bytes)
{
return JdbcBytes.instance.compose(bytes);
return BytesSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(ByteBuffer value)
{
return JdbcBytes.instance.decompose(value);
return BytesSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -55,7 +57,7 @@ public class BytesType extends AbstractType<ByteBuffer>
public String getString(ByteBuffer bytes)
{
return JdbcBytes.instance.getString(bytes);
return BytesSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source)
@ -72,7 +74,7 @@ public class BytesType extends AbstractType<ByteBuffer>
public void validate(ByteBuffer bytes) throws MarshalException
{
// all bytes are legal.
BytesSerializer.instance.validate(bytes);
}
@Override
@ -87,4 +89,10 @@ public class BytesType extends AbstractType<ByteBuffer>
{
return CQL3Type.Native.BLOB;
}
@Override
public AbstractSerializer<ByteBuffer> asComposer()
{
return BytesSerializer.instance;
}
}

View File

@ -22,6 +22,7 @@ import java.util.List;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.Pair;

View File

@ -25,6 +25,9 @@ import com.google.common.collect.ImmutableMap;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.BytesSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class ColumnToCollectionType extends AbstractType<ByteBuffer>
@ -103,6 +106,11 @@ public class ColumnToCollectionType extends AbstractType<ByteBuffer>
throw new UnsupportedOperationException("ColumnToCollectionType should only be used in composite types, never alone");
}
public AbstractSerializer<ByteBuffer> asComposer()
{
return BytesSerializer.instance;
}
public void validateCollectionMember(ByteBuffer bytes, ByteBuffer collectionName) throws MarshalException
{
CollectionType t = defined.get(collectionName);

View File

@ -34,6 +34,7 @@ import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.cql3.ColumnNameBuilder;
import org.apache.cassandra.cql3.Relation;
import org.apache.cassandra.io.util.DataOutputBuffer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
/*

View File

@ -21,6 +21,9 @@ import java.nio.ByteBuffer;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.db.*;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.CounterSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class CounterColumnType extends AbstractCommutativeType
@ -65,4 +68,9 @@ public class CounterColumnType extends AbstractCommutativeType
{
return CQL3Type.Native.COUNTER;
}
public AbstractSerializer<Long> asComposer()
{
return CounterSerializer.instance;
}
}

View File

@ -17,15 +17,17 @@
*/
package org.apache.cassandra.db.marshal;
import static org.apache.cassandra.cql.jdbc.JdbcDate.iso8601Patterns;
import static org.apache.cassandra.type.DateSerializer.iso8601Patterns;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.cassandra.cql.jdbc.JdbcDate;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.DateSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.commons.lang.time.DateUtils;
@ -40,12 +42,12 @@ public class DateType extends AbstractType<Date>
public Date compose(ByteBuffer bytes)
{
return JdbcDate.instance.compose(bytes);
return DateSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Date value)
{
return JdbcDate.instance.decompose(value);
return DateSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -64,14 +66,7 @@ public class DateType extends AbstractType<Date>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcDate.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return DateSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -121,12 +116,16 @@ public class DateType extends AbstractType<Date>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte long for date (%d)", bytes.remaining()));
DateSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.TIMESTAMP;
}
public AbstractSerializer<Date> asComposer()
{
return DateSerializer.instance;
}
}

View File

@ -20,8 +20,10 @@ package org.apache.cassandra.db.marshal;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcDecimal;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.DecimalSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class DecimalType extends AbstractType<BigDecimal>
@ -46,7 +48,7 @@ public class DecimalType extends AbstractType<BigDecimal>
public BigDecimal compose(ByteBuffer bytes)
{
return JdbcDecimal.instance.compose(bytes);
return DecimalSerializer.instance.serialize(bytes);
}
/**
@ -55,12 +57,12 @@ public class DecimalType extends AbstractType<BigDecimal>
*/
public ByteBuffer decompose(BigDecimal value)
{
return JdbcDecimal.instance.decompose(value);
return DecimalSerializer.instance.deserialize(value);
}
public String getString(ByteBuffer bytes)
{
return JdbcDecimal.instance.getString(bytes);
return DecimalSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -84,11 +86,17 @@ public class DecimalType extends AbstractType<BigDecimal>
public void validate(ByteBuffer bytes) throws MarshalException
{
// no useful check for invalid decimals.
DecimalSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.DECIMAL;
}
@Override
public AbstractSerializer<BigDecimal> asComposer()
{
return DecimalSerializer.instance;
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcDouble;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.DoubleSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class DoubleType extends AbstractType<Double>
@ -31,12 +33,12 @@ public class DoubleType extends AbstractType<Double>
public Double compose(ByteBuffer bytes)
{
return JdbcDouble.instance.compose(bytes);
return DoubleSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Double value)
{
return JdbcDouble.instance.decompose(value);
return DoubleSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -55,14 +57,7 @@ public class DoubleType extends AbstractType<Double>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcDouble.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return DoubleSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -86,12 +81,17 @@ public class DoubleType extends AbstractType<Double>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte value for a double (%d)", bytes.remaining()));
DoubleSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.DOUBLE;
}
@Override
public AbstractSerializer<Double> asComposer()
{
return DoubleSerializer.instance;
}
}

View File

@ -24,6 +24,8 @@ import java.util.Map;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
/*
@ -358,5 +360,11 @@ public class DynamicCompositeType extends AbstractCompositeType
{
throw new UnsupportedOperationException();
}
@Override
public AbstractSerializer<Void> asComposer()
{
throw new UnsupportedOperationException();
}
}
}

View File

@ -19,6 +19,9 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.EmptySerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
/**
@ -61,7 +64,11 @@ public class EmptyType extends AbstractType<Void>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() > 0)
throw new MarshalException("EmptyType only accept empty values");
EmptySerializer.instance.validate(bytes);
}
public AbstractSerializer<Void> asComposer()
{
return EmptySerializer.instance;
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcFloat;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.FloatSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -32,12 +34,12 @@ public class FloatType extends AbstractType<Float>
public Float compose(ByteBuffer bytes)
{
return JdbcFloat.instance.compose(bytes);
return FloatSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Float value)
{
return JdbcFloat.instance.decompose(value);
return FloatSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -56,14 +58,7 @@ public class FloatType extends AbstractType<Float>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcFloat.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return FloatSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -85,12 +80,17 @@ public class FloatType extends AbstractType<Float>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 4 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 4 or 0 byte value for a float (%d)", bytes.remaining()));
FloatSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.FLOAT;
}
@Override
public AbstractSerializer<Float> asComposer()
{
return FloatSerializer.instance;
}
}

View File

@ -18,11 +18,12 @@
package org.apache.cassandra.db.marshal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcInetAddress;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.InetAddressSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class InetAddressType extends AbstractType<InetAddress>
@ -33,12 +34,12 @@ public class InetAddressType extends AbstractType<InetAddress>
public InetAddress compose(ByteBuffer bytes)
{
return JdbcInetAddress.instance.compose(bytes);
return InetAddressSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(InetAddress value)
{
return JdbcInetAddress.instance.decompose(value);
return InetAddressSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -48,7 +49,7 @@ public class InetAddressType extends AbstractType<InetAddress>
public String getString(ByteBuffer bytes)
{
return JdbcInetAddress.instance.getString(bytes);
return InetAddressSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -73,18 +74,17 @@ public class InetAddressType extends AbstractType<InetAddress>
public void validate(ByteBuffer bytes) throws MarshalException
{
try
{
InetAddress.getByAddress(ByteBufferUtil.getArray(bytes));
}
catch (UnknownHostException e)
{
throw new MarshalException(String.format("Expected 4 or 16 byte inetaddress; got %s", ByteBufferUtil.bytesToHex(bytes)));
}
InetAddressSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.INET;
}
@Override
public AbstractSerializer<InetAddress> asComposer()
{
return InetAddressSerializer.instance;
}
}

View File

@ -19,24 +19,28 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcInt32;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.Int32Serializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class Int32Type extends AbstractType<Integer>
{
public static final Int32Type instance = new Int32Type();
Int32Type() {} // singleton
Int32Type()
{
} // singleton
public Integer compose(ByteBuffer bytes)
{
return JdbcInt32.instance.compose(bytes);
return Int32Serializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Integer value)
{
return JdbcInt32.instance.decompose(value);
return Int32Serializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -60,14 +64,7 @@ public class Int32Type extends AbstractType<Integer>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcInt32.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return Int32Serializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -92,12 +89,17 @@ public class Int32Type extends AbstractType<Integer>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 4 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 4 or 0 byte int (%d)", bytes.remaining()));
Int32Serializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.INT;
}
@Override
public AbstractSerializer<Integer> asComposer()
{
return Int32Serializer.instance;
}
}

View File

@ -20,8 +20,10 @@ package org.apache.cassandra.db.marshal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcInteger;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.IntegerSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public final class IntegerType extends AbstractType<BigInteger>
@ -58,12 +60,12 @@ public final class IntegerType extends AbstractType<BigInteger>
public BigInteger compose(ByteBuffer bytes)
{
return JdbcInteger.instance.compose(bytes);
return IntegerSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(BigInteger value)
{
return JdbcInteger.instance.decompose(value);
return IntegerSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer lhs, ByteBuffer rhs)
@ -126,7 +128,7 @@ public final class IntegerType extends AbstractType<BigInteger>
public String getString(ByteBuffer bytes)
{
return JdbcInteger.instance.getString(bytes);
return IntegerSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -151,11 +153,17 @@ public final class IntegerType extends AbstractType<BigInteger>
public void validate(ByteBuffer bytes) throws MarshalException
{
// no invalid integers.
IntegerSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.VARINT;
}
@Override
public AbstractSerializer<BigInteger> asComposer()
{
return IntegerSerializer.instance;
}
}

View File

@ -20,7 +20,9 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.apache.cassandra.cql.jdbc.JdbcLexicalUUID;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.type.UUIDSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
@ -28,16 +30,18 @@ public class LexicalUUIDType extends AbstractType<UUID>
{
public static final LexicalUUIDType instance = new LexicalUUIDType();
LexicalUUIDType() {} // singleton
LexicalUUIDType()
{
} // singleton
public UUID compose(ByteBuffer bytes)
{
return JdbcLexicalUUID.instance.compose(bytes);
return UUIDSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(UUID value)
{
return JdbcLexicalUUID.instance.decompose(value);
return UUIDSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -56,14 +60,7 @@ public class LexicalUUIDType extends AbstractType<UUID>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcLexicalUUID.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return UUIDSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -84,8 +81,12 @@ public class LexicalUUIDType extends AbstractType<UUID>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 16 && bytes.remaining() != 0)
throw new MarshalException(String.format("LexicalUUID should be 16 or 0 bytes (%d)", bytes.remaining()));
// not sure what the version should be for this.
UUIDSerializer.instance.validate(bytes);
}
@Override
public AbstractSerializer<UUID> asComposer()
{
return UUIDSerializer.instance;
}
}

View File

@ -17,13 +17,14 @@
*/
package org.apache.cassandra.db.marshal;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.ListSerializer;
import org.apache.cassandra.utils.Pair;
public class ListType<T> extends CollectionType<List<T>>
@ -32,6 +33,7 @@ public class ListType<T> extends CollectionType<List<T>>
private static final Map<AbstractType<?>, ListType> instances = new HashMap<AbstractType<?>, ListType>();
public final AbstractType<T> elements;
public final ListSerializer<T> composer;
public static ListType<?> getInstance(TypeParser parser) throws ConfigurationException, SyntaxException
{
@ -57,6 +59,7 @@ public class ListType<T> extends CollectionType<List<T>>
{
super(Kind.LIST);
this.elements = elements;
this.composer = ListSerializer.getInstance(elements.asComposer());
}
public AbstractType<UUID> nameComparator()
@ -71,26 +74,7 @@ public class ListType<T> extends CollectionType<List<T>>
public List<T> compose(ByteBuffer bytes)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = getUnsignedShort(input);
List<T> l = new ArrayList<T>(n);
for (int i = 0; i < n; i++)
{
int s = getUnsignedShort(input);
byte[] data = new byte[s];
input.get(data);
ByteBuffer databb = ByteBuffer.wrap(data);
elements.validate(databb);
l.add(elements.compose(databb));
}
return l;
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a list");
}
return composer.serialize(bytes);
}
/**
@ -102,15 +86,12 @@ public class ListType<T> extends CollectionType<List<T>>
*/
public ByteBuffer decompose(List<T> value)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(value.size());
int size = 0;
for (T elt : value)
{
ByteBuffer bb = elements.decompose(elt);
bbs.add(bb);
size += 2 + bb.remaining();
}
return pack(bbs, value.size(), size);
return composer.deserialize(value);
}
public AbstractSerializer<List<T>> asComposer()
{
return composer;
}
protected void appendToStringBuilder(StringBuilder sb)

View File

@ -19,6 +19,8 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.commons.lang.NotImplementedException;
import org.apache.cassandra.db.RowPosition;
@ -67,4 +69,9 @@ public class LocalByPartionerType<T extends Token> extends AbstractType<ByteBuff
{
throw new IllegalStateException("You shouldn't be validating this.");
}
public AbstractSerializer<ByteBuffer> asComposer()
{
throw new UnsupportedOperationException("You can't do this with a local partitioner.");
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcLong;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.LongSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.ByteBufferUtil;
public class LongType extends AbstractType<Long>
@ -31,12 +33,12 @@ public class LongType extends AbstractType<Long>
public Long compose(ByteBuffer bytes)
{
return JdbcLong.instance.compose(bytes);
return LongSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(Long value)
{
return JdbcLong.instance.decompose(value);
return LongSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -60,14 +62,7 @@ public class LongType extends AbstractType<Long>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcLong.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return LongSerializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source) throws MarshalException
@ -92,12 +87,17 @@ public class LongType extends AbstractType<Long>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte long (%d)", bytes.remaining()));
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.BIGINT;
}
@Override
public AbstractSerializer<Long> asComposer()
{
return LongSerializer.instance;
}
}

View File

@ -24,6 +24,9 @@ import java.util.*;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MapSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.Pair;
public class MapType<K, V> extends CollectionType<Map<K, V>>
@ -33,6 +36,7 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
public final AbstractType<K> keys;
public final AbstractType<V> values;
private final MapSerializer<K, V> composer;
public static MapType<?, ?> getInstance(TypeParser parser) throws ConfigurationException, SyntaxException
{
@ -60,6 +64,7 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
super(Kind.MAP);
this.keys = keys;
this.values = values;
this.composer = MapSerializer.getInstance(keys.asComposer(), values.asComposer());
}
public AbstractType<K> nameComparator()
@ -127,13 +132,19 @@ public class MapType<K, V> extends CollectionType<Map<K, V>>
return pack(bbs, value.size(), size);
}
@Override
public AbstractSerializer<Map<K, V>> asComposer()
{
return composer;
}
protected void appendToStringBuilder(StringBuilder sb)
{
sb.append(getClass().getName()).append(TypeParser.stringifyTypeParameters(Arrays.asList(keys, values)));
}
/**
* Creates the same output than decompose, but from the internal representation.
* Creates the same output than deserialize, but from the internal representation.
*/
public ByteBuffer serialize(List<Pair<ByteBuffer, Column>> columns)
{

View File

@ -25,6 +25,8 @@ import java.util.List;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
public class ReversedType<T> extends AbstractType<T>
{
@ -103,6 +105,12 @@ public class ReversedType<T> extends AbstractType<T>
return baseType.asCQL3Type();
}
@Override
public AbstractSerializer<T> asComposer()
{
return baseType.asComposer();
}
@Override
public String toString()
{

View File

@ -17,13 +17,14 @@
*/
package org.apache.cassandra.db.marshal;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.db.Column;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.SyntaxException;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.SetSerializer;
import org.apache.cassandra.utils.Pair;
public class SetType<T> extends CollectionType<Set<T>>
@ -32,6 +33,7 @@ public class SetType<T> extends CollectionType<Set<T>>
private static final Map<AbstractType<?>, SetType> instances = new HashMap<AbstractType<?>, SetType>();
public final AbstractType<T> elements;
private final SetSerializer<T> composer;
public static SetType<?> getInstance(TypeParser parser) throws ConfigurationException, SyntaxException
{
@ -57,6 +59,7 @@ public class SetType<T> extends CollectionType<Set<T>>
{
super(Kind.SET);
this.elements = elements;
this.composer = SetSerializer.getInstance(elements.asComposer());
}
public AbstractType<T> nameComparator()
@ -71,46 +74,17 @@ public class SetType<T> extends CollectionType<Set<T>>
public Set<T> compose(ByteBuffer bytes)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = getUnsignedShort(input);
Set<T> l = new LinkedHashSet<T>(n);
for (int i = 0; i < n; i++)
{
int s = getUnsignedShort(input);
byte[] data = new byte[s];
input.get(data);
ByteBuffer databb = ByteBuffer.wrap(data);
elements.validate(databb);
l.add(elements.compose(databb));
}
return l;
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a set");
}
return composer.serialize(bytes);
}
/**
* Layout is: {@code <n><s_1><b_1>...<s_n><b_n> }
* where:
* n is the number of elements
* s_i is the number of bytes composing the ith element
* b_i is the s_i bytes composing the ith element
*/
public ByteBuffer decompose(Set<T> value)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(value.size());
int size = 0;
for (T elt : value)
{
ByteBuffer bb = elements.decompose(elt);
bbs.add(bb);
size += 2 + bb.remaining();
}
return pack(bbs, value.size(), size);
return composer.deserialize(value);
}
public AbstractSerializer<Set<T>> asComposer()
{
return composer;
}
protected void appendToStringBuilder(StringBuilder sb)

View File

@ -21,8 +21,10 @@ import java.nio.ByteBuffer;
import java.util.UUID;
import java.util.regex.Pattern;
import org.apache.cassandra.cql.jdbc.JdbcTimeUUID;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.type.TimeUUIDSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
@ -32,16 +34,18 @@ public class TimeUUIDType extends AbstractType<UUID>
static final Pattern regexPattern = Pattern.compile("[A-Fa-f0-9]{8}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{4}\\-[A-Fa-f0-9]{12}");
TimeUUIDType() {} // singleton
TimeUUIDType()
{
} // singleton
public UUID compose(ByteBuffer bytes)
{
return JdbcTimeUUID.instance.compose(bytes);
return TimeUUIDSerializer.instance.serialize(bytes);
}
public ByteBuffer decompose(UUID value)
{
return JdbcTimeUUID.instance.decompose(value);
return TimeUUIDSerializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -65,40 +69,33 @@ public class TimeUUIDType extends AbstractType<UUID>
int o1Pos = o1.position();
int o2Pos = o2.position();
int d = (o1.get(o1Pos+6) & 0xF) - (o2.get(o2Pos+6) & 0xF);
int d = (o1.get(o1Pos + 6) & 0xF) - (o2.get(o2Pos + 6) & 0xF);
if (d != 0) return d;
d = (o1.get(o1Pos+7) & 0xFF) - (o2.get(o2Pos+7) & 0xFF);
d = (o1.get(o1Pos + 7) & 0xFF) - (o2.get(o2Pos + 7) & 0xFF);
if (d != 0) return d;
d = (o1.get(o1Pos+4) & 0xFF) - (o2.get(o2Pos+4) & 0xFF);
d = (o1.get(o1Pos + 4) & 0xFF) - (o2.get(o2Pos + 4) & 0xFF);
if (d != 0) return d;
d = (o1.get(o1Pos+5) & 0xFF) - (o2.get(o2Pos+5) & 0xFF);
d = (o1.get(o1Pos + 5) & 0xFF) - (o2.get(o2Pos + 5) & 0xFF);
if (d != 0) return d;
d = (o1.get(o1Pos) & 0xFF) - (o2.get(o2Pos) & 0xFF);
if (d != 0) return d;
d = (o1.get(o1Pos+1) & 0xFF) - (o2.get(o2Pos+1) & 0xFF);
d = (o1.get(o1Pos + 1) & 0xFF) - (o2.get(o2Pos + 1) & 0xFF);
if (d != 0) return d;
d = (o1.get(o1Pos+2) & 0xFF) - (o2.get(o2Pos+2) & 0xFF);
d = (o1.get(o1Pos + 2) & 0xFF) - (o2.get(o2Pos + 2) & 0xFF);
if (d != 0) return d;
return (o1.get(o1Pos+3) & 0xFF) - (o2.get(o2Pos+3) & 0xFF);
return (o1.get(o1Pos + 3) & 0xFF) - (o2.get(o2Pos + 3) & 0xFF);
}
public String getString(ByteBuffer bytes)
{
try
{
return JdbcTimeUUID.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return TimeUUIDSerializer.instance.getString(bytes);
}
// This accepts dates are valid TimeUUID represensation, which is bogus
@ -128,8 +125,7 @@ public class TimeUUIDType extends AbstractType<UUID>
if (uuid.version() != 1)
throw new MarshalException("TimeUUID supports only version 1 UUIDs");
}
else
} else
{
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes(DateType.dateStringToTimestamp(source)));
}
@ -161,8 +157,7 @@ public class TimeUUIDType extends AbstractType<UUID>
if (uuid.version() != 1)
throw new MarshalException("TimeUUID supports only version 1 UUIDs");
}
else
} else
{
throw new MarshalException(String.format("Unknown timeuuid representation: %s", source));
}
@ -171,20 +166,18 @@ public class TimeUUIDType extends AbstractType<UUID>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 16 && bytes.remaining() != 0)
throw new MarshalException(String.format("TimeUUID should be 16 or 0 bytes (%d)", bytes.remaining()));
ByteBuffer slice = bytes.slice();
// version is bits 4-7 of byte 6.
if (bytes.remaining() > 0)
{
slice.position(6);
if ((slice.get() & 0xf0) != 0x10)
throw new MarshalException("Invalid version for TimeUUID type.");
}
TimeUUIDSerializer.instance.validate(bytes);
}
public CQL3Type asCQL3Type()
{
return CQL3Type.Native.TIMEUUID;
}
@Override
public AbstractSerializer<UUID> asComposer()
{
return TimeUUIDSerializer.instance;
}
}

View File

@ -19,8 +19,10 @@ package org.apache.cassandra.db.marshal;
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcUTF8;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.type.UTF8Serializer;
public class UTF8Type extends AbstractType<String>
{
@ -30,12 +32,12 @@ public class UTF8Type extends AbstractType<String>
public String compose(ByteBuffer bytes)
{
return JdbcUTF8.instance.compose(bytes);
return UTF8Serializer.instance.serialize(bytes);
}
public ByteBuffer decompose(String value)
{
return JdbcUTF8.instance.decompose(value);
return UTF8Serializer.instance.deserialize(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
@ -45,14 +47,7 @@ public class UTF8Type extends AbstractType<String>
public String getString(ByteBuffer bytes)
{
try
{
return JdbcUTF8.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return UTF8Serializer.instance.getString(bytes);
}
public ByteBuffer fromString(String source)
@ -62,126 +57,7 @@ public class UTF8Type extends AbstractType<String>
public void validate(ByteBuffer bytes) throws MarshalException
{
if (!UTF8Validator.validate(bytes))
throw new MarshalException("String didn't validate.");
}
static class UTF8Validator
{
enum State {
START,
TWO,
TWO_80,
THREE_a0bf,
THREE_80bf_1,
THREE_80bf_2,
FOUR_90bf,
FOUR_80bf_3,
};
// since we're not converting to java strings, we don't need to worry about converting to surrogates.
// buf has already been sliced/duplicated.
static boolean validate(ByteBuffer buf)
{
buf = buf.slice();
int b = 0;
State state = State.START;
while (buf.remaining() > 0)
{
b = buf.get();
switch (state)
{
case START:
if (b >= 0)
{
// ascii, state stays start.
if (b > 127)
return false;
}
else if ((b >> 5) == -2)
{
// validate first byte of 2-byte char, 0xc2-0xdf
if (b == (byte) 0xc0)
// speical case: modified utf8 null is 0xc080.
state = State.TWO_80;
else if ((b & 0x1e) == 0)
return false;
state = State.TWO;
}
else if ((b >> 4) == -2)
{
// 3 bytes. first byte will be 0xe0 or 0xe1-0xef. handling of second byte will differ.
// so 0xe0,0xa0-0xbf,0x80-0xbf or 0xe1-0xef,0x80-0xbf,0x80-0xbf.
if (b == (byte)0xe0)
state = State.THREE_a0bf;
else
state = State.THREE_80bf_2;
break;
}
else if ((b >> 3) == -2)
{
// 4 bytes. this is where the fun starts.
if (b == (byte)0xf0)
// 0xf0, 0x90-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_90bf;
else if (b == (byte)0xf4)
// 0xf4, 0x80-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_80bf_3;
else
// 0xf1-0xf3, 0x80-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_80bf_3;
break;
}
else
return false; // malformed.
break;
case TWO:
// validate second byte of 2-byte char, 0x80-0xbf
if ((b & 0xc0) != 0x80)
return false;
state = State.START;
break;
case TWO_80:
if (b != (byte)0x80)
return false;
state = State.START;
break;
case THREE_a0bf:
if ((b & 0xe0) == 0x80)
return false;
state = State.THREE_80bf_1;
break;
case THREE_80bf_1:
// expecting 0x80-0xbf
if ((b & 0xc0) != 0x80)
return false;
state = State.START;
break;
case THREE_80bf_2:
// expecting 0x80-bf and then another of the same.
if ((b & 0xc0) != 0x80)
return false;
state = State.THREE_80bf_1;
break;
case FOUR_90bf:
// expecting 0x90-bf. 2nd byte of 4byte sequence. after that it should degrade to 80-bf,80-bf (like 3byte seq).
if ((b & 0x30) == 0)
return false;
state = State.THREE_80bf_2;
break;
case FOUR_80bf_3:
// expecting 0x80-bf 3 times. degenerates to THREE_80bf_2.
if ((b & 0xc0) != 0x80)
return false;
state = State.THREE_80bf_2;
break;
default:
return false; // invalid state.
}
}
// if state != start, we've got underflow. that's an error.
return state == State.START;
}
UTF8Serializer.instance.validate(bytes);
}
@Override
@ -196,4 +72,10 @@ public class UTF8Type extends AbstractType<String>
{
return CQL3Type.Native.TEXT;
}
@Override
public AbstractSerializer<String> asComposer()
{
return UTF8Serializer.instance;
}
}

View File

@ -22,13 +22,15 @@ import java.nio.ByteBuffer;
import java.text.ParseException;
import java.util.UUID;
import org.apache.cassandra.cql.jdbc.JdbcUUID;
import org.apache.cassandra.cql3.CQL3Type;
import org.apache.cassandra.type.AbstractSerializer;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.type.UUIDSerializer;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.UUIDGen;
import org.apache.commons.lang.time.DateUtils;
import static org.apache.cassandra.cql.jdbc.JdbcDate.iso8601Patterns;
import static org.apache.cassandra.type.DateSerializer.iso8601Patterns;
/**
* Compares UUIDs using the following criteria:<br>
@ -159,32 +161,22 @@ public class UUIDType extends AbstractType<UUID>
public UUID compose(ByteBuffer bytes)
{
return JdbcUUID.instance.compose(bytes);
return UUIDSerializer.instance.serialize(bytes);
}
public void validate(ByteBuffer bytes)
{
if ((bytes.remaining() != 0) && (bytes.remaining() != 16))
{
throw new MarshalException("UUIDs must be exactly 16 bytes");
}
UUIDSerializer.instance.validate(bytes);
}
public String getString(ByteBuffer bytes)
{
try
{
return JdbcUUID.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
return UUIDSerializer.instance.getString(bytes);
}
public ByteBuffer decompose(UUID value)
{
return JdbcUUID.instance.decompose(value);
return UUIDSerializer.instance.deserialize(value);
}
@Override
@ -209,8 +201,7 @@ public class UUIDType extends AbstractType<UUID>
{
throw new MarshalException(String.format("unable to make UUID from '%s'", source), e);
}
}
else if (source.toLowerCase().equals("now"))
} else if (source.toLowerCase().equals("now"))
{
idBytes = ByteBuffer.wrap(UUIDGen.getTimeUUIDBytes());
}
@ -247,4 +238,10 @@ public class UUIDType extends AbstractType<UUID>
{
return CQL3Type.Native.UUID;
}
@Override
public AbstractSerializer<UUID> asComposer()
{
return UUIDSerializer.instance;
}
}

View File

@ -414,7 +414,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
return previousIndex - 1;
}
/** compose the prepared query, pair.left is query id, pair.right is query */
/** serialize the prepared query, pair.left is query id, pair.right is query */
private Pair<Integer, String> composeQuery(String columns)
{
Pair<Integer, String> clause = whereClause();
@ -464,7 +464,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
return result;
}
/** compose the where clause */
/** serialize the where clause */
private Pair<Integer, String> whereClause()
{
if (partitionKeyString == null)
@ -488,7 +488,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
" WHERE token(" + partitionKeyString + ") = token(" + partitionKeyMarkers + ") " + clause.right);
}
/** recursively compose the where clause */
/** recursively serialize the where clause */
private Pair<Integer, String> whereClause(List<BoundColumn> column, int position)
{
if (position == column.size() - 1 || column.get(position + 1).value == null)
@ -509,7 +509,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
return true;
}
/** compose the partition key string in format of <key1>, <key2>, <key3> */
/** serialize the partition key string in format of <key1>, <key2>, <key3> */
private String keyString(List<BoundColumn> columns)
{
String result = null;
@ -519,7 +519,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
return result == null ? "" : result;
}
/** compose the question marks for partition key string in format of ?, ? , ? */
/** serialize the question marks for partition key string in format of ?, ? , ? */
private String partitionKeyMarkers()
{
String result = null;
@ -529,7 +529,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
return result;
}
/** compose the query binding variables, pair.left is query id, pair.right is the binding variables */
/** serialize the query binding variables, pair.left is query id, pair.right is the binding variables */
private Pair<Integer, List<ByteBuffer>> preparedQueryBindValues()
{
List<ByteBuffer> values = new LinkedList<ByteBuffer>();
@ -561,7 +561,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
}
}
/** recursively compose the query binding variables */
/** recursively serialize the query binding variables */
private int preparedQueryBindValues(List<BoundColumn> column, int position, List<ByteBuffer> bindValues)
{
if (position == column.size() - 1 || column.get(position + 1).value == null)
@ -721,7 +721,7 @@ public class CqlPagingRecordReader extends RecordReader<Map<String, ByteBuffer>,
{
try
{
// always treat counters like longs, specifically CCT.compose is not what we need
// always treat counters like longs, specifically CCT.serialize is not what we need
if (type != null && type.equals("org.apache.cassandra.db.marshal.CounterColumnType"))
return LongType.instance;
return TypeParser.parse(type);

View File

@ -356,7 +356,7 @@ final class CqlRecordWriter extends AbstractColumnFamilyRecordWriter<Map<String,
{
try
{
// always treat counters like longs, specifically CCT.compose is not what we need
// always treat counters like longs, specifically CCT.serialize is not what we need
if (type != null && type.equals("org.apache.cassandra.db.marshal.CounterColumnType"))
return LongType.instance;
return TypeParser.parse(type);

View File

@ -20,13 +20,13 @@ package org.apache.cassandra.io.sstable;
import java.io.*;
import java.util.Iterator;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.db.*;
import org.apache.cassandra.db.columniterator.OnDiskAtomIterator;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.io.util.RandomAccessReader;
public class SSTableIdentityIterator implements Comparable<SSTableIdentityIterator>, OnDiskAtomIterator

View File

@ -50,7 +50,7 @@ import org.apache.cassandra.db.filter.IDiskAtomFilter;
import org.apache.cassandra.db.filter.NamesQueryFilter;
import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.db.marshal.TimeUUIDType;
import org.apache.cassandra.dht.*;
import org.apache.cassandra.exceptions.*;

View File

@ -20,6 +20,7 @@ package org.apache.cassandra.thrift;
import java.nio.ByteBuffer;
import java.util.*;
import org.apache.cassandra.type.MarshalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -31,7 +32,6 @@ import org.apache.cassandra.db.filter.SliceQueryFilter;
import org.apache.cassandra.db.index.SecondaryIndexManager;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.service.StorageService;

View File

@ -28,6 +28,7 @@ import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import org.apache.cassandra.type.MarshalException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Option;
@ -43,7 +44,6 @@ import org.apache.cassandra.config.Schema;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.db.marshal.CompositeType;
import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.io.sstable.SSTableWriter;
import org.apache.cassandra.utils.ByteBufferUtil;

View File

@ -43,7 +43,7 @@ import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.cassandra.cql.jdbc.JdbcDate;
import org.apache.cassandra.type.DateSerializer;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.locator.EndpointSnitchInfoMBean;
@ -389,7 +389,7 @@ public class Shuffle extends AbstractJmxClient
ByteBuffer tokenBytes = ByteBuffer.wrap(row.getColumns().get(0).getValue());
ByteBuffer requestedAt = ByteBuffer.wrap(row.getColumns().get(1).getValue());
Date time = JdbcDate.instance.compose(requestedAt);
Date time = DateSerializer.instance.serialize(requestedAt);
Token<?> token = partitioner.getTokenFactory().fromByteArray(tokenBytes);
writeln("%-42s %-15s %s", token.toString(), host, time.toString());

View File

@ -15,22 +15,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import java.nio.ByteBuffer;
public abstract class AbstractJdbcType<T>
public abstract class AbstractSerializer<T>
{
public abstract boolean isCaseSensitive();
public abstract int getScale(T obj);
public abstract int getPrecision(T obj);
public abstract boolean isCurrency();
public abstract boolean isSigned();
public abstract String toString(T obj);
public abstract boolean needsQuotes();
public abstract T serialize(ByteBuffer bytes);
public abstract ByteBuffer deserialize(T value);
/* validate that the byte array is a valid sequence for the type we are supposed to be comparing */
public abstract void validate(ByteBuffer bytes) throws MarshalException;
public abstract String getString(ByteBuffer bytes);
public abstract String toString(T value);
public abstract Class<T> getType();
public abstract int getJdbcType();
public abstract T compose(ByteBuffer bytes);
public abstract ByteBuffer decompose(T obj);
}

View File

@ -15,57 +15,45 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcAscii extends AbstractJdbcType<String>
public class AsciiSerializer extends AbstractSerializer<String>
{
public static final AsciiSerializer instance = new AsciiSerializer();
private static final Charset US_ASCII = Charset.forName("US-ASCII");
public static final JdbcAscii instance = new JdbcAscii();
JdbcAscii() {}
public boolean isCaseSensitive()
@Override
public String serialize(ByteBuffer bytes)
{
return true;
return getString(bytes);
}
public int getScale(String obj)
@Override
public ByteBuffer deserialize(String value)
{
return -1;
return ByteBufferUtil.bytes(value, US_ASCII);
}
public int getPrecision(String obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public String toString(String obj)
{
return obj;
}
public boolean needsQuotes()
{
return true;
// 0-127
for (int i = bytes.position(); i < bytes.limit(); i++)
{
byte b = bytes.get(i);
if (b < 0 || b > 127)
throw new MarshalException("Invalid byte for ascii: " + Byte.toString(b));
}
}
@Override
public String getString(ByteBuffer bytes)
{
try
@ -78,23 +66,15 @@ public class JdbcAscii extends AbstractJdbcType<String>
}
}
@Override
public String toString(String value)
{
return value;
}
@Override
public Class<String> getType()
{
return String.class;
}
public int getJdbcType()
{
return Types.VARCHAR;
}
public String compose(ByteBuffer bytes)
{
return getString(bytes);
}
public ByteBuffer decompose(String value)
{
return ByteBufferUtil.bytes(value, US_ASCII);
}
}

View File

@ -15,54 +15,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcBoolean extends AbstractJdbcType<Boolean>
import java.nio.ByteBuffer;
public class BooleanSerializer extends AbstractSerializer<Boolean>
{
public static final JdbcBoolean instance = new JdbcBoolean();
public static final BooleanSerializer instance = new BooleanSerializer();
JdbcBoolean() {}
public boolean isCaseSensitive()
@Override
public Boolean serialize(ByteBuffer bytes)
{
return false;
byte value = bytes.get(bytes.position());
return value != 0;
}
public int getScale(Boolean obj)
@Override
public ByteBuffer deserialize(Boolean value)
{
return -1;
return (value == null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER
: value ? ByteBuffer.wrap(new byte[] {1}) // true
: ByteBuffer.wrap(new byte[] {0}); // false
}
public int getPrecision(Boolean obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public String toString(Boolean obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 1 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 1 or 0 byte value (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -71,33 +57,23 @@ public class JdbcBoolean extends AbstractJdbcType<Boolean>
}
if (bytes.remaining() != 1)
{
throw new MarshalException("A boolean is stored in exactly 1 byte: "+bytes.remaining());
throw new MarshalException("A boolean is stored in exactly 1 byte: " + bytes.remaining());
}
byte value = bytes.get(bytes.position());
return value ==0 ? Boolean.FALSE.toString(): Boolean.TRUE.toString();
return value == 0 ? Boolean.FALSE.toString() : Boolean.TRUE.toString();
}
@Override
public String toString(Boolean value)
{
return value == null ? "" : value.toString();
}
@Override
public Class<Boolean> getType()
{
return Boolean.class;
}
public int getJdbcType()
{
return Types.BOOLEAN;
}
public Boolean compose(ByteBuffer bytes)
{
byte value = bytes.get(bytes.position());
return Boolean.valueOf(value ==0 ? false:true);
}
public ByteBuffer decompose(Boolean value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER
: value ? ByteBuffer.wrap(new byte[]{1}) // true
: ByteBuffer.wrap(new byte[]{0}); // false
}
}

View File

@ -15,77 +15,52 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
public class JdbcBytes extends AbstractJdbcType<ByteBuffer>
public class BytesSerializer extends AbstractSerializer<ByteBuffer>
{
public static final JdbcBytes instance = new JdbcBytes();
public static final BytesSerializer instance = new BytesSerializer();
JdbcBytes() {}
public boolean isCaseSensitive()
@Override
public ByteBuffer serialize(ByteBuffer bytes)
{
return false;
// We make a copy in case the user modifies the input
return bytes.duplicate();
}
public int getScale(ByteBuffer obj)
@Override
public ByteBuffer deserialize(ByteBuffer value)
{
return -1;
// This is from the DB, so it is not shared with someone else
return value;
}
public int getPrecision(ByteBuffer obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public String toString(ByteBuffer obj)
{
return getString(obj);
}
public boolean needsQuotes()
{
return true;
// all bytes are legal.
}
@Override
public String getString(ByteBuffer bytes)
{
return ByteBufferUtil.bytesToHex(bytes);
}
@Override
public String toString(ByteBuffer value)
{
return getString(value);
}
@Override
public Class<ByteBuffer> getType()
{
return ByteBuffer.class;
}
public int getJdbcType()
{
return Types.BINARY;
}
public ByteBuffer compose(ByteBuffer bytes)
{
return bytes.duplicate();
}
public ByteBuffer decompose(ByteBuffer value)
{
return value;
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.type;
import java.nio.ByteBuffer;
import java.util.List;
public abstract class CollectionSerializer<T> extends AbstractSerializer<T>
{
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
// The collection is not currently being properly validated.
}
public String getString(ByteBuffer bytes)
{
return BytesSerializer.instance.getString(bytes);
}
// Utilitary method
protected static ByteBuffer pack(List<ByteBuffer> buffers, int elements, int size)
{
ByteBuffer result = ByteBuffer.allocate(2 + size);
result.putShort((short)elements);
for (ByteBuffer bb : buffers)
{
result.putShort((short)bb.remaining());
result.put(bb.duplicate());
}
return (ByteBuffer)result.flip();
}
public static ByteBuffer pack(List<ByteBuffer> buffers, int elements)
{
int size = 0;
for (ByteBuffer bb : buffers)
size += 2 + bb.remaining();
return pack(buffers, elements, size);
}
protected static int getUnsignedShort(ByteBuffer bb)
{
int length = (bb.get() & 0xFF) << 8;
return length | (bb.get() & 0xFF);
}
}

View File

@ -15,11 +15,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
public class JdbcCounterColumn extends JdbcLong
package org.apache.cassandra.type;
public class CounterSerializer extends LongSerializer
{
public static final JdbcCounterColumn instance = new JdbcCounterColumn();
JdbcCounterColumn() {}
}

View File

@ -15,30 +15,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Date;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcDate extends AbstractJdbcType<Date>
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateSerializer extends AbstractSerializer<Date>
{
public static final String[] iso8601Patterns = new String[] {
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mmZ",
"yyyy-MM-dd HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm",
"yyyy-MM-dd'T'HH:mmZ",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd",
"yyyy-MM-ddZ"
"yyyy-MM-dd HH:mm",
"yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mmZ",
"yyyy-MM-dd HH:mm:ssZ",
"yyyy-MM-dd'T'HH:mm",
"yyyy-MM-dd'T'HH:mmZ",
"yyyy-MM-dd'T'HH:mm:ss",
"yyyy-MM-dd'T'HH:mm:ssZ",
"yyyy-MM-dd",
"yyyy-MM-ddZ"
};
static final String DEFAULT_FORMAT = iso8601Patterns[3];
static final ThreadLocal<SimpleDateFormat> FORMATTER = new ThreadLocal<SimpleDateFormat>()
{
protected SimpleDateFormat initialValue()
@ -47,45 +49,32 @@ public class JdbcDate extends AbstractJdbcType<Date>
}
};
public static final JdbcDate instance = new JdbcDate();
public static final DateSerializer instance = new DateSerializer();
JdbcDate() {}
public boolean isCaseSensitive()
@Override
public Date serialize(ByteBuffer bytes)
{
return false;
return bytes.remaining() > 0
? new Date(ByteBufferUtil.toLong(bytes))
: null;
}
public int getScale(Date obj)
@Override
public ByteBuffer deserialize(Date value)
{
return -1;
return (value == null)
? ByteBufferUtil.EMPTY_BYTE_BUFFER
: ByteBufferUtil.bytes(value.getTime());
}
public int getPrecision(Date obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return -1;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return false;
}
public String toString(Date obj)
{
return FORMATTER.get().format(obj);
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte long for date (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -98,30 +87,18 @@ public class JdbcDate extends AbstractJdbcType<Date>
}
// uses ISO-8601 formatted string
return FORMATTER.get().format(new Date(bytes.getLong(bytes.position())));
return FORMATTER.get().format(new Date(ByteBufferUtil.toLong(bytes)));
}
@Override
public String toString(Date value)
{
return FORMATTER.get().format(value);
}
@Override
public Class<Date> getType()
{
return Date.class;
}
public int getJdbcType()
{
return Types.TIMESTAMP;
}
public Date compose(ByteBuffer bytes)
{
return bytes.remaining() > 0
? new Date(ByteBufferUtil.toLong(bytes))
: null;
}
public ByteBuffer decompose(Date value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER
: ByteBufferUtil.bytes(value.getTime());
}
}

View File

@ -15,76 +15,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcDecimal extends AbstractJdbcType<BigDecimal>
public class DecimalSerializer extends AbstractSerializer<BigDecimal>
{
public static final JdbcDecimal instance = new JdbcDecimal();
public static final DecimalSerializer instance = new DecimalSerializer();
JdbcDecimal() {}
public boolean isCaseSensitive()
@Override
public BigDecimal serialize(ByteBuffer bytes)
{
return false;
}
public int getScale(BigDecimal obj)
{
return obj.scale();
}
public int getPrecision(BigDecimal obj)
{
return obj.precision();
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(BigDecimal obj)
{
return obj.toPlainString();
}
public boolean needsQuotes()
{
return false;
}
public String getString(ByteBuffer bytes)
{
if (bytes == null) return "null";
if (bytes.remaining() == 0) return "empty";
return compose(bytes).toPlainString();
}
public Class<BigDecimal> getType()
{
return BigDecimal.class;
}
public int getJdbcType()
{
return Types.DECIMAL;
}
public BigDecimal compose(ByteBuffer bytes)
{
if (bytes == null) return null;
if (bytes == null)
return null;
// do not consume the contents of the ByteBuffer
bytes = bytes.duplicate();
@ -93,27 +41,54 @@ public class JdbcDecimal extends AbstractJdbcType<BigDecimal>
bytes.get(bibytes);
BigInteger bi = new BigInteger(bibytes);
return new BigDecimal(bi,scale);
return new BigDecimal(bi, scale);
}
/**
* The bytes of the ByteBuffer are made up of 4 bytes of int containing the scale
* followed by the n bytes it takes to store a BigInteger.
*/
public ByteBuffer decompose(BigDecimal value)
@Override
public ByteBuffer deserialize(BigDecimal value)
{
if (value == null) return ByteBufferUtil.EMPTY_BYTE_BUFFER;
if (value == null)
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
BigInteger bi = value.unscaledValue();
Integer scale = value.scale();
byte[] bibytes = bi.toByteArray();
byte[] sbytes = ByteBufferUtil.bytes(scale).array();
byte[] bytes = new byte[bi.toByteArray().length+4];
byte[] bytes = new byte[bi.toByteArray().length + 4];
for (int i = 0 ; i < 4 ; i++) bytes[i] = sbytes[i];
for (int i = 4 ; i < bibytes.length+4 ; i++) bytes[i] = bibytes[i-4];
for (int i = 0; i < 4; i++)
bytes[i] = sbytes[i];
for (int i = 4; i < bibytes.length + 4; i++)
bytes[i] = bibytes[i - 4];
return ByteBuffer.wrap(bytes);
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
// no useful check for invalid decimals.
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
return serialize(bytes).toPlainString();
}
@Override
public String toString(BigDecimal value)
{
return value == null ? "" : value.toPlainString();
}
@Override
public Class<BigDecimal> getType()
{
return BigDecimal.class;
}
}

View File

@ -15,54 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcDouble extends AbstractJdbcType<Double>
import java.nio.ByteBuffer;
public class DoubleSerializer extends AbstractSerializer<Double>
{
public static final JdbcDouble instance = new JdbcDouble();
public static final DoubleSerializer instance = new DoubleSerializer();
JdbcDouble() {}
public boolean isCaseSensitive()
@Override
public Double serialize(ByteBuffer bytes)
{
return false;
return ByteBufferUtil.toDouble(bytes);
}
public int getScale(Double obj)
@Override
public ByteBuffer deserialize(Double value)
{
return 300;
return (value == null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public int getPrecision(Double obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return 15;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(Double obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte value for a double (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -71,29 +54,21 @@ public class JdbcDouble extends AbstractJdbcType<Double>
}
if (bytes.remaining() != 8)
{
throw new MarshalException("A double is exactly 8 bytes : "+bytes.remaining());
throw new MarshalException("A double is exactly 8 bytes : " + bytes.remaining());
}
return ((Double)ByteBufferUtil.toDouble(bytes)).toString();
return String.valueOf(ByteBufferUtil.toDouble(bytes));
}
@Override
public String toString(Double value)
{
return value == null ? "" : value.toString();
}
@Override
public Class<Double> getType()
{
return Double.class;
}
public int getJdbcType()
{
return Types.DOUBLE;
}
public Double compose(ByteBuffer bytes)
{
return ByteBufferUtil.toDouble(bytes);
}
public ByteBuffer decompose(Double value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
}

View File

@ -15,43 +15,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.apache.cassandra.utils.UUIDGen;
public class JdbcUUID extends AbstractJdbcUUID
public class EmptySerializer extends AbstractSerializer<Void>
{
public static final JdbcUUID instance = new JdbcUUID();
public static final EmptySerializer instance = new EmptySerializer();
JdbcUUID() {}
public UUID compose(ByteBuffer bytes)
@Override
public Void serialize(ByteBuffer bytes)
{
bytes = bytes.slice();
if (bytes.remaining() < 16)
return new UUID(0, 0);
return new UUID(bytes.getLong(), bytes.getLong());
return null;
}
@Override
public ByteBuffer deserialize(Void value)
{
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() > 0)
throw new MarshalException("EmptyType only accept empty values");
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 16)
{
throw new MarshalException("UUIDs must be exactly 16 bytes");
}
return compose(bytes).toString();
return "";
}
public ByteBuffer decompose(UUID value)
@Override
public String toString(Void value)
{
return ByteBuffer.wrap(UUIDGen.decompose(value));
return "";
}
@Override
public Class<Void> getType()
{
return Void.class;
}
}

View File

@ -15,54 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcFloat extends AbstractJdbcType<Float>
import java.nio.ByteBuffer;
public class FloatSerializer extends AbstractSerializer<Float>
{
public static final JdbcFloat instance = new JdbcFloat();
public static final FloatSerializer instance = new FloatSerializer();
JdbcFloat() {}
public boolean isCaseSensitive()
@Override
public Float serialize(ByteBuffer bytes)
{
return false;
return ByteBufferUtil.toFloat(bytes);
}
public int getScale(Float obj)
@Override
public ByteBuffer deserialize(Float value)
{
return 40;
return (value == null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public int getPrecision(Float obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return 7;
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(Float obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 4 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 4 or 0 byte value for a float (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -71,29 +54,21 @@ public class JdbcFloat extends AbstractJdbcType<Float>
}
if (bytes.remaining() != 4)
{
throw new MarshalException("A float is exactly 4 bytes : "+bytes.remaining());
throw new MarshalException("A float is exactly 4 bytes : " + bytes.remaining());
}
return ((Float)ByteBufferUtil.toFloat(bytes)).toString();
return String.valueOf(ByteBufferUtil.toFloat(bytes));
}
@Override
public String toString(Float value)
{
return value == null ? "" : String.valueOf(value);
}
@Override
public Class<Float> getType()
{
return Float.class;
}
public int getJdbcType()
{
return Types.FLOAT;
}
public Float compose(ByteBuffer bytes)
{
return ByteBufferUtil.toFloat(bytes);
}
public ByteBuffer decompose(Float value)
{
return (value==null) ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
}

View File

@ -15,74 +15,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcInetAddress extends AbstractJdbcType<InetAddress>
public class InetAddressSerializer extends AbstractSerializer<InetAddress>
{
public static final JdbcInetAddress instance = new JdbcInetAddress();
public static final InetAddressSerializer instance = new InetAddressSerializer();
JdbcInetAddress()
{
}
public boolean isCaseSensitive()
{
return false;
}
public int getScale(InetAddress obj)
{
return 0;
}
public int getPrecision(InetAddress obj)
{
return obj.toString().length();
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(InetAddress obj)
{
return obj.getHostAddress();
}
public boolean needsQuotes()
{
return false;
}
public String getString(ByteBuffer bytes)
{
return compose(bytes).getHostAddress();
}
public Class<InetAddress> getType()
{
return InetAddress.class;
}
public int getJdbcType()
{
return Types.OTHER;
}
public InetAddress compose(ByteBuffer bytes)
@Override
public InetAddress serialize(ByteBuffer bytes)
{
try
{
@ -94,8 +41,40 @@ public class JdbcInetAddress extends AbstractJdbcType<InetAddress>
}
}
public ByteBuffer decompose(InetAddress value)
@Override
public ByteBuffer deserialize(InetAddress value)
{
return ByteBuffer.wrap(value.getAddress());
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
try
{
InetAddress.getByAddress(ByteBufferUtil.getArray(bytes));
}
catch (UnknownHostException e)
{
throw new MarshalException(String.format("Expected 4 or 16 byte inetaddress; got %s", ByteBufferUtil.bytesToHex(bytes)));
}
}
@Override
public String getString(ByteBuffer bytes)
{
return serialize(bytes).getHostAddress();
}
@Override
public String toString(InetAddress value)
{
return value.getHostAddress();
}
@Override
public Class<InetAddress> getType()
{
return InetAddress.class;
}
}

View File

@ -15,56 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcInt32 extends AbstractJdbcType<Integer>
import java.nio.ByteBuffer;
public class Int32Serializer extends AbstractSerializer<Integer>
{
public static final JdbcInt32 instance = new JdbcInt32();
public static final Int32Serializer instance = new Int32Serializer();
JdbcInt32()
@Override
public Integer serialize(ByteBuffer bytes)
{
return ByteBufferUtil.toInt(bytes);
}
public boolean isCaseSensitive()
@Override
public ByteBuffer deserialize(Integer value)
{
return false;
return value == null ? ByteBufferUtil.EMPTY_BYTE_BUFFER : ByteBufferUtil.bytes(value);
}
public int getScale(Integer obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return 0;
}
public int getPrecision(Integer obj)
{
return obj.toString().length();
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(Integer obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 4 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 4 or 0 byte int (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -76,26 +57,18 @@ public class JdbcInt32 extends AbstractJdbcType<Integer>
throw new MarshalException("A int is exactly 4 bytes: " + bytes.remaining());
}
return String.valueOf(bytes.getInt(bytes.position()));
return String.valueOf(ByteBufferUtil.toInt(bytes));
}
@Override
public String toString(Integer value)
{
return value == null ? "" : String.valueOf(value);
}
@Override
public Class<Integer> getType()
{
return Integer.class;
}
public int getJdbcType()
{
return Types.INTEGER;
}
public Integer compose(ByteBuffer bytes)
{
return ByteBufferUtil.toInt(bytes);
}
public ByteBuffer decompose(Integer value)
{
return ByteBufferUtil.bytes(value);
}
}

View File

@ -15,82 +15,56 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcInteger extends AbstractJdbcType<BigInteger>
import java.math.BigInteger;
import java.nio.ByteBuffer;
public class IntegerSerializer extends AbstractSerializer<BigInteger>
{
public static final JdbcInteger instance = new JdbcInteger();
public static final IntegerSerializer instance = new IntegerSerializer();
JdbcInteger() {}
public boolean isCaseSensitive()
{
return false;
}
public int getScale(BigInteger obj)
{
return 0;
}
public int getPrecision(BigInteger obj)
{
return obj.toString().length();
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(BigInteger obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
}
public String getString(ByteBuffer bytes)
{
if (bytes == null)
return "null";
if (bytes.remaining() == 0)
return "empty";
return new BigInteger(ByteBufferUtil.getArray(bytes)).toString(10);
}
public Class<BigInteger> getType()
{
return BigInteger.class;
}
public int getJdbcType()
{
return Types.BIGINT;
}
public BigInteger compose(ByteBuffer bytes)
@Override
public BigInteger serialize(ByteBuffer bytes)
{
return new BigInteger(ByteBufferUtil.getArray(bytes));
}
public ByteBuffer decompose(BigInteger value)
@Override
public ByteBuffer deserialize(BigInteger value)
{
return ByteBuffer.wrap(value.toByteArray());
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
// no invalid integers.
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
return new BigInteger(ByteBufferUtil.getArray(bytes)).toString(10);
}
@Override
public String toString(BigInteger value)
{
return value.toString(10);
}
@Override
public Class<BigInteger> getType()
{
return BigInteger.class;
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.type;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
public class ListSerializer<T> extends CollectionSerializer<List<T>>
{
// interning instances
private static final Map<AbstractSerializer<?>, ListSerializer> instances = new HashMap<AbstractSerializer<?>, ListSerializer>();
public final AbstractSerializer<T> elements;
public static synchronized <T> ListSerializer<T> getInstance(AbstractSerializer<T> elements)
{
ListSerializer<T> t = instances.get(elements);
if (t == null)
{
t = new ListSerializer<T>(elements);
instances.put(elements, t);
}
return t;
}
private ListSerializer(AbstractSerializer<T> elements)
{
this.elements = elements;
}
public List<T> serialize(ByteBuffer bytes)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = getUnsignedShort(input);
List<T> l = new ArrayList<T>(n);
for (int i = 0; i < n; i++)
{
int s = getUnsignedShort(input);
byte[] data = new byte[s];
input.get(data);
ByteBuffer databb = ByteBuffer.wrap(data);
elements.validate(databb);
l.add(elements.serialize(databb));
}
return l;
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a list");
}
}
/**
* Layout is: {@code <n><s_1><b_1>...<s_n><b_n> }
* where:
* n is the number of elements
* s_i is the number of bytes composing the ith element
* b_i is the s_i bytes composing the ith element
*/
public ByteBuffer deserialize(List<T> value)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(value.size());
int size = 0;
for (T elt : value)
{
ByteBuffer bb = elements.deserialize(elt);
bbs.add(bb);
size += 2 + bb.remaining();
}
return pack(bbs, value.size(), size);
}
public String toString(List<T> value)
{
StringBuffer sb = new StringBuffer();
boolean isFirst = true;
for (T element : value)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.append("; ");
}
sb.append(elements.toString(element));
}
return sb.toString();
}
public Class<List<T>> getType()
{
return (Class) List.class;
}
}

View File

@ -15,56 +15,37 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
import java.nio.ByteBuffer;
import java.sql.Types;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcLong extends AbstractJdbcType<Long>
import java.nio.ByteBuffer;
public class LongSerializer extends AbstractSerializer<Long>
{
public static final JdbcLong instance = new JdbcLong();
public static final LongSerializer instance = new LongSerializer();
JdbcLong()
@Override
public Long serialize(ByteBuffer bytes)
{
return ByteBufferUtil.toLong(bytes);
}
public boolean isCaseSensitive()
@Override
public ByteBuffer deserialize(Long value)
{
return false;
return ByteBufferUtil.bytes(value);
}
public int getScale(Long obj)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
return 0;
}
public int getPrecision(Long obj)
{
return obj.toString().length();
}
public boolean isCurrency()
{
return false;
}
public boolean isSigned()
{
return true;
}
public String toString(Long obj)
{
return obj.toString();
}
public boolean needsQuotes()
{
return false;
if (bytes.remaining() != 8 && bytes.remaining() != 0)
throw new MarshalException(String.format("Expected 8 or 0 byte long (%d)", bytes.remaining()));
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -76,26 +57,18 @@ public class JdbcLong extends AbstractJdbcType<Long>
throw new MarshalException("A long is exactly 8 bytes: " + bytes.remaining());
}
return String.valueOf(bytes.getLong(bytes.position()));
return String.valueOf(ByteBufferUtil.toLong(bytes));
}
@Override
public String toString(Long value)
{
return String.valueOf(value);
}
@Override
public Class<Long> getType()
{
return Long.class;
}
public int getJdbcType()
{
return Types.BIGINT;
}
public Long compose(ByteBuffer bytes)
{
return ByteBufferUtil.toLong(bytes);
}
public ByteBuffer decompose(Long value)
{
return ByteBufferUtil.bytes(value);
}
}

View File

@ -0,0 +1,130 @@
/*
* 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.type;
import org.apache.cassandra.utils.Pair;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
public class MapSerializer<K, V> extends CollectionSerializer<Map<K, V>>
{
// interning instances
private static final Map<Pair<AbstractSerializer<?>, AbstractSerializer<?>>, MapSerializer> instances = new HashMap<Pair<AbstractSerializer<?>, AbstractSerializer<?>>, MapSerializer>();
public final AbstractSerializer<K> keys;
public final AbstractSerializer<V> values;
public static synchronized <K, V> MapSerializer<K, V> getInstance(AbstractSerializer<K> keys, AbstractSerializer<V> values)
{
Pair<AbstractSerializer<?>, AbstractSerializer<?>> p = Pair.<AbstractSerializer<?>, AbstractSerializer<?>>create(keys, values);
MapSerializer<K, V> t = instances.get(p);
if (t == null)
{
t = new MapSerializer<K, V>(keys, values);
instances.put(p, t);
}
return t;
}
private MapSerializer(AbstractSerializer<K> keys, AbstractSerializer<V> values)
{
this.keys = keys;
this.values = values;
}
@Override
public Map<K, V> serialize(ByteBuffer bytes)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = getUnsignedShort(input);
Map<K, V> m = new LinkedHashMap<K, V>(n);
for (int i = 0; i < n; i++)
{
int sk = getUnsignedShort(input);
byte[] datak = new byte[sk];
input.get(datak);
ByteBuffer kbb = ByteBuffer.wrap(datak);
keys.validate(kbb);
int sv = getUnsignedShort(input);
byte[] datav = new byte[sv];
input.get(datav);
ByteBuffer vbb = ByteBuffer.wrap(datav);
values.validate(vbb);
m.put(keys.serialize(kbb), values.serialize(vbb));
}
return m;
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a map");
}
}
@Override
public ByteBuffer deserialize(Map<K, V> value)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(2 * value.size());
int size = 0;
for (Map.Entry<K, V> entry : value.entrySet())
{
ByteBuffer bbk = keys.deserialize(entry.getKey());
ByteBuffer bbv = values.deserialize(entry.getValue());
bbs.add(bbk);
bbs.add(bbv);
size += 4 + bbk.remaining() + bbv.remaining();
}
return pack(bbs, value.size(), size);
}
@Override
public String toString(Map<K, V> value)
{
StringBuffer sb = new StringBuffer();
boolean isFirst = true;
for (Map.Entry<K, V> element : value.entrySet())
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.append("; ");
}
sb.append('(');
sb.append(keys.toString(element.getKey()));
sb.append(", ");
sb.append(values.toString(element.getValue()));
sb.append(')');
}
return sb.toString();
}
@Override
public Class<Map<K, V>> getType()
{
return (Class)Map.class;
}
}

View File

@ -15,7 +15,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
public class MarshalException extends RuntimeException
{

View File

@ -0,0 +1,115 @@
/*
* 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.type;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.*;
public class SetSerializer<T> extends CollectionSerializer<Set<T>>
{
// interning instances
private static final Map<AbstractSerializer<?>, SetSerializer> instances = new HashMap<AbstractSerializer<?>, SetSerializer>();
public final AbstractSerializer<T> elements;
public static synchronized <T> SetSerializer<T> getInstance(AbstractSerializer<T> elements)
{
SetSerializer<T> t = instances.get(elements);
if (t == null)
{
t = new SetSerializer<T>(elements);
instances.put(elements, t);
}
return t;
}
private SetSerializer(AbstractSerializer<T> elements)
{
this.elements = elements;
}
public Set<T> serialize(ByteBuffer bytes)
{
try
{
ByteBuffer input = bytes.duplicate();
int n = getUnsignedShort(input);
Set<T> l = new LinkedHashSet<T>(n);
for (int i = 0; i < n; i++)
{
int s = getUnsignedShort(input);
byte[] data = new byte[s];
input.get(data);
ByteBuffer databb = ByteBuffer.wrap(data);
elements.validate(databb);
l.add(elements.serialize(databb));
}
return l;
}
catch (BufferUnderflowException e)
{
throw new MarshalException("Not enough bytes to read a list");
}
}
/**
* Layout is: {@code <n><s_1><b_1>...<s_n><b_n> }
* where:
* n is the number of elements
* s_i is the number of bytes composing the ith element
* b_i is the s_i bytes composing the ith element
*/
public ByteBuffer deserialize(Set<T> value)
{
List<ByteBuffer> bbs = new ArrayList<ByteBuffer>(value.size());
int size = 0;
for (T elt : value)
{
ByteBuffer bb = elements.deserialize(elt);
bbs.add(bb);
size += 2 + bb.remaining();
}
return pack(bbs, value.size(), size);
}
public String toString(Set<T> value)
{
StringBuffer sb = new StringBuffer();
boolean isFirst = true;
for (T element : value)
{
if (isFirst)
{
isFirst = false;
}
else
{
sb.append("; ");
}
sb.append(elements.toString(element));
}
return sb.toString();
}
public Class<Set<T>> getType()
{
return (Class) Set.class;
}
}

View File

@ -15,17 +15,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.db.marshal;
public class MarshalException extends RuntimeException
package org.apache.cassandra.type;
import java.nio.ByteBuffer;
public class TimeUUIDSerializer extends UUIDSerializer
{
public MarshalException(String message)
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
super(message);
}
super.validate(bytes);
public MarshalException(String message, Throwable cause)
{
super(message, cause);
// Super class only validates the Time UUID
ByteBuffer slice = bytes.slice();
// version is bits 4-7 of byte 6.
if (bytes.remaining() > 0)
{
slice.position(6);
if ((slice.get() & 0xf0) != 0x10)
throw new MarshalException("Invalid version for TimeUUID type.");
}
}
}

View File

@ -0,0 +1,193 @@
/*
* 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.type;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
public class UTF8Serializer extends AbstractSerializer<String>
{
public static final UTF8Serializer instance = new UTF8Serializer();
private static final Charset UTF_8 = Charset.forName("UTF-8");
@Override
public String serialize(ByteBuffer bytes)
{
return getString(bytes);
}
@Override
public ByteBuffer deserialize(String value)
{
return ByteBufferUtil.bytes(value, UTF_8);
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
if (!UTF8Validator.validate(bytes))
throw new MarshalException("String didn't validate.");
}
static class UTF8Validator
{
enum State {
START,
TWO,
TWO_80,
THREE_a0bf,
THREE_80bf_1,
THREE_80bf_2,
FOUR_90bf,
FOUR_80bf_3,
};
// since we're not converting to java strings, we don't need to worry about converting to surrogates.
// buf has already been sliced/duplicated.
static boolean validate(ByteBuffer buf)
{
buf = buf.slice();
int b = 0;
State state = State.START;
while (buf.remaining() > 0)
{
b = buf.get();
switch (state)
{
case START:
if (b >= 0)
{
// ascii, state stays start.
if (b > 127)
return false;
}
else if ((b >> 5) == -2)
{
// validate first byte of 2-byte char, 0xc2-0xdf
if (b == (byte) 0xc0)
// speical case: modified utf8 null is 0xc080.
state = State.TWO_80;
else if ((b & 0x1e) == 0)
return false;
state = State.TWO;
}
else if ((b >> 4) == -2)
{
// 3 bytes. first byte will be 0xe0 or 0xe1-0xef. handling of second byte will differ.
// so 0xe0,0xa0-0xbf,0x80-0xbf or 0xe1-0xef,0x80-0xbf,0x80-0xbf.
if (b == (byte)0xe0)
state = State.THREE_a0bf;
else
state = State.THREE_80bf_2;
break;
}
else if ((b >> 3) == -2)
{
// 4 bytes. this is where the fun starts.
if (b == (byte)0xf0)
// 0xf0, 0x90-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_90bf;
else if (b == (byte)0xf4)
// 0xf4, 0x80-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_80bf_3;
else
// 0xf1-0xf3, 0x80-0xbf, 0x80-0xbf, 0x80-0xbf
state = State.FOUR_80bf_3;
break;
}
else
return false; // malformed.
break;
case TWO:
// validate second byte of 2-byte char, 0x80-0xbf
if ((b & 0xc0) != 0x80)
return false;
state = State.START;
break;
case TWO_80:
if (b != (byte)0x80)
return false;
state = State.START;
break;
case THREE_a0bf:
if ((b & 0xe0) == 0x80)
return false;
state = State.THREE_80bf_1;
break;
case THREE_80bf_1:
// expecting 0x80-0xbf
if ((b & 0xc0) != 0x80)
return false;
state = State.START;
break;
case THREE_80bf_2:
// expecting 0x80-bf and then another of the same.
if ((b & 0xc0) != 0x80)
return false;
state = State.THREE_80bf_1;
break;
case FOUR_90bf:
// expecting 0x90-bf. 2nd byte of 4byte sequence. after that it should degrade to 80-bf,80-bf (like 3byte seq).
if ((b & 0x30) == 0)
return false;
state = State.THREE_80bf_2;
break;
case FOUR_80bf_3:
// expecting 0x80-bf 3 times. degenerates to THREE_80bf_2.
if ((b & 0xc0) != 0x80)
return false;
state = State.THREE_80bf_2;
break;
default:
return false; // invalid state.
}
}
// if state != start, we've got underflow. that's an error.
return state == State.START;
}
}
@Override
public String getString(ByteBuffer bytes)
{
try
{
return ByteBufferUtil.string(bytes, UTF_8);
}
catch (CharacterCodingException e)
{
throw new MarshalException("Invalid ascii bytes " + ByteBufferUtil.bytesToHex(bytes));
}
}
@Override
public String toString(String value)
{
return value;
}
@Override
public Class<String> getType()
{
return String.class;
}
}

View File

@ -15,19 +15,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
import org.apache.cassandra.utils.UUIDGen;
import java.nio.ByteBuffer;
import java.util.UUID;
import org.apache.cassandra.utils.UUIDGen;
public class JdbcTimeUUID extends AbstractJdbcUUID
public class UUIDSerializer extends AbstractSerializer<UUID>
{
public static final JdbcTimeUUID instance = new JdbcTimeUUID();
public static final UUIDSerializer instance = new UUIDSerializer();
JdbcTimeUUID() {}
@Override
public UUID serialize(ByteBuffer bytes)
{
return UUIDGen.getUUID(bytes);
}
@Override
public ByteBuffer deserialize(UUID value)
{
return ByteBuffer.wrap(UUIDGen.decompose(value));
}
@Override
public void validate(ByteBuffer bytes) throws MarshalException
{
if (bytes.remaining() != 16 && bytes.remaining() != 0)
throw new MarshalException(String.format("UUID should be 16 or 0 bytes (%d)", bytes.remaining()));
// not sure what the version should be for this.
}
@Override
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
@ -39,20 +59,18 @@ public class JdbcTimeUUID extends AbstractJdbcUUID
throw new MarshalException("UUIDs must be exactly 16 bytes");
}
UUID uuid = UUIDGen.getUUID(bytes);
if (uuid.version() != 1)
{
throw new MarshalException("TimeUUID only makes sense with version 1 UUIDs");
}
return uuid.toString();
}
public UUID compose(ByteBuffer bytes)
@Override
public String toString(UUID value)
{
return UUIDGen.getUUID(bytes);
return value.toString();
}
public ByteBuffer decompose(UUID value)
@Override
public Class<UUID> getType()
{
return ByteBuffer.wrap(UUIDGen.decompose(value));
return UUID.class;
}
}

View File

@ -21,6 +21,7 @@ package org.apache.cassandra.cql.jdbc;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import org.apache.cassandra.type.DecimalSerializer;
import org.junit.Assert;
import org.junit.Test;
@ -30,10 +31,10 @@ public class JdbcDecimalTest
public void testComposeDecompose()
{
BigDecimal expected = new BigDecimal("123456789123456789.987654321");
JdbcDecimal decimal = new JdbcDecimal();
DecimalSerializer decimal = new DecimalSerializer();
ByteBuffer buffer = decimal.decompose(expected);
BigDecimal actual = decimal.compose(buffer);
ByteBuffer buffer = decimal.deserialize(expected);
BigDecimal actual = decimal.serialize(buffer);
Assert.assertEquals(expected, actual);
}
}

View File

@ -19,6 +19,7 @@
*/
package org.apache.cassandra.db.marshal;
import org.apache.cassandra.type.MarshalException;
import org.junit.Test;
public class BytesTypeTest

View File

@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.apache.cassandra.type.MarshalException;
import org.junit.Test;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertEquals;

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.cassandra.type.MarshalException;
import org.junit.Test;
import static org.junit.Assert.fail;

View File

@ -23,7 +23,7 @@ package org.apache.cassandra.db.marshal;
import com.google.common.base.Charsets;
import org.apache.cassandra.cql.jdbc.*;
import org.apache.cassandra.type.*;
import org.apache.cassandra.utils.Hex;
import org.apache.cassandra.utils.UUIDGen;
import org.junit.Test;
@ -43,7 +43,7 @@ public class RoundTripTest
assert IntegerType.instance.fromString(IntegerType.instance.getString(ByteBuffer.wrap(bi.toByteArray())))
.equals(ByteBuffer.wrap(bi.toByteArray()));
assert IntegerType.instance.compose(ByteBuffer.wrap(bi.toByteArray())).equals(bi);
assert JdbcInteger.instance.toString(bi).equals("1");
assert IntegerSerializer.instance.toString(bi).equals("1");
}
@Test
@ -54,7 +54,7 @@ public class RoundTripTest
assert LongType.instance.fromString(LongType.instance.getString(ByteBuffer.wrap(v)))
.equals(ByteBuffer.wrap(v));
assert LongType.instance.compose(ByteBuffer.wrap(v)) == 1L;
assert JdbcLong.instance.toString(1L).equals("1");
assert LongSerializer.instance.toString(1L).equals("1");
}
@Test
@ -65,7 +65,7 @@ public class RoundTripTest
assert Int32Type.instance.fromString(Int32Type.instance.getString(ByteBuffer.wrap(v)))
.equals(ByteBuffer.wrap(v));
assert Int32Type.instance.compose(ByteBuffer.wrap(v)) == 1;
// assert Int32Type.instance.toString(1).equals("1");
assert Int32Serializer.instance.toString(1).equals("1");
}
@Test
@ -76,31 +76,31 @@ public class RoundTripTest
assert AsciiType.instance.fromString(AsciiType.instance.getString(ByteBuffer.wrap(abc)))
.equals(ByteBuffer.wrap(abc));
assert AsciiType.instance.compose(ByteBuffer.wrap(abc)).equals("abc");
assert JdbcAscii.instance.toString("abc").equals("abc");
assert AsciiSerializer.instance.toString("abc").equals("abc");
}
@Test
public void testBytes()
{
byte[] v = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
assert JdbcBytes.instance.toString(BytesType.instance.fromString(Hex.bytesToHex(v)))
assert BytesSerializer.instance.getString(BytesType.instance.fromString(Hex.bytesToHex(v)))
.equals(Hex.bytesToHex(v));
assert BytesType.instance.fromString(JdbcBytes.instance.toString(ByteBuffer.wrap(v)))
assert BytesType.instance.fromString(BytesSerializer.instance.getString(ByteBuffer.wrap(v)))
.equals(ByteBuffer.wrap(v));
assert BytesType.instance.compose(ByteBuffer.wrap(v)).equals(ByteBuffer.wrap(v));
assert JdbcBytes.instance.toString(ByteBuffer.wrap(v)).equals(Hex.bytesToHex(v));
assert BytesSerializer.instance.toString(ByteBuffer.wrap(v)).equals(Hex.bytesToHex(v));
}
@Test
public void testLexicalUUID()
{
UUID uuid = UUIDGen.getTimeUUID();
assert JdbcLexicalUUID.instance.getString(LexicalUUIDType.instance.fromString(uuid.toString()))
assert UUIDSerializer.instance.getString(LexicalUUIDType.instance.fromString(uuid.toString()))
.equals(uuid.toString());
assert LexicalUUIDType.instance.fromString(LexicalUUIDType.instance.getString(ByteBuffer.wrap(UUIDGen.decompose(uuid))))
.equals(ByteBuffer.wrap(UUIDGen.decompose(uuid)));
assert LexicalUUIDType.instance.compose(ByteBuffer.wrap(UUIDGen.decompose(uuid))).equals(uuid);
assert JdbcLexicalUUID.instance.toString(uuid).equals(uuid.toString());
assert UUIDSerializer.instance.toString(uuid).equals(uuid.toString());
}
@Test
@ -114,7 +114,7 @@ public class RoundTripTest
assert TimeUUIDType.instance.compose(ByteBuffer.wrap(UUIDGen.decompose(uuid))).equals(uuid);
assert uuid.equals(TimeUUIDType.instance.compose(TimeUUIDType.instance.fromString(uuid.toString())));
assert JdbcTimeUUID.instance.toString(uuid).equals(uuid.toString());
assert UUIDSerializer.instance.toString(uuid).equals(uuid.toString());
}
@Test
@ -125,6 +125,6 @@ public class RoundTripTest
assert UTF8Type.instance.fromString(UTF8Type.instance.getString(ByteBuffer.wrap(v.getBytes(Charsets.UTF_8))))
.equals(ByteBuffer.wrap(v.getBytes(Charsets.UTF_8)));
assert UTF8Type.instance.compose(ByteBuffer.wrap(v.getBytes(Charsets.UTF_8))).equals(v);
assert JdbcUTF8.instance.toString(v).equals(v);
assert UTF8Serializer.instance.toString(v).equals(v);
}
}

View File

@ -24,6 +24,7 @@ import java.util.Arrays;
import java.util.Random;
import java.util.UUID;
import org.apache.cassandra.type.MarshalException;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

View File

@ -1,6 +1,7 @@
package org.apache.cassandra.db.marshal;
import org.apache.cassandra.Util;
import org.apache.cassandra.type.MarshalException;
import org.apache.cassandra.utils.UUIDGen;
import org.junit.Test;

View File

@ -1,4 +1,4 @@
package org.apache.cassandra.cql.jdbc;
package org.apache.cassandra.type;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@ -37,33 +37,31 @@ public class ClientUtilsTest
@Test
public void test() throws UnknownHostException
{
JdbcAscii.instance.compose(JdbcAscii.instance.decompose("string"));
JdbcBoolean.instance.compose(JdbcBoolean.instance.decompose(true));
JdbcBytes.instance.compose(JdbcBytes.instance.decompose(ByteBuffer.wrap("string".getBytes())));
AsciiSerializer.instance.serialize(AsciiSerializer.instance.deserialize("string"));
BooleanSerializer.instance.serialize(BooleanSerializer.instance.deserialize(true));
BytesSerializer.instance.serialize(BytesSerializer.instance.deserialize(ByteBuffer.wrap("string".getBytes())));
Date date = new Date(System.currentTimeMillis());
ByteBuffer dateBB = JdbcDate.instance.decompose(date);
JdbcDate.instance.compose(dateBB);
assert (JdbcDate.instance.toString(date).equals(JdbcDate.instance.getString(dateBB)));
ByteBuffer dateBB = DateSerializer.instance.deserialize(date);
DateSerializer.instance.serialize(dateBB);
assert (DateSerializer.instance.toString(date).equals(DateSerializer.instance.getString(dateBB)));
JdbcDecimal.instance.compose(JdbcDecimal.instance.decompose(new BigDecimal(1)));
JdbcDouble.instance.compose(JdbcDouble.instance.decompose(new Double(1.0d)));
JdbcFloat.instance.compose(JdbcFloat.instance.decompose(new Float(1.0f)));
JdbcInt32.instance.compose(JdbcInt32.instance.decompose(1));
JdbcInteger.instance.compose(JdbcInteger.instance.decompose(new BigInteger("1")));
JdbcLong.instance.compose(JdbcLong.instance.decompose(1L));
JdbcUTF8.instance.compose(JdbcUTF8.instance.decompose("string"));
DecimalSerializer.instance.serialize(DecimalSerializer.instance.deserialize(new BigDecimal(1)));
DoubleSerializer.instance.serialize(DoubleSerializer.instance.deserialize(new Double(1.0d)));
FloatSerializer.instance.serialize(FloatSerializer.instance.deserialize(new Float(1.0f)));
Int32Serializer.instance.serialize(Int32Serializer.instance.deserialize(1));
IntegerSerializer.instance.serialize(IntegerSerializer.instance.deserialize(new BigInteger("1")));
LongSerializer.instance.serialize(LongSerializer.instance.deserialize(1L));
UTF8Serializer.instance.serialize(UTF8Serializer.instance.deserialize("string"));
// UUIDGen
UUID uuid = UUIDGen.getTimeUUID();
JdbcTimeUUID.instance.compose(JdbcTimeUUID.instance.decompose(uuid));
JdbcUUID.instance.compose(JdbcUUID.instance.decompose(uuid));
JdbcLexicalUUID.instance.compose(JdbcLexicalUUID.instance.decompose(uuid));
UUIDSerializer.instance.serialize(UUIDSerializer.instance.deserialize(uuid));
// Raise a MarshalException
try
{
JdbcLexicalUUID.instance.getString(ByteBuffer.wrap("notauuid".getBytes()));
UUIDSerializer.instance.getString(ByteBuffer.wrap("notauuid".getBytes()));
}
catch (MarshalException me)
{