You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2013/04/30 01:46:54 UTC

svn commit: r1477415 - in /jena/Experimental/jena-jdbc: jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/ jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/ jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/ ...

Author: rvesse
Date: Mon Apr 29 23:46:54 2013
New Revision: 1477415

URL: http://svn.apache.org/r1477415
Log:
More work on adding PreparedStatement support

Added:
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/DatasetPreparedStatement.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/JenaParameterMetadata.java
Modified:
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaPreparedStatement.java
    jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java?rev=1477415&r1=1477414&r2=1477415&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/DatasetConnection.java Mon Apr 29 23:46:54 2013
@@ -18,12 +18,12 @@
 
 package org.apache.jena.jdbc.connections;
 
-import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
 import org.apache.jena.jdbc.JdbcCompatibility;
+import org.apache.jena.jdbc.statements.DatasetPreparedStatement;
 import org.apache.jena.jdbc.statements.DatasetStatement;
+import org.apache.jena.jdbc.statements.JenaPreparedStatement;
 import org.apache.jena.jdbc.statements.JenaStatement;
 
 import com.hp.hpl.jena.query.Dataset;
@@ -87,10 +87,19 @@ public abstract class DatasetConnection 
         if (resultSetType != ResultSet.TYPE_FORWARD_ONLY)
             throw new SQLException("Dataset backed connections currently only supports forward-only result sets");
         if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
-            throw new SQLException("Database backed connections only supports read-only result sets");
+            throw new SQLException("Dataset backed connections only supports read-only result sets");
         return new DatasetStatement(this, ResultSet.FETCH_FORWARD, 0, resultSetHoldability, this.getAutoCommit(),
                 this.getTransactionIsolation());
     }
+    
+    @Override
+    protected JenaPreparedStatement createPreparedStatementInternal(String sparql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+        if (resultSetType != ResultSet.TYPE_FORWARD_ONLY)
+            throw new SQLException("Dataset backed connections currently only supports forward-only result sets");
+        if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
+            throw new SQLException("Dataset backed connections only supports read-only result sets");
+        return new DatasetPreparedStatement(sparql, this, ResultSet.FETCH_FORWARD, 0, resultSetHoldability, this.getAutoCommit(), this.getTransactionIsolation());
+    }
 
     @Override public boolean isClosed() throws SQLException {
         return this.ds == null;
@@ -105,37 +114,6 @@ public abstract class DatasetConnection 
     }
 
     @Override
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
-            throws SQLException {
-        throw new SQLFeatureNotSupportedException("Prepared statements are not yet supported for Jena JDBC");
-    }
-
-    @Override
     public void setReadOnly(boolean readOnly) throws SQLException {
         if (this.isClosed())
             throw new SQLException("Cannot set read-only mode on a closed connection");

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java?rev=1477415&r1=1477414&r2=1477415&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/connections/JenaConnection.java Mon Apr 29 23:46:54 2013
@@ -45,6 +45,7 @@ import java.util.Properties;
 import org.apache.jena.jdbc.JdbcCompatibility;
 import org.apache.jena.jdbc.metadata.JenaMetadata;
 import org.apache.jena.jdbc.preprocessing.CommandPreProcessor;
+import org.apache.jena.jdbc.statements.JenaPreparedStatement;
 import org.apache.jena.jdbc.statements.JenaStatement;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -465,24 +466,59 @@ public abstract class JenaConnection imp
     }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql) throws SQLException;
+    public PreparedStatement prepareStatement(String sql) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+    }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException;
+    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.prepareStatement(sql);
+    }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException;
+    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.prepareStatement(sql);
+    }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException;
+    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.prepareStatement(sql);
+    }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
-            throws SQLException;
+    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.prepareStatement(sql, resultSetType, resultSetConcurrency, this.holdability);
+    }
 
     @Override
-    public abstract PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
-            int resultSetHoldability) throws SQLException;
+    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+            throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        return this.createPreparedStatementInternal(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+    }
+    
+    /**
+     * Helper method which derived implementations must implement to provide an actual prepared statement implementation
+     * @param sql SPARQL command
+     * @param resultSetType Desired result set type
+     * @param resultSetConcurrency Result set concurrency
+     * @param resultSetHoldability Result set holdability
+     * @return Prepared statement
+     * @throws SQLException
+     */
+    protected abstract JenaPreparedStatement createPreparedStatementInternal(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+            throws SQLException;
 
     @Override
     public void releaseSavepoint(Savepoint savepoint) throws SQLException {

Added: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/DatasetPreparedStatement.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/DatasetPreparedStatement.java?rev=1477415&view=auto
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/DatasetPreparedStatement.java (added)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/DatasetPreparedStatement.java Mon Apr 29 23:46:54 2013
@@ -0,0 +1,125 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.jdbc.statements;
+
+import java.sql.SQLException;
+
+import org.apache.jena.jdbc.connections.DatasetConnection;
+
+import com.hp.hpl.jena.query.Dataset;
+import com.hp.hpl.jena.query.Query;
+import com.hp.hpl.jena.query.QueryExecution;
+import com.hp.hpl.jena.query.QueryExecutionFactory;
+import com.hp.hpl.jena.query.ReadWrite;
+import com.hp.hpl.jena.update.GraphStoreFactory;
+import com.hp.hpl.jena.update.UpdateExecutionFactory;
+import com.hp.hpl.jena.update.UpdateProcessor;
+import com.hp.hpl.jena.update.UpdateRequest;
+
+/**
+ * A Jena JDBC statement over a {@link Dataset}
+ * 
+ */
+public class DatasetPreparedStatement extends JenaPreparedStatement {
+
+    private DatasetConnection dsConn;
+
+    /**
+     * Creates a new statement
+     * 
+     * @param sparql
+     *            SPARQL command
+     * @param connection
+     *            Connection
+     * @throws SQLException
+     *             Thrown if there is an error with the statement parameters
+     */
+    public DatasetPreparedStatement(String sparql, DatasetConnection connection) throws SQLException {
+        this(sparql, connection, DEFAULT_FETCH_DIRECTION, DEFAULT_FETCH_SIZE, DEFAULT_HOLDABILITY, DEFAULT_AUTO_COMMIT,
+                DEFAULT_TRANSACTION_LEVEL);
+    }
+
+    /**
+     * Creates a new statement
+     * 
+     * @param sparql
+     *            SPARQL command
+     * @param connection
+     *            Connection
+     * @param fetchDir
+     *            Fetch Direction
+     * @param fetchSize
+     *            Fetch Size
+     * @param holdability
+     *            Result Set holdability
+     * @param autoCommit
+     *            Auto commit behaviour
+     * @param transactionLevel
+     *            Transaction level
+     * @throws SQLException
+     *             Thrown if there is an error with the statement parameters
+     * 
+     */
+    public DatasetPreparedStatement(String sparql, DatasetConnection connection, int fetchDir, int fetchSize, int holdability,
+            boolean autoCommit, int transactionLevel) throws SQLException {
+        super(sparql, connection, fetchDir, fetchSize, holdability, autoCommit, transactionLevel);
+        this.dsConn = connection;
+    }
+
+    /**
+     * Creates a query execution over the dataset
+     */
+    @Override
+    protected QueryExecution createQueryExecution(Query q) {
+        return QueryExecutionFactory.create(q, this.dsConn.getJenaDataset());
+    }
+
+    /**
+     * Creates an update execution over the dataset
+     */
+    @Override
+    protected UpdateProcessor createUpdateProcessor(UpdateRequest u) {
+        return UpdateExecutionFactory.create(u, GraphStoreFactory.create(this.dsConn.getJenaDataset()));
+    }
+
+    @Override
+    protected void beginTransaction(ReadWrite type) throws SQLException {
+        try {
+            this.dsConn.getJenaDataset().begin(type);
+        } catch (Exception e) {
+            throw new SQLException("Unexpected error starting a transaction", e);
+        }
+    }
+
+    @Override
+    protected void commitTransaction() throws SQLException {
+        this.dsConn.commit();
+    }
+
+    @Override
+    protected void rollbackTransaction() throws SQLException {
+        this.dsConn.rollback();
+    }
+
+    @Override
+    protected boolean hasActiveTransaction() throws SQLException {
+        return this.dsConn.getJenaDataset().isInTransaction();
+    }
+
+}

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaPreparedStatement.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaPreparedStatement.java?rev=1477415&r1=1477414&r2=1477415&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaPreparedStatement.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/JenaPreparedStatement.java Mon Apr 29 23:46:54 2013
@@ -41,36 +41,54 @@ import java.sql.Timestamp;
 import java.util.Calendar;
 
 import org.apache.jena.jdbc.connections.JenaConnection;
+import org.apache.jena.jdbc.statements.metadata.JenaParameterMetadata;
 
+import com.hp.hpl.jena.datatypes.TypeMapper;
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.graph.NodeFactory;
 import com.hp.hpl.jena.query.ParameterizedSparqlString;
+import com.hp.hpl.jena.sparql.util.NodeFactoryExtra;
+import com.hp.hpl.jena.vocabulary.XSD;
 
 /**
- * Abstract Jena JDBC implementation of a prepared statement 
- *
+ * Abstract Jena JDBC implementation of a prepared statement
+ * 
  */
 public abstract class JenaPreparedStatement extends JenaStatement implements PreparedStatement {
-    
+
     private ParameterizedSparqlString sparqlStr = new ParameterizedSparqlString();
+    private ParameterMetaData paramMetadata;
 
     /**
      * Creates a new prepared statement
+     * 
+     * @param sparql
      * @param connection
+     *            Connection
      * @param fetchDir
+     *            Fetch Direction
      * @param fetchSize
+     *            Fetch Size
      * @param holdability
+     *            Result Set holdability
      * @param autoCommit
+     *            Auto-commit
      * @param transactionLevel
+     *            Transaction Isolation level
      * @throws SQLException
+     *             Thrown if there is a problem preparing the statement
      */
-    public JenaPreparedStatement(JenaConnection connection, int fetchDir, int fetchSize, int holdability, boolean autoCommit,
-            int transactionLevel) throws SQLException {
+    public JenaPreparedStatement(String sparql, JenaConnection connection, int fetchDir, int fetchSize, int holdability,
+            boolean autoCommit, int transactionLevel) throws SQLException {
         super(connection, fetchDir, fetchSize, holdability, autoCommit, transactionLevel);
+
+        this.sparqlStr.setCommandText(sparql);
+        this.paramMetadata = new JenaParameterMetadata(this.sparqlStr);
     }
 
     @Override
     public void addBatch() throws SQLException {
-        // TODO Auto-generated method stub
-        
+        this.addBatch(this.sparqlStr.toString());
     }
 
     @Override
@@ -92,275 +110,275 @@ public abstract class JenaPreparedStatem
     public int executeUpdate() throws SQLException {
         return this.executeUpdate(this.sparqlStr.toString());
     }
-
+    
     @Override
     public ResultSetMetaData getMetaData() throws SQLException {
-        // TODO Auto-generated method stub
+        // Return null because we don't know in advance the column types
         return null;
     }
 
     @Override
     public ParameterMetaData getParameterMetaData() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
+        return this.paramMetadata;
+    }
+
+    protected final void setParameter(int parameterIndex, Node n) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (parameterIndex < 1 || parameterIndex > this.paramMetadata.getParameterCount())
+            throw new SQLException("Paramater Index is out of bounds");
+
+        this.sparqlStr.setParam(parameterIndex - 1, n);
     }
 
     @Override
-    public void setArray(int arg0, Array arg1) throws SQLException {
+    public void setArray(int parameterIndex, Array value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setAsciiStream(int arg0, InputStream arg1) throws SQLException {
+    public void setAsciiStream(int parameterIndex, InputStream value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setAsciiStream(int arg0, InputStream arg1, int arg2) throws SQLException {
+    public void setAsciiStream(int parameterIndex, InputStream value, int arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setAsciiStream(int arg0, InputStream arg1, long arg2) throws SQLException {
+    public void setAsciiStream(int parameterIndex, InputStream value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBigDecimal(int arg0, BigDecimal arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setBigDecimal(int parameterIndex, BigDecimal value) throws SQLException {
+        // TODO Auto generated method stub
     }
 
     @Override
-    public void setBinaryStream(int arg0, InputStream arg1) throws SQLException {
+    public void setBinaryStream(int parameterIndex, InputStream value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBinaryStream(int arg0, InputStream arg1, int arg2) throws SQLException {
+    public void setBinaryStream(int parameterIndex, InputStream value, int arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBinaryStream(int arg0, InputStream arg1, long arg2) throws SQLException {
+    public void setBinaryStream(int parameterIndex, InputStream value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBlob(int arg0, Blob arg1) throws SQLException {
+    public void setBlob(int parameterIndex, Blob value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBlob(int arg0, InputStream arg1) throws SQLException {
+    public void setBlob(int parameterIndex, InputStream value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBlob(int arg0, InputStream arg1, long arg2) throws SQLException {
+    public void setBlob(int parameterIndex, InputStream value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setBoolean(int arg0, boolean arg1) throws SQLException {
-        this.sparqlStr.setLiteral(arg0 - 1, arg1);
+    public void setBoolean(int parameterIndex, boolean value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactory.createLiteral(Boolean.toString(value), TypeMapper.getInstance().getSafeTypeByName(XSD.xboolean.getURI())));
     }
 
     @Override
-    public void setByte(int arg0, byte arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setByte(int parameterIndex, byte value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactory.createLiteral(Byte.toString(value), TypeMapper.getInstance().getSafeTypeByName(XSD.xbyte.getURI())));
     }
 
     @Override
-    public void setBytes(int arg0, byte[] arg1) throws SQLException {
+    public void setBytes(int parameterIndex, byte[] value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setCharacterStream(int arg0, Reader arg1) throws SQLException {
+    public void setCharacterStream(int parameterIndex, Reader value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setCharacterStream(int arg0, Reader arg1, int arg2) throws SQLException {
+    public void setCharacterStream(int parameterIndex, Reader value, int arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException {
+    public void setCharacterStream(int parameterIndex, Reader value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setClob(int arg0, Clob arg1) throws SQLException {
+    public void setClob(int parameterIndex, Clob value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setClob(int arg0, Reader arg1) throws SQLException {
+    public void setClob(int parameterIndex, Reader value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setClob(int arg0, Reader arg1, long arg2) throws SQLException {
+    public void setClob(int parameterIndex, Reader value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setDate(int arg0, Date arg1) throws SQLException {
+    public void setDate(int parameterIndex, Date value) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setDate(int arg0, Date arg1, Calendar arg2) throws SQLException {
+    public void setDate(int parameterIndex, Date value, Calendar arg2) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setDouble(int arg0, double arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setDouble(int parameterIndex, double value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactoryExtra.doubleToNode(value));
     }
 
     @Override
-    public void setFloat(int arg0, float arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setFloat(int parameterIndex, float value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactoryExtra.floatToNode(value));
     }
 
     @Override
-    public void setInt(int arg0, int arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setInt(int parameterIndex, int value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactoryExtra.intToNode(value));
     }
 
     @Override
-    public void setLong(int arg0, long arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setLong(int parameterIndex, long value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactoryExtra.intToNode(value));
     }
 
     @Override
-    public void setNCharacterStream(int arg0, Reader arg1) throws SQLException {
+    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setNCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException {
+    public void setNCharacterStream(int parameterIndex, Reader value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setNClob(int arg0, NClob arg1) throws SQLException {
+    public void setNClob(int parameterIndex, NClob value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setNClob(int arg0, Reader arg1) throws SQLException {
+    public void setNClob(int parameterIndex, Reader value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setNClob(int arg0, Reader arg1, long arg2) throws SQLException {
+    public void setNClob(int parameterIndex, Reader value, long arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setNString(int arg0, String arg1) throws SQLException {
-        throw new SQLFeatureNotSupportedException();
+    public void setNString(int parameterIndex, String value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactory.createLiteral(value));
     }
 
     @Override
-    public void setNull(int arg0, int arg1) throws SQLException {
-        throw new SQLFeatureNotSupportedException();
+    public void setNull(int parameterIndex, int value) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Parameters for SPARQL statements are not nullable");
     }
 
     @Override
-    public void setNull(int arg0, int arg1, String arg2) throws SQLException {
-        throw new SQLFeatureNotSupportedException();
+    public void setNull(int parameterIndex, int value, String arg2) throws SQLException {
+        throw new SQLFeatureNotSupportedException("Parameters for SPARQL statements are not nullable");
     }
 
     @Override
-    public void setObject(int arg0, Object arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setObject(int parameterIndex, Object value) throws SQLException {
+        if (value instanceof Node) {
+            this.setParameter(parameterIndex, (Node)value);
+        } else {
+            throw new SQLException("Calls to setObject() must pass an object of type Node");
+        }
     }
 
     @Override
-    public void setObject(int arg0, Object arg1, int arg2) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setObject(int parameterIndex, Object value, int arg2) throws SQLException {
+        throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setObject(int arg0, Object arg1, int arg2, int arg3) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setObject(int parameterIndex, Object value, int arg2, int arg3) throws SQLException {
+        throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setRef(int arg0, Ref arg1) throws SQLException {
+    public void setRef(int parameterIndex, Ref value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setRowId(int arg0, RowId arg1) throws SQLException {
+    public void setRowId(int parameterIndex, RowId value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setSQLXML(int arg0, SQLXML arg1) throws SQLException {
+    public void setSQLXML(int parameterIndex, SQLXML value) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 
     @Override
-    public void setShort(int arg0, short arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setShort(int parameterIndex, short value) throws SQLException {
+        this.setParameter(parameterIndex,
+                NodeFactory.createLiteral(Short.toString(value), TypeMapper.getInstance().getSafeTypeByName(XSD.xshort.getURI())));
     }
 
     @Override
-    public void setString(int arg0, String arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setString(int parameterIndex, String value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactory.createLiteral(value));
     }
 
     @Override
-    public void setTime(int arg0, Time arg1) throws SQLException {
+    public void setTime(int parameterIndex, Time value) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setTime(int arg0, Time arg1, Calendar arg2) throws SQLException {
+    public void setTime(int parameterIndex, Time value, Calendar arg2) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setTimestamp(int arg0, Timestamp arg1) throws SQLException {
+    public void setTimestamp(int parameterIndex, Timestamp value) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setTimestamp(int arg0, Timestamp arg1, Calendar arg2) throws SQLException {
+    public void setTimestamp(int parameterIndex, Timestamp value, Calendar arg2) throws SQLException {
         // TODO Auto-generated method stub
-        
+
     }
 
     @Override
-    public void setURL(int arg0, URL arg1) throws SQLException {
-        // TODO Auto-generated method stub
-        
+    public void setURL(int parameterIndex, URL value) throws SQLException {
+        this.setParameter(parameterIndex, NodeFactory.createURI(value.toString()));
     }
 
     @Deprecated
     @Override
-    public void setUnicodeStream(int arg0, InputStream arg1, int arg2) throws SQLException {
+    public void setUnicodeStream(int parameterIndex, InputStream value, int arg2) throws SQLException {
         throw new SQLFeatureNotSupportedException();
     }
 }

Added: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/JenaParameterMetadata.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/JenaParameterMetadata.java?rev=1477415&view=auto
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/JenaParameterMetadata.java (added)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/statements/metadata/JenaParameterMetadata.java Mon Apr 29 23:46:54 2013
@@ -0,0 +1,130 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jena.jdbc.statements.metadata;
+
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.Types;
+
+import org.apache.jena.atlas.iterator.Iter;
+import org.apache.jena.jdbc.statements.JenaPreparedStatement;
+
+import com.hp.hpl.jena.graph.Node;
+import com.hp.hpl.jena.query.ParameterizedSparqlString;
+
+/**
+ * Implementation of {@link ParameterMetaData} for {@link ParameterizedSparqlString} instances to support {@link JenaPreparedStatement}
+ *
+ */
+public class JenaParameterMetadata implements ParameterMetaData {
+    
+    private ParameterizedSparqlString sparqlStr;
+    private int paramCount;
+    
+    /**
+     * Creates new parameter metadata
+     * @param sparqlStr Parameterized SPARQL String
+     * @throws SQLException
+     */
+    public JenaParameterMetadata(ParameterizedSparqlString sparqlStr) throws SQLException {
+        if (sparqlStr == null) throw new SQLException("Parameterized SPARQL String cannot be null");
+        this.sparqlStr = sparqlStr;
+        this.paramCount = (int) Iter.count(this.sparqlStr.getEligiblePositionalParameters());
+    }
+
+    @Override
+    public boolean isWrapperFor(Class<?> arg0) throws SQLException {
+        throw new SQLFeatureNotSupportedException();
+    }
+
+    @Override
+    public <T> T unwrap(Class<T> arg0) throws SQLException {
+        throw new SQLFeatureNotSupportedException();
+    }
+
+    @Override
+    public String getParameterClassName(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // All parameters are typed as Node
+        return Node.class.getCanonicalName();
+    }
+
+    @Override
+    public int getParameterCount() throws SQLException {
+        return this.paramCount;
+    }
+
+    @Override
+    public int getParameterMode(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        return parameterModeIn;
+    }
+
+    @Override
+    public int getParameterType(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // Treat all parameters as being typed as Java Objects
+        return Types.JAVA_OBJECT;
+    }
+
+    @Override
+    public String getParameterTypeName(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // All parameters are typed as Node
+        return Node.class.getCanonicalName();
+    }
+
+    @Override
+    public int getPrecision(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // Return zero since parameters aren't typed as numerics
+        return 0;
+    }
+
+    @Override
+    public int getScale(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // Return zero since parameters aren't typed as numerics
+        return 0;
+    }
+
+    @Override
+    public int isNullable(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // Parameters are not nullable
+        return parameterNoNulls;
+    }
+
+    @Override
+    public boolean isSigned(int param) throws SQLException {
+        // Remember that JDBC used a 1 based index
+        if (param < 1 || param > this.paramCount) throw new SQLException("Parameter Index is out of bounds");
+        // Return false since parameters aren't typed as numerics
+        return false;
+    }
+
+}

Modified: jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java?rev=1477415&r1=1477414&r2=1477415&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-driver-remote/src/main/java/org/apache/jena/jdbc/remote/connections/RemoteEndpointConnection.java Mon Apr 29 23:46:54 2013
@@ -30,6 +30,7 @@ import org.apache.jena.jdbc.JdbcCompatib
 import org.apache.jena.jdbc.connections.JenaConnection;
 import org.apache.jena.jdbc.remote.metadata.RemoteEndpointMetadata;
 import org.apache.jena.jdbc.remote.statements.RemoteEndpointStatement;
+import org.apache.jena.jdbc.statements.JenaPreparedStatement;
 import org.apache.jena.jdbc.statements.JenaStatement;
 
 /**
@@ -182,6 +183,17 @@ public class RemoteEndpointConnection ex
             throw new SQLException("Remote endpoint backed connections only support read-only result sets");
         return new RemoteEndpointStatement(this, this.username, this.password, ResultSet.FETCH_FORWARD, 0, resultSetHoldability);
     }
+    
+    @Override
+    protected JenaPreparedStatement createPreparedStatementInternal(String sparql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+        if (this.isClosed())
+            throw new SQLException("Cannot create a statement after the connection was closed");
+        if (resultSetType != ResultSet.TYPE_FORWARD_ONLY)
+            throw new SQLException("Remote endpoint backed connection currently only support forward-only result sets");
+        if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY)
+            throw new SQLException("Remote endpoint backed connections only support read-only result sets");
+        throw new SQLFeatureNotSupportedException("Remote endpoint backed connections do not yet support prepared statements");
+    }
 
     @Override
     public boolean isClosed() throws SQLException {