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 <garydgreg...@gmail.com> Authored: Wed Jun 20 12:00:05 2018 -0600 Committer: Gary Gregory <garydgreg...@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";