You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2018/06/20 18:00:11 UTC

commons-dbcp git commit: [DBCP-508] Prepared statement keys should take a Connection's schema into account.

Repository: commons-dbcp
Updated Branches:
  refs/heads/master e5707c514 -> 8c2c5f6b0


[DBCP-508] Prepared statement keys should take a Connection's schema
into account.

Project: http://git-wip-us.apache.org/repos/asf/commons-dbcp/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-dbcp/commit/8c2c5f6b
Tree: http://git-wip-us.apache.org/repos/asf/commons-dbcp/tree/8c2c5f6b
Diff: http://git-wip-us.apache.org/repos/asf/commons-dbcp/diff/8c2c5f6b

Branch: refs/heads/master
Commit: 8c2c5f6b0bf96c162bd98eae595f06b5ba990bc9
Parents: e5707c5
Author: Gary Gregory <ga...@gmail.com>
Authored: Wed Jun 20 12:00:05 2018 -0600
Committer: Gary Gregory <ga...@gmail.com>
Committed: Wed Jun 20 12:00:05 2018 -0600

----------------------------------------------------------------------
 src/changes/changes.xml                         |   3 +
 .../java/org/apache/commons/dbcp2/PStmtKey.java | 381 +++++++++++++++++--
 .../apache/commons/dbcp2/PoolingConnection.java |  42 +-
 .../dbcp2/cpdsadapter/PooledConnectionImpl.java |  32 +-
 .../org/apache/commons/dbcp2/TestPStmtKey.java  | 131 ++++++-
 5 files changed, 531 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/8c2c5f6b/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4dba0b2..f01b979 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -76,6 +76,9 @@ The <action> type attribute can be add,update,fix,remove.
        <action dev="ggregory" type="update" issue="DBCP-507" due-to="Vladimir Konkov, Phil Steitz, Gary Gregory">
         Change default for fail-fast connections from false to true.
       </action>
+      <action dev="ggregory" type="fix" issue="DBCP-508" due-to="Gary Gregory">
+        Prepared statement keys should take a Connection's schema into account.
+      </action>
     </release>
     <release version="2.4.0" date="2018-06-12" description="This is a minor release, including bug fixes and enhancements.">
       <action dev="ggregory" type="fix" issue="DBCP-484" due-to="Emanuel Freitas">

http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/8c2c5f6b/src/main/java/org/apache/commons/dbcp2/PStmtKey.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/dbcp2/PStmtKey.java b/src/main/java/org/apache/commons/dbcp2/PStmtKey.java
index e118a2c..92eb2c9 100644
--- a/src/main/java/org/apache/commons/dbcp2/PStmtKey.java
+++ b/src/main/java/org/apache/commons/dbcp2/PStmtKey.java
@@ -152,9 +152,12 @@ public class PStmtKey {
      */
     private final Integer resultSetHoldability;
 
-    /** Database catalog */
+    /** Database catalog. */
     private final String catalog;
 
+    /** Database schema. */
+    private final String schema;
+
     /**
      * A flag indicating whether auto-generated keys should be returned; one of
      * <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
@@ -177,14 +180,16 @@ public class PStmtKey {
     private final StatementType statementType;
 
     /** Statement builder */
-    private StatementBuilder builder;
+    private transient StatementBuilder builder;
 
     /**
      * Constructs a key to uniquely identify a prepared statement.
      *
      * @param sql
      *            The SQL statement.
+     * @deprecated Use {@link #PStmtKey(String, String, String)}.
      */
+    @Deprecated
     public PStmtKey(final String sql) {
         this(sql, null, StatementType.PREPARED_STATEMENT);
     }
@@ -200,7 +205,9 @@ public class PStmtKey {
      * @param resultSetConcurrency
      *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
      *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) {
         this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT);
     }
@@ -212,7 +219,9 @@ public class PStmtKey {
      *            The SQL statement.
      * @param catalog
      *            The catalog.
+     * @deprecated Use {@link #PStmtKey(String, String, String)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog) {
         this(sql, catalog, StatementType.PREPARED_STATEMENT);
     }
@@ -227,7 +236,9 @@ public class PStmtKey {
      * @param autoGeneratedKeys
      *            A flag indicating whether auto-generated keys should be returned; one of
      *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
+     * @deprecated Use {@link #PStmtKey(String, String, String, int)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int autoGeneratedKeys) {
         this(sql, catalog, StatementType.PREPARED_STATEMENT, Integer.valueOf(autoGeneratedKeys));
     }
@@ -245,7 +256,9 @@ public class PStmtKey {
      * @param resultSetConcurrency
      *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
      *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @deprecated Use @link {@link #PStmtKey(String, String, String, int, int)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) {
         this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT);
     }
@@ -266,7 +279,9 @@ public class PStmtKey {
      * @param resultSetHoldability
      *            One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
      *            or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+     * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability) {
         this(sql, catalog, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT);
@@ -290,11 +305,14 @@ public class PStmtKey {
      *            or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
      * @param statementType
      *            The SQL statement type, prepared or callable.
+     * @deprecated Use {#link {@link #PStmtKey(String, String, String, int, int, int, StatementType)}
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability, final StatementType statementType) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
         this.resultSetType = Integer.valueOf(resultSetType);
         this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
         this.resultSetHoldability = Integer.valueOf(resultSetHoldability);
@@ -325,11 +343,14 @@ public class PStmtKey {
      *            <code>ResultSet.CONCUR_UPDATABLE</code>.
      * @param statementType
      *            The SQL statement type, prepared or callable.
+     * @deprecated Use {@link #PStmtKey(String, String, String, int, int, StatementType)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency,
             final StatementType statementType) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
         this.resultSetType = Integer.valueOf(resultSetType);
         this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
         this.resultSetHoldability = null;
@@ -355,10 +376,13 @@ public class PStmtKey {
      * @param columnIndexes
      *            An array of column indexes indicating the columns that should be returned from the inserted row or
      *            rows.
+     * @deprecated Use {@link #PStmtKey(String, String, String, int[])}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
         this.statementType = StatementType.PREPARED_STATEMENT;
         this.autoGeneratedKeys = null;
         this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length);
@@ -379,10 +403,13 @@ public class PStmtKey {
      *            The catalog.
      * @param statementType
      *            The SQL statement type, prepared or callable.
+     * @deprecated Use {@link #PStmtKey(String, String, String, StatementType)}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final StatementType statementType) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
         this.statementType = statementType;
         this.autoGeneratedKeys = null;
         this.columnIndexes = null;
@@ -410,11 +437,269 @@ public class PStmtKey {
      * @param autoGeneratedKeys
      *            A flag indicating whether auto-generated keys should be returned; one of
      *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
+     * @deprecated Use {@link #PStmtKey(String, String, String, StatementType, Integer)}
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final StatementType statementType,
             final Integer autoGeneratedKeys) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
+        this.statementType = statementType;
+        this.autoGeneratedKeys = autoGeneratedKeys;
+        this.columnIndexes = null;
+        this.columnNames = null;
+        this.resultSetType = null;
+        this.resultSetConcurrency = null;
+        this.resultSetHoldability = null;
+        // create builder
+        if (statementType == StatementType.PREPARED_STATEMENT) {
+            this.builder = new PreparedStatementWithAutoGeneratedKeys();
+        } else if (statementType == StatementType.CALLABLE_STATEMENT) {
+            this.builder = new PreparedCallSQL();
+        }
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema) {
+        this(sql, catalog, schema, StatementType.PREPARED_STATEMENT);
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema
+     * @param autoGeneratedKeys
+     *            A flag indicating whether auto-generated keys should be returned; one of
+     *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int autoGeneratedKeys) {
+        this(sql, catalog, schema, StatementType.PREPARED_STATEMENT, Integer.valueOf(autoGeneratedKeys));
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema
+     * @param resultSetType
+     *            A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency) {
+        this(sql, catalog, schema, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT);
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema
+     * @param resultSetType
+     *            a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>
+     * @param resultSetHoldability
+     *            One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
+     *            or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability) {
+        this(sql, catalog, schema, resultSetType, resultSetConcurrency, resultSetHoldability, StatementType.PREPARED_STATEMENT);
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param resultSetType
+     *            a result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+     * @param resultSetConcurrency
+     *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @param resultSetHoldability
+     *            One of the following <code>ResultSet</code> constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
+     *            or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>.
+     * @param statementType
+     *            The SQL statement type, prepared or callable.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
+            final int resultSetHoldability, final StatementType statementType) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
+        this.resultSetType = Integer.valueOf(resultSetType);
+        this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
+        this.resultSetHoldability = Integer.valueOf(resultSetHoldability);
+        this.statementType = statementType;
+        this.autoGeneratedKeys = null;
+        this.columnIndexes = null;
+        this.columnNames = null;
+        // create builder
+        if (statementType == StatementType.PREPARED_STATEMENT) {
+            this.builder = new PreparedStatementWithResultSetHoldability();
+        } else if (statementType == StatementType.CALLABLE_STATEMENT) {
+            this.builder = new PreparedCallWithResultSetHoldability();
+        }
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param resultSetType
+     *            A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+     *            <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>.
+     * @param resultSetConcurrency
+     *            A concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or
+     *            <code>ResultSet.CONCUR_UPDATABLE</code>.
+     * @param statementType
+     *            The SQL statement type, prepared or callable.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int resultSetType, final int resultSetConcurrency,
+            final StatementType statementType) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
+        this.resultSetType = Integer.valueOf(resultSetType);
+        this.resultSetConcurrency = Integer.valueOf(resultSetConcurrency);
+        this.resultSetHoldability = null;
+        this.statementType = statementType;
+        this.autoGeneratedKeys = null;
+        this.columnIndexes = null;
+        this.columnNames = null;
+        // create builder
+        if (statementType == StatementType.PREPARED_STATEMENT) {
+            this.builder = new PreparedStatementWithResultSetConcurrency();
+        } else if (statementType == StatementType.CALLABLE_STATEMENT) {
+            this.builder = new PreparedCallWithResultSetConcurrency();
+        }
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param columnIndexes
+     *            An array of column indexes indicating the columns that should be returned from the inserted row or
+     *            rows.
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final int[] columnIndexes) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
+        this.statementType = StatementType.PREPARED_STATEMENT;
+        this.autoGeneratedKeys = null;
+        this.columnIndexes = columnIndexes == null ? null : Arrays.copyOf(columnIndexes, columnIndexes.length);
+        this.columnNames = null;
+        this.resultSetType = null;
+        this.resultSetConcurrency = null;
+        this.resultSetHoldability = null;
+        // create builder
+        this.builder = new PreparedStatementWithColumnIndexes();
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param statementType
+     *            The SQL statement type, prepared or callable.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
+        this.statementType = statementType;
+        this.autoGeneratedKeys = null;
+        this.columnIndexes = null;
+        this.columnNames = null;
+        this.resultSetType = null;
+        this.resultSetConcurrency = null;
+        this.resultSetHoldability = null;
+        // create builder
+        if (statementType == StatementType.PREPARED_STATEMENT) {
+            this.builder = new PreparedStatementSQL();
+        } else if (statementType == StatementType.CALLABLE_STATEMENT) {
+            this.builder = new PreparedCallSQL();
+        }
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param statementType
+     *            The SQL statement type, prepared or callable.
+     * @param autoGeneratedKeys
+     *            A flag indicating whether auto-generated keys should be returned; one of
+     *            <code>Statement.RETURN_GENERATED_KEYS</code> or <code>Statement.NO_GENERATED_KEYS</code>.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final StatementType statementType,
+            final Integer autoGeneratedKeys) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
         this.statementType = statementType;
         this.autoGeneratedKeys = autoGeneratedKeys;
         this.columnIndexes = null;
@@ -437,12 +722,43 @@ public class PStmtKey {
      *            The SQL statement.
      * @param catalog
      *            The catalog.
+     * @param schema
+     *            The schema.
+     * @param columnNames
+     *            An array of column names indicating the columns that should be returned from the inserted row or rows.
+     * @since 2.5.0
+     */
+    public PStmtKey(final String sql, final String catalog, final String schema, final String[] columnNames) {
+        this.sql = sql;
+        this.catalog = catalog;
+        this.schema = schema;
+        this.statementType = StatementType.PREPARED_STATEMENT;
+        this.autoGeneratedKeys = null;
+        this.columnIndexes = null;
+        this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length);
+        this.resultSetType = null;
+        this.resultSetConcurrency = null;
+        this.resultSetHoldability = null;
+        // create builder
+        builder = new PreparedStatementWithColumnNames();
+    }
+
+    /**
+     * Constructs a key to uniquely identify a prepared statement.
+     *
+     * @param sql
+     *            The SQL statement.
+     * @param catalog
+     *            The catalog.
      * @param columnNames
      *            An array of column names indicating the columns that should be returned from the inserted row or rows.
+     * @deprecated Use {@link #PStmtKey(String, String, String, String[])}.
      */
+    @Deprecated
     public PStmtKey(final String sql, final String catalog, final String[] columnNames) {
         this.sql = sql;
         this.catalog = catalog;
+        this.schema = null;
         this.statementType = StatementType.PREPARED_STATEMENT;
         this.autoGeneratedKeys = null;
         this.columnIndexes = null;
@@ -482,6 +798,13 @@ public class PStmtKey {
             return false;
         }
         final PStmtKey other = (PStmtKey) obj;
+        if (autoGeneratedKeys == null) {
+            if (other.autoGeneratedKeys != null) {
+                return false;
+            }
+        } else if (!autoGeneratedKeys.equals(other.autoGeneratedKeys)) {
+            return false;
+        }
         if (catalog == null) {
             if (other.catalog != null) {
                 return false;
@@ -489,6 +812,12 @@ public class PStmtKey {
         } else if (!catalog.equals(other.catalog)) {
             return false;
         }
+        if (!Arrays.equals(columnIndexes, other.columnIndexes)) {
+            return false;
+        }
+        if (!Arrays.equals(columnNames, other.columnNames)) {
+            return false;
+        }
         if (resultSetConcurrency == null) {
             if (other.resultSetConcurrency != null) {
                 return false;
@@ -496,13 +825,6 @@ public class PStmtKey {
         } else if (!resultSetConcurrency.equals(other.resultSetConcurrency)) {
             return false;
         }
-        if (resultSetType == null) {
-            if (other.resultSetType != null) {
-                return false;
-            }
-        } else if (!resultSetType.equals(other.resultSetType)) {
-            return false;
-        }
         if (resultSetHoldability == null) {
             if (other.resultSetHoldability != null) {
                 return false;
@@ -510,17 +832,18 @@ public class PStmtKey {
         } else if (!resultSetHoldability.equals(other.resultSetHoldability)) {
             return false;
         }
-        if (autoGeneratedKeys == null) {
-            if (other.autoGeneratedKeys != null) {
+        if (resultSetType == null) {
+            if (other.resultSetType != null) {
                 return false;
             }
-        } else if (!autoGeneratedKeys.equals(other.autoGeneratedKeys)) {
-            return false;
-        }
-        if (!Arrays.equals(columnIndexes, other.columnIndexes)) {
+        } else if (!resultSetType.equals(other.resultSetType)) {
             return false;
         }
-        if (!Arrays.equals(columnNames, other.columnNames)) {
+        if (schema == null) {
+            if (other.schema != null) {
+                return false;
+            }
+        } else if (!schema.equals(other.schema)) {
             return false;
         }
         if (sql == null) {
@@ -604,6 +927,15 @@ public class PStmtKey {
     }
 
     /**
+     * The schema.
+     *
+     * @return The catalog.
+     */
+    public String getSchema() {
+        return schema;
+    }
+
+    /**
      * Gets the SQL statement.
      *
      * @return the SQL statement.
@@ -625,15 +957,16 @@ public class PStmtKey {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + (catalog == null ? 0 : catalog.hashCode());
-        result = prime * result + (resultSetConcurrency == null ? 0 : resultSetConcurrency.hashCode());
-        result = prime * result + (resultSetType == null ? 0 : resultSetType.hashCode());
-        result = prime * result + (resultSetHoldability == null ? 0 : resultSetHoldability.hashCode());
-        result = prime * result + (sql == null ? 0 : sql.hashCode());
-        result = prime * result + (autoGeneratedKeys == null ? 0 : autoGeneratedKeys.hashCode());
+        result = prime * result + ((autoGeneratedKeys == null) ? 0 : autoGeneratedKeys.hashCode());
+        result = prime * result + ((catalog == null) ? 0 : catalog.hashCode());
         result = prime * result + Arrays.hashCode(columnIndexes);
         result = prime * result + Arrays.hashCode(columnNames);
-        result = prime * result + statementType.hashCode();
+        result = prime * result + ((resultSetConcurrency == null) ? 0 : resultSetConcurrency.hashCode());
+        result = prime * result + ((resultSetHoldability == null) ? 0 : resultSetHoldability.hashCode());
+        result = prime * result + ((resultSetType == null) ? 0 : resultSetType.hashCode());
+        result = prime * result + ((schema == null) ? 0 : schema.hashCode());
+        result = prime * result + ((sql == null) ? 0 : sql.hashCode());
+        result = prime * result + ((statementType == null) ? 0 : statementType.hashCode());
         return result;
     }
 
@@ -644,6 +977,8 @@ public class PStmtKey {
         buf.append(sql);
         buf.append(", catalog=");
         buf.append(catalog);
+        buf.append(", schema=");
+        buf.append(schema);
         buf.append(", resultSetType=");
         buf.append(resultSetType);
         buf.append(", resultSetConcurrency=");

http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/8c2c5f6b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
index 03f70aa..d4df45f 100644
--- a/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
+++ b/src/main/java/org/apache/commons/dbcp2/PoolingConnection.java
@@ -125,7 +125,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull());
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull());
     }
 
     /**
@@ -139,11 +139,11 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int columnIndexes[]) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnIndexes);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
     }
 
     protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), autoGeneratedKeys);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys);
     }
 
     /**
@@ -159,7 +159,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency);
     }
 
     /**
@@ -178,7 +178,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency,
                 resultSetHoldability);
     }
 
@@ -193,15 +193,15 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *            result set concurrency
      * @param resultSetHoldability
      *            result set holdability
-     * @param stmtType
+     * @param statementType
      *            statement type
      *
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
-            final int resultSetHoldability, final StatementType stmtType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
-                resultSetHoldability, stmtType);
+            final int resultSetHoldability, final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency,
+                resultSetHoldability, statementType);
     }
 
     /**
@@ -213,14 +213,14 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *            result set type
      * @param resultSetConcurrency
      *            result set concurrency
-     * @param stmtType
+     * @param statementType
      *            statement type
      *
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
-            final StatementType stmtType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency, stmtType);
+            final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType, resultSetConcurrency, statementType);
     }
 
     /**
@@ -228,13 +228,13 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      *
      * @param sql
      *            the SQL string used to define the statement
-     * @param stmtType
+     * @param statementType
      *            statement type
      *
      * @return the PStmtKey created for the given arguments.
      */
-    protected PStmtKey createKey(final String sql, final StatementType stmtType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), stmtType, null);
+    protected PStmtKey createKey(final String sql, final StatementType statementType) {
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), statementType, null);
     }
 
     /**
@@ -248,7 +248,7 @@ public class PoolingConnection extends DelegatingConnection<Connection>
      * @return the PStmtKey created for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final String columnNames[]) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnNames);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames);
     }
 
     /**
@@ -276,6 +276,16 @@ public class PoolingConnection extends DelegatingConnection<Connection>
         return catalog;
     }
 
+    private String getSchemaOrNull() {
+        String catalog = null;
+        try {
+            catalog = getSchema();
+        } catch (final SQLException e) {
+            // Ignored
+        }
+        return catalog;
+    }
+
     /**
      * {@link KeyedPooledObjectFactory} method for creating {@link PoolablePreparedStatement}s or
      * {@link PoolableCallableStatement}s. The <code>stmtType</code> field in the key determines whether a

http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/8c2c5f6b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
index c708e16..8cb4670 100644
--- a/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
+++ b/src/main/java/org/apache/commons/dbcp2/cpdsadapter/PooledConnectionImpl.java
@@ -182,28 +182,29 @@ class PooledConnectionImpl
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull());
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull());
     }
 
     /**
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int autoGeneratedKeys) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), autoGeneratedKeys);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), autoGeneratedKeys);
     }
 
     /**
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int columnIndexes[]) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnIndexes);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnIndexes);
     }
 
     /**
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
+                resultSetConcurrency);
     }
 
     /**
@@ -211,8 +212,8 @@ class PooledConnectionImpl
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
-                resultSetHoldability);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
+                resultSetConcurrency, resultSetHoldability);
     }
 
     /**
@@ -222,8 +223,8 @@ class PooledConnectionImpl
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
             final int resultSetHoldability, final StatementType statementType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency,
-                resultSetHoldability, statementType);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
+                resultSetConcurrency, resultSetHoldability, statementType);
     }
 
     /**
@@ -233,21 +234,22 @@ class PooledConnectionImpl
      */
     protected PStmtKey createKey(final String sql, final int resultSetType, final int resultSetConcurrency,
             final StatementType statementType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), resultSetType, resultSetConcurrency, statementType);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), resultSetType,
+                resultSetConcurrency, statementType);
     }
 
     /**
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final StatementType statementType) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), statementType);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), statementType);
     }
 
     /**
      * Creates a {@link PStmtKey} for the given arguments.
      */
     protected PStmtKey createKey(final String sql, final String columnNames[]) {
-        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), columnNames);
+        return new PStmtKey(normalizeSQL(sql), getCatalogOrNull(), getSchemaOrNull(), columnNames);
     }
 
     /**
@@ -291,6 +293,14 @@ class PooledConnectionImpl
         }
     }
 
+    private String getSchemaOrNull() {
+        try {
+            return connection == null ? null : connection.getSchema();
+        } catch (final SQLException e) {
+            return null;
+        }
+    }
+
     /**
      * Returns a JDBC connection.
      *

http://git-wip-us.apache.org/repos/asf/commons-dbcp/blob/8c2c5f6b/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java b/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java
index 3b12cc5..2cdd932 100644
--- a/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java
+++ b/src/test/java/org/apache/commons/dbcp2/TestPStmtKey.java
@@ -18,6 +18,7 @@ package org.apache.commons.dbcp2;
 
 import java.util.Arrays;
 
+import org.apache.commons.dbcp2.PoolingConnection.StatementType;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -29,14 +30,128 @@ import org.junit.Test;
 public class TestPStmtKey {
 
     /**
-     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, int[])}.
+     * Tests constructors with different schemas.
+     */
+    @Test
+    public void testCtorDifferentSchema() {
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema2"));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0),
+                new PStmtKey("sql", "catalog1", "schema2", 0));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0, null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema2", 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null),
+                new PStmtKey("sql", "catalog1", "schema2", (int[]) null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]),
+                new PStmtKey("sql", "catalog1", "schema2", new int[1]));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null),
+                new PStmtKey("sql", "catalog1", "schema2", (String[]) null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }),
+                new PStmtKey("sql", "catalog1", "schema2", new String[] {"A" }));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT));
+        Assert.assertNotEquals(
+                new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE),
+                new PStmtKey("sql", "catalog1", "schema2", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE));
+    }
+
+    /**
+     * Tests constructors with different catalog.
+     */
+    @Test
+    public void testCtorDifferentCatalog() {
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog2", "schema1"));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0),
+                new PStmtKey("sql", "catalog2", "schema1", 0));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0, null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog2", "schema1", 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null),
+                new PStmtKey("sql", "catalog2", "schema1", (int[]) null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]),
+                new PStmtKey("sql", "catalog2", "schema1", new int[1]));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null),
+                new PStmtKey("sql", "catalog2", "schema1", (String[]) null));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }),
+                new PStmtKey("sql", "catalog2", "schema1", new String[] {"A" }));
+        Assert.assertNotEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT));
+        Assert.assertNotEquals(
+                new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE),
+                new PStmtKey("sql", "catalog2", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE));
+    }
+
+    /**
+     * Tests constructors with different catalog.
+     */
+    @Test
+    public void testCtorEquals() {
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1"), new PStmtKey("sql", "catalog1", "schema1"));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0),
+                new PStmtKey("sql", "catalog1", "schema1", 0));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0));
+        //
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, null));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, null),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0, null));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema1", 0, 0, StatementType.PREPARED_STATEMENT));
+        //
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (int[]) null),
+                new PStmtKey("sql", "catalog1", "schema1", (int[]) null));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new int[1]),
+                new PStmtKey("sql", "catalog1", "schema1", new int[1]));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", (String[]) null),
+                new PStmtKey("sql", "catalog1", "schema1", (String[]) null));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }),
+                new PStmtKey("sql", "catalog1", "schema1", new String[] {"A" }));
+        Assert.assertEquals(new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT),
+                new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT));
+        Assert.assertEquals(
+                new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE),
+                new PStmtKey("sql", "catalog1", "schema1", StatementType.PREPARED_STATEMENT, Integer.MAX_VALUE));
+    }
+
+    /**
+     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, int[])}.
      *
      * See https://issues.apache.org/jira/browse/DBCP-494
      */
     @Test
     public void testCtorStringStringArrayOfInts() {
         final int[] input = {0, 0 };
-        final PStmtKey pStmtKey = new PStmtKey("", "", input);
+        final PStmtKey pStmtKey = new PStmtKey("", "", "", input);
         Assert.assertArrayEquals(input, pStmtKey.getColumnIndexes());
         input[0] = 1;
         input[1] = 1;
@@ -44,38 +159,38 @@ public class TestPStmtKey {
     }
 
     /**
-     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, int[])}.
+     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, int[])}.
      *
      * See https://issues.apache.org/jira/browse/DBCP-494
      */
     @Test
     public void testCtorStringStringArrayOfNullInts() {
         final int[] input = null;
-        final PStmtKey pStmtKey = new PStmtKey("", "", input);
+        final PStmtKey pStmtKey = new PStmtKey("", "", "", input);
         Assert.assertArrayEquals(input, pStmtKey.getColumnIndexes());
     }
 
     /**
-     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String[])}.
+     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, String[])}.
      *
      * See https://issues.apache.org/jira/browse/DBCP-494
      */
     @Test
     public void testCtorStringStringArrayOfNullStrings() {
         final String[] input = null;
-        final PStmtKey pStmtKey = new PStmtKey("", "", input);
+        final PStmtKey pStmtKey = new PStmtKey("", "", "", input);
         Assert.assertArrayEquals(input, pStmtKey.getColumnNames());
     }
 
     /**
-     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String[])}.
+     * Tests {@link org.apache.commons.dbcp2.PStmtKey#PStmtKey(String, String, String, String[])}.
      *
      * See https://issues.apache.org/jira/browse/DBCP-494
      */
     @Test
     public void testCtorStringStringArrayOfStrings() {
         final String[] input = {"A", "B" };
-        final PStmtKey pStmtKey = new PStmtKey("", "", input);
+        final PStmtKey pStmtKey = new PStmtKey("", "", "", input);
         Assert.assertArrayEquals(input, pStmtKey.getColumnNames());
         input[0] = "C";
         input[1] = "D";