3 new revisions:

Revision: 5458a35f6e6d
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:31:03 2011
Log: Rewrite CassandraPreparedStatement to use server-side processing...
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=5458a35f6e6d

Revision: 174f0264f80a
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:36:57 2011
Log:      Update pom to use 1.1-dev-SNAPSHOT for testing
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=174f0264f80a

Revision: 259efa0caf1a
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:38:15 2011
Log: Update PreparedStatementTest to remove implementation specific code
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=259efa0caf1a

==============================================================================
Revision: 5458a35f6e6d
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:31:03 2011
Log:      Rewrite CassandraPreparedStatement to use server-side processing

* Rewrite CassandraPreparedStatement

* modify CassandraStatement to provide support for new design

* modify CassandraConnection to provide support for new design

* add unsupported methods to AbstractStatement

http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=5458a35f6e6d

Modified:
 /src/main/java/org/apache/cassandra/cql/jdbc/AbstractStatement.java
 /src/main/java/org/apache/cassandra/cql/jdbc/CassandraConnection.java
/src/main/java/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java
 /src/main/java/org/apache/cassandra/cql/jdbc/CassandraStatement.java
 /src/main/resources/log4j.properties

=======================================
--- /src/main/java/org/apache/cassandra/cql/jdbc/AbstractStatement.java Thu Oct 13 00:45:22 2011 +++ /src/main/java/org/apache/cassandra/cql/jdbc/AbstractStatement.java Thu Dec 1 10:31:03 2011
@@ -20,14 +20,31 @@
  */
 package org.apache.cassandra.cql.jdbc;

+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;

 abstract class AbstractStatement
 {
protected static final String NOT_SUPPORTED = "the Cassandra implementation does not support this method";

+    /*
+     * From the Statement Implementation
+     */
     public void cancel() throws SQLException
     {
         throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
@@ -71,4 +88,142 @@
     {
         throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
     }
-}
+
+    /*
+     * From the PreparedStatement Implementation
+     */
+
+    public void setArray(int parameterIndex, Array x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+    public void setBlob(int parameterIndex, Blob x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+    public void setClob(int parameterIndex, Clob x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException("method not supported");
+    }
+
+ public void setClob(int parameterIndex, Reader reader) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setNClob(int parameterIndex, NClob value) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+
+
+    public void setRef(int parameterIndex, Ref x) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+ public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
+    {
+        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+    }
+
+}
=======================================
--- /src/main/java/org/apache/cassandra/cql/jdbc/CassandraConnection.java Thu Nov 17 12:13:48 2011 +++ /src/main/java/org/apache/cassandra/cql/jdbc/CassandraConnection.java Thu Dec 1 10:31:03 2011
@@ -22,6 +22,7 @@

 import java.sql.*;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
@@ -407,11 +408,69 @@
* @throws SchemaDisagreementException when the client side and server side are at different versions of schema (Thrift) * @throws TException when there is a error in Thrift processing
      */
- protected CqlResult execute(String queryStr) throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException, TException
+    protected CqlResult execute(String queryStr)
+ throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException, TException
     {
         return execute(queryStr, defaultCompression);
     }

+    protected CqlResult execute(int itemId, List<CqlBindValue> values)
+ throws InvalidRequestException, UnavailableException, TimedOutException, SchemaDisagreementException, TException
+    {
+        try
+        {
+            return client.execute_prepared_cql_query(itemId, values);
+        }
+        catch (TException error)
+        {
+            numFailures++;
+            timeOfLastFailure = System.currentTimeMillis();
+            throw error;
+        }
+    }
+
+ protected CqlPreparedResult prepare(String queryStr, Compression compression)throws InvalidRequestException, TException
+    {
+        try
+        {
+ return client.prepare_cql_query(Utils.compressQuery(queryStr, compression), compression);
+        }
+        catch (TException error)
+        {
+            numFailures++;
+            timeOfLastFailure = System.currentTimeMillis();
+            throw error;
+        }
+    }
+
+ protected CqlPreparedResult prepare(String queryStr) throws InvalidRequestException, TException
+    {
+        try
+        {
+            return prepare(queryStr, defaultCompression);
+        }
+        catch (TException error)
+        {
+            numFailures++;
+            timeOfLastFailure = System.currentTimeMillis();
+            throw error;
+        }
+    }
+
+ protected void release(int itemId) throws InvalidRequestException, TException
+    {
+        try
+        {
+            client.remove_prepared_cql_query(itemId);
+        }
+        catch (TException error)
+        {
+            numFailures++;
+            timeOfLastFailure = System.currentTimeMillis();
+            throw error;
+        }
+    }
+
     /**
      * Remove a Statement from the Open Statements List
      */
=======================================
--- /src/main/java/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java Mon Nov 21 14:56:04 2011 +++ /src/main/java/org/apache/cassandra/cql/jdbc/CassandraPreparedStatement.java Thu Dec 1 10:31:03 2011
@@ -1,4 +1,3 @@
-package org.apache.cassandra.cql.jdbc;
 /*
  *
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -19,14 +18,23 @@
  * under the License.
  *
  */
-
+package org.apache.cassandra.cql.jdbc;
+
+import static org.apache.cassandra.cql.jdbc.Utils.NO_RESULTSET;
+import static org.apache.cassandra.cql.jdbc.Utils.NO_SERVER;
+import static org.apache.cassandra.cql.jdbc.Utils.NO_UPDATE_COUNT;
+import static org.apache.cassandra.cql.jdbc.Utils.SCHEMA_MISMATCH;
 import static org.apache.cassandra.cql.jdbc.Utils.determineCurrentKeyspace;
import static org.apache.cassandra.cql.jdbc.Utils.determineCurrentColumnFamily;
 import static org.apache.cassandra.cql.jdbc.Utils.NO_CF;
 import static org.apache.cassandra.cql.jdbc.Utils.NO_COMPARATOR;
 import static org.apache.cassandra.cql.jdbc.Utils.NO_VALIDATOR;

+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
 import java.io.Reader;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -46,6 +54,11 @@
 import java.sql.SQLDataException;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLNonTransientException;
+import java.sql.SQLRecoverableException;
+import java.sql.SQLSyntaxErrorException;
+import java.sql.SQLTransientConnectionException;
 import java.sql.SQLTransientException;
 import java.sql.SQLXML;
 import java.sql.Time;
@@ -53,500 +66,398 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;

+import org.apache.cassandra.thrift.CqlBindValue;
+import org.apache.cassandra.thrift.CqlPreparedResult;
+import org.apache.cassandra.thrift.CqlResult;
+import org.apache.cassandra.thrift.CqlStatementType;
+import org.apache.cassandra.thrift.InvalidRequestException;
+import org.apache.cassandra.thrift.SchemaDisagreementException;
+import org.apache.cassandra.thrift.TimedOutException;
+import org.apache.cassandra.thrift.UnavailableException;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.thrift.TException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
class CassandraPreparedStatement extends CassandraStatement implements PreparedStatement
 {
- // private static final Pattern Parameterizable = Pattern.compile("(SELECT|DELETE|UPDATE)\\s+.*", Pattern.CASE_INSENSITIVE); - private static final Pattern Select = Pattern.compile("SELECT[\\s+FIRST\\s+\\d+]?[\\s+REVERSED]?\\s+(.*)WHERE\\s+(.*)", Pattern.CASE_INSENSITIVE); - private static final Pattern Update = Pattern.compile("UPDATE\\s+\\w+.*\\s+SET\\s+(.*)\\s+WHERE KEY(.*)", Pattern.CASE_INSENSITIVE); - private static final Pattern Delete = Pattern.compile("DELETE\\s+(.*)\\s+FROM\\s+\\w+\\s+WHERE KEY(.*)", Pattern.CASE_INSENSITIVE);
-
-    // current set of bound variables.
- private final Map<Integer, Object> variables = new HashMap<Integer, Object>();
-
- // for batching. These are the queries that have been batched and not executed.
-    private final List<String> queries = new ArrayList<String>();
-
+ private static final Logger LOG = LoggerFactory.getLogger(CassandraPreparedStatement.class);
+
+ /** the statement type (SELECT,INSERT,..) from the parse of the CQL in the server-side */
+    private CqlStatementType type;
+
+ /** the key token passed back from server-side to identify the prepared statement */
+    private int itemId;
+
+ /** the count of bound variable markers (?) encountered in the parse o the CQL server-side */
+    private int count;
+
+    /** a Map of the current bound values encountered in setXXX methods */
+ private Map<Integer,CqlBindValue> bindValues = new LinkedHashMap<Integer,CqlBindValue>();
+
+
CassandraPreparedStatement(CassandraConnection con, String cql) throws SQLException
     {
         super(con, cql);
-    }
-
-    // impl specific methods start here.
-
-    // double quotes strings (in parameters)
-    private static String makeCqlString(String s)
-    {
-        // escape any single-quotes with double single-quotes.
-        return s.replaceAll("\'", "\'\'");
-    }
-
- // null type means just call param.toString() and quote it (default for keys). - private static String applySimpleBindings(String q, AbstractJdbcType type, ParameterIterator params) throws SQLException
-    {
-        assert type != null;
- // we need to keep track of whether or not we are between quotes and ignore any question marks within them
-        // so that they are not substituted.
-        StringBuffer sb = new StringBuffer();
-        boolean between = false;
-        for (char c : q.toCharArray())
-        {
-            if (c == '\'')
-                between = !between;
-            if (between)
-                sb.append(c);
-            else if (c == '?') // !between if we got here.
-            {
-                try
-                {
-                    // perform substitution!
-                    Object param = params.nextParam();
- String stringParam = type == null ? param.toString() : type.toString(param);
-                    stringParam = makeCqlString(stringParam);
-                    if (type == null || type.needsQuotes())
-                        stringParam = "'" + stringParam + "'";
-                    sb.append(stringParam);
-                }
-                catch (ClassCastException ex)
-                {
- throw new SQLException("Mismatched types: " + ex.getLocalizedMessage());
-                }
-            }
-            else
-                sb.append(c);
-
-        }
-        return sb.toString();
-    }
-
- private static String applyDualBindings(String q, AbstractJdbcType ltype, AbstractJdbcType rtype, ParameterIterator params) throws SQLException
-    {
-        StringBuffer sb = new StringBuffer();
-        boolean between = false;
- boolean left = true; // we always start on the left-hand side of a statement. we switch state if we reach a comma and we are not between.
-        for (char c : q.toCharArray())
-        {
-            if (c == '\'')
-                between = !between;
-            if (c == '=' && !between)
-                left = false;
-            if (c == ',' && !between)
-                left = true;
-
-            if (c == '?' && !between)
-            {
-                try
-                {
-                    Object param = params.nextParam();
-                    AbstractJdbcType type = left ? ltype : rtype;
- String stringParam = makeCqlString(type.toString(param));
-                    if (type.needsQuotes())
-                        stringParam = "'" + stringParam + "'";
-                    sb.append(stringParam);
-                }
-                catch (ClassCastException ex)
-                {
- throw new SQLException("Mismatched types: " + ex.getLocalizedMessage());
-                }
-            }
-            else
-                sb.append(c);
-        }
-        return sb.toString();
+        if (LOG.isTraceEnabled()) LOG.trace("CQL: "+ this.cql);
+        try
+        {
+            CqlPreparedResult result = con.prepare(cql);
+
+            type = result.type;
+            itemId = result.itemId;
+            count = result.count;
+        }
+        catch (InvalidRequestException e)
+        {
+            throw new SQLSyntaxErrorException(e);
+        }
+         catch (TException e)
+        {
+            throw new SQLNonTransientConnectionException(e);
+        }
     }

-    /**
- * applies current bindings to produce a string that can be sent to the server.
-     */
-    public synchronized String makeCql() throws SQLException
-    {
-        // break cql up
-        Matcher m;
-        m = Delete.matcher(cql);
-        if (m.matches())
-            return makeDelete(m.end(1));
-        m = Update.matcher(cql);
-        if (m.matches())
-            return makeUpdate(m.end(1));
-        m = Select.matcher(cql);
-        if (m.matches())
-            return makeSelect(m.end(1));
-
- // if we made it this far, cql is not parameterizable. this isn't bad, there is just nothing to be done.
-        return cql;
-    }
-
-    // subs parameters into a delete statement.
-    private String makeDelete(int pivot) throws SQLException
-    {
- String keyspace = determineCurrentKeyspace(cql, connection.currentKeyspace);
-        String columnFamily = determineCurrentColumnFamily(cql);
-        if (columnFamily == null) throw new SQLTransientException(NO_CF);
-
-        ParameterIterator params = new ParameterIterator();
-        String left = cql.substring(0, pivot);
- AbstractJdbcType leftType = connection.decoder.getComparator(keyspace, columnFamily); - if (leftType == null) throw new SQLDataException(String.format(NO_COMPARATOR, keyspace, columnFamily));
-        left = applySimpleBindings(left, leftType, params);
-
-        String right = cql.substring(pivot);
- AbstractJdbcType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily); - if (keyVald == null) throw new SQLDataException(String.format(NO_VALIDATOR, keyspace, columnFamily));
-        right = applySimpleBindings(right, keyVald, params);
-        return left + right;
+    private final void checkIndex(int index) throws SQLException
+    {
+ if (index > count ) throw new SQLRecoverableException(String.format("the column index : %d is greater than the count of bound variable markers in the CQL: %d", index,count)); + if (index < 1 ) throw new SQLRecoverableException(String.format("the column index must be a positive number : %d", index));
+    }
+
+    private List<CqlBindValue> getBindValues() throws SQLException
+    {
+        List<CqlBindValue> values = new ArrayList<CqlBindValue>();
+//        System.out.println("bindValues.size() = "+bindValues.size());
+//        System.out.println("count             = "+count);
+        if (bindValues.size() != count )
+ throw new SQLRecoverableException(String.format("the number of bound variables: %d must match the count of bound variable markers in the CQL: %d", bindValues.size(),count));
+
+        for (int i = 1; i <= count ; i++)
+        {
+            CqlBindValue value = bindValues.get(i);
+ if (value==null) throw new SQLRecoverableException(String.format("the bound value for index: %d was not set", i));
+           values.add(value);
+        }
+        return values;
     }

-    // subs parameters into a select statement.
-    private String makeSelect(int pivot) throws SQLException
-    {
- String keyspace = determineCurrentKeyspace(cql, connection.currentKeyspace);
-        String columnFamily = determineCurrentColumnFamily(cql);
-        if (columnFamily == null) throw new SQLTransientException(NO_CF);
-
-        ParameterIterator params = new ParameterIterator();
-        String left = cql.substring(0, pivot);
- AbstractJdbcType leftType = connection.decoder.getComparator(keyspace, columnFamily); - if (leftType == null) throw new SQLDataException(String.format(NO_COMPARATOR, keyspace, columnFamily));
-        left = applySimpleBindings(left, leftType, params);
-
-        String right = cql.substring(pivot);
- AbstractJdbcType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily); - if (keyVald == null) throw new SQLDataException(String.format(NO_VALIDATOR, keyspace, columnFamily));
-        right = applySimpleBindings(right, keyVald, params);
-        return left + right;
-    }
-
-    // subs parameters into an update statement.
-    private String makeUpdate(int pivot) throws SQLException
-    {
- // this one is a little bit different. left contains key=value pairs. we use the comparator for the left side, - // the validator for the right side. right side is treated as a key. - String keyspace = determineCurrentKeyspace(cql, connection.currentKeyspace);
-        String columnFamily = determineCurrentColumnFamily(cql);
-        if (columnFamily == null) throw new SQLTransientException(NO_CF);
-
-        ParameterIterator params = new ParameterIterator();
-        String left = cql.substring(0, pivot);
- AbstractJdbcType leftComp = connection.decoder.getComparator(keyspace, columnFamily); - if (leftComp == null) throw new SQLDataException(String.format(NO_COMPARATOR, keyspace, columnFamily)); - AbstractJdbcType leftVald = connection.decoder.getDefaultValidator(keyspace, columnFamily); - if (leftVald == null) throw new SQLDataException(String.format(NO_VALIDATOR, keyspace, columnFamily));
-        left = applyDualBindings(left, leftComp, leftVald, params);
-
-        String right = cql.substring(pivot);
- AbstractJdbcType keyVald = connection.decoder.getKeyValidator(keyspace, columnFamily); - if (keyVald == null) throw new SQLDataException(String.format(NO_VALIDATOR, keyspace, columnFamily));
-        right = applySimpleBindings(right, keyVald, params);
-        return left + right;
-    }
-
-
-    // standard API methods follow.
-
+    public void close() throws SQLException
+    {
+        connection.removeStatement(this);
+        try
+        {
+            connection.release(itemId);
+        }
+        catch (InvalidRequestException e)
+        {
+            throw new SQLSyntaxErrorException(e);
+        }
+         catch (TException e)
+        {
+            throw new SQLNonTransientConnectionException(e);
+        }
+
+        connection = null;
+    }
+
+    private void doExecute() throws SQLException
+    {
+        if (LOG.isTraceEnabled()) LOG.trace("CQL: "+ cql);
+       try
+        {
+            resetResults();
+            CqlResult result = connection.execute(itemId, getBindValues());
+            String keyspace = connection.currentKeyspace;
+
+            switch (result.getType())
+            {
+                case ROWS:
+ currentResultSet = new CResultSet(this, result, keyspace);
+                    break;
+                case INT:
+                    updateCount = result.getNum();
+                    break;
+                case VOID:
+                    updateCount = 0;
+                    break;
+            }
+        }
+        catch (InvalidRequestException e)
+        {
+            throw new SQLSyntaxErrorException(e.getWhy());
+        }
+        catch (UnavailableException e)
+        {
+            throw new SQLNonTransientConnectionException(NO_SERVER, e);
+        }
+        catch (TimedOutException e)
+        {
+            throw new SQLTransientConnectionException(e.getMessage());
+        }
+        catch (SchemaDisagreementException e)
+        {
+            throw new SQLRecoverableException(SCHEMA_MISMATCH);
+        }
+        catch (TException e)
+        {
+            throw new SQLNonTransientConnectionException(e.getMessage());
+        }
+    }
+
     public void addBatch() throws SQLException
     {
-        queries.add(makeCql());
+        // TODO Auto-generated method stub
+
     }

-    public synchronized void clearParameters() throws SQLException
-    {
-        variables.clear();
-    }
-
-    public boolean execute() throws SQLException
-    {
-        return this.cql != null && super.execute(makeCql());
+
+    public void clearParameters() throws SQLException
+    {
+        checkNotClosed();
+        bindValues.clear();
     }

-    public ResultSet executeQuery() throws SQLException
-    {
-        return this.cql == null ? null : super.executeQuery(makeCql());
-    }
-
-    public int executeUpdate() throws SQLException
-    {
-        return this.cql == null ? 0 : super.executeUpdate(makeCql());
+
+    public boolean execute() throws SQLException
+    {
+        checkNotClosed();
+        doExecute();
+        return !(currentResultSet == null);
     }

-    public ResultSetMetaData getMetaData() throws SQLException
-    {
- // todo: current impl of RSMD relies on knowing the results. implementing this will require refactoring CRSMD into - // two classes: the first will be an implementation whose methods don't rely on knowing the results, the second - // will implement the full CRSMD interface and extend or compose the first. - throw new SQLFeatureNotSupportedException("PreparedStatement.getMetaData() hasn't been implemented yet.");
-    }
-
-    public void setByte(int parameterIndex, byte x) throws SQLException
-    {
-        setObject(parameterIndex, new byte[]{ x });
+
+    public ResultSet executeQuery() throws SQLException
+    {
+        checkNotClosed();
+        doExecute();
+ if (currentResultSet == null) throw new SQLNonTransientException(NO_RESULTSET);
+        return currentResultSet;
     }

-    public void setBytes(int parameterIndex, byte[] x) throws SQLException
-    {
-        setObject(parameterIndex, ByteBuffer.wrap(x));
-    }
-
-    public void setInt(int parameterIndex, int x) throws SQLException
-    {
-        setObject(parameterIndex, new BigInteger(Integer.toString(x)));
-    }
-
-    public void setLong(int parameterIndex, long x) throws SQLException
-    {
-        setObject(parameterIndex, x);
-    }
-
- public void setNString(int parameterIndex, String value) throws SQLException
-    {
-        setString(parameterIndex, value);
+
+    public int executeUpdate() throws SQLException
+    {
+        checkNotClosed();
+        doExecute();
+ if (currentResultSet != null) throw new SQLNonTransientException(NO_UPDATE_COUNT);
+        return updateCount;
+     }
+
+
+    public ResultSetMetaData getMetaData() throws SQLException
+    {
+        // TODO Auto-generated method stub
+        return null;
     }

-    public void setObject(int parameterIndex, Object x) throws SQLException
-    {
-        variables.put(parameterIndex, x);
-    }
-
- public void setRowId(int parameterIndex, RowId rowid) throws SQLException
-    {
-        setObject(parameterIndex, ByteBuffer.wrap(rowid.getBytes()));
+
+    public ParameterMetaData getParameterMetaData() throws SQLException
+    {
+        // TODO Auto-generated method stub
+        return null;
     }

-    public void setShort(int parameterIndex, short x) throws SQLException
-    {
-        setInt(parameterIndex, x);
-    }
-
-    public void setString(int parameterIndex, String x) throws SQLException
-    {
-        setObject(parameterIndex, x);
+
+ public void setBigDecimal(int parameterIndex, BigDecimal decimal) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(decimal.toPlainString())));
     }


- // everything below here is not implemented and will let you know about it.
-
-
-    public ParameterMetaData getParameterMetaData() throws SQLException
-    {
- throw new SQLFeatureNotSupportedException("PreparedStatement.getParameterMetaData() hasn't been implemented yet."); + public void setBoolean(int parameterIndex, boolean truth) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Boolean.valueOf(truth).toString())));
     }

-    public void setArray(int parameterIndex, Array x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+    public void setByte(int parameterIndex, byte b) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Byte.valueOf(b).toString())));
     }

- public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setBytes(int parameterIndex, byte[] bytes) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(true, ByteBuffer.wrap(bytes)));
     }

- public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+    public void setDate(int parameterIndex, Date value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ // date type data is handled as an 8 byte Long value of milliseconds since the epoch
+        String millis = Long.valueOf(value.getTime()).toString();
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(millis)));
     }

- public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setDate(int parameterIndex, Date date, Calendar cal) throws SQLException
+    {
+ // silently ignore the calendar argument it is not useful for the Cassandra implementation
+        setDate(parameterIndex,date);
     }

-    public void setBlob(int parameterIndex, Blob x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setDouble(int parameterIndex, double decimal) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Double.valueOf(decimal).toString())));
     }

- public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setBoolean(int parameterIndex, boolean x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setFloat(int parameterIndex, float decimal) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Float.valueOf(decimal).toString())));
     }

- public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+    public void setInt(int parameterIndex, int integer) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Integer.valueOf(integer).toString())));
     }

- public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
-    public void setClob(int parameterIndex, Clob x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException("method not supported");
+
+ public void setLong(int parameterIndex, long bigint) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Long.valueOf(bigint).toString())));
     }

- public void setClob(int parameterIndex, Reader reader) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setClob(int parameterIndex, Reader reader, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setNString(int parameterIndex, String value) throws SQLException
+    {
+        // treat like a String
+        setString(parameterIndex,value);
     }

-    public void setDate(int parameterIndex, Date x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setNull(int parameterIndex, int sqlType) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+        // silently ignore type for cassandra... just store an empty BB
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.EMPTY_BYTE_BUFFER));
     }

-    public void setDouble(int parameterIndex, double x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
-    public void setFloat(int parameterIndex, float x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException
+    {
+ // silently ignore type and type name for cassandra... just store an empty BB
+        setNull(parameterIndex,sqlType);
     }

- public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setNClob(int parameterIndex, NClob value) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setObject(int parameterIndex, Object object) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+
+        byte[] bytes = null;
+        try
+        {
+            // Serialize to a byte array
+            ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
+            ObjectOutput out = new ObjectOutputStream(bos) ;
+            out.writeObject(object);
+            out.close();
+
+            // Get the bytes of the serialized object
+            bytes = bos.toByteArray();
+        }
+        catch (IOException e)
+        {
+ throw new SQLNonTransientException("Problem serializing the object", e);
+        }
+
+ bindValues.put(parameterIndex, new CqlBindValue(true, ByteBuffer.wrap(bytes)));
     }

- public void setNClob(int parameterIndex, Reader reader) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setRowId(int parameterIndex, RowId value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(true, ByteBuffer.wrap(value.getBytes())));
     }

- public void setNull(int parameterIndex, int sqlType) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setShort(int parameterIndex, short smallint) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(Short.valueOf(smallint).toString())));
     }

- public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setString(int parameterIndex, String value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(value)));
     }

-    public void setRef(int parameterIndex, Ref x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+    public void setTime(int parameterIndex, Time value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ // time type data is handled as an 8 byte Long value of milliseconds since the epoch
+        String millis = Long.valueOf(value.getTime()).toString();
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(millis)));
     }

-    public void setTime(int parameterIndex, Time x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setTime(int parameterIndex, Time value, Calendar cal) throws SQLException
+    {
+ // silently ignore the calendar argument it is not useful for the Cassandra implementation
+        setTime(parameterIndex,value);
     }

- public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setTimestamp(int parameterIndex, Timestamp value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+ // timestamp type data is handled as an 8 byte Long value of milliseconds since the epoch
+        String millis = Long.valueOf(value.getTime()).toString();
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(millis)));
     }

-    public void setURL(int parameterIndex, URL x) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
-    }
-
- public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
-    {
-        throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
+
+ public void setTimestamp(int parameterIndex, Timestamp value, Calendar cal) throws SQLException
+    {
+ // silently ignore the calendar argument it is not useful for the Cassandra implementation
+        setTimestamp(parameterIndex,value);
     }


-    // done with API methods.
-
-
- // provides a way to iterate through the parameters. it will blow up if it discovers any missing parameters.
-    // not thread-safe.
-    private class ParameterIterator
-    {
- private Map<Integer, Object> params = new HashMap<Integer, Object>(variables);
-        private int index = 1;
-
-        // throws SQLException if a parameter is not specified.
-        private Object nextParam() throws SQLException
-        {
-            Object p = params.get(index++);
-            if (p == null)
- throw new SQLException("No parameter bound to " + (index - 1));
-            return p;
-        }
+    public void setURL(int parameterIndex, URL value) throws SQLException
+    {
+        checkNotClosed();
+        checkIndex(parameterIndex);
+        // URl type data is handled as an string
+        String url = value.toString();
+ bindValues.put(parameterIndex, new CqlBindValue(false, ByteBufferUtil.bytes(url)));
     }
 }
=======================================
--- /src/main/java/org/apache/cassandra/cql/jdbc/CassandraStatement.java Mon Nov 21 14:56:04 2011 +++ /src/main/java/org/apache/cassandra/cql/jdbc/CassandraStatement.java Thu Dec 1 10:31:03 2011
@@ -125,7 +125,7 @@
         throw new SQLFeatureNotSupportedException(NO_BATCH);
     }

-    private final void checkNotClosed() throws SQLException
+    protected final void checkNotClosed() throws SQLException
     {
         if (isClosed()) throw new SQLRecoverableException(WAS_CLOSED_STMT);
     }
@@ -149,8 +149,7 @@
         connection = null;
         cql = null;
     }
-
-
+

     private void doExecute(String sql) throws SQLException
     {
@@ -368,7 +367,7 @@
         return false;
     }

-    private final void resetResults()
+    protected final void resetResults()
     {
         currentResultSet = null;
         updateCount = -1;
=======================================
--- /src/main/resources/log4j.properties        Mon Nov 21 14:37:51 2011
+++ /src/main/resources/log4j.properties        Thu Dec  1 10:31:03 2011
@@ -1,7 +1,7 @@
 #  Test Log4J Properties File

 log4j.rootLogger=WARN, stdout
-log4j.logger.org.apache.cassandra.cql.jdbc=INFO
+log4j.logger.org.apache.cassandra.cql.jdbc=TRACE

 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

==============================================================================
Revision: 174f0264f80a
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:36:57 2011
Log:      Update pom to use 1.1-dev-SNAPSHOT for testing
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=174f0264f80a

Modified:
 /pom.xml

=======================================
--- /pom.xml    Mon Nov  7 15:59:43 2011
+++ /pom.xml    Thu Dec  1 10:36:57 2011
@@ -98,7 +98,7 @@
     <dependency>
       <groupId>org.apache.cassandra</groupId>
       <artifactId>cassandra-thrift</artifactId>
-      <version>1.0.2</version>
+      <version>1.1-dev-SNAPSHOT</version>
       <exclusions>
         <exclusion>
           <groupId>javax.servlet</groupId>
@@ -113,7 +113,7 @@
     <dependency>
       <groupId>org.apache.cassandra</groupId>
       <artifactId>cassandra-clientutil</artifactId>
-      <version>1.0.2</version>
+      <version>1.1-dev-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>

==============================================================================
Revision: 259efa0caf1a
Author:   Rick Shaw <wfs...@gmail.com>
Date:     Thu Dec  1 10:38:15 2011
Log: Update PreparedStatementTest to remove implementation specific code
http://code.google.com/a/apache-extras.org/p/cassandra-jdbc/source/detail?r=259efa0caf1a

Modified:
 /src/test/java/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java

=======================================
--- /src/test/java/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java Thu Oct 13 01:56:33 2011 +++ /src/test/java/org/apache/cassandra/cql/jdbc/PreparedStatementTest.java Thu Dec 1 10:38:15 2011
@@ -38,7 +38,9 @@
 public class PreparedStatementTest
 {
     private static java.sql.Connection con = null;
- private static final Schema schema = new Schema(ConnectionDetails.getHost(), ConnectionDetails.getPort());
+
+// private static final Schema schema = new Schema(ConnectionDetails.getHost(), ConnectionDetails.getPort());
+    private static final Schema schema = new Schema("localhost", 9160);

     @BeforeClass
     public static void waxOn() throws Exception
@@ -46,6 +48,7 @@
         schema.createSchema();
         Class.forName("org.apache.cassandra.cql.jdbc.CassandraDriver");
con = DriverManager.getConnection(String.format("jdbc:cassandra://%s:%d/%s", ConnectionDetails.getHost(), ConnectionDetails.getPort(), Schema.KEYSPACE_NAME)); +// con = DriverManager.getConnection(String.format("jdbc:cassandra://%s:%d/%s", "localhost", 9160, Schema.KEYSPACE_NAME));
     }

     @Test
@@ -350,38 +353,6 @@
         }
     }

-    @Test
-    public void testParamSubstitution() throws SQLException
-    {
-        byte[] key = "key".getBytes();
-        String q = "SELECT 'fo??est', ?, ? from JdbcUtf8 WHERE KEY = ?";
- CassandraPreparedStatement stmt = (CassandraPreparedStatement)con.prepareStatement(q);
-        stmt.setString(1, "pathological param: ?'make it?? '' sto'p?'");
-        stmt.setString(2, "simple");
-        stmt.setBytes(3, key);
-        String qq = stmt.makeCql();
- assert qq.equals("SELECT 'fo??est', 'pathological param: ?''make it?? '''' sto''p?''', 'simple' from JdbcUtf8 WHERE KEY = '6b6579'");
-
- q = "UPDATE JdbcUtf8 USING CONSISTENCY ONE SET 'fru??us'=?, ?='gr''d?', ?=?, ?=? WHERE key=?";
-        stmt = (CassandraPreparedStatement)con.prepareStatement(q);
-        stmt.setString(1, "o?e");
-        stmt.setString(2, "tw'o");
-        stmt.setString(3, "thr'?'ee");
-        stmt.setString(4, "fo''?'ur");
-        stmt.setString(5, "five");
-        stmt.setString(6, "six");
-        stmt.setBytes(7, key);
-        qq = stmt.makeCql();
- assert qq.equals("UPDATE JdbcUtf8 USING CONSISTENCY ONE SET 'fru??us'='o?e', 'tw''o'='gr''d?', 'thr''?''ee'='fo''''?''ur', 'five'='six' WHERE key='6b6579'");
-
-        q = "DELETE ?, ? FROM JdbcUtf8 WHERE KEY=?";
-        stmt = (CassandraPreparedStatement)con.prepareStatement(q);
-        stmt.setString(1, "on'?'");
-        stmt.setString(2, "two");
-        stmt.setBytes(3, key);
-        qq = stmt.makeCql();
- assert qq.equals("DELETE 'on''?''', 'two' FROM JdbcUtf8 WHERE KEY='6b6579'");
-    }

     /**
      * Copy bytes from int into bytes starting from offset.

Reply via email to