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/03/14 20:46:36 UTC
svn commit: r1081542 - in /cassandra/trunk/drivers/java:
src/org/apache/cassandra/cql/jdbc/ test/org/apache/cassandra/cql/
Author: gdusbabek
Date: Mon Mar 14 19:46:36 2011
New Revision: 1081542
URL: http://svn.apache.org/viewvc?rev=1081542&view=rev
Log:
RowData exposes sparse column attributes through CassandraResultSet
Added:
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/RowMetaData.java
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java
- copied, changed from r1080774, cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Col.java
Removed:
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Col.java
Modified:
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java
cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java?rev=1081542&r1=1081541&r2=1081542&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraResultSet.java Mon Mar 14 19:46:36 2011
@@ -68,11 +68,11 @@ class CassandraResultSet implements Resu
/** The r set iter. */
private Iterator<CqlRow> rSetIter;
-// /** The row. */
-// private CqlRow row;
+ // the current row key when iterating through results.
+ private byte[] curRowKey = null;
/** The values. */
- private List<Col> values = new ArrayList<Col>();
+ private List<TypedColumn> values = new ArrayList<TypedColumn>();
/** The value map. */
private Map<String, Object> valueMap = new WeakHashMap<String, Object>();
@@ -102,17 +102,6 @@ class CassandraResultSet implements Resu
}
/**
- * @param <T>
- * @param iface
- * @return
- * @throws SQLException
- */
- public <T> T unwrap(Class<T> iface) throws SQLException
- {
- throw new UnsupportedOperationException("method not supported");
- }
-
- /**
* @param arg0
* @return
* @throws SQLException
@@ -1034,7 +1023,22 @@ class CassandraResultSet implements Resu
{
throw new UnsupportedOperationException("method not supported");
}
-
+
+ /**
+ * @param <T>
+ * @param iface
+ * @return
+ * @throws SQLException
+ */
+ public <T> T unwrap(Class<T> iface) throws SQLException
+ {
+ // exposes the current row only.
+ if (iface.equals(RowMetaData.class))
+ return (T)new CassandraRowMetaData(this);
+ else
+ throw new SQLException("Unsupported unwrap interface: " + iface.getSimpleName());
+ }
+
/**
* @return
* @throws SQLException
@@ -1049,12 +1053,13 @@ class CassandraResultSet implements Resu
if (rSetIter != null && rSetIter.hasNext())
{
CqlRow row = rSetIter.next();
+ curRowKey = row.getKey();
List<Column> cols = row.getColumns();
for (Column col : cols)
{
byte[] name = col.getName();
byte[] value = col.getValue();
- Col c = decoder.makeCol(keyspace, columnFamily, name, value);
+ TypedColumn c = decoder.makeCol(keyspace, columnFamily, name, value);
values.add(c);
valueMap.put(decoder.colNameAsString(keyspace, columnFamily, name), c.getValue());
}
@@ -1995,4 +2000,29 @@ class CassandraResultSet implements Resu
throw new UnsupportedOperationException("method not supported");
}
+ private class CassandraRowMetaData implements RowMetaData
+ {
+ private final List<TypedColumn> cols;
+ private final byte[] key;
+
+ private CassandraRowMetaData(CassandraResultSet rs) {
+ cols = new ArrayList<TypedColumn>(rs.values);
+ key = curRowKey;
+ }
+
+ public int getColumnCount()
+ {
+ return cols.size();
+ }
+
+ public TypedColumn getColumn(int index)
+ {
+ return cols.get(index);
+ }
+
+ public byte[] getKey()
+ {
+ return key;
+ }
+ }
}
Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java?rev=1081542&r1=1081541&r2=1081542&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/CassandraStatement.java Mon Mar 14 19:46:36 2011
@@ -42,8 +42,10 @@ import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
+import java.util.regex.Pattern;
import org.apache.cassandra.thrift.CqlResult;
+import org.apache.cassandra.thrift.CqlResultType;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.TimedOutException;
import org.apache.cassandra.thrift.UnavailableException;
@@ -55,6 +57,7 @@ import org.apache.thrift.TException;
class CassandraStatement implements PreparedStatement
{
+ private static final Pattern UpdatePattern = Pattern.compile("UPDATE .*", Pattern.CASE_INSENSITIVE);
/** The connection. */
private org.apache.cassandra.cql.jdbc.Connection connection;
@@ -148,12 +151,11 @@ class CassandraStatement implements Prep
/**
+ * This is a no-op.
* @throws SQLException
*/
public void close() throws SQLException
{
- throw new UnsupportedOperationException("method not supported");
-
}
@@ -264,15 +266,38 @@ class CassandraStatement implements Prep
}
}
-
/**
- * @param arg0
+ * @param query
* @return
* @throws SQLException
*/
- public int executeUpdate(String arg0) throws SQLException
+ public int executeUpdate(String query) throws SQLException
{
- throw new UnsupportedOperationException("method not supported");
+ if (!UpdatePattern.matcher(query).matches())
+ throw new SQLException("Not an update statement.");
+ try
+ {
+ CqlResult rSet = connection.execute(query);
+ assert rSet.getType().equals(CqlResultType.VOID);
+ // if only we knew how many rows were updated.
+ return 0;
+ }
+ catch (InvalidRequestException e)
+ {
+ throw new SQLException(e.getWhy());
+ }
+ catch (UnavailableException e)
+ {
+ throw new SQLException(e.getMessage());
+ }
+ catch (TimedOutException e)
+ {
+ throw new SQLException(e.getMessage());
+ }
+ catch (TException e)
+ {
+ throw new SQLException(e.getMessage());
+ }
}
Modified: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java?rev=1081542&r1=1081541&r2=1081542&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/ColumnDecoder.java Mon Mar 14 19:46:36 2011
@@ -122,12 +122,12 @@ class ColumnDecoder
}
/** constructs a typed column */
- public Col makeCol(String keyspace, String columnFamily, byte[] name, byte[] value)
+ public TypedColumn 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)));
+ return new TypedColumn(comparator.compose(ByteBuffer.wrap(name)), validator.compose(ByteBuffer.wrap(value)));
}
}
Added: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/RowMetaData.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/RowMetaData.java?rev=1081542&view=auto
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/RowMetaData.java (added)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/RowMetaData.java Mon Mar 14 19:46:36 2011
@@ -0,0 +1,21 @@
+package org.apache.cassandra.cql.jdbc;
+
+/**
+ * Addresses the metadata needs of a sparse row of columns. ResultSetMetaData doesn't fit the bill because it
+ * expects every row to have the same set of columns.
+ *
+ * I didn't feel compelled to go the distance and implement distinct getXXXType(), getXXXTypeName(), getXXX()
+ * methods for both column names and values a la ResultSetMetaData. If we did want that, I recommend an optional
+ * method in AbstractType called getSqlType() or something like that.
+ */
+public interface RowMetaData
+{
+ /** number of columns in a row of data */
+ public int getColumnCount();
+
+ /** column name and value */
+ public TypedColumn getColumn(int index);
+
+ /** key */
+ public byte[] getKey(); // todo: update when typed keys are available.
+}
Copied: cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java (from r1080774, cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Col.java)
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java?p2=cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java&p1=cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Col.java&r1=1080774&r2=1081542&rev=1081542&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/Col.java (original)
+++ cassandra/trunk/drivers/java/src/org/apache/cassandra/cql/jdbc/TypedColumn.java Mon Mar 14 19:46:36 2011
@@ -1,11 +1,11 @@
package org.apache.cassandra.cql.jdbc;
-class Col<N, V>
+public class TypedColumn<N, V>
{
public final N name;
public final V value;
- public Col(N name, V value)
+ public TypedColumn(N name, V value)
{
this.name = name;
this.value = value;
Modified: cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java?rev=1081542&r1=1081541&r2=1081542&view=diff
==============================================================================
--- cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java (original)
+++ cassandra/trunk/drivers/java/test/org/apache/cassandra/cql/JdbcDriverTest.java Mon Mar 14 19:46:36 2011
@@ -23,14 +23,17 @@ package org.apache.cassandra.cql;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.nio.FloatBuffer;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.Arrays;
+import org.apache.cassandra.cql.jdbc.RowMetaData;
import org.apache.cassandra.utils.FBUtilities;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -68,6 +71,96 @@ public class JdbcDriverTest extends Embe
executeNoResults(con, q);
}
+ @Test
+ public void testIntegerMetadata() throws SQLException
+ {
+ Statement stmt = con.createStatement();
+ stmt.executeUpdate("UPDATE JdbcInteger SET 1=111, 2=222 WHERE KEY = 'Integer'");
+ ResultSet rs = stmt.executeQuery("SELECT 1, 2 from JdbcInteger WHERE KEY = 'Integer'");
+ assert rs.next();
+ assert rs.getInt("1") == 111;
+ assert rs.getInt("2") == 222;
+ RowMetaData rd = rs.unwrap(RowMetaData.class);
+ assert rd.getColumnCount() == 2;
+ assert rd.getColumn(0).getName().equals(new BigInteger("1"));
+ assert rd.getColumn(0).getValue().equals(new BigInteger("111"));
+ assert rd.getColumn(1).getName().equals(new BigInteger("2"));
+ assert rd.getColumn(1).getValue().equals(new BigInteger("222"));
+ }
+
+ @Test
+ public void testLongMetadata() throws SQLException
+ {
+ Statement stmt = con.createStatement();
+ stmt.executeUpdate("UPDATE JdbcLong SET 1=111, 2=222 WHERE KEY = 'Long'");
+ ResultSet rs = stmt.executeQuery("SELECT 1, 2 from JdbcLong WHERE KEY = 'Long'");
+ assert rs.next();
+ assert rs.getLong("1") == 111;
+ assert rs.getLong("2") == 222;
+ RowMetaData rd = rs.unwrap(RowMetaData.class);
+ assert rd.getColumnCount() == 2;
+ assert rd.getColumn(0).getName().equals(new Long("1"));
+ assert rd.getColumn(0).getValue().equals(new Long("111"));
+ assert rd.getColumn(1).getName().equals(new Long("2"));
+ assert rd.getColumn(1).getValue().equals(new Long("222"));
+ assert (Long)rd.getColumn(0).getName() == 1L;
+ assert (Long)rd.getColumn(0).getValue() == 111L;
+ assert (Long)rd.getColumn(1).getName() == 2L;
+ assert (Long)rd.getColumn(1).getValue() == 222L;
+ }
+
+ @Test
+ public void testStringMetadata() throws SQLException
+ {
+ Statement stmt = con.createStatement();
+ stmt.executeUpdate("UPDATE JdbcAscii SET 'a'='aa', 'b'='bb' WHERE KEY = 'ascii'");
+ stmt.executeUpdate("UPDATE JdbcUtf8 SET 'a'='aa', 'b'='bb' WHERE KEY = 'utf8'");
+ ResultSet rs0 = stmt.executeQuery("SELECT 'a', 'b' FROM JdbcAscii WHERE KEY = 'ascii'");
+ ResultSet rs1 = stmt.executeQuery("SELECT 'a', 'b' FROM JdbcUtf8 WHERE KEY = 'utf8'");
+ for (ResultSet rs : new ResultSet[] { rs0, rs1 })
+ {
+ assert rs.next();
+ assert rs.getString("a").equals("aa");
+ assert rs.getString("b").equals("bb");
+ RowMetaData rd = rs.unwrap(RowMetaData.class);
+ assert rd.getColumnCount() == 2;
+ assert rd.getColumn(0).getName().equals("a");
+ assert rd.getColumn(0).getValue().equals("aa");
+ assert rd.getColumn(1).getName().equals("b");
+ assert rd.getColumn(1).getValue().equals("bb");
+ }
+ }
+
+ @Test
+ public void testBytesMetadata() throws SQLException
+ {
+ Statement stmt = con.createStatement();
+ byte[] a = "a_".getBytes();
+ byte[] b = "b_".getBytes();
+ byte[] aa = "_aa_".getBytes();
+ byte[] bb = "_bb_".getBytes();
+ stmt.executeUpdate(String.format(
+ "UPDATE JdbcBytes set '%s'='%s', '%s'='%s' WHERE KEY = 'bytes'",
+ FBUtilities.bytesToHex(a),
+ FBUtilities.bytesToHex(aa),
+ FBUtilities.bytesToHex(b),
+ FBUtilities.bytesToHex(bb)));
+ ResultSet rs = stmt.executeQuery(String.format(
+ "SELECT '%s', '%s' from JdbcBytes WHERE KEY = 'bytes'",
+ FBUtilities.bytesToHex(a),
+ FBUtilities.bytesToHex(b)));
+ assert rs.next();
+ assert Arrays.equals(aa, rs.getBytes(0));
+ assert Arrays.equals(bb, rs.getBytes(1));
+ assert Arrays.equals(aa, rs.getBytes(FBUtilities.bytesToHex(a)));
+ assert Arrays.equals(bb, rs.getBytes(FBUtilities.bytesToHex(b)));
+ RowMetaData rd = rs.unwrap(RowMetaData.class);
+ assert rd.getColumn(0).getName().equals(ByteBuffer.wrap(a));
+ assert rd.getColumn(1).getName().equals(ByteBuffer.wrap(b));
+ assert rd.getColumn(0).getValue().equals(ByteBuffer.wrap(aa));
+ assert rd.getColumn(1).getValue().equals(ByteBuffer.wrap(bb));
+ }
+
/** Method to test statement. */
@Test
public void testWithStatement() throws SQLException