db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From krist...@apache.org
Subject svn commit: r629734 [1/2] - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/client/net/ testing/org/apache/derby/client/ testing/org/apache/derby/client/am/
Date Thu, 21 Feb 2008 10:26:35 GMT
Author: kristwaa
Date: Thu Feb 21 02:26:31 2008
New Revision: 629734

URL: http://svn.apache.org/viewvc?rev=629734&view=rev
Log:
DERBY-3326, DERBY-3328: (partial) Introduce a caching logical connection and logical prepared statement in the client driver & Extend client JDBC object factory with methods to create objects required for statement pooling.
Adds the basic machinery to support statement pooling. There are known defects in the code, but no code has been enabled yet.
The most important defect is the action taken on statement reset, which is currently Statement.reset(true) (a full reset). This will be changed very soon.
Patch file: derby-3326-3c-new_classes.diff, derby-3328-1a-extend_jdbc_objectfactories.diff

Added:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java   (with props)
    db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java   (with props)
    db/derby/code/trunk/java/testing/org/apache/derby/client/
    db/derby/code/trunk/java/testing/org/apache/derby/client/am/
    db/derby/code/trunk/java/testing/org/apache/derby/client/am/LogicalStatementEntityTest.java   (with props)
Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/ClientJDBCObjectFactory.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/ClientJDBCObjectFactoryImpl.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/ClientJDBCObjectFactoryImpl40.java

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,192 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.CachingLogicalConnection
+
+   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.derby.client.am;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.apache.derby.client.ClientPooledConnection;
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * A logical connection used in a connection pool with capabilities for
+ * caching prepared statements.
+ * <p>
+ * An instance of this class is what is passed out the the client. It uses a
+ * JDBC statement object cache to avoid re-preparing commonly used queries.
+ * The cache has scope of a physical connection, and is lost when the pooled
+ * connection is closed (which includes closing the physical connection).
+ *
+ * @see StatementCacheInteractor
+ */
+public class CachingLogicalConnection
+    extends LogicalConnection {
+
+    /** JDBC statement cache interactor used to prepare statements and calls. */
+    private StatementCacheInteractor cacheInteractor;
+
+    /**
+     * Creates a new logical connection which caches prepared statements.
+     *
+     * @param physicalConnection underlying physical database connection
+     * @param pooledConnection associated pooled connection
+     * @param stmtCache associated statement cache
+     *
+     * @throws SqlException if creating the logical connection fails
+     */
+    public CachingLogicalConnection(Connection physicalConnection,
+                                    ClientPooledConnection pooledConnection,
+                                    JDBCStatementCache stmtCache)
+            throws SqlException {
+        super(physicalConnection, pooledConnection);
+        this.cacheInteractor =
+                new StatementCacheInteractor(stmtCache, physicalConnection);
+    }
+
+    public void close()
+            throws SQLException {
+        // Nullify reference to cache interactor to allow it to be GC'ed.
+        // It should not be used again when the logical connection is closed.
+        this.cacheInteractor = null;
+        super.close();
+    }
+
+    public synchronized PreparedStatement prepareStatement(String sql)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(sql);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(
+                    sql, resultSetType, resultSetConcurrency);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency,
+                                                int resultSetHoldability)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(
+                sql, resultSetType,resultSetConcurrency, resultSetHoldability);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int autoGeneratedKeys)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(sql, autoGeneratedKeys);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int[] columnIndexes)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        PreparedStatement ps = null;
+        if (columnIndexes != null && columnIndexes.length > 1) {
+            // This should probably be extended to use a separate type of
+            // statement key (instead of just saying its a statement which
+            // returns auto-generated keys), to force it throught the driver
+            // validation code.
+            // For now, disable statement pooling and fail in sane builds only,
+            // or in the relevant parts of the driver if still not supported.
+            ps = super.prepareStatement(sql, columnIndexes);
+            // If we get this far, the driver rest of the driver has extended
+            // its capabilities and this class is lagging behind...
+            if (SanityManager.DEBUG) {
+                SanityManager.THROWASSERT("CachingLogicalConnection is " +
+                        "missing the capability to handle prepareStatement " +
+                        "with an int array with more than one elemenet.");
+            }
+            // No caching being done, but we are able to continue.
+        } else {
+            ps = cacheInteractor.prepareStatement(
+                    sql, Statement.RETURN_GENERATED_KEYS);
+        }
+        return ps;
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                String[] columnNames)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        PreparedStatement ps = null;
+        if (columnNames != null && columnNames.length > 1) {
+            // This should probably be extended to use a separate type of
+            // statement key (instead of just saying its a statement which
+            // returns auto-generated keys), to force it throught the driver
+            // validation code.
+            // For now, disable statement pooling and fail in sane builds only,
+            // or in the relevant parts of the driver if still not supported.
+            ps = super.prepareStatement(sql, columnNames);
+            // If we get this far, the driver rest of the driver has extended
+            // its capabilities and this class is lagging behind...
+            if (SanityManager.DEBUG) {
+                SanityManager.THROWASSERT("CachingLogicalConnection is " +
+                        "missing the capability to handle prepareStatement " +
+                        "with a string array with more than one elemenet.");
+            }
+            // No caching being done, but we are able to continue.
+        } else {
+            ps = cacheInteractor.prepareStatement(
+                    sql, Statement.RETURN_GENERATED_KEYS);
+        }
+        return ps;
+    }
+
+    public synchronized CallableStatement prepareCall(String sql)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(sql);
+    }
+
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(
+                sql, resultSetType, resultSetConcurrency);
+    }
+
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency,
+                                                      int resultSetHoldability)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(
+                sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,187 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.CachingLogicalConnection40
+
+   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.derby.client.am;
+
+import java.sql.PreparedStatement;
+import java.sql.CallableStatement;
+import java.sql.SQLException;
+
+import org.apache.derby.client.ClientPooledConnection;
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * A logical connection used in a connection pool with capabilities for
+ * caching prepared statements.
+ *
+ * @see CachingLogicalConnection
+ */
+public class CachingLogicalConnection40
+    extends LogicalConnection40 {
+
+    /** JDBC statement cache interactor used to prepare statements and calls. */
+    private StatementCacheInteractor cacheInteractor;
+
+    /**
+     * Creates a new logical connection which caches prepared statements.
+     *
+     * @param physicalConnection underlying physical database connection
+     * @param pooledConnection associated pooled connection
+     * @param stmtCache associated statement cache
+     *
+     * @throws SqlException if creating the logical connection fails
+     */
+    public CachingLogicalConnection40(Connection physicalConnection,
+                                      ClientPooledConnection pooledConnection,
+                                      JDBCStatementCache stmtCache)
+            throws SqlException {
+        super(physicalConnection, pooledConnection);
+        this.cacheInteractor =
+                new StatementCacheInteractor(stmtCache, physicalConnection);
+    }
+
+    public void close()
+            throws SQLException {
+        // Nullify reference to cache interactor to allow it to be GC'ed.
+        // It should not be used again when the logical connection is closed.
+        this.cacheInteractor = null;
+        super.close();
+    }
+
+    public synchronized PreparedStatement prepareStatement(String sql)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(sql);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(
+                    sql, resultSetType, resultSetConcurrency);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency,
+                                                int resultSetHoldability)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(
+                sql, resultSetType,resultSetConcurrency, resultSetHoldability);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int autoGeneratedKeys)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareStatement(sql, autoGeneratedKeys);
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int[] columnIndexes)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        PreparedStatement ps = null;
+        if (columnIndexes != null && columnIndexes.length > 1) {
+            // This should probably be extended to use a separate type of
+            // statement key (instead of just saying its a statement which
+            // returns auto-generated keys), to force it throught the driver
+            // validation code.
+            // For now, disable statement pooling and fail in sane builds only,
+            // or in the relevant parts of the driver if still not supported.
+            ps = super.prepareStatement(sql, columnIndexes);
+            // If we get this far, the driver rest of the driver has extended
+            // its capabilities and this class is lagging behind...
+            if (SanityManager.DEBUG) {
+                SanityManager.THROWASSERT("CachingLogicalConnection is " +
+                        "missing the capability to handle prepareStatement " +
+                        "with an int array with more than one elemenet.");
+            }
+            // No caching being done, but we are able to continue.
+        } else {
+            ps = cacheInteractor.prepareStatement(
+                    sql, Statement.RETURN_GENERATED_KEYS);
+        }
+        return ps;
+    }
+
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                String[] columnNames)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        PreparedStatement ps = null;
+        if (columnNames != null && columnNames.length > 1) {
+            // This should probably be extended to use a separate type of
+            // statement key (instead of just saying its a statement which
+            // returns auto-generated keys), to force it throught the driver
+            // validation code.
+            // For now, disable statement pooling and fail in sane builds only,
+            // or in the relevant parts of the driver if still not supported.
+            ps = super.prepareStatement(sql, columnNames);
+            // If we get this far, the driver rest of the driver has extended
+            // its capabilities and this class is lagging behind...
+            if (SanityManager.DEBUG) {
+                SanityManager.THROWASSERT("CachingLogicalConnection is " +
+                        "missing the capability to handle prepareStatement " +
+                        "with a string array with more than one elemenet.");
+            }
+            // No caching being done, but we are able to continue.
+        } else {
+            ps = cacheInteractor.prepareStatement(
+                    sql, Statement.RETURN_GENERATED_KEYS);
+        }
+        return ps;
+    }
+
+    public synchronized CallableStatement prepareCall(String sql)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(sql);
+    }
+
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(
+                sql, resultSetType, resultSetConcurrency);
+    }
+
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency,
+                                                      int resultSetHoldability)
+            throws SQLException {
+        checkForNullPhysicalConnection();
+        return cacheInteractor.prepareCall(
+                sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/CachingLogicalConnection40.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ClientJDBCObjectFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ClientJDBCObjectFactory.java?rev=629734&r1=629733&r2=629734&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/ClientJDBCObjectFactory.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ClientJDBCObjectFactory.java Thu Feb 21 02:26:31 2008
@@ -25,6 +25,8 @@
 import org.apache.derby.client.ClientXAConnection;
 import org.apache.derby.jdbc.ClientDataSource;
 import java.sql.SQLException;
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
 import org.apache.derby.jdbc.ClientBaseDataSource;
 
 /**
@@ -98,6 +100,22 @@
                     ClientPooledConnection pooledConnection)
         throws SqlException;
     
+   /**
+    * Returns an instance of a {@code CachingLogicalConnection}, which
+    * provides caching of prepared statements.
+    *
+    * @param physicalConnection the underlying physical connection
+    * @param pooledConnection the pooled connection
+    * @param stmtCache statement cache
+    * @return A logical connection with statement caching capabilities.
+    *
+    * @throws SqlException if creation of the logical connection fails
+    */
+    public LogicalConnection newCachingLogicalConnection(
+            org.apache.derby.client.am.Connection physicalConnection,
+            ClientPooledConnection pooledConnection,
+            JDBCStatementCache stmtCache) throws SqlException;
+
     /**
      * This method returns an instance of PreparedStatement
      * (or PreparedStatement40) which implements java.sql.PreparedStatement
@@ -162,6 +180,32 @@
             throws SqlException;
     
     
+    /**
+     * Returns a new logcial prepared statement object.
+     *
+     * @param ps underlying physical prepared statement
+     * @param stmtKey key for the underlying physical prepared statement
+     * @param stmtCache the statement cache
+     * @return A logical prepared statement.
+     */
+    java.sql.PreparedStatement newLogicalPreparedStatement(
+            java.sql.PreparedStatement ps,
+            StatementKey stmtKey,
+            JDBCStatementCache stmtCache);
+
+    /**
+     * Returns a new logical callable statement object.
+     *
+     * @param cs underlying physical callable statement
+     * @param stmtKey key for the underlying physical callable statement
+     * @param stmtCache the statement cache
+     * @return A logical callable statement.
+     */
+    public java.sql.CallableStatement newLogicalCallableStatement(
+            java.sql.CallableStatement cs,
+            StatementKey stmtKey,
+            JDBCStatementCache stmtCache);
+
     /**
      * This method returns an instance of NetConnection (or NetConnection40) class
      * which extends from org.apache.derby.client.am.Connection

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,386 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.LogicalCallableStatement
+
+   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.derby.client.am;
+
+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.Ref;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+
+/**
+ * A wrapper class for a physical Derby callable statement.
+ * <p>
+ * The idea behind the logical prepared statement is to allow reuse of the
+ * physical callable statement. In general the logical entity will forward all
+ * calls to the physical entity. A few methods have special implementations, the
+ * most important one being {@link #close}. Each method will check that the
+ * logical statement is still open before the call is forwarded to the
+ * underlying physical statement.
+ *
+ * @see LogicalStatementEntity
+ */
+public class LogicalCallableStatement
+    extends LogicalPreparedStatement
+    implements java.sql.CallableStatement {
+
+    /**
+     * Creates a new logical callable statement.
+     *
+     * @param physicalCs underlying physical statement
+     * @param stmtKey key for the physical statement
+     * @param cache associated statement cache
+     * @throws IllegalArgumentException if {@code cache} is {@code null}
+     */
+    public LogicalCallableStatement(java.sql.CallableStatement physicalCs,
+                                    StatementKey stmtKey,
+                                    JDBCStatementCache cache) {
+        super(physicalCs, stmtKey, cache);
+    }
+
+    public boolean wasNull() throws SQLException {
+        return getPhysCs().wasNull();
+    }
+
+    public byte getByte(int parameterIndex) throws SQLException {
+        return getPhysCs().getByte(parameterIndex);
+    }
+
+    public double getDouble(int parameterIndex) throws SQLException {
+        return getPhysCs().getDouble(parameterIndex);
+    }
+
+    public float getFloat(int parameterIndex) throws SQLException {
+        return getPhysCs().getFloat(parameterIndex);
+    }
+
+    public int getInt(int parameterIndex) throws SQLException {
+        return getPhysCs().getInt(parameterIndex);
+    }
+
+    public long getLong(int parameterIndex) throws SQLException {
+        return getPhysCs().getLong(parameterIndex);
+    }
+
+    public short getShort(int parameterIndex) throws SQLException {
+        return getPhysCs().getShort(parameterIndex);
+    }
+
+    public boolean getBoolean(int parameterIndex) throws SQLException {
+        return getPhysCs().getBoolean(parameterIndex);
+    }
+
+    public byte[] getBytes(int parameterIndex) throws SQLException {
+        return getPhysCs().getBytes(parameterIndex);
+    }
+
+    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
+         getPhysCs().registerOutParameter(parameterIndex, sqlType);
+    }
+
+    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {
+         getPhysCs().registerOutParameter(parameterIndex, sqlType, scale);
+    }
+
+    public Object getObject(int parameterIndex) throws SQLException {
+        return getPhysCs().getObject(parameterIndex);
+    }
+
+    public String getString(int parameterIndex) throws SQLException {
+        return getPhysCs().getString(parameterIndex);
+    }
+
+    public void registerOutParameter(int paramIndex, int sqlType, String typeName) throws SQLException {
+         getPhysCs().registerOutParameter(paramIndex, sqlType, typeName);
+    }
+
+    public byte getByte(String parameterName) throws SQLException {
+        return getPhysCs().getByte(parameterName);
+    }
+
+    public double getDouble(String parameterName) throws SQLException {
+        return getPhysCs().getDouble(parameterName);
+    }
+
+    public float getFloat(String parameterName) throws SQLException {
+        return getPhysCs().getFloat(parameterName);
+    }
+
+    public int getInt(String parameterName) throws SQLException {
+        return getPhysCs().getInt(parameterName);
+    }
+
+    public long getLong(String parameterName) throws SQLException {
+        return getPhysCs().getLong(parameterName);
+    }
+
+    public short getShort(String parameterName) throws SQLException {
+        return getPhysCs().getShort(parameterName);
+    }
+
+    public boolean getBoolean(String parameterName) throws SQLException {
+        return getPhysCs().getBoolean(parameterName);
+    }
+
+    public byte[] getBytes(String parameterName) throws SQLException {
+        return getPhysCs().getBytes(parameterName);
+    }
+
+    public void setByte(String parameterName, byte x) throws SQLException {
+         getPhysCs().setByte(parameterName, x);
+    }
+
+    public void setDouble(String parameterName, double x) throws SQLException {
+         getPhysCs().setDouble(parameterName, x);
+    }
+
+    public void setFloat(String parameterName, float x) throws SQLException {
+         getPhysCs().setFloat(parameterName, x);
+    }
+
+    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {
+         getPhysCs().registerOutParameter(parameterName, sqlType);
+    }
+
+    public void setInt(String parameterName, int x) throws SQLException {
+         getPhysCs().setInt(parameterName, x);
+    }
+
+    public void setNull(String parameterName, int sqlType) throws SQLException {
+         getPhysCs().setNull(parameterName, sqlType);
+    }
+
+    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {
+         getPhysCs().registerOutParameter(parameterName, sqlType, scale);
+    }
+
+    public void setLong(String parameterName, long x) throws SQLException {
+         getPhysCs().setLong(parameterName, x);
+    }
+
+    public void setShort(String parameterName, short x) throws SQLException {
+         getPhysCs().setShort(parameterName, x);
+    }
+
+    public void setBoolean(String parameterName, boolean x) throws SQLException {
+         getPhysCs().setBoolean(parameterName, x);
+    }
+
+    public void setBytes(String parameterName, byte[] x) throws SQLException {
+         getPhysCs().setBytes(parameterName, x);
+    }
+
+    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
+        return getPhysCs().getBigDecimal(parameterIndex);
+    }
+
+    public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
+        return getPhysCs().getBigDecimal(parameterIndex, scale);
+    }
+
+    public URL getURL(int parameterIndex) throws SQLException {
+        return getPhysCs().getURL(parameterIndex);
+    }
+
+    public Array getArray(int i) throws SQLException {
+        return getPhysCs().getArray(i);
+    }
+
+    public Blob getBlob(int i) throws SQLException {
+        return getPhysCs().getBlob(i);
+    }
+
+    public Clob getClob(int i) throws SQLException {
+        return getPhysCs().getClob(i);
+    }
+
+    public Date getDate(int parameterIndex) throws SQLException {
+        return getPhysCs().getDate(parameterIndex);
+    }
+
+    public Ref getRef(int i) throws SQLException {
+        return getPhysCs().getRef(i);
+    }
+
+    public Time getTime(int parameterIndex) throws SQLException {
+        return getPhysCs().getTime(parameterIndex);
+    }
+
+    public Timestamp getTimestamp(int parameterIndex) throws SQLException {
+        return getPhysCs().getTimestamp(parameterIndex);
+    }
+
+    public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {
+         getPhysCs().setAsciiStream(parameterName, x, length);
+    }
+
+    public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {
+         getPhysCs().setBinaryStream(parameterName, x, length);
+    }
+
+    public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {
+         getPhysCs().setCharacterStream(parameterName, reader, length);
+    }
+
+    public Object getObject(String parameterName) throws SQLException {
+        return getPhysCs().getObject(parameterName);
+    }
+
+    public void setObject(String parameterName, Object x) throws SQLException {
+         getPhysCs().setObject(parameterName, x);
+    }
+
+    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {
+         getPhysCs().setObject(parameterName, x, targetSqlType);
+    }
+
+    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {
+         getPhysCs().setObject(parameterName, x, targetSqlType, scale);
+    }
+
+    public Object getObject(int i, Map map) throws SQLException {
+        return getPhysCs().getObject(i, map);
+    }
+
+    public String getString(String parameterName) throws SQLException {
+        return getPhysCs().getString(parameterName);
+    }
+
+    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {
+         getPhysCs().registerOutParameter(parameterName, sqlType, typeName);
+    }
+
+    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {
+         getPhysCs().setNull(parameterName, sqlType, typeName);
+    }
+
+    public void setString(String parameterName, String x) throws SQLException {
+         getPhysCs().setString(parameterName, x);
+    }
+
+    public BigDecimal getBigDecimal(String parameterName) throws SQLException {
+        return getPhysCs().getBigDecimal(parameterName);
+    }
+
+    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {
+         getPhysCs().setBigDecimal(parameterName, x);
+    }
+
+    public URL getURL(String parameterName) throws SQLException {
+        return getPhysCs().getURL(parameterName);
+    }
+
+    public void setURL(String parameterName, URL val) throws SQLException {
+         getPhysCs().setURL(parameterName, val);
+    }
+
+    public Array getArray(String parameterName) throws SQLException {
+        return getPhysCs().getArray(parameterName);
+    }
+
+    public Blob getBlob(String parameterName) throws SQLException {
+        return getPhysCs().getBlob(parameterName);
+    }
+
+    public Clob getClob(String parameterName) throws SQLException {
+        return getPhysCs().getClob(parameterName);
+    }
+
+    public Date getDate(String parameterName) throws SQLException {
+        return getPhysCs().getDate(parameterName);
+    }
+
+    public void setDate(String parameterName, Date x) throws SQLException {
+         getPhysCs().setDate(parameterName, x);
+    }
+
+    public Date getDate(int parameterIndex, Calendar cal) throws SQLException {
+        return getPhysCs().getDate(parameterIndex, cal);
+    }
+
+    public Ref getRef(String parameterName) throws SQLException {
+        return getPhysCs().getRef(parameterName);
+    }
+
+    public Time getTime(String parameterName) throws SQLException {
+        return getPhysCs().getTime(parameterName);
+    }
+
+    public void setTime(String parameterName, Time x) throws SQLException {
+         getPhysCs().setTime(parameterName, x);
+    }
+
+    public Time getTime(int parameterIndex, Calendar cal) throws SQLException {
+        return getPhysCs().getTime(parameterIndex, cal);
+    }
+
+    public Timestamp getTimestamp(String parameterName) throws SQLException {
+        return getPhysCs().getTimestamp(parameterName);
+    }
+
+    public void setTimestamp(String parameterName, Timestamp x) throws SQLException {
+         getPhysCs().setTimestamp(parameterName, x);
+    }
+
+    public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {
+        return getPhysCs().getTimestamp(parameterIndex, cal);
+    }
+
+    public Object getObject(String parameterName, Map map) throws SQLException {
+        return getPhysCs().getObject(parameterName, map);
+    }
+
+    public Date getDate(String parameterName, Calendar cal) throws SQLException {
+        return getPhysCs().getDate(parameterName, cal);
+    }
+
+    public Time getTime(String parameterName, Calendar cal) throws SQLException {
+        return getPhysCs().getTime(parameterName, cal);
+    }
+
+    public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
+        return getPhysCs().getTimestamp(parameterName, cal);
+    }
+
+    public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {
+         getPhysCs().setDate(parameterName, x, cal);
+    }
+
+    public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {
+         getPhysCs().setTime(parameterName, x, cal);
+    }
+
+    public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {
+         getPhysCs().setTimestamp(parameterName, x, cal);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,352 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.LogicalCallableStatement40
+
+   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.derby.client.am;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.NClob;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+
+import org.apache.derby.shared.common.reference.SQLState;
+
+/**
+ * JDBC 4 specific wrapper class for a Derby physical callable statement.
+ *
+ * @see LogicalCallableStatement
+ * @see #isClosed
+ */
+public class LogicalCallableStatement40
+    extends LogicalCallableStatement {
+
+    /**
+     * Creates a new logical callable statement.
+     *
+     * @param physicalCs underlying physical statement
+     * @param stmtKey key for the physical statement
+     * @param cache associated statement cache
+     * @throws IllegalArgumentException if {@code cache} is {@code null}
+     */
+    public LogicalCallableStatement40(java.sql.CallableStatement physicalCs,
+                                      StatementKey stmtKey,
+                                      JDBCStatementCache cache) {
+        super(physicalCs, stmtKey, cache);
+    }
+
+    public void setRowId(int arg0, RowId arg1)
+            throws SQLException {
+         getPhysCs().setRowId(arg0, arg1);
+    }
+
+    public void setNString(int arg0, String arg1)
+            throws SQLException {
+         getPhysCs().setNString(arg0, arg1);
+    }
+
+    public void setNCharacterStream(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setNCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setNClob(int arg0, NClob arg1)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1);
+    }
+
+    public void setClob(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setClob(arg0, arg1, arg2);
+    }
+
+    public void setBlob(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setBlob(arg0, arg1, arg2);
+    }
+
+    public void setNClob(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1, arg2);
+    }
+
+    public void setSQLXML(int arg0, SQLXML arg1)
+            throws SQLException {
+         getPhysCs().setSQLXML(arg0, arg1);
+    }
+
+    public void setAsciiStream(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setAsciiStream(arg0, arg1, arg2);
+    }
+
+    public void setBinaryStream(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setBinaryStream(arg0, arg1, arg2);
+    }
+
+    public void setCharacterStream(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setAsciiStream(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setAsciiStream(arg0, arg1);
+    }
+
+    public void setBinaryStream(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setBinaryStream(arg0, arg1);
+    }
+
+    public void setCharacterStream(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setCharacterStream(arg0, arg1);
+    }
+
+    public void setNCharacterStream(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setNCharacterStream(arg0, arg1);
+    }
+
+    public void setClob(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setClob(arg0, arg1);
+    }
+
+    public void setBlob(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setBlob(arg0, arg1);
+    }
+
+    public void setNClob(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1);
+    }
+
+    public synchronized boolean isClosed()
+            throws SQLException {
+        // Note the extra synchronization.
+        boolean closed = isLogicalEntityClosed();
+        if (!closed) {
+            // Consult the underlying physical statement.
+            closed = getPhysCs().isClosed();
+        }
+        return closed;
+    }
+
+    public void setPoolable(boolean arg0)
+            throws SQLException {
+         getPhysCs().setPoolable(arg0);
+    }
+
+    public boolean isPoolable()
+            throws SQLException {
+        return getPhysCs().isPoolable();
+    }
+
+    public <T> T unwrap(Class<T> arg0)
+            throws SQLException {
+        try {
+            if (getPhysCs().isClosed()) {
+                throw (new SqlException(null,
+                    new ClientMessageId(SQLState.ALREADY_CLOSED),
+                                        "CallableStatement")).getSQLException();
+            }
+            return arg0.cast(this);
+        } catch (ClassCastException cce) {
+            throw new SqlException(
+                    null,
+                    new ClientMessageId(SQLState.UNABLE_TO_UNWRAP),
+                    arg0).getSQLException();
+        }
+    }
+
+    public boolean isWrapperFor(Class<?> arg0)
+            throws SQLException {
+        return getPhysCs().isWrapperFor(arg0);
+    }
+
+    public RowId getRowId(int arg0)
+            throws SQLException {
+        return getPhysCs().getRowId(arg0);
+    }
+
+    public RowId getRowId(String arg0)
+            throws SQLException {
+        return getPhysCs().getRowId(arg0);
+    }
+
+    public void setRowId(String arg0, RowId arg1)
+            throws SQLException {
+         getPhysCs().setRowId(arg0, arg1);
+    }
+
+    public void setNString(String arg0, String arg1)
+            throws SQLException {
+         getPhysCs().setNString(arg0, arg1);
+    }
+
+    public void setNCharacterStream(String arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setNCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setNClob(String arg0, NClob arg1)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1);
+    }
+
+    public void setClob(String arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setClob(arg0, arg1, arg2);
+    }
+
+    public void setBlob(String arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setBlob(arg0, arg1, arg2);
+    }
+
+    public void setNClob(String arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1, arg2);
+    }
+
+    public NClob getNClob(int arg0)
+            throws SQLException {
+        return getPhysCs().getNClob(arg0);
+    }
+
+    public NClob getNClob(String arg0)
+            throws SQLException {
+        return getPhysCs().getNClob(arg0);
+    }
+
+    public void setSQLXML(String arg0, SQLXML arg1)
+            throws SQLException {
+         getPhysCs().setSQLXML(arg0, arg1);
+    }
+
+    public SQLXML getSQLXML(int arg0)
+            throws SQLException {
+        return getPhysCs().getSQLXML(arg0);
+    }
+
+    public SQLXML getSQLXML(String arg0)
+            throws SQLException {
+        return getPhysCs().getSQLXML(arg0);
+    }
+
+    public String getNString(int arg0)
+            throws SQLException {
+        return getPhysCs().getNString(arg0);
+    }
+
+    public String getNString(String arg0)
+            throws SQLException {
+        return getPhysCs().getNString(arg0);
+    }
+
+    public Reader getNCharacterStream(int arg0)
+            throws SQLException {
+        return getPhysCs().getNCharacterStream(arg0);
+    }
+
+    public Reader getNCharacterStream(String arg0)
+            throws SQLException {
+        return getPhysCs().getNCharacterStream(arg0);
+    }
+
+    public Reader getCharacterStream(int arg0)
+            throws SQLException {
+        return getPhysCs().getCharacterStream(arg0);
+    }
+
+    public Reader getCharacterStream(String arg0)
+            throws SQLException {
+        return getPhysCs().getCharacterStream(arg0);
+    }
+
+    public void setBlob(String arg0, Blob arg1)
+            throws SQLException {
+         getPhysCs().setBlob(arg0, arg1);
+    }
+
+    public void setClob(String arg0, Clob arg1)
+            throws SQLException {
+         getPhysCs().setClob(arg0, arg1);
+    }
+
+    public void setAsciiStream(String arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setAsciiStream(arg0, arg1, arg2);
+    }
+
+    public void setBinaryStream(String arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setBinaryStream(arg0, arg1, arg2);
+    }
+
+    public void setCharacterStream(String arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysCs().setCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setAsciiStream(String arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setAsciiStream(arg0, arg1);
+    }
+
+    public void setBinaryStream(String arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setBinaryStream(arg0, arg1);
+    }
+
+    public void setCharacterStream(String arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setCharacterStream(arg0, arg1);
+    }
+
+    public void setNCharacterStream(String arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setNCharacterStream(arg0, arg1);
+    }
+
+    public void setClob(String arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setClob(arg0, arg1);
+    }
+
+    public void setBlob(String arg0, InputStream arg1)
+            throws SQLException {
+         getPhysCs().setBlob(arg0, arg1);
+    }
+
+    public void setNClob(String arg0, Reader arg1)
+            throws SQLException {
+         getPhysCs().setNClob(arg0, arg1);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalCallableStatement40.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,387 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.LogicalPreparedStatement
+
+   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.derby.client.am;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.util.Calendar;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.ParameterMetaData;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Time;
+import java.sql.Timestamp;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+
+/**
+ * A wrapper class for a physical Derby prepared statement.
+ * <p>
+ * The idea behind the logical prepared statement is to allow reuse of the
+ * physical prepared statement. In general the logical entity will forward all
+ * calls to the physical entity. A few methods have special implementations, the
+ * most important one being {@link #close}. Each method will check that the
+ * logical statement is still open before the call is forwarded to the
+ * underlying physical statement.
+ *
+ * @see LogicalStatementEntity
+ */
+public class LogicalPreparedStatement
+    extends LogicalStatementEntity
+    implements java.sql.PreparedStatement {
+
+    /**
+     * Creates a new logical prepared statement.
+     *
+     * @param physicalPs underlying physical statement
+     * @param stmtKey key for the physical statement
+     * @param cache associated statement cache
+     * @throws IllegalArgumentException if {@code cache} is {@code null}
+     */
+    public LogicalPreparedStatement(java.sql.PreparedStatement physicalPs,
+                                    StatementKey stmtKey,
+                                    JDBCStatementCache cache) {
+        super(physicalPs, stmtKey, cache);
+    }
+
+    public int executeUpdate() throws SQLException {
+        return getPhysPs().executeUpdate();
+    }
+
+    public void addBatch() throws SQLException {
+         getPhysPs().addBatch();
+    }
+
+    public void clearParameters() throws SQLException {
+         getPhysPs().clearParameters();
+    }
+
+    public boolean execute() throws SQLException {
+        return getPhysPs().execute();
+    }
+
+    public void setByte(int parameterIndex, byte x) throws SQLException {
+         getPhysPs().setByte(parameterIndex, x);
+    }
+
+    public void setDouble(int parameterIndex, double x) throws SQLException {
+         getPhysPs().setDouble(parameterIndex, x);
+    }
+
+    public void setFloat(int parameterIndex, float x) throws SQLException {
+         getPhysPs().setFloat(parameterIndex, x);
+    }
+
+    public void setInt(int parameterIndex, int x) throws SQLException {
+         getPhysPs().setInt(parameterIndex, x);
+    }
+
+    public void setNull(int parameterIndex, int sqlType) throws SQLException {
+         getPhysPs().setNull(parameterIndex, sqlType);
+    }
+
+    public void setLong(int parameterIndex, long x) throws SQLException {
+         getPhysPs().setLong(parameterIndex, x);
+    }
+
+    public void setShort(int parameterIndex, short x) throws SQLException {
+         getPhysPs().setShort(parameterIndex, x);
+    }
+
+    public void setBoolean(int parameterIndex, boolean x) throws SQLException {
+         getPhysPs().setBoolean(parameterIndex, x);
+    }
+
+    public void setBytes(int parameterIndex, byte[] x) throws SQLException {
+         getPhysPs().setBytes(parameterIndex, x);
+    }
+
+    public void setAsciiStream(int parameterIndex, InputStream x, int length)
+            throws SQLException {
+         getPhysPs().setAsciiStream(parameterIndex, x, length);
+    }
+
+    public void setBinaryStream(int parameterIndex, InputStream x, int length)
+            throws SQLException {
+         getPhysPs().setBinaryStream(parameterIndex, x, length);
+    }
+
+    public void setUnicodeStream(int parameterIndex, InputStream x, int length)
+            throws SQLException {
+         getPhysPs().setUnicodeStream(parameterIndex, x, length);
+    }
+
+    public void setCharacterStream(int parameterIndex, Reader reader, int length)
+            throws SQLException {
+         getPhysPs().setCharacterStream(parameterIndex, reader, length);
+    }
+
+    public void setObject(int parameterIndex, Object x) throws SQLException {
+         getPhysPs().setObject(parameterIndex, x);
+    }
+
+    public void setObject(int parameterIndex, Object x, int targetSqlType)
+                throws SQLException {
+         getPhysPs().setObject(parameterIndex, x, targetSqlType);
+    }
+
+    public void setObject(int parameterIndex, Object x,
+                          int targetSqlType, int scale)
+            throws SQLException {
+         getPhysPs().setObject(parameterIndex, x, targetSqlType, scale);
+    }
+
+    public void setNull(int paramIndex, int sqlType, String typeName)
+            throws SQLException {
+         getPhysPs().setNull(paramIndex, sqlType, typeName);
+    }
+
+    public void setString(int parameterIndex, String x) throws SQLException {
+         getPhysPs().setString(parameterIndex, x);
+    }
+
+    public void setBigDecimal(int parameterIndex, BigDecimal x)
+            throws SQLException {
+         getPhysPs().setBigDecimal(parameterIndex, x);
+    }
+
+    public void setURL(int parameterIndex, URL x) throws SQLException {
+         getPhysPs().setURL(parameterIndex, x);
+    }
+
+    public void setArray(int i, Array x) throws SQLException {
+         getPhysPs().setArray(i, x);
+    }
+
+    public void setBlob(int i, Blob x) throws SQLException {
+         getPhysPs().setBlob(i, x);
+    }
+
+    public void setClob(int i, Clob x) throws SQLException {
+         getPhysPs().setClob(i, x);
+    }
+
+    public void setDate(int parameterIndex, Date x) throws SQLException {
+         getPhysPs().setDate(parameterIndex, x);
+    }
+
+    public ParameterMetaData getParameterMetaData() throws SQLException {
+        return getPhysPs().getParameterMetaData();
+    }
+
+    public void setRef(int i, Ref x) throws SQLException {
+         getPhysPs().setRef(i, x);
+    }
+
+    public ResultSet executeQuery() throws SQLException {
+        return getPhysPs().executeQuery();
+    }
+
+    public ResultSetMetaData getMetaData() throws SQLException {
+        return getPhysPs().getMetaData();
+    }
+
+    public void setTime(int parameterIndex, Time x) throws SQLException {
+         getPhysPs().setTime(parameterIndex, x);
+    }
+
+    public void setTimestamp(int parameterIndex, Timestamp x)
+            throws SQLException {
+         getPhysPs().setTimestamp(parameterIndex, x);
+    }
+
+    public void setDate(int parameterIndex, Date x, Calendar cal)
+            throws SQLException {
+         getPhysPs().setDate(parameterIndex, x, cal);
+    }
+
+    public void setTime(int parameterIndex, Time x, Calendar cal)
+            throws SQLException {
+         getPhysPs().setTime(parameterIndex, x, cal);
+    }
+
+    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
+            throws SQLException {
+         getPhysPs().setTimestamp(parameterIndex, x, cal);
+    }
+
+    public int getFetchDirection() throws SQLException {
+        return getPhysPs().getFetchDirection();
+    }
+
+    public int getFetchSize() throws SQLException {
+        return getPhysPs().getFetchSize();
+    }
+
+    public int getMaxFieldSize() throws SQLException {
+        return getPhysPs().getMaxFieldSize();
+    }
+
+    public int getMaxRows() throws SQLException {
+        return getPhysPs().getMaxRows();
+    }
+
+    public int getQueryTimeout() throws SQLException {
+        return getPhysPs().getQueryTimeout();
+    }
+
+    public int getResultSetConcurrency() throws SQLException {
+        return getPhysPs().getResultSetConcurrency();
+    }
+
+    public int getResultSetHoldability() throws SQLException {
+        return getPhysPs().getResultSetHoldability();
+    }
+
+    public int getResultSetType() throws SQLException {
+        return getPhysPs().getResultSetType();
+    }
+
+    public int getUpdateCount() throws SQLException {
+        return getPhysPs().getUpdateCount();
+    }
+
+    public void cancel() throws SQLException {
+         getPhysPs().cancel();
+    }
+
+    public void clearBatch() throws SQLException {
+         getPhysPs().clearBatch();
+    }
+
+    public void clearWarnings() throws SQLException {
+         getPhysPs().clearWarnings();
+    }
+
+
+    public boolean getMoreResults() throws SQLException {
+        return getPhysPs().getMoreResults();
+    }
+
+    public int[] executeBatch() throws SQLException {
+        return getPhysPs().executeBatch();
+    }
+
+    public void setFetchDirection(int direction) throws SQLException {
+         getPhysPs().setFetchDirection(direction);
+    }
+
+    public void setFetchSize(int rows) throws SQLException {
+         getPhysPs().setFetchSize(rows);
+    }
+
+    public void setMaxFieldSize(int max) throws SQLException {
+         getPhysPs().setMaxFieldSize(max);
+    }
+
+    public void setMaxRows(int max) throws SQLException {
+         getPhysPs().setMaxRows(max);
+    }
+
+    public void setQueryTimeout(int seconds) throws SQLException {
+         getPhysPs().setQueryTimeout(seconds);
+    }
+
+    public boolean getMoreResults(int current) throws SQLException {
+        return getPhysPs().getMoreResults(current);
+    }
+
+    public void setEscapeProcessing(boolean enable) throws SQLException {
+         getPhysPs().setEscapeProcessing(enable);
+    }
+
+    public int executeUpdate(String sql) throws SQLException {
+        return getPhysPs().executeUpdate(sql);
+    }
+
+    public void addBatch(String sql) throws SQLException {
+         getPhysPs().addBatch(sql);
+    }
+
+    public void setCursorName(String name) throws SQLException {
+         getPhysPs().setCursorName(name);
+    }
+
+    public boolean execute(String sql) throws SQLException {
+        return getPhysPs().execute(sql);
+    }
+
+    public int executeUpdate(String sql, int autoGeneratedKeys)
+            throws SQLException {
+        return getPhysPs().executeUpdate(sql, autoGeneratedKeys);
+    }
+
+    public boolean execute(String sql, int autoGeneratedKeys)
+            throws SQLException {
+        return getPhysPs().execute(sql, autoGeneratedKeys);
+    }
+
+    public int executeUpdate(String sql, int[] columnIndexes)
+            throws SQLException {
+        return getPhysPs().executeUpdate(sql, columnIndexes);
+    }
+
+    public boolean execute(String sql, int[] columnIndexes)
+            throws SQLException {
+        return getPhysPs().execute(sql, columnIndexes);
+    }
+
+    public Connection getConnection() throws SQLException {
+        return getPhysPs().getConnection();
+    }
+
+    public ResultSet getGeneratedKeys() throws SQLException {
+        return getPhysPs().getGeneratedKeys();
+    }
+
+    public ResultSet getResultSet() throws SQLException {
+        return getPhysPs().getResultSet();
+    }
+
+    public SQLWarning getWarnings() throws SQLException {
+        return getPhysPs().getWarnings();
+    }
+
+    public int executeUpdate(String sql, String[] columnNames)
+            throws SQLException {
+        return getPhysPs().executeUpdate(sql, columnNames);
+    }
+
+    public boolean execute(String sql, String[] columnNames)
+            throws SQLException {
+        return getPhysPs().execute(sql, columnNames);
+    }
+
+    public ResultSet executeQuery(String sql) throws SQLException {
+        return getPhysPs().executeQuery(sql);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,191 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.LogicalPreparedStatement40
+
+   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.derby.client.am;
+
+import java.io.InputStream;
+import java.io.Reader;
+
+import java.sql.NClob;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLXML;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+
+import org.apache.derby.shared.common.reference.SQLState;
+
+/**
+ * JDBC 4 specific wrapper class for a Derby physical prepared statement.
+ *
+ * @see LogicalPreparedStatement
+ * @see #isClosed
+ */
+public class LogicalPreparedStatement40
+    extends LogicalPreparedStatement {
+
+    /**
+     * Creates a new logical prepared statement.
+     *
+     * @param physicalPs underlying physical statement
+     * @param stmtKey key for the physical statement
+     * @param cache associated statement cache
+     * @throws IllegalArgumentException if {@code cache} is {@code null}
+     */
+    public LogicalPreparedStatement40(java.sql.PreparedStatement physicalPs,
+                                      StatementKey stmtKey,
+                                      JDBCStatementCache cache) {
+        super(physicalPs, stmtKey, cache);
+    }
+
+    public void setRowId(int arg0, RowId arg1)
+            throws SQLException {
+         getPhysPs().setRowId(arg0, arg1);
+    }
+
+    public void setNString(int arg0, String arg1)
+            throws SQLException {
+         getPhysPs().setNString(arg0, arg1);
+    }
+
+    public void setNCharacterStream(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setNCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setNClob(int arg0, NClob arg1)
+            throws SQLException {
+         getPhysPs().setNClob(arg0, arg1);
+    }
+
+    public void setClob(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setClob(arg0, arg1, arg2);
+    }
+
+    public void setBlob(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setBlob(arg0, arg1, arg2);
+    }
+
+    public void setNClob(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setNClob(arg0, arg1, arg2);
+    }
+
+    public void setSQLXML(int arg0, SQLXML arg1)
+            throws SQLException {
+         getPhysPs().setSQLXML(arg0, arg1);
+    }
+
+    public void setAsciiStream(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setAsciiStream(arg0, arg1, arg2);
+    }
+
+    public void setBinaryStream(int arg0, InputStream arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setBinaryStream(arg0, arg1, arg2);
+    }
+
+    public void setCharacterStream(int arg0, Reader arg1, long arg2)
+            throws SQLException {
+         getPhysPs().setCharacterStream(arg0, arg1, arg2);
+    }
+
+    public void setAsciiStream(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysPs().setAsciiStream(arg0, arg1);
+    }
+
+    public void setBinaryStream(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysPs().setBinaryStream(arg0, arg1);
+    }
+
+    public void setCharacterStream(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysPs().setCharacterStream(arg0, arg1);
+    }
+
+    public void setNCharacterStream(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysPs().setNCharacterStream(arg0, arg1);
+    }
+
+    public void setClob(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysPs().setClob(arg0, arg1);
+    }
+
+    public void setBlob(int arg0, InputStream arg1)
+            throws SQLException {
+         getPhysPs().setBlob(arg0, arg1);
+    }
+
+    public void setNClob(int arg0, Reader arg1)
+            throws SQLException {
+         getPhysPs().setNClob(arg0, arg1);
+    }
+
+    public synchronized boolean isClosed()
+            throws SQLException {
+        // Note the extra synchronization.
+        boolean closed = isLogicalEntityClosed();
+        if (!closed) {
+            // Consult the underlying physical statement.
+            closed = getPhysCs().isClosed();
+        }
+        return closed;
+    }
+
+    public void setPoolable(boolean arg0)
+            throws SQLException {
+         getPhysPs().setPoolable(arg0);
+    }
+
+    public boolean isPoolable()
+            throws SQLException {
+        return getPhysPs().isPoolable();
+    }
+
+    public <T> T unwrap(Class<T> arg0)
+            throws SQLException {
+        try {
+            if (getPhysPs().isClosed()) {
+                throw (new SqlException(null,
+                    new ClientMessageId(SQLState.ALREADY_CLOSED),
+                                        "PreparedStatement")).getSQLException();
+            }
+            return arg0.cast(this);
+        } catch (ClassCastException cce) {
+            throw new SqlException(
+                    null,
+                    new ClientMessageId(SQLState.UNABLE_TO_UNWRAP),
+                    arg0).getSQLException();
+        }
+    }
+
+    public boolean isWrapperFor(Class<?> arg0)
+            throws SQLException {
+        return getPhysPs().isWrapperFor(arg0);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalPreparedStatement40.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,192 @@
+/*
+
+   Derby - Class org.apache.derby.client.am.LogicalStatementEntity
+
+   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.derby.client.am;
+
+import java.sql.SQLException;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+/**
+ * Common class interacting with the JDBC statement cache for logical prepared
+ * statements and logical callable statements.
+ * <p>
+ * Note that {@link #getPhysPs} and {@link #getPhysCs} takes care of checking if
+ * the logical statement has been closed. The physical statement will take care
+ * of validating itself.
+ * <p>
+ * Beside from the above, special treatment of logical entities happens
+ * on close. This is the point where cache interaction takes place, and also
+ * where the appropriate methods are called on the physical statement to perform
+ * the necessary clean up for later reuse.
+ * <p>
+ * A note regarding the thread safety of this class, is that access to
+ * {@code physicalPs} and {@code physicalCs} is guarded by the instance of this
+ * class, but it is assumed that operation on/within the physical statement is
+ * synchronized in the physical statement itself .
+ */
+//@ThreadSafe
+class LogicalStatementEntity {
+
+    /**
+     * Tells if we're holding a callable statement or not.
+     * <p>
+     * Used for sanity checking.
+     */
+    private final boolean hasCallableStmt;
+    /**
+     * Associated physical prepared statement.
+     * <p>
+     * If this is {@code null}, the logical entity is closed.
+     */
+    //@GuardedBy("this")
+    private java.sql.PreparedStatement physicalPs;
+    /**
+     * Assoicated physical callable statement, if any.
+     * <p>
+     * This is a convenience reference, to avoid having to cast on every
+     * invokation of {@link #getPhysCs} if the logical entity represents a
+     * callable statement.
+     */
+    //@GuardedBy("this)
+    private java.sql.CallableStatement physicalCs;
+    /** The key for the associated statement. */
+    private final StatementKey stmtKey;
+    /** Cache for physical statements. */
+    //@GuardedBy("this)
+    private final JDBCStatementCache cache;
+
+    /**
+     * Create a logical entity for a {@link java.sql.PreparedStatement}.
+     *
+     * @param physicalPs a physical {@link java.sql.PreparedStatement}
+     * @param stmtKey cache key for the physical statement
+     * @param cache statement cache
+     * @throws IllegalArgumentException if {@code cache} is {@code null}
+     */
+    protected LogicalStatementEntity(java.sql.PreparedStatement physicalPs,
+                                     StatementKey stmtKey,
+                                     JDBCStatementCache cache) {
+        if (cache == null) {
+            // Internal check, failure indicates programming error.
+            // No need to localize error message.
+            throw new IllegalArgumentException(
+                    "statement cache reference cannot be <null>");
+        }
+        this.stmtKey = stmtKey;
+        this.cache = cache;
+        this.physicalPs = physicalPs;
+        if (physicalPs instanceof CallableStatement) {
+            this.hasCallableStmt = true;
+            this.physicalCs = (CallableStatement)physicalPs;
+        } else {
+            this.hasCallableStmt = false;
+            this.physicalCs = null;
+        }
+    }
+
+    /**
+     * Returns the associated physical prepared statement.
+     *
+     * @return A prepared statement.
+     * @throws SQLException if the logical statement has been closed
+     */
+    synchronized java.sql.PreparedStatement getPhysPs()
+            throws SQLException {
+        if (physicalPs == null) {
+            throw (new SqlException(null,
+                new ClientMessageId(SQLState.ALREADY_CLOSED),
+                                    "PreparedStatement")).getSQLException();
+        }
+        return physicalPs;
+    }
+
+    /**
+     * Returns the associated physical callable statement.
+     *
+     * @return A callable statement.
+     * @throws SQLException if the logical statement has been closed
+     */
+    synchronized java.sql.CallableStatement getPhysCs()
+            throws SQLException {
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(hasCallableStmt,
+                    "called getPhysCs(), but created with PreparedStatement");
+        }
+        if (physicalCs == null) {
+            throw (new SqlException(null,
+                new ClientMessageId(SQLState.ALREADY_CLOSED),
+                                    "CallableStatement")).getSQLException();
+        }
+        return physicalCs;
+    }
+
+    /**
+     * Close the logical statement.
+     *
+     * @throws SQLException if closing the statement fails
+     */
+    public synchronized void close() throws SQLException {
+        if (physicalPs != null) {
+            final PreparedStatement temporaryPsRef =
+                    (org.apache.derby.client.am.PreparedStatement)physicalPs;
+            // Nullify both references.
+            physicalPs = null;
+            physicalCs = null;
+
+            // If the underlying statement has become closed, don't cache it.
+            if (temporaryPsRef.isClosed()) {
+                return;
+            }
+
+            // Reset the statement for reuse.
+            try {
+                // WARNING: This is just a placeholder and is incorrect!!!
+                //          A proper reset procedure must be implemented.
+                temporaryPsRef.reset(true);
+            } catch (SqlException sqle) {
+                throw sqle.getSQLException();
+            }
+
+            // Try to insert the statement into the cache.
+            if (!cache.cacheStatement(stmtKey, temporaryPsRef)) {
+                // Statement was already in the cache, discard this one.
+                temporaryPsRef.close();
+            }
+        }
+    }
+
+    /**
+     * Tells if the logical entity is closed.
+     * <p>
+     * If this method is used to avoid the possibility of raising an exception
+     * because the logical statement has been closed and then invoke a method on
+     * the physical statement, one must synchronize on this instance in the
+     * calling code.
+     *
+     * @return {@code true} if closed, {@code false} if open.
+     */
+    synchronized boolean isLogicalEntityClosed() {
+        return (physicalPs == null);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/LogicalStatementEntity.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java?rev=629734&view=auto
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java (added)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java Thu Feb 21 02:26:31 2008
@@ -0,0 +1,180 @@
+package org.apache.derby.client.am;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.apache.derby.client.am.stmtcache.JDBCStatementCache;
+import org.apache.derby.client.am.stmtcache.StatementKey;
+import org.apache.derby.client.am.stmtcache.StatementKeyFactory;
+import org.apache.derby.jdbc.ClientDriver;
+
+/**
+ * Utility class encapsulating the logic for interacting with the JDBC statement
+ * cache when creating new logical statements.
+ * <p>
+ * This class was introduced to share code between the pre-JDBC 4 and the JDBC
+ * 4+ versions of the JDBC classes.
+ * <p>
+ * The pattern for the {@code prepareX} methods is:
+ * <ol> <li>Generate a key for the statement to create.</li>
+ *      <li>Consult cache to see if an existing statement can be used.</li>
+ *      <li>Create new statement on physical connection if necessary.</li>
+ *      <li>Return referecne to existing or newly created statement.</li>
+ * </ol>
+ */
+final class StatementCacheInteractor {
+
+    /** TODO: Fetch from connection, see DERBY-3192. */
+    private final String currentSchema = "APP";
+    /** Statement cache for the associated physical connection. */
+    private final JDBCStatementCache cache;
+    /**
+     * The underlying physical connection.
+     * <p>
+     * Note that it is the responsibility of the logical statement assoiciated
+     * with this cache interactor to ensure the interactor methods are not
+     * invoked if the logical statement has been closed.
+     */
+    private final Connection physicalConnection;
+
+    /**
+     * Creates a new JDBC statement cache interactor.
+     *
+     * @param cache statement cache
+     * @param physicalConnection associated physical connection
+     */
+    StatementCacheInteractor(JDBCStatementCache cache,
+                             Connection physicalConnection) {
+        this.cache = cache;
+        this.physicalConnection = physicalConnection;
+    }
+
+    /**
+     * @see java.sql.Connection#prepareStatement(String)
+     */
+    public synchronized PreparedStatement prepareStatement(String sql)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newPrepared(
+                sql, currentSchema, physicalConnection.holdability());
+        PreparedStatement ps = cache.getCached(stmtKey);
+        if (ps == null) {
+            ps = physicalConnection.prepareStatement(sql);
+        }
+        return ClientDriver.getFactory().newLogicalPreparedStatement(
+                    ps, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareStatement(String,int,int)
+     */
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newPrepared(
+                sql, currentSchema, resultSetType, resultSetConcurrency,
+                physicalConnection.holdability());
+        PreparedStatement ps = cache.getCached(stmtKey);
+        if (ps == null) {
+            ps = physicalConnection.prepareStatement(
+                    sql, resultSetType, resultSetConcurrency);
+        }
+        return ClientDriver.getFactory().newLogicalPreparedStatement(
+                ps, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareStatement(String,int,int,int)
+     */
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int resultSetType,
+                                                int resultSetConcurrency,
+                                                int resultSetHoldability)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newPrepared(
+                sql, currentSchema, resultSetType, resultSetConcurrency,
+                resultSetHoldability);
+
+        PreparedStatement ps = cache.getCached(stmtKey);
+        if (ps == null) {
+            ps = physicalConnection.prepareStatement(
+                sql, resultSetType,resultSetConcurrency, resultSetHoldability);
+        }
+        return ClientDriver.getFactory().newLogicalPreparedStatement(
+                    ps, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareStatement(String,int)
+     */
+    public synchronized PreparedStatement prepareStatement(
+                                                String sql,
+                                                int autoGeneratedKeys)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newPrepared(
+                sql, currentSchema, physicalConnection.getHoldability(),
+                autoGeneratedKeys);
+        PreparedStatement ps = cache.getCached(stmtKey);
+        if (ps == null) {
+            ps = physicalConnection.prepareStatement(sql, autoGeneratedKeys);
+        }
+        return ClientDriver.getFactory().newLogicalPreparedStatement(
+                    ps, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareCall(String)
+     */
+    public synchronized CallableStatement prepareCall(String sql)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newCallable(
+                sql, currentSchema, physicalConnection.holdability());
+        CallableStatement cs = (CallableStatement)cache.getCached(stmtKey);
+        if (cs == null) {
+            cs = physicalConnection.prepareCall(sql);
+        }
+        return ClientDriver.getFactory().newLogicalCallableStatement(
+                    cs, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareCall(String,int,int)
+     */
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newCallable(
+                sql, currentSchema, resultSetType, resultSetConcurrency,
+                physicalConnection.holdability());
+        CallableStatement cs = (CallableStatement)cache.getCached(stmtKey);
+        if (cs == null) {
+            cs = physicalConnection.prepareCall(sql, resultSetType, resultSetConcurrency);
+        }
+        return ClientDriver.getFactory().newLogicalCallableStatement(
+                    cs, stmtKey, cache);
+    }
+
+    /**
+     * @see java.sql.Connection#prepareCall(String,int,int,int)
+     */
+    public synchronized CallableStatement prepareCall(String sql,
+                                                      int resultSetType,
+                                                      int resultSetConcurrency,
+                                                      int resultSetHoldability)
+            throws SQLException {
+        StatementKey stmtKey = StatementKeyFactory.newCallable(
+                sql, currentSchema, resultSetType, resultSetConcurrency,
+                resultSetHoldability);
+        CallableStatement cs = (CallableStatement)cache.getCached(stmtKey);
+        if (cs == null) {
+            cs = physicalConnection.prepareCall(sql, resultSetType, resultSetConcurrency,
+                    resultSetHoldability);
+        }
+        return ClientDriver.getFactory().newLogicalCallableStatement(
+                    cs, stmtKey, cache);
+    }
+}

Propchange: db/derby/code/trunk/java/client/org/apache/derby/client/am/StatementCacheInteractor.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message