Author: gdusbabek Date: Wed Mar 9 20:22:45 2011 New Revision: 1079973 URL: http://svn.apache.org/viewvc?rev=1079973&view=rev Log: first pass at column decoding. patch by gdusbabek, reviewed by eevans. CASSANDRA-2124
Added: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Col.java cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Results.java cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/SchemaDecoder.java cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/jdbc/EmbeddedServiceBase.java - copied, changed from r1079849, cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/EmbeddedServiceBase.java Removed: cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/EmbeddedServiceBase.java Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Connection.java cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraResultSet.java cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraStatement.java Added: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Col.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Col.java?rev=1079973&view=auto ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Col.java (added) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Col.java Wed Mar 9 20:22:45 2011 @@ -0,0 +1,23 @@ +package org.apache.cassandra.cql.driver; + +public class Col<N, V> +{ + public final N name; + public final V value; + + public Col(N name, V value) + { + this.name = name; + this.value = value; + } + + public N getName() + { + return name; + } + + public V getValue() + { + return value; + } +} Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Connection.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Connection.java?rev=1079973&r1=1079972&r2=1079973&view=diff ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Connection.java (original) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Connection.java Wed Mar 9 20:22:45 2011 @@ -23,6 +23,8 @@ package org.apache.cassandra.cql.driver; import java.util.HashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.cassandra.thrift.AuthenticationException; import org.apache.cassandra.thrift.AuthenticationRequest; @@ -46,6 +48,9 @@ import org.slf4j.LoggerFactory; /** CQL connection object. */ public class Connection { + private static final Pattern KeyspacePattern = Pattern.compile("USE (\\w+);?", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + private static final Pattern SelectPattern = Pattern.compile("SELECT\\s+.+\\s+FROM\\s+(\\w+).*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); + public static Compression defaultCompression = Compression.GZIP; public final String hostName; public final int portNo; @@ -56,6 +61,11 @@ public class Connection private Cassandra.Client client; private TTransport transport; + // todo: encapsulate. + public String curKeyspace; + public String curColumnFamily; + public SchemaDecoder decoder; + /** * Create a new <code>Connection</code> instance. * @@ -67,7 +77,6 @@ public class Connection { this.hostName = hostName; this.portNo = portNo; - TSocket socket = new TSocket(hostName, portNo); transport = new TFramedTransport(socket); TProtocol protocol = new TBinaryProtocol(transport); @@ -127,6 +136,15 @@ public class Connection public CqlResult execute(String queryStr, Compression compress) throws InvalidRequestException, UnavailableException, TimedOutException, TException { + if (decoder == null) + decoder = new SchemaDecoder(client.describe_keyspaces()); + + Matcher isKeyspace = KeyspacePattern.matcher(queryStr); + if (isKeyspace.matches()) + curKeyspace = isKeyspace.group(1); + Matcher isSelect = SelectPattern.matcher(queryStr); + if (isSelect.matches()) + curColumnFamily = isSelect.group(1); try { return client.execute_cql_query(Utils.compressQuery(queryStr, compress), compress); Added: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Results.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Results.java?rev=1079973&view=auto ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Results.java (added) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/Results.java Wed Mar 9 20:22:45 2011 @@ -0,0 +1,21 @@ +package org.apache.cassandra.cql.driver; + + +public class Results +{ + private final SchemaDecoder decoder; + private final String keyspace; + private final String columnFamily; + + public Results(SchemaDecoder decoder, String keyspace, String columnFamily) + { + this.decoder = decoder; + this.keyspace = keyspace; + this.columnFamily = columnFamily; + } + + public Col makeCol(byte[] name, byte[] value) { + return decoder.makeCol(keyspace, columnFamily, name, value); + } + +} Added: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/SchemaDecoder.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/SchemaDecoder.java?rev=1079973&view=auto ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/SchemaDecoder.java (added) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/SchemaDecoder.java Wed Mar 9 20:22:45 2011 @@ -0,0 +1,110 @@ +package org.apache.cassandra.cql.driver; + +import org.apache.cassandra.config.ConfigurationException; +import org.apache.cassandra.db.marshal.AbstractType; +import org.apache.cassandra.db.marshal.AsciiType; +import org.apache.cassandra.db.marshal.BytesType; +import org.apache.cassandra.db.marshal.IntegerType; +import org.apache.cassandra.db.marshal.LexicalUUIDType; +import org.apache.cassandra.db.marshal.LongType; +import org.apache.cassandra.db.marshal.TimeUUIDType; +import org.apache.cassandra.db.marshal.UTF8Type; +import org.apache.cassandra.thrift.CfDef; +import org.apache.cassandra.thrift.KsDef; +import org.apache.cassandra.utils.FBUtilities; +import org.apache.cassandra.utils.UUIDGen; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class SchemaDecoder +{ + private static final Logger logger = LoggerFactory.getLogger(SchemaDecoder.class); + private static final String MapFormatString = "%s.%s.%s"; + + enum Specifier + { + Comparator, + Validator + } + + private Map<String, CfDef> cfDefs = new HashMap<String, CfDef>(); + + // cache the comparators for efficiency. + private Map<String, AbstractType> comparators = new HashMap<String, AbstractType>(); + + public SchemaDecoder(List<KsDef> defs) + { + for (KsDef ks : defs) + for (CfDef cf : ks.getCf_defs()) + cfDefs.put(String.format("%s.%s", ks.getName(), cf.getName()), cf); + } + + /** + * @param keyspace ALWAYS specify + * @param columnFamily ALWAYS specify + * @param specifier ALWAYS specify + * @param def avoids additional map lookup if specified. null is ok. though. + * @return + */ + private AbstractType getComparator(String keyspace, String columnFamily, Specifier specifier, CfDef def) + { + // check cache first. + String key = String.format(MapFormatString, keyspace, columnFamily, specifier.name()); + AbstractType comparator = comparators.get(key); + + // make and put in cache. + if (comparator == null) + { + if (def == null) + def = cfDefs.get(String.format("%s.%s", keyspace, columnFamily)); + try + { + switch (specifier) + { + case Validator: + comparator = FBUtilities.getComparator(def.getDefault_validation_class()); + break; + case Comparator: + default: + comparator = FBUtilities.getComparator(def.getComparator_type()); + break; + } + comparators.put(key, comparator); + } + catch (ConfigurationException ex) + { + throw new RuntimeException(ex); + } + } + return comparator; + } + + public String colNameAsString(String keyspace, String columnFamily, String name) + { + AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, null); + ByteBuffer bb = comparator.fromString(name); + return comparator.getString(bb); + } + + public String colNameAsString(String keyspace, String columnFamily, byte[] name) + { + AbstractType comparator = getComparator(keyspace, columnFamily, Specifier.Comparator, null); + return comparator.getString(ByteBuffer.wrap(name)); + } + + public Col makeCol(String keyspace, String columnFamily, byte[] name, byte[] value) + { + 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); + // todo: generate less garbage. + return new Col(comparator.compose(ByteBuffer.wrap(name)), validator.compose(ByteBuffer.wrap(value))); + } +} Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraResultSet.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraResultSet.java?rev=1079973&r1=1079972&r2=1079973&view=diff ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraResultSet.java (original) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraResultSet.java Wed Mar 9 20:22:45 2011 @@ -45,6 +45,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.WeakHashMap; + +import org.apache.cassandra.cql.driver.Col; +import org.apache.cassandra.cql.driver.Results; +import org.apache.cassandra.cql.driver.SchemaDecoder; import org.apache.cassandra.thrift.Column; import org.apache.cassandra.thrift.CqlResult; import org.apache.cassandra.thrift.CqlRow; @@ -56,16 +60,20 @@ class CassandraResultSet implements Resu { /** The r set. */ - private CqlResult rSet; + private final CqlResult rSet; + + private final SchemaDecoder decoder; + private final String keyspace; + private final String columnFamily; /** The r set iter. */ private Iterator<CqlRow> rSetIter; - /** The row. */ - private CqlRow row; +// /** The row. */ +// private CqlRow row; /** The values. */ - private List<Object> values = new ArrayList<Object>(); + private List<Col> values = new ArrayList<Col>(); /** The value map. */ private Map<String, Object> valueMap = new WeakHashMap<String, Object>(); @@ -75,9 +83,12 @@ class CassandraResultSet implements Resu * * @param resultSet the result set */ - CassandraResultSet(CqlResult resultSet) + CassandraResultSet(CqlResult resultSet, SchemaDecoder decoder, String keyspace, String columnFamily) { this.rSet = resultSet; + this.decoder = decoder; + this.keyspace = keyspace; + this.columnFamily = columnFamily; rSetIter = rSet.getRowsIterator(); } @@ -787,7 +798,7 @@ class CassandraResultSet implements Resu */ public String getString(int index) throws SQLException { - return values.get(index) != null ? values.get(index).toString() : null; + return values.get(index) != null ? values.get(index).getValue().toString() : null; } /** @@ -797,7 +808,8 @@ class CassandraResultSet implements Resu */ public String getString(String name) throws SQLException { - return valueMap.get(name) != null ? valueMap.get(name).toString() : null; + String nameAsString = this.decoder.colNameAsString(this.keyspace, this.columnFamily, name); + return valueMap.get(nameAsString) != null ? valueMap.get(nameAsString).toString() : null; } /** @@ -1033,14 +1045,15 @@ class CassandraResultSet implements Resu } if (rSetIter != null && rSetIter.hasNext()) { - row = rSetIter.next(); + CqlRow row = rSetIter.next(); List<Column> cols = row.getColumns(); for (Column col : cols) { - String name = new String(col.getName()); - String value = new String(col.getValue()); - values.add(value); - valueMap.put(name, value); + byte[] name = col.getName(); + byte[] value = col.getValue(); + Col c = decoder.makeCol(keyspace, columnFamily, name, value); + values.add(c); + valueMap.put(decoder.colNameAsString(keyspace, columnFamily, name), c.getValue()); } return !(values.isEmpty() && valueMap.isEmpty()); } Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraStatement.java URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraStatement.java?rev=1079973&r1=1079972&r2=1079973&view=diff ============================================================================== --- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraStatement.java (original) +++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/driver/jdbc/CassandraStatement.java Wed Mar 9 20:22:45 2011 @@ -43,6 +43,7 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; +import org.apache.cassandra.cql.driver.Results; import org.apache.cassandra.thrift.CqlResult; import org.apache.cassandra.thrift.InvalidRequestException; import org.apache.cassandra.thrift.TimedOutException; @@ -243,7 +244,8 @@ class CassandraStatement implements Prep try { CqlResult rSet = connection.execute(query); - return new CassandraResultSet(rSet); + // todo: encapsulate. + return new CassandraResultSet(rSet, connection.decoder, connection.curKeyspace, connection.curColumnFamily); } catch (InvalidRequestException e) { Copied: cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/jdbc/EmbeddedServiceBase.java (from r1079849, cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/EmbeddedServiceBase.java) URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/jdbc/EmbeddedServiceBase.java?p2=cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/jdbc/EmbeddedServiceBase.java&p1=cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/driver/EmbeddedServiceBase.java&r1=1079849&r2=1079973&rev=1079973&view=diff ============================================================================== (empty)