You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by gd...@apache.org on 2011/04/17 01:08:46 UTC
svn commit: r1094085 - in /cassandra/branches/cassandra-0.8:
drivers/java/src/org/apache/cassandra/cql/jdbc/
drivers/java/test/org/apache/cassandra/cql/ test/unit/org/apache/cassandra/
Author: gdusbabek
Date: Sat Apr 16 23:08:46 2011
New Revision: 1094085
URL: http://svn.apache.org/viewvc?rev=1094085&view=rev
Log:
honor specific column validators in JDBC driver. patch by gdusbabek, reviewed by jbellis. CASSANDRA-2410
Modified:
cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/SchemaLoader.java
Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java?rev=1094085&r1=1094084&r2=1094085&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java Sat Apr 16 23:08:46 2011
@@ -42,13 +42,7 @@ import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.WeakHashMap;
+import java.util.*;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.BytesType;
@@ -58,7 +52,6 @@ import org.apache.cassandra.thrift.Colum
import org.apache.cassandra.thrift.CqlResult;
import org.apache.cassandra.thrift.CqlRow;
-// todo: get by index is off by one.
/**
* The Class CassandraResultSet.
*/
@@ -87,7 +80,6 @@ class CassandraResultSet implements Resu
private final RsMetaData meta;
private final AbstractType nameType;
- private final AbstractType valueType;
/**
* Instantiates a new cassandra result set.
@@ -103,7 +95,6 @@ class CassandraResultSet implements Resu
rSetIter = rSet.getRowsIterator();
meta = new RsMetaData();
nameType = decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Comparator, null);
- valueType = decoder.getComparator(keyspace, columnFamily, ColumnDecoder.Specifier.Validator, null);
}
/**
@@ -2037,10 +2028,11 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- if (valueType instanceof ColumnMetaData)
- return ((ColumnMetaData)valueType).isCaseSensitive();
+ TypedColumn tc = values.get(column);
+ if (tc.getValidator() instanceof ColumnMetaData)
+ return ((ColumnMetaData)tc.getValidator()).isCaseSensitive();
else
- return valueType.getType().equals(String.class);
+ return tc.getValidator().getType().equals(String.class);
}
public boolean isNameCurrency(int column) throws SQLException
@@ -2057,8 +2049,9 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- if (valueType instanceof ColumnMetaData)
- return ((ColumnMetaData)valueType).isCurrency();
+ TypedColumn tc = values.get(column);
+ if (tc.getValidator() instanceof ColumnMetaData)
+ return ((ColumnMetaData)tc.getValidator()).isCurrency();
else
return false;
}
@@ -2074,7 +2067,8 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return Utils.isTypeSigned(valueType);
+ TypedColumn tc = values.get(column);
+ return Utils.isTypeSigned(tc.getValidator());
}
public int getNameDisplaySize(int column) throws SQLException
@@ -2113,15 +2107,15 @@ class CassandraResultSet implements Resu
column--;
checkIndex(column);
TypedColumn col = values.get(column);
- if (valueType instanceof ColumnMetaData)
- return ((ColumnMetaData)valueType).getPrecision();
- else if (valueType.getType().equals(String.class))
+ if (col.getValidator() instanceof ColumnMetaData)
+ return ((ColumnMetaData)col.getValidator()).getPrecision();
+ else if (col.getValidator().getType().equals(String.class))
return col.getValueString().length();
- else if (valueType == BytesType.instance)
+ else if (col.getValidator() == BytesType.instance)
return col.getValueString().length();
- else if (valueType.getType().equals(UUID.class))
+ else if (col.getValidator().getType().equals(UUID.class))
return 36; // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- else if (valueType == LongType.instance)
+ else if (col.getValidator() == LongType.instance)
return 19; // number of digits in 2**63-1.
else
return 0;
@@ -2138,7 +2132,7 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return Utils.getTypeScale(valueType);
+ return Utils.getTypeScale(values.get(column).getValidator());
}
public int getNameType(int column) throws SQLException
@@ -2152,7 +2146,7 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return Utils.getJdbcType(valueType);
+ return Utils.getJdbcType(values.get(column).getValidator());
}
public String getNameTypeName(int column) throws SQLException
@@ -2166,7 +2160,7 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return valueType.getClass().getSimpleName();
+ return values.get(column).getValidator().getClass().getSimpleName();
}
public String getNameClassName(int column) throws SQLException
@@ -2180,7 +2174,7 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return valueType.getType().getName();
+ return values.get(column).getValidator().getType().getName();
}
//
@@ -2202,7 +2196,7 @@ class CassandraResultSet implements Resu
{
column--;
checkIndex(column);
- return valueType instanceof CounterColumnType; // todo: check Value is correct.
+ return values.get(column).getValidator() instanceof CounterColumnType; // todo: check Value is correct.
}
public boolean isCaseSensitive(int column) throws SQLException
Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java?rev=1094085&r1=1094084&r2=1094085&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java Sat Apr 16 23:08:46 2011
@@ -24,6 +24,7 @@ package org.apache.cassandra.cql.jdbc;
import org.apache.cassandra.config.ConfigurationException;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.thrift.CfDef;
+import org.apache.cassandra.thrift.ColumnDef;
import org.apache.cassandra.thrift.KsDef;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
@@ -39,14 +40,15 @@ import java.util.Map;
class ColumnDecoder
{
private static final Logger logger = LoggerFactory.getLogger(ColumnDecoder.class);
- private static final String MapFormatString = "%s.%s.%s";
+ private static final String MapFormatString = "%s.%s.%s.%s";
// basically denotes column or value.
enum Specifier
{
Comparator,
Validator,
- Key
+ Key,
+ ColumnSpecific
}
private Map<String, CfDef> cfDefs = new HashMap<String, CfDef>();
@@ -58,8 +60,29 @@ class ColumnDecoder
public ColumnDecoder(List<KsDef> defs)
{
for (KsDef ks : defs)
+ {
for (CfDef cf : ks.getCf_defs())
+ {
cfDefs.put(String.format("%s.%s", ks.getName(), cf.getName()), cf);
+ for (ColumnDef cd : cf.getColumn_metadata())
+ {
+ try
+ {
+ // prefill the validators (because they aren't kept in a convenient lookup map and we don't
+ // want to iterate over the list for every miss in getComparator.
+ comparators.put(String.format(MapFormatString,
+ ks.getName(),
+ cf.getName(),
+ Specifier.ColumnSpecific.name(),
+ ByteBufferUtil.bytesToHex(cd.bufferForName())),
+ FBUtilities.getComparator(cd.getValidation_class()));
+ }
+ catch (ConfigurationException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+ }
}
/**
@@ -69,10 +92,20 @@ class ColumnDecoder
* @param def avoids additional map lookup if specified. null is ok though.
* @return
*/
- AbstractType getComparator(String keyspace, String columnFamily, Specifier specifier, CfDef def)
+ AbstractType getComparator(String keyspace, String columnFamily, Specifier specifier, CfDef def)
+ {
+ return getComparator(keyspace, columnFamily, null, specifier, def);
+ }
+
+ // same as above, but can get column-specific validators.
+ AbstractType getComparator(String keyspace, String columnFamily, byte[] column, Specifier specifier, CfDef def)
{
// check cache first.
- String key = String.format(MapFormatString, keyspace, columnFamily, specifier.name());
+ String key = String.format(MapFormatString,
+ keyspace,
+ columnFamily,
+ specifier.name(),
+ FBUtilities.bytesToHex(column == null ? new byte[] {} : column));
AbstractType comparator = comparators.get(key);
// make and put in cache.
@@ -90,6 +123,8 @@ class ColumnDecoder
case Key:
comparator = FBUtilities.getComparator(def.getKey_validation_class());
break;
+ case ColumnSpecific:
+ // if we get here this means there is no column-specific validator, so fall through to the default.
case Validator:
comparator = FBUtilities.getComparator(def.getDefault_validation_class());
break;
@@ -154,7 +189,7 @@ class ColumnDecoder
{
CfDef cfDef = cfDefs.get(String.format("%s.%s", keyspace, columnFamily));
AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, cfDef);
- AbstractType validator = getComparator(keyspace, columnFamily, Specifier.Validator, null);
+ AbstractType validator = getComparator(keyspace, columnFamily, name, Specifier.ColumnSpecific, null);
return new TypedColumn(comparator, name, validator, value);
}
}
Modified: cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java?rev=1094085&r1=1094084&r2=1094085&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java Sat Apr 16 23:08:46 2011
@@ -34,6 +34,7 @@ class TypedColumn<N, V>
// (a good example is byte buffers) as the stringified versions supplied by the AbstractTypes.
private final String nameString;
private final String valueString;
+ private final AbstractType<V> validator;
public TypedColumn(AbstractType<N> comparator, byte[] name, AbstractType<V> validator, byte[] value)
{
@@ -43,6 +44,7 @@ class TypedColumn<N, V>
this.value = validator.compose(bbValue);
nameString = comparator.getString(bbName);
valueString = validator.getString(bbValue);
+ this.validator = validator;
}
public N getName()
@@ -64,4 +66,9 @@ class TypedColumn<N, V>
{
return valueString;
}
+
+ public AbstractType<V> getValidator()
+ {
+ return validator;
+ }
}
Modified: cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java?rev=1094085&r1=1094084&r2=1094085&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java (original)
+++ cassandra/branches/cassandra-0.8/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java Sat Apr 16 23:08:46 2011
@@ -68,12 +68,12 @@ public class JdbcDriverTest extends Embe
String[] inserts =
{
String.format("UPDATE Standard1 SET '%s' = '%s', '%s' = '%s' WHERE KEY = '%s'", first, firstrec, last, lastrec, jsmith),
- "UPDATE JdbcInteger SET 1 = 11, 2 = 22 WHERE KEY = '" + jsmith + "'",
+ "UPDATE JdbcInteger SET 1 = 11, 2 = 22, 42='fortytwo' WHERE KEY = '" + jsmith + "'",
"UPDATE JdbcInteger SET 3 = 33, 4 = 44 WHERE KEY = '" + jsmith + "'",
"UPDATE JdbcLong SET 1 = 11, 2 = 22 WHERE KEY = '" + jsmith + "'",
"UPDATE JdbcAscii SET 'first' = 'firstrec', 'last' = 'lastrec' WHERE key = '" + jsmith + "'",
String.format("UPDATE JdbcBytes SET '%s' = '%s', '%s' = '%s' WHERE key = '%s'", first, firstrec, last, lastrec, jsmith),
- "UPDATE JdbcUtf8 SET 'first' = 'firstrec', 'last' = 'lastrec' WHERE key = '" + jsmith + "'",
+ "UPDATE JdbcUtf8 SET 'first' = 'firstrec', 'fortytwo' = '42', 'last' = 'lastrec' WHERE key = '" + jsmith + "'",
};
for (String q : inserts)
{
@@ -119,6 +119,37 @@ public class JdbcDriverTest extends Embe
assert valuCaseSense == md.isValueCaseSensitive(col);
}
+ @Test
+ public void testNonDefaultColumnValidators() throws SQLException
+ {
+ String key = FBUtilities.bytesToHex("Integer".getBytes());
+ Statement stmt = con.createStatement();
+ stmt.executeUpdate("update JdbcInteger set 1=1111, 2=2222, 42='fortytwofortytwo' where key='" + key + "'");
+ ResultSet rs = stmt.executeQuery("select 1, 2, 42 from JdbcInteger where key='" + key + "'");
+ assert rs.next();
+ assert rs.getInt("1") == 1111;
+ assert rs.getInt("2") == 2222;
+ assert rs.getString("42").equals("fortytwofortytwo") : rs.getString("42");
+
+ ResultSetMetaData md = rs.getMetaData();
+ assert md.getColumnCount() == 3;
+ expectedMetaData(md, 1, BigInteger.class.getName(), "JdbcInteger", "Keyspace1", "1", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
+ expectedMetaData(md, 2, BigInteger.class.getName(), "JdbcInteger", "Keyspace1", "2", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
+ expectedMetaData(md, 3, String.class.getName(), "JdbcInteger", "Keyspace1", "42", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
+
+ stmt.executeUpdate("update JdbcUtf8 set 'a'='aa', 'b'='bb', 'fortytwo'='4242' where key='" + key + "'");
+ rs = stmt.executeQuery("select 'a', 'b', 'fortytwo' from JdbcUtf8 where key='" + key + "'");
+ assert rs.next();
+ assert rs.getString("a").equals("aa");
+ assert rs.getString("b").equals("bb");
+ assert rs.getInt("fortytwo") == 4242L;
+
+ md = rs.getMetaData();
+ expectedMetaData(md, 1, String.class.getName(), "JdbcUtf8", "Keyspace1", "a", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
+ expectedMetaData(md, 2, String.class.getName(), "JdbcUtf8", "Keyspace1", "b", Types.VARCHAR, UTF8Type.class.getSimpleName(), false, true);
+ expectedMetaData(md, 3, BigInteger.class.getName(), "JdbcUtf8", "Keyspace1", "fortytwo", Types.BIGINT, IntegerType.class.getSimpleName(), true, false);
+ }
+
@Test
public void testIntegerMetadata() throws SQLException
{
Modified: cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/SchemaLoader.java
URL: http://svn.apache.org/viewvc/cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/SchemaLoader.java?rev=1094085&r1=1094084&r2=1094085&view=diff
==============================================================================
--- cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/SchemaLoader.java (original)
+++ cassandra/branches/cassandra-0.8/test/unit/org/apache/cassandra/SchemaLoader.java Sat Apr 16 23:08:46 2011
@@ -77,6 +77,20 @@ public class SchemaLoader
ColumnFamilyType st = ColumnFamilyType.Standard;
ColumnFamilyType su = ColumnFamilyType.Super;
AbstractType bytes = BytesType.instance;
+
+ // these column definitions will will be applied to the jdbc utf and integer column familes respectively.
+ Map<ByteBuffer, ColumnDefinition> integerColumn = new HashMap<ByteBuffer, ColumnDefinition>();
+ integerColumn.put(IntegerType.instance.fromString("42"), new ColumnDefinition(
+ IntegerType.instance.fromString("42"),
+ UTF8Type.instance,
+ null,
+ "Column42"));
+ Map<ByteBuffer, ColumnDefinition> utf8Column = new HashMap<ByteBuffer, ColumnDefinition>();
+ utf8Column.put(UTF8Type.instance.fromString("fortytwo"), new ColumnDefinition(
+ UTF8Type.instance.fromString("fortytwo"),
+ IntegerType.instance,
+ null,
+ "Column42"));
// Keyspace 1
schema.add(new KSMetaData(ks1,
@@ -115,8 +129,8 @@ public class SchemaLoader
bytes,
bytes)
.defaultValidator(CounterColumnType.instance),
- jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance),
- jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance),
+ jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance).columnMetadata(integerColumn),
+ jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance).columnMetadata(utf8Column),
jdbcCFMD(ks1, "JdbcLong", LongType.instance),
jdbcCFMD(ks1, "JdbcBytes", bytes),
jdbcCFMD(ks1, "JdbcAscii", AsciiType.instance)));