diff --git a/CHANGES.txt b/CHANGES.txt index 5d597bd033..eaa5eea656 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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 diff --git a/build.xml b/build.xml index 05ed9e7b43..30ca0077ad 100644 --- a/build.xml +++ b/build.xml @@ -736,7 +736,7 @@ - + @@ -794,7 +794,7 @@ - + @@ -827,7 +827,7 @@ - + @@ -1045,7 +1045,7 @@ --> - + diff --git a/src/java/org/apache/cassandra/cli/CliClient.java b/src/java/org/apache/cassandra/cli/CliClient.java index 066c1cc51c..200c64f41a 100644 --- a/src/java/org/apache/cassandra/cli/CliClient.java +++ b/src/java/org/apache/cassandra/cli/CliClient.java @@ -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; diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java index cf1c1790d3..415bc78903 100644 --- a/src/java/org/apache/cassandra/config/CFMetaData.java +++ b/src/java/org/apache/cassandra/config/CFMetaData.java @@ -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; diff --git a/src/java/org/apache/cassandra/cql/QueryProcessor.java b/src/java/org/apache/cassandra/cql/QueryProcessor.java index 8e63021329..f70effddf2 100644 --- a/src/java/org/apache/cassandra/cql/QueryProcessor.java +++ b/src/java/org/apache/cassandra/cql/QueryProcessor.java @@ -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.*; diff --git a/src/java/org/apache/cassandra/cql/Term.java b/src/java/org/apache/cassandra/cql/Term.java index e2f53d8008..89d10ab568 100644 --- a/src/java/org/apache/cassandra/cql/Term.java +++ b/src/java/org/apache/cassandra/cql/Term.java @@ -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 diff --git a/src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcUUID.java b/src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcUUID.java deleted file mode 100644 index 2190a8f658..0000000000 --- a/src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcUUID.java +++ /dev/null @@ -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 -{ - 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 getType() - { - return UUID.class; - } - - public int getJdbcType() - { - return Types.OTHER; - } -} diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcLexicalUUID.java b/src/java/org/apache/cassandra/cql/jdbc/JdbcLexicalUUID.java deleted file mode 100644 index c79e7f7667..0000000000 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcLexicalUUID.java +++ /dev/null @@ -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)); - } -} diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcUTF8.java b/src/java/org/apache/cassandra/cql/jdbc/JdbcUTF8.java deleted file mode 100644 index ddcb4aa13a..0000000000 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcUTF8.java +++ /dev/null @@ -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 -{ - 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 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); - } -} diff --git a/src/java/org/apache/cassandra/cql/jdbc/TypesMap.java b/src/java/org/apache/cassandra/cql/jdbc/TypesMap.java deleted file mode 100644 index 50ccbda32f..0000000000 --- a/src/java/org/apache/cassandra/cql/jdbc/TypesMap.java +++ /dev/null @@ -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> map = new HashMap>(); - - 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); - } -} diff --git a/src/java/org/apache/cassandra/cql3/Attributes.java b/src/java/org/apache/cassandra/cql3/Attributes.java index 511f34eeef..4366ff27b6 100644 --- a/src/java/org/apache/cassandra/cql3/Attributes.java +++ b/src/java/org/apache/cassandra/cql3/Attributes.java @@ -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 diff --git a/src/java/org/apache/cassandra/cql3/Constants.java b/src/java/org/apache/cassandra/cql3/Constants.java index 0580413252..643c7f343b 100644 --- a/src/java/org/apache/cassandra/cql3/Constants.java +++ b/src/java/org/apache/cassandra/cql3/Constants.java @@ -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; diff --git a/src/java/org/apache/cassandra/cql3/Lists.java b/src/java/org/apache/cassandra/cql3/Lists.java index d89283c90e..4aa0c514e5 100644 --- a/src/java/org/apache/cassandra/cql3/Lists.java +++ b/src/java/org/apache/cassandra/cql3/Lists.java @@ -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; diff --git a/src/java/org/apache/cassandra/cql3/Maps.java b/src/java/org/apache/cassandra/cql3/Maps.java index e6d7c7e8a9..7c62c05369 100644 --- a/src/java/org/apache/cassandra/cql3/Maps.java +++ b/src/java/org/apache/cassandra/cql3/Maps.java @@ -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; diff --git a/src/java/org/apache/cassandra/cql3/Sets.java b/src/java/org/apache/cassandra/cql3/Sets.java index fed6625921..2c31520c4f 100644 --- a/src/java/org/apache/cassandra/cql3/Sets.java +++ b/src/java/org/apache/cassandra/cql3/Sets.java @@ -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; diff --git a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java index d21bbd1e80..b5e4f5505e 100644 --- a/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/SelectStatement.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/Column.java b/src/java/org/apache/cassandra/db/Column.java index b210d22f65..99a8b445ce 100644 --- a/src/java/org/apache/cassandra/db/Column.java +++ b/src/java/org/apache/cassandra/db/Column.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/CounterColumn.java b/src/java/org/apache/cassandra/db/CounterColumn.java index 207ded60ae..6e081666bc 100644 --- a/src/java/org/apache/cassandra/db/CounterColumn.java +++ b/src/java/org/apache/cassandra/db/CounterColumn.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/DeletedColumn.java b/src/java/org/apache/cassandra/db/DeletedColumn.java index 57c9bf99ff..b30ed2fb31 100644 --- a/src/java/org/apache/cassandra/db/DeletedColumn.java +++ b/src/java/org/apache/cassandra/db/DeletedColumn.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/ExpiringColumn.java b/src/java/org/apache/cassandra/db/ExpiringColumn.java index f342310295..0bef26661e 100644 --- a/src/java/org/apache/cassandra/db/ExpiringColumn.java +++ b/src/java/org/apache/cassandra/db/ExpiringColumn.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/OnDiskAtom.java b/src/java/org/apache/cassandra/db/OnDiskAtom.java index 14a21c8a41..06e9b5a579 100644 --- a/src/java/org/apache/cassandra/db/OnDiskAtom.java +++ b/src/java/org/apache/cassandra/db/OnDiskAtom.java @@ -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 diff --git a/src/java/org/apache/cassandra/db/RangeTombstone.java b/src/java/org/apache/cassandra/db/RangeTombstone.java index e30cd5bb75..ec1f21552b 100644 --- a/src/java/org/apache/cassandra/db/RangeTombstone.java +++ b/src/java/org/apache/cassandra/db/RangeTombstone.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/context/CounterContext.java b/src/java/org/apache/cassandra/db/context/CounterContext.java index 9e309f98dd..ef57c4a98a 100644 --- a/src/java/org/apache/cassandra/db/context/CounterContext.java +++ b/src/java/org/apache/cassandra/db/context/CounterContext.java @@ -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.*; /** diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java index 06a0a8256e..e354de0ba8 100644 --- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java @@ -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 return value; } + @Override + public AbstractSerializer 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 diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java b/src/java/org/apache/cassandra/db/marshal/AbstractType.java index a6e7b98bd1..07bf6941a5 100644 --- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java +++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java @@ -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 implements Comparator return new CQL3Type.Custom(this); } + public abstract AbstractSerializer asComposer(); + /** @deprecated use reverseComparator field instead */ public Comparator getReverseComparator() { diff --git a/src/java/org/apache/cassandra/db/marshal/AsciiType.java b/src/java/org/apache/cassandra/db/marshal/AsciiType.java index 990b3d46cb..09e562ca4c 100644 --- a/src/java/org/apache/cassandra/db/marshal/AsciiType.java +++ b/src/java/org/apache/cassandra/db/marshal/AsciiType.java @@ -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 { @@ -30,14 +32,7 @@ public class AsciiType extends AbstractType 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 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 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 asComposer() + { + return AsciiSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/BooleanType.java b/src/java/org/apache/cassandra/db/marshal/BooleanType.java index c5f2cfba9a..307664f825 100644 --- a/src/java/org/apache/cassandra/db/marshal/BooleanType.java +++ b/src/java/org/apache/cassandra/db/marshal/BooleanType.java @@ -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 { @@ -30,12 +32,12 @@ public class BooleanType extends AbstractType 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 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 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 asComposer() + { + return BooleanSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/BytesType.java b/src/java/org/apache/cassandra/db/marshal/BytesType.java index 1bb2bd2a6b..571e6e7f79 100644 --- a/src/java/org/apache/cassandra/db/marshal/BytesType.java +++ b/src/java/org/apache/cassandra/db/marshal/BytesType.java @@ -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 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 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 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 { return CQL3Type.Native.BLOB; } + + @Override + public AbstractSerializer asComposer() + { + return BytesSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/CollectionType.java b/src/java/org/apache/cassandra/db/marshal/CollectionType.java index f7cdf28b03..7b2bce2262 100644 --- a/src/java/org/apache/cassandra/db/marshal/CollectionType.java +++ b/src/java/org/apache/cassandra/db/marshal/CollectionType.java @@ -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; diff --git a/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java b/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java index bb5d2fa033..fa9705b8c4 100644 --- a/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java +++ b/src/java/org/apache/cassandra/db/marshal/ColumnToCollectionType.java @@ -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 @@ -103,6 +106,11 @@ public class ColumnToCollectionType extends AbstractType throw new UnsupportedOperationException("ColumnToCollectionType should only be used in composite types, never alone"); } + public AbstractSerializer asComposer() + { + return BytesSerializer.instance; + } + public void validateCollectionMember(ByteBuffer bytes, ByteBuffer collectionName) throws MarshalException { CollectionType t = defined.get(collectionName); diff --git a/src/java/org/apache/cassandra/db/marshal/CompositeType.java b/src/java/org/apache/cassandra/db/marshal/CompositeType.java index 76799072d0..6a25d142f8 100644 --- a/src/java/org/apache/cassandra/db/marshal/CompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/CompositeType.java @@ -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; /* diff --git a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java index 9ee772c69c..4a84eceaeb 100644 --- a/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java +++ b/src/java/org/apache/cassandra/db/marshal/CounterColumnType.java @@ -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 asComposer() + { + return CounterSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/DateType.java b/src/java/org/apache/cassandra/db/marshal/DateType.java index 875169d144..dcd8c9f779 100644 --- a/src/java/org/apache/cassandra/db/marshal/DateType.java +++ b/src/java/org/apache/cassandra/db/marshal/DateType.java @@ -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 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 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 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 asComposer() + { + return DateSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/DecimalType.java b/src/java/org/apache/cassandra/db/marshal/DecimalType.java index 825f208ca8..e2137035a7 100644 --- a/src/java/org/apache/cassandra/db/marshal/DecimalType.java +++ b/src/java/org/apache/cassandra/db/marshal/DecimalType.java @@ -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 @@ -46,7 +48,7 @@ public class DecimalType extends AbstractType public BigDecimal compose(ByteBuffer bytes) { - return JdbcDecimal.instance.compose(bytes); + return DecimalSerializer.instance.serialize(bytes); } /** @@ -55,12 +57,12 @@ public class DecimalType extends AbstractType */ 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 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 asComposer() + { + return DecimalSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/DoubleType.java b/src/java/org/apache/cassandra/db/marshal/DoubleType.java index f2c7378444..89f11af936 100644 --- a/src/java/org/apache/cassandra/db/marshal/DoubleType.java +++ b/src/java/org/apache/cassandra/db/marshal/DoubleType.java @@ -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 @@ -31,12 +33,12 @@ public class DoubleType extends AbstractType 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 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 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 asComposer() + { + return DoubleSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java index 027f9c4502..b00a0269e1 100644 --- a/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/DynamicCompositeType.java @@ -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 asComposer() + { + throw new UnsupportedOperationException(); + } } } diff --git a/src/java/org/apache/cassandra/db/marshal/EmptyType.java b/src/java/org/apache/cassandra/db/marshal/EmptyType.java index 6bbd006342..0ad704f1ab 100644 --- a/src/java/org/apache/cassandra/db/marshal/EmptyType.java +++ b/src/java/org/apache/cassandra/db/marshal/EmptyType.java @@ -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 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 asComposer() + { + return EmptySerializer.instance; } } diff --git a/src/java/org/apache/cassandra/db/marshal/FloatType.java b/src/java/org/apache/cassandra/db/marshal/FloatType.java index cb3cc3b347..c0940f4e96 100644 --- a/src/java/org/apache/cassandra/db/marshal/FloatType.java +++ b/src/java/org/apache/cassandra/db/marshal/FloatType.java @@ -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 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 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 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 asComposer() + { + return FloatSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java index f06035486e..a86f5785f2 100644 --- a/src/java/org/apache/cassandra/db/marshal/InetAddressType.java +++ b/src/java/org/apache/cassandra/db/marshal/InetAddressType.java @@ -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 @@ -33,12 +34,12 @@ public class InetAddressType extends AbstractType 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 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 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 asComposer() + { + return InetAddressSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/Int32Type.java b/src/java/org/apache/cassandra/db/marshal/Int32Type.java index 1e206ff915..0ec72405d1 100644 --- a/src/java/org/apache/cassandra/db/marshal/Int32Type.java +++ b/src/java/org/apache/cassandra/db/marshal/Int32Type.java @@ -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 { 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 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 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 asComposer() + { + return Int32Serializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/IntegerType.java b/src/java/org/apache/cassandra/db/marshal/IntegerType.java index de675f6b06..7fed5f6d63 100644 --- a/src/java/org/apache/cassandra/db/marshal/IntegerType.java +++ b/src/java/org/apache/cassandra/db/marshal/IntegerType.java @@ -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 @@ -58,12 +60,12 @@ public final class IntegerType extends AbstractType 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 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 public void validate(ByteBuffer bytes) throws MarshalException { - // no invalid integers. + IntegerSerializer.instance.validate(bytes); } public CQL3Type asCQL3Type() { return CQL3Type.Native.VARINT; } + + @Override + public AbstractSerializer asComposer() + { + return IntegerSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java index c1f20492c2..dacd81b774 100644 --- a/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java +++ b/src/java/org/apache/cassandra/db/marshal/LexicalUUIDType.java @@ -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 { 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 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 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 asComposer() + { + return UUIDSerializer.instance; } } diff --git a/src/java/org/apache/cassandra/db/marshal/ListType.java b/src/java/org/apache/cassandra/db/marshal/ListType.java index 32eb13a1a9..49e7319569 100644 --- a/src/java/org/apache/cassandra/db/marshal/ListType.java +++ b/src/java/org/apache/cassandra/db/marshal/ListType.java @@ -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 extends CollectionType> @@ -32,6 +33,7 @@ public class ListType extends CollectionType> private static final Map, ListType> instances = new HashMap, ListType>(); public final AbstractType elements; + public final ListSerializer composer; public static ListType getInstance(TypeParser parser) throws ConfigurationException, SyntaxException { @@ -57,6 +59,7 @@ public class ListType extends CollectionType> { super(Kind.LIST); this.elements = elements; + this.composer = ListSerializer.getInstance(elements.asComposer()); } public AbstractType nameComparator() @@ -71,26 +74,7 @@ public class ListType extends CollectionType> public List compose(ByteBuffer bytes) { - try - { - ByteBuffer input = bytes.duplicate(); - int n = getUnsignedShort(input); - List l = new ArrayList(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 extends CollectionType> */ public ByteBuffer decompose(List value) { - List bbs = new ArrayList(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> asComposer() + { + return composer; } protected void appendToStringBuilder(StringBuilder sb) diff --git a/src/java/org/apache/cassandra/db/marshal/LocalByPartionerType.java b/src/java/org/apache/cassandra/db/marshal/LocalByPartionerType.java index 68b4715ddd..62b5d9f17f 100644 --- a/src/java/org/apache/cassandra/db/marshal/LocalByPartionerType.java +++ b/src/java/org/apache/cassandra/db/marshal/LocalByPartionerType.java @@ -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 extends AbstractType asComposer() + { + throw new UnsupportedOperationException("You can't do this with a local partitioner."); + } } diff --git a/src/java/org/apache/cassandra/db/marshal/LongType.java b/src/java/org/apache/cassandra/db/marshal/LongType.java index 71ad36f7ee..45edc2fb52 100644 --- a/src/java/org/apache/cassandra/db/marshal/LongType.java +++ b/src/java/org/apache/cassandra/db/marshal/LongType.java @@ -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 @@ -31,12 +33,12 @@ public class LongType extends AbstractType 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 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 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 asComposer() + { + return LongSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java b/src/java/org/apache/cassandra/db/marshal/MapType.java index c7772d7d6c..fc51189def 100644 --- a/src/java/org/apache/cassandra/db/marshal/MapType.java +++ b/src/java/org/apache/cassandra/db/marshal/MapType.java @@ -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 extends CollectionType> @@ -33,6 +36,7 @@ public class MapType extends CollectionType> public final AbstractType keys; public final AbstractType values; + private final MapSerializer composer; public static MapType getInstance(TypeParser parser) throws ConfigurationException, SyntaxException { @@ -60,6 +64,7 @@ public class MapType extends CollectionType> super(Kind.MAP); this.keys = keys; this.values = values; + this.composer = MapSerializer.getInstance(keys.asComposer(), values.asComposer()); } public AbstractType nameComparator() @@ -127,13 +132,19 @@ public class MapType extends CollectionType> return pack(bbs, value.size(), size); } + @Override + public AbstractSerializer> 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> columns) { diff --git a/src/java/org/apache/cassandra/db/marshal/ReversedType.java b/src/java/org/apache/cassandra/db/marshal/ReversedType.java index 9fdecb88e7..d7816a745c 100644 --- a/src/java/org/apache/cassandra/db/marshal/ReversedType.java +++ b/src/java/org/apache/cassandra/db/marshal/ReversedType.java @@ -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 extends AbstractType { @@ -103,6 +105,12 @@ public class ReversedType extends AbstractType return baseType.asCQL3Type(); } + @Override + public AbstractSerializer asComposer() + { + return baseType.asComposer(); + } + @Override public String toString() { diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java b/src/java/org/apache/cassandra/db/marshal/SetType.java index dd90273716..89ddc7d085 100644 --- a/src/java/org/apache/cassandra/db/marshal/SetType.java +++ b/src/java/org/apache/cassandra/db/marshal/SetType.java @@ -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 extends CollectionType> @@ -32,6 +33,7 @@ public class SetType extends CollectionType> private static final Map, SetType> instances = new HashMap, SetType>(); public final AbstractType elements; + private final SetSerializer composer; public static SetType getInstance(TypeParser parser) throws ConfigurationException, SyntaxException { @@ -57,6 +59,7 @@ public class SetType extends CollectionType> { super(Kind.SET); this.elements = elements; + this.composer = SetSerializer.getInstance(elements.asComposer()); } public AbstractType nameComparator() @@ -71,46 +74,17 @@ public class SetType extends CollectionType> public Set compose(ByteBuffer bytes) { - try - { - ByteBuffer input = bytes.duplicate(); - int n = getUnsignedShort(input); - Set l = new LinkedHashSet(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 ... } - * 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 value) { - List bbs = new ArrayList(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> asComposer() + { + return composer; } protected void appendToStringBuilder(StringBuilder sb) diff --git a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java index a28f6a5158..61b02a54a0 100644 --- a/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java +++ b/src/java/org/apache/cassandra/db/marshal/TimeUUIDType.java @@ -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 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 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 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 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 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 asComposer() + { + return TimeUUIDSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/UTF8Type.java b/src/java/org/apache/cassandra/db/marshal/UTF8Type.java index 56879b14da..26631959f5 100644 --- a/src/java/org/apache/cassandra/db/marshal/UTF8Type.java +++ b/src/java/org/apache/cassandra/db/marshal/UTF8Type.java @@ -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 { @@ -30,12 +32,12 @@ public class UTF8Type extends AbstractType 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 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 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 { return CQL3Type.Native.TEXT; } + + @Override + public AbstractSerializer asComposer() + { + return UTF8Serializer.instance; + } } diff --git a/src/java/org/apache/cassandra/db/marshal/UUIDType.java b/src/java/org/apache/cassandra/db/marshal/UUIDType.java index a0193dd960..159cab3753 100644 --- a/src/java/org/apache/cassandra/db/marshal/UUIDType.java +++ b/src/java/org/apache/cassandra/db/marshal/UUIDType.java @@ -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:
@@ -159,32 +161,22 @@ public class UUIDType extends AbstractType 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 { 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 { return CQL3Type.Native.UUID; } + + @Override + public AbstractSerializer asComposer() + { + return UUIDSerializer.instance; + } } diff --git a/src/java/org/apache/cassandra/hadoop/cql3/CqlPagingRecordReader.java b/src/java/org/apache/cassandra/hadoop/cql3/CqlPagingRecordReader.java index 55f67ccb7d..70db75a2ee 100644 --- a/src/java/org/apache/cassandra/hadoop/cql3/CqlPagingRecordReader.java +++ b/src/java/org/apache/cassandra/hadoop/cql3/CqlPagingRecordReader.java @@ -414,7 +414,7 @@ public class CqlPagingRecordReader extends RecordReader, 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 composeQuery(String columns) { Pair clause = whereClause(); @@ -464,7 +464,7 @@ public class CqlPagingRecordReader extends RecordReader, return result; } - /** compose the where clause */ + /** serialize the where clause */ private Pair whereClause() { if (partitionKeyString == null) @@ -488,7 +488,7 @@ public class CqlPagingRecordReader extends RecordReader, " WHERE token(" + partitionKeyString + ") = token(" + partitionKeyMarkers + ") " + clause.right); } - /** recursively compose the where clause */ + /** recursively serialize the where clause */ private Pair whereClause(List column, int position) { if (position == column.size() - 1 || column.get(position + 1).value == null) @@ -509,7 +509,7 @@ public class CqlPagingRecordReader extends RecordReader, return true; } - /** compose the partition key string in format of , , */ + /** serialize the partition key string in format of , , */ private String keyString(List columns) { String result = null; @@ -519,7 +519,7 @@ public class CqlPagingRecordReader extends RecordReader, 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, 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> preparedQueryBindValues() { List values = new LinkedList(); @@ -561,7 +561,7 @@ public class CqlPagingRecordReader extends RecordReader, } } - /** recursively compose the query binding variables */ + /** recursively serialize the query binding variables */ private int preparedQueryBindValues(List column, int position, List bindValues) { if (position == column.size() - 1 || column.get(position + 1).value == null) @@ -721,7 +721,7 @@ public class CqlPagingRecordReader extends RecordReader, { 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); diff --git a/src/java/org/apache/cassandra/hadoop/cql3/CqlRecordWriter.java b/src/java/org/apache/cassandra/hadoop/cql3/CqlRecordWriter.java index 642d8c448d..cc8500e396 100644 --- a/src/java/org/apache/cassandra/hadoop/cql3/CqlRecordWriter.java +++ b/src/java/org/apache/cassandra/hadoop/cql3/CqlRecordWriter.java @@ -356,7 +356,7 @@ final class CqlRecordWriter extends AbstractColumnFamilyRecordWriter, OnDiskAtomIterator diff --git a/src/java/org/apache/cassandra/thrift/CassandraServer.java b/src/java/org/apache/cassandra/thrift/CassandraServer.java index 41e04ef998..c9cb9eb78f 100644 --- a/src/java/org/apache/cassandra/thrift/CassandraServer.java +++ b/src/java/org/apache/cassandra/thrift/CassandraServer.java @@ -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.*; diff --git a/src/java/org/apache/cassandra/thrift/ThriftValidation.java b/src/java/org/apache/cassandra/thrift/ThriftValidation.java index 6f8324367d..6f14a37297 100644 --- a/src/java/org/apache/cassandra/thrift/ThriftValidation.java +++ b/src/java/org/apache/cassandra/thrift/ThriftValidation.java @@ -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; diff --git a/src/java/org/apache/cassandra/tools/SSTableImport.java b/src/java/org/apache/cassandra/tools/SSTableImport.java index ecdcdd5da5..6e032d0fed 100644 --- a/src/java/org/apache/cassandra/tools/SSTableImport.java +++ b/src/java/org/apache/cassandra/tools/SSTableImport.java @@ -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; diff --git a/src/java/org/apache/cassandra/tools/Shuffle.java b/src/java/org/apache/cassandra/tools/Shuffle.java index cb9f2a4e13..5749a81b2d 100644 --- a/src/java/org/apache/cassandra/tools/Shuffle.java +++ b/src/java/org/apache/cassandra/tools/Shuffle.java @@ -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()); diff --git a/src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcType.java b/src/java/org/apache/cassandra/type/AbstractSerializer.java similarity index 64% rename from src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcType.java rename to src/java/org/apache/cassandra/type/AbstractSerializer.java index 7557c3abd6..85a0e39e16 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/AbstractJdbcType.java +++ b/src/java/org/apache/cassandra/type/AbstractSerializer.java @@ -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 +public abstract class AbstractSerializer { - 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 getType(); - public abstract int getJdbcType(); - public abstract T compose(ByteBuffer bytes); - public abstract ByteBuffer decompose(T obj); } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcAscii.java b/src/java/org/apache/cassandra/type/AsciiSerializer.java similarity index 65% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcAscii.java rename to src/java/org/apache/cassandra/type/AsciiSerializer.java index d013dc8d20..72a83120df 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcAscii.java +++ b/src/java/org/apache/cassandra/type/AsciiSerializer.java @@ -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 +public class AsciiSerializer extends AbstractSerializer { + 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 } } + @Override + public String toString(String value) + { + return value; + } + + @Override public Class 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); - } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcBoolean.java b/src/java/org/apache/cassandra/type/BooleanSerializer.java similarity index 53% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcBoolean.java rename to src/java/org/apache/cassandra/type/BooleanSerializer.java index 29d2ec5303..e2d200c875 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcBoolean.java +++ b/src/java/org/apache/cassandra/type/BooleanSerializer.java @@ -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 +import java.nio.ByteBuffer; + +public class BooleanSerializer extends AbstractSerializer { - 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 } 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 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 - } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcBytes.java b/src/java/org/apache/cassandra/type/BytesSerializer.java similarity index 58% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcBytes.java rename to src/java/org/apache/cassandra/type/BytesSerializer.java index cc031635e6..28897396b0 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcBytes.java +++ b/src/java/org/apache/cassandra/type/BytesSerializer.java @@ -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 +public class BytesSerializer extends AbstractSerializer { - 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 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; - } } diff --git a/src/java/org/apache/cassandra/type/CollectionSerializer.java b/src/java/org/apache/cassandra/type/CollectionSerializer.java new file mode 100644 index 0000000000..2eb3944e1c --- /dev/null +++ b/src/java/org/apache/cassandra/type/CollectionSerializer.java @@ -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 extends AbstractSerializer +{ + @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 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 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); + } +} diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcCounterColumn.java b/src/java/org/apache/cassandra/type/CounterSerializer.java similarity index 80% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcCounterColumn.java rename to src/java/org/apache/cassandra/type/CounterSerializer.java index 644d5943c4..c0625c318f 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcCounterColumn.java +++ b/src/java/org/apache/cassandra/type/CounterSerializer.java @@ -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() {} } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcDate.java b/src/java/org/apache/cassandra/type/DateSerializer.java similarity index 56% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcDate.java rename to src/java/org/apache/cassandra/type/DateSerializer.java index 2c8aa2c6ba..4f0186c9fc 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcDate.java +++ b/src/java/org/apache/cassandra/type/DateSerializer.java @@ -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 +import java.nio.ByteBuffer; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateSerializer extends AbstractSerializer { 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 FORMATTER = new ThreadLocal() { protected SimpleDateFormat initialValue() @@ -47,45 +49,32 @@ public class JdbcDate extends AbstractJdbcType } }; - 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 } // 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 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()); - } - } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcDecimal.java b/src/java/org/apache/cassandra/type/DecimalSerializer.java similarity index 51% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcDecimal.java rename to src/java/org/apache/cassandra/type/DecimalSerializer.java index 9d1c6ab7df..b8ad00b7b0 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcDecimal.java +++ b/src/java/org/apache/cassandra/type/DecimalSerializer.java @@ -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 +public class DecimalSerializer extends AbstractSerializer { - 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 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 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 getType() + { + return BigDecimal.class; + } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcDouble.java b/src/java/org/apache/cassandra/type/DoubleSerializer.java similarity index 56% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcDouble.java rename to src/java/org/apache/cassandra/type/DoubleSerializer.java index 4424d05290..d9b1776383 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcDouble.java +++ b/src/java/org/apache/cassandra/type/DoubleSerializer.java @@ -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 +import java.nio.ByteBuffer; + +public class DoubleSerializer extends AbstractSerializer { - 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 } 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 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); - } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcUUID.java b/src/java/org/apache/cassandra/type/EmptySerializer.java similarity index 53% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcUUID.java rename to src/java/org/apache/cassandra/type/EmptySerializer.java index 1c62b03a4d..760ee29d6d 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcUUID.java +++ b/src/java/org/apache/cassandra/type/EmptySerializer.java @@ -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 { - 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 getType() + { + return Void.class; } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcFloat.java b/src/java/org/apache/cassandra/type/FloatSerializer.java similarity index 56% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcFloat.java rename to src/java/org/apache/cassandra/type/FloatSerializer.java index 3c08fc5a46..d43003f5ce 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcFloat.java +++ b/src/java/org/apache/cassandra/type/FloatSerializer.java @@ -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 +import java.nio.ByteBuffer; + +public class FloatSerializer extends AbstractSerializer { - 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 } 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 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); - } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcInetAddress.java b/src/java/org/apache/cassandra/type/InetAddressSerializer.java similarity index 59% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcInetAddress.java rename to src/java/org/apache/cassandra/type/InetAddressSerializer.java index ac0bc09a33..f1a30d9202 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcInetAddress.java +++ b/src/java/org/apache/cassandra/type/InetAddressSerializer.java @@ -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 +public class InetAddressSerializer extends AbstractSerializer { - 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 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 } } - 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 getType() + { + return InetAddress.class; + } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcInt32.java b/src/java/org/apache/cassandra/type/Int32Serializer.java similarity index 58% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcInt32.java rename to src/java/org/apache/cassandra/type/Int32Serializer.java index 7044640c43..2688218898 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcInt32.java +++ b/src/java/org/apache/cassandra/type/Int32Serializer.java @@ -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 +import java.nio.ByteBuffer; + +public class Int32Serializer extends AbstractSerializer { - 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 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 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); - } } diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcInteger.java b/src/java/org/apache/cassandra/type/IntegerSerializer.java similarity index 58% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcInteger.java rename to src/java/org/apache/cassandra/type/IntegerSerializer.java index d4338ffedf..d54a47ce4e 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcInteger.java +++ b/src/java/org/apache/cassandra/type/IntegerSerializer.java @@ -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 +import java.math.BigInteger; +import java.nio.ByteBuffer; + +public class IntegerSerializer extends AbstractSerializer { - 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 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 getType() + { + return BigInteger.class; + } } diff --git a/src/java/org/apache/cassandra/type/ListSerializer.java b/src/java/org/apache/cassandra/type/ListSerializer.java new file mode 100644 index 0000000000..1cbaf08181 --- /dev/null +++ b/src/java/org/apache/cassandra/type/ListSerializer.java @@ -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 extends CollectionSerializer> +{ + // interning instances + private static final Map, ListSerializer> instances = new HashMap, ListSerializer>(); + + public final AbstractSerializer elements; + + public static synchronized ListSerializer getInstance(AbstractSerializer elements) + { + ListSerializer t = instances.get(elements); + if (t == null) + { + t = new ListSerializer(elements); + instances.put(elements, t); + } + return t; + } + + private ListSerializer(AbstractSerializer elements) + { + this.elements = elements; + } + + public List serialize(ByteBuffer bytes) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = getUnsignedShort(input); + List l = new ArrayList(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 ... } + * 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 value) + { + List bbs = new ArrayList(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 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> getType() + { + return (Class) List.class; + } +} diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcLong.java b/src/java/org/apache/cassandra/type/LongSerializer.java similarity index 60% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcLong.java rename to src/java/org/apache/cassandra/type/LongSerializer.java index fec06f2dff..f9835391c0 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcLong.java +++ b/src/java/org/apache/cassandra/type/LongSerializer.java @@ -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 +import java.nio.ByteBuffer; + +public class LongSerializer extends AbstractSerializer { - 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 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 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); - } } diff --git a/src/java/org/apache/cassandra/type/MapSerializer.java b/src/java/org/apache/cassandra/type/MapSerializer.java new file mode 100644 index 0000000000..44253fbddc --- /dev/null +++ b/src/java/org/apache/cassandra/type/MapSerializer.java @@ -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 extends CollectionSerializer> +{ + // interning instances + private static final Map, AbstractSerializer>, MapSerializer> instances = new HashMap, AbstractSerializer>, MapSerializer>(); + + public final AbstractSerializer keys; + public final AbstractSerializer values; + + public static synchronized MapSerializer getInstance(AbstractSerializer keys, AbstractSerializer values) + { + Pair, AbstractSerializer> p = Pair., AbstractSerializer>create(keys, values); + MapSerializer t = instances.get(p); + if (t == null) + { + t = new MapSerializer(keys, values); + instances.put(p, t); + } + return t; + } + + private MapSerializer(AbstractSerializer keys, AbstractSerializer values) + { + this.keys = keys; + this.values = values; + } + + @Override + public Map serialize(ByteBuffer bytes) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = getUnsignedShort(input); + Map m = new LinkedHashMap(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 value) + { + List bbs = new ArrayList(2 * value.size()); + int size = 0; + for (Map.Entry 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 value) + { + StringBuffer sb = new StringBuffer(); + boolean isFirst = true; + for (Map.Entry 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> getType() + { + return (Class)Map.class; + } +} diff --git a/src/java/org/apache/cassandra/cql/jdbc/MarshalException.java b/src/java/org/apache/cassandra/type/MarshalException.java similarity index 96% rename from src/java/org/apache/cassandra/cql/jdbc/MarshalException.java rename to src/java/org/apache/cassandra/type/MarshalException.java index 571e841e17..b556a887f0 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/MarshalException.java +++ b/src/java/org/apache/cassandra/type/MarshalException.java @@ -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 { diff --git a/src/java/org/apache/cassandra/type/SetSerializer.java b/src/java/org/apache/cassandra/type/SetSerializer.java new file mode 100644 index 0000000000..f60acb486e --- /dev/null +++ b/src/java/org/apache/cassandra/type/SetSerializer.java @@ -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 extends CollectionSerializer> +{ + // interning instances + private static final Map, SetSerializer> instances = new HashMap, SetSerializer>(); + + public final AbstractSerializer elements; + + public static synchronized SetSerializer getInstance(AbstractSerializer elements) + { + SetSerializer t = instances.get(elements); + if (t == null) + { + t = new SetSerializer(elements); + instances.put(elements, t); + } + return t; + } + + private SetSerializer(AbstractSerializer elements) + { + this.elements = elements; + } + + public Set serialize(ByteBuffer bytes) + { + try + { + ByteBuffer input = bytes.duplicate(); + int n = getUnsignedShort(input); + Set l = new LinkedHashSet(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 ... } + * 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 value) + { + List bbs = new ArrayList(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 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> getType() + { + return (Class) Set.class; + } +} diff --git a/src/java/org/apache/cassandra/db/marshal/MarshalException.java b/src/java/org/apache/cassandra/type/TimeUUIDSerializer.java similarity index 58% rename from src/java/org/apache/cassandra/db/marshal/MarshalException.java rename to src/java/org/apache/cassandra/type/TimeUUIDSerializer.java index f512b0cf45..b76701224b 100644 --- a/src/java/org/apache/cassandra/db/marshal/MarshalException.java +++ b/src/java/org/apache/cassandra/type/TimeUUIDSerializer.java @@ -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."); + } } } diff --git a/src/java/org/apache/cassandra/type/UTF8Serializer.java b/src/java/org/apache/cassandra/type/UTF8Serializer.java new file mode 100644 index 0000000000..4c4478849d --- /dev/null +++ b/src/java/org/apache/cassandra/type/UTF8Serializer.java @@ -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 +{ + 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 getType() + { + return String.class; + } +} diff --git a/src/java/org/apache/cassandra/cql/jdbc/JdbcTimeUUID.java b/src/java/org/apache/cassandra/type/UUIDSerializer.java similarity index 62% rename from src/java/org/apache/cassandra/cql/jdbc/JdbcTimeUUID.java rename to src/java/org/apache/cassandra/type/UUIDSerializer.java index 0d8d5012ea..07b86b6725 100644 --- a/src/java/org/apache/cassandra/cql/jdbc/JdbcTimeUUID.java +++ b/src/java/org/apache/cassandra/type/UUIDSerializer.java @@ -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 { - 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 getType() { - return ByteBuffer.wrap(UUIDGen.decompose(value)); + return UUID.class; } } diff --git a/test/unit/org/apache/cassandra/cql/jdbc/JdbcDecimalTest.java b/test/unit/org/apache/cassandra/cql/jdbc/JdbcDecimalTest.java index 5620d33db7..90a8200433 100644 --- a/test/unit/org/apache/cassandra/cql/jdbc/JdbcDecimalTest.java +++ b/test/unit/org/apache/cassandra/cql/jdbc/JdbcDecimalTest.java @@ -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); } } diff --git a/test/unit/org/apache/cassandra/db/marshal/BytesTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/BytesTypeTest.java index 4d96b76b1e..24804fd2cc 100644 --- a/test/unit/org/apache/cassandra/db/marshal/BytesTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/BytesTypeTest.java @@ -19,6 +19,7 @@ */ package org.apache.cassandra.db.marshal; +import org.apache.cassandra.type.MarshalException; import org.junit.Test; public class BytesTypeTest diff --git a/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java index 4fba73ce20..fa31b9e459 100644 --- a/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/CompositeTypeTest.java @@ -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; diff --git a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java index 4b3958224b..8a4588dd1c 100644 --- a/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/DynamicCompositeTypeTest.java @@ -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; diff --git a/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java b/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java index 2bdc5ba64d..4b0228a11a 100644 --- a/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/RoundTripTest.java @@ -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); } } diff --git a/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java b/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java index ca9d35bd7e..2cd6da0fb2 100644 --- a/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/TimeUUIDTypeTest.java @@ -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; diff --git a/test/unit/org/apache/cassandra/db/marshal/TypeValidationTest.java b/test/unit/org/apache/cassandra/db/marshal/TypeValidationTest.java index 552582edda..9f2b3e2b05 100644 --- a/test/unit/org/apache/cassandra/db/marshal/TypeValidationTest.java +++ b/test/unit/org/apache/cassandra/db/marshal/TypeValidationTest.java @@ -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; diff --git a/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java b/test/unit/org/apache/cassandra/type/ClientUtilsTest.java similarity index 51% rename from test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java rename to test/unit/org/apache/cassandra/type/ClientUtilsTest.java index 33cdfea6b7..74d3e20792 100644 --- a/test/unit/org/apache/cassandra/cql/jdbc/ClientUtilsTest.java +++ b/test/unit/org/apache/cassandra/type/ClientUtilsTest.java @@ -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) {