add int/int32 data type

patch by Radim Kolar; reviewed by jbellis for CASSANDRA-3031

git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-1.0.0@1167287 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jonathan Ellis 2011-09-09 16:49:35 +00:00
parent 55b43a71fe
commit 58df830e41
19 changed files with 3097 additions and 24 deletions

View File

@ -66,7 +66,7 @@
(CASSANDRA-3148)
* fix inconsistency of the CLI syntax when {} should be used instead of [{}]
(CASSANDRA-3119)
* rename CQL type names to match expected SQL behavior (CASSANDRA-3149)
* rename CQL type names to match expected SQL behavior (CASSANDRA-3149, 3031)
* Arena-based allocation for memtables (CASSANDRA-2252, 3162)

View File

@ -9,7 +9,8 @@ Upgrading
cassandra.yaml (use compaction_throughput_mb_per_sec to throttle
compaction instead)
- CQL types bytea and date were renamed to blob and timestamp, respectively,
to conform with SQL norms
to conform with SQL norms. CQL type int is now a 4-byte int, not 8
(which is still available as bigint).
Features
--------

View File

@ -273,6 +273,7 @@ It is possible to assign columns a type during column family creation. Columns
|decimal|Variable-precision decimal|
|double|8-byte floating point|
|float|4-byte floating point|
|int|4-byte int|
|text|UTF8 encoded string|
|timestamp|Date + Time, encoded as 8 bytes since epoch|
|uuid|Type 1, or type 4 UUID|
@ -384,6 +385,9 @@ Versioning of the CQL language adheres to the "Semantic Versioning":http://semve
h1. Changes
pre.
Fri, 09 Sep 2011 11:43:00 -0500 - Jonathan Ellis
* add int data type
Wed, 07 Sep 2011 09:01:00 -0500 - Jonathan Ellis
* Updated version to 2.0; Documented row-based count()
* Updated list of supported data types

View File

@ -66,6 +66,7 @@ public class CliClient
BYTES (BytesType.instance),
INTEGER (IntegerType.instance),
LONG (LongType.instance),
INT (Int32Type.instance),
LEXICALUUID (LexicalUUIDType.instance),
TIMEUUID (TimeUUIDType.instance),
UTF8 (UTF8Type.instance),

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,7 @@ public class CreateColumnFamilyStatement
comparators.put("decimal", "DecimalType");
comparators.put("double", "DoubleType");
comparators.put("float", "FloatType");
// comparators.put("int", "LongType"); TODO add int -> Int32Type
comparators.put("int", "Int32Type");
comparators.put("text", "UTF8Type");
comparators.put("timestamp", "DateType");
comparators.put("uuid", "UUIDType");

View File

@ -0,0 +1,100 @@
package org.apache.cassandra.cql.jdbc;
/*
*
* 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.
*
*/
import java.nio.ByteBuffer;
import java.sql.Types;
import org.apache.cassandra.utils.ByteBufferUtil;
public class JdbcInt32 extends AbstractJdbcType<Integer>
{
public static final JdbcInt32 instance = new JdbcInt32();
JdbcInt32()
{
}
public boolean isCaseSensitive()
{
return false;
}
public int getScale(Integer obj)
{
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;
}
public String getString(ByteBuffer bytes)
{
if (bytes.remaining() == 0)
{
return "";
}
if (bytes.remaining() != 4)
{
throw new MarshalException("A int is exactly 4 bytes: " + bytes.remaining());
}
return String.valueOf(bytes.getInt(bytes.position()));
}
public Class<Integer> getType()
{
return Integer.class;
}
public int getJdbcType()
{
return Types.INTEGER;
}
public Integer compose(ByteBuffer bytes)
{
return ByteBufferUtil.toInt(bytes);
}
}

View File

@ -90,7 +90,7 @@ public class JdbcLong extends AbstractJdbcType<Long>
public int getJdbcType()
{
return Types.INTEGER;
return Types.BIGINT;
}
public Long compose(ByteBuffer bytes)

View File

@ -17,6 +17,7 @@ public class TypesMap
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.IntegerType", JdbcInteger.instance);
map.put("org.apache.cassandra.db.marshal.LexicalUUIDType", JdbcLexicalUUID.instance);
map.put("org.apache.cassandra.db.marshal.LongType", JdbcLong.instance);

View File

@ -0,0 +1,102 @@
package org.apache.cassandra.db.marshal;
/*
*
* 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.
*
*/
import java.nio.ByteBuffer;
import org.apache.cassandra.cql.jdbc.JdbcInt32;
import org.apache.cassandra.utils.ByteBufferUtil;
public class Int32Type extends AbstractType<Integer>
{
public static final Int32Type instance = new Int32Type();
Int32Type() {} // singleton
public Integer compose(ByteBuffer bytes)
{
return ByteBufferUtil.toInt(bytes);
}
public ByteBuffer decompose(Integer value)
{
return ByteBufferUtil.bytes(value);
}
public int compare(ByteBuffer o1, ByteBuffer o2)
{
if (o1.remaining() == 0)
{
return o2.remaining() == 0 ? 0 : -1;
}
if (o2.remaining() == 0)
{
return 1;
}
int diff = o1.get(o1.position()) - o2.get(o2.position());
if (diff != 0)
return diff;
return ByteBufferUtil.compareUnsigned(o1, o2);
}
public String getString(ByteBuffer bytes)
{
try
{
return JdbcInt32.instance.getString(bytes);
}
catch (org.apache.cassandra.cql.jdbc.MarshalException e)
{
throw new MarshalException(e.getMessage());
}
}
public ByteBuffer fromString(String source) throws MarshalException
{
// Return an empty ByteBuffer for an empty string.
if (source.isEmpty())
return ByteBufferUtil.EMPTY_BYTE_BUFFER;
int int32Type;
try
{
int32Type = Integer.parseInt(source);
}
catch (Exception e)
{
throw new MarshalException(String.format("unable to make int from '%s'", source), e);
}
return decompose(int32Type);
}
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()));
}
}

View File

@ -363,6 +363,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -401,6 +402,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -417,6 +419,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -431,6 +434,7 @@ commands:
Supported values are:
- AsciiType
- BytesType
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -511,6 +515,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -626,6 +631,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -668,6 +674,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -684,6 +691,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -698,6 +706,7 @@ commands:
Supported values are:
- AsciiType
- BytesType
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -778,6 +787,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -919,6 +929,7 @@ commands:
Valid options are:
- ascii
- bytes: if used without arguments generates a zero length byte array
- int32
- integer
- lexicaluuid: if used without arguments generates a new random uuid
- long
@ -944,6 +955,7 @@ commands:
- AsciiType
- BytesType
- CounterColumnType (distributed counter column)
- Int32Type
- IntegerType (a generic variable-length integer type)
- LexicalUUIDType
- LongType
@ -987,6 +999,7 @@ commands:
Valid options are:
- ascii
- bytes: if used without arguments generates a zero length byte array
- int32
- integer
- lexicaluuid: if used without arguments generates a new random uuid
- long
@ -1030,6 +1043,7 @@ commands:
Supported values are:
- ascii
- bytes: if used without arguments generates a zero length byte array
- int32
- integer
- lexicaluuid: if used without arguments generates a new random uuid
- long
@ -1134,6 +1148,7 @@ commands:
- ascii
- bytes
- counterColumn (distributed counter column)
- int32
- integer (a generic variable-length integer type)
- lexicalUUID
- long

View File

@ -103,6 +103,15 @@ public class Util
return bb;
}
public static ByteBuffer getBytes(int v)
{
byte[] bytes = new byte[4];
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.putInt(v);
bb.rewind();
return bb;
}
public static List<Row> getRangeSlice(ColumnFamilyStore cfs) throws IOException, ExecutionException, InterruptedException
{
return getRangeSlice(cfs, null);

View File

@ -499,16 +499,16 @@ public class ColumnFamilyStoreTest extends CleanupHelper
// create an isolated sstable.
putColsSuper(cfs, key, scfName,
new Column(getBytes(1), ByteBufferUtil.bytes("val1"), 1),
new Column(getBytes(2), ByteBufferUtil.bytes("val2"), 1),
new Column(getBytes(3), ByteBufferUtil.bytes("val3"), 1));
new Column(getBytes(1L), ByteBufferUtil.bytes("val1"), 1),
new Column(getBytes(2L), ByteBufferUtil.bytes("val2"), 1),
new Column(getBytes(3L), ByteBufferUtil.bytes("val3"), 1));
cfs.forceBlockingFlush();
// insert, don't flush.
putColsSuper(cfs, key, scfName,
new Column(getBytes(4), ByteBufferUtil.bytes("val4"), 1),
new Column(getBytes(5), ByteBufferUtil.bytes("val5"), 1),
new Column(getBytes(6), ByteBufferUtil.bytes("val6"), 1));
new Column(getBytes(4L), ByteBufferUtil.bytes("val4"), 1),
new Column(getBytes(5L), ByteBufferUtil.bytes("val5"), 1),
new Column(getBytes(6L), ByteBufferUtil.bytes("val6"), 1));
// verify insert.
final SlicePredicate sp = new SlicePredicate();
@ -535,17 +535,17 @@ public class ColumnFamilyStoreTest extends CleanupHelper
// late insert.
putColsSuper(cfs, key, scfName,
new Column(getBytes(4), ByteBufferUtil.bytes("val4"), 1L),
new Column(getBytes(7), ByteBufferUtil.bytes("val7"), 1L));
new Column(getBytes(4L), ByteBufferUtil.bytes("val4"), 1L),
new Column(getBytes(7L), ByteBufferUtil.bytes("val7"), 1L));
// re-verify delete.
assertRowAndColCount(1, 0, scfName, false, cfs.getRangeSlice(scfName, Util.range("f", "g"), 100, QueryFilter.getFilter(sp, cfs.getComparator())));
// make sure new writes are recognized.
putColsSuper(cfs, key, scfName,
new Column(getBytes(3), ByteBufferUtil.bytes("val3"), 3),
new Column(getBytes(8), ByteBufferUtil.bytes("val8"), 3),
new Column(getBytes(9), ByteBufferUtil.bytes("val9"), 3));
new Column(getBytes(3L), ByteBufferUtil.bytes("val3"), 3),
new Column(getBytes(8L), ByteBufferUtil.bytes("val8"), 3),
new Column(getBytes(9L), ByteBufferUtil.bytes("val9"), 3));
assertRowAndColCount(1, 3, scfName, false, cfs.getRangeSlice(scfName, Util.range("f", "g"), 100, QueryFilter.getFilter(sp, cfs.getComparator())));
}

View File

@ -51,11 +51,11 @@ public class RemoveSubColumnTest extends CleanupHelper
// remove
rm = new RowMutation("Keyspace1", dk.key);
rm.delete(new QueryPath("Super1", ByteBufferUtil.bytes("SC1"), getBytes(1)), 1);
rm.delete(new QueryPath("Super1", ByteBufferUtil.bytes("SC1"), getBytes(1L)), 1);
rm.apply();
ColumnFamily retrieved = store.getColumnFamily(QueryFilter.getIdentityFilter(dk, new QueryPath("Super1", ByteBufferUtil.bytes("SC1"))));
assert retrieved.getColumn(ByteBufferUtil.bytes("SC1")).getSubColumn(getBytes(1)).isMarkedForDelete();
assert retrieved.getColumn(ByteBufferUtil.bytes("SC1")).getSubColumn(getBytes(1L)).isMarkedForDelete();
assertNull(Util.cloneAndRemoveDeleted(retrieved, Integer.MAX_VALUE));
}
}

View File

@ -85,7 +85,7 @@ public class RemoveSuperColumnTest extends CleanupHelper
// remove
rm = new RowMutation("Keyspace1", dk.key);
rm.delete(new QueryPath("Super3", ByteBufferUtil.bytes("SC1"), Util.getBytes(1)), 1);
rm.delete(new QueryPath("Super3", ByteBufferUtil.bytes("SC1"), Util.getBytes(1L)), 1);
rm.apply();
validateRemoveSubColumn(dk);
@ -97,9 +97,9 @@ public class RemoveSuperColumnTest extends CleanupHelper
private void validateRemoveSubColumn(DecoratedKey dk) throws IOException
{
ColumnFamilyStore store = Table.open("Keyspace1").getColumnFamilyStore("Super3");
ColumnFamily cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super3", ByteBufferUtil.bytes("SC1")), Util.getBytes(1)));
ColumnFamily cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super3", ByteBufferUtil.bytes("SC1")), Util.getBytes(1L)));
assertNull(Util.cloneAndRemoveDeleted(cf, Integer.MAX_VALUE));
cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super3", ByteBufferUtil.bytes("SC1")), Util.getBytes(2)));
cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super3", ByteBufferUtil.bytes("SC1")), Util.getBytes(2L)));
assertNotNull(Util.cloneAndRemoveDeleted(cf, Integer.MAX_VALUE));
}
@ -162,7 +162,7 @@ public class RemoveSuperColumnTest extends CleanupHelper
private void validateRemoveWithNewData(DecoratedKey dk) throws IOException
{
ColumnFamilyStore store = Table.open("Keyspace1").getColumnFamilyStore("Super2");
ColumnFamily cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super2", ByteBufferUtil.bytes("SC1")), getBytes(2)));
ColumnFamily cf = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath("Super2", ByteBufferUtil.bytes("SC1")), getBytes(2L)));
Collection<IColumn> subColumns = cf.getSortedColumns().iterator().next().getSubColumns();
assert subColumns.size() == 1;
assert subColumns.iterator().next().timestamp() == 2;

View File

@ -41,7 +41,7 @@ import static org.apache.cassandra.Util.column;
import static org.apache.cassandra.Util.getBytes;
import org.apache.cassandra.Util;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.LongType;
import org.apache.cassandra.db.marshal.Int32Type;
import org.apache.cassandra.io.sstable.IndexHelper;
import org.apache.cassandra.io.sstable.SSTableReader;
import org.apache.cassandra.utils.ByteBufferUtil;
@ -487,7 +487,7 @@ public class TableTest extends CleanupHelper
RowMutation rm = new RowMutation("Keyspace1", ROW.key);
ColumnFamily cf = ColumnFamily.create("Keyspace1", "Super1");
SuperColumn sc = new SuperColumn(ByteBufferUtil.bytes("sc1"), LongType.instance);
SuperColumn sc = new SuperColumn(ByteBufferUtil.bytes("sc1"), Int32Type.instance);
sc.addColumn(new Column(getBytes(1), ByteBufferUtil.bytes("val1"), 1L));
cf.addColumn(sc);
rm.add(cf);

View File

@ -59,6 +59,17 @@ public class RoundTripTest
assert JdbcLong.instance.toString(1L).equals("1");
}
@Test
public void intLong()
{
byte[] v = new byte[]{0,0,0,1};
assert Int32Type.instance.getString(Int32Type.instance.fromString("1")).equals("1");
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");
}
@Test
public void testAscii() throws Exception
{

View File

@ -92,6 +92,28 @@ public class TypeCompareTest
}
}
@Test
public void testInt()
{
Random rng = new Random();
ByteBuffer[] data = new ByteBuffer[1000];
for (int i = 0; i < data.length; i++)
{
data[i] = ByteBuffer.allocate(4);
rng.nextBytes(data[i].array());
}
Arrays.sort(data, Int32Type.instance);
for (int i = 1; i < data.length; i++)
{
int l0 = data[i - 1].getInt(data[i - 1].position());
int l1 = data[i].getInt(data[i].position());
assert l0 <= l1;
}
}
@Test
public void testTimeUUID()
{

View File

@ -52,10 +52,17 @@ public class TypeValidationTest
@Test
public void testLong()
{
LongType.instance.validate(Util.getBytes(5));
LongType.instance.validate(Util.getBytes(5L));
LongType.instance.validate(Util.getBytes(5555555555555555555L));
}
@Test
public void testInt()
{
Int32Type.instance.validate(Util.getBytes(5));
Int32Type.instance.validate(Util.getBytes(2057022603));
}
@Test
public void testValidUtf8() throws UnsupportedEncodingException
{