Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java Thu Aug 9 16:50:30 2018 @@ -42,6 +42,8 @@ public class DelegatingStatement extends /** The connection that created me. **/ private DelegatingConnection<?> connection; + private boolean closed = false; + /** * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code * which created it. @@ -58,65 +60,60 @@ public class DelegatingStatement extends } /** - * Returns my underlying {@link Statement}. * - * @return my underlying {@link Statement}. - * @see #getInnermostDelegate + * @throws SQLException + * thrown by the delegating statement. + * @since 2.4.0 made public, was protected in 2.3.0. */ - public Statement getDelegate() { - return statement; + public void activate() throws SQLException { + if (statement instanceof DelegatingStatement) { + ((DelegatingStatement) statement).activate(); + } } - /** - * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively - * invokes this method on my delegate. - * <p> - * Hence this method will return the first delegate that is not a {@code DelegatingStatement} or {@code null} when - * no non-{@code DelegatingStatement} delegate can be found by traversing this chain. - * </p> - * <p> - * This method is useful when you may have nested {@code DelegatingStatement}s, and you want to make sure to obtain - * a "genuine" {@link Statement}. - * </p> - * - * @return The innermost delegate. - * - * @see #getDelegate - */ - public Statement getInnermostDelegate() { - Statement s = statement; - while (s != null && s instanceof DelegatingStatement) { - s = ((DelegatingStatement) s).getDelegate(); - if (this == s) { - return null; - } + @Override + public void addBatch(final String sql) throws SQLException { + checkOpen(); + try { + statement.addBatch(sql); + } catch (final SQLException e) { + handleException(e); } - return s; } - /** - * Sets my delegate. - * - * @param statement - * my delegate. - */ - public void setDelegate(final Statement statement) { - this.statement = statement; + @Override + public void cancel() throws SQLException { + checkOpen(); + try { + statement.cancel(); + } catch (final SQLException e) { + handleException(e); + } } - private boolean closed = false; - - protected boolean isClosedInternal() { - return closed; + protected void checkOpen() throws SQLException { + if (isClosed()) { + throw new SQLException(this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed."); + } } - protected void setClosedInternal(final boolean closed) { - this.closed = closed; + @Override + public void clearBatch() throws SQLException { + checkOpen(); + try { + statement.clearBatch(); + } catch (final SQLException e) { + handleException(e); + } } - protected void checkOpen() throws SQLException { - if (isClosed()) { - throw new SQLException(this.getClass().getName() + " with address: \"" + this.toString() + "\" is closed."); + @Override + public void clearWarnings() throws SQLException { + checkOpen(); + try { + statement.clearWarnings(); + } catch (final SQLException e) { + handleException(e); } } @@ -160,113 +157,169 @@ public class DelegatingStatement extends } } - protected void handleException(final SQLException e) throws SQLException { - if (connection != null) { - connection.handleException(e); - } else { - throw e; + @Override + public void closeOnCompletion() throws SQLException { + checkOpen(); + try { + statement.closeOnCompletion(); + } catch (final SQLException e) { + handleException(e); } } - /** - * - * @throws SQLException - * thrown by the delegating statement. - * @since 2.4.0 made public, was protected in 2.3.0. - */ - public void activate() throws SQLException { - if (statement instanceof DelegatingStatement) { - ((DelegatingStatement) statement).activate(); + @Override + public boolean execute(final String sql) throws SQLException { + checkOpen(); + setLastUsedInParent(); + try { + return statement.execute(sql); + } catch (final SQLException e) { + handleException(e); + return false; } } - /** - * - * @throws SQLException - * thrown by the delegating statement. - * @since 2.4.0 made public, was protected in 2.3.0. - */ - public void passivate() throws SQLException { - if (statement instanceof DelegatingStatement) { - ((DelegatingStatement) statement).passivate(); + @Override + public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException { + checkOpen(); + setLastUsedInParent(); + try { + return statement.execute(sql, autoGeneratedKeys); + } catch (final SQLException e) { + handleException(e); + return false; } } @Override - public Connection getConnection() throws SQLException { + public boolean execute(final String sql, final int columnIndexes[]) throws SQLException { checkOpen(); - return getConnectionInternal(); // return the delegating connection that created this + setLastUsedInParent(); + try { + return statement.execute(sql, columnIndexes); + } catch (final SQLException e) { + handleException(e); + return false; + } } - protected DelegatingConnection<?> getConnectionInternal() { - return connection; + @Override + public boolean execute(final String sql, final String columnNames[]) throws SQLException { + checkOpen(); + setLastUsedInParent(); + try { + return statement.execute(sql, columnNames); + } catch (final SQLException e) { + handleException(e); + return false; + } } @Override - public ResultSet executeQuery(final String sql) throws SQLException { + public int[] executeBatch() throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } + setLastUsedInParent(); try { - return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql)); + return statement.executeBatch(); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } + /** + * @since 2.5.0 + */ @Override - public ResultSet getResultSet() throws SQLException { + public long[] executeLargeBatch() throws SQLException { checkOpen(); + setLastUsedInParent(); try { - return DelegatingResultSet.wrapResultSet(this, statement.getResultSet()); + return statement.executeLargeBatch(); } catch (final SQLException e) { handleException(e); - throw new AssertionError(); + return null; } } + /** + * @since 2.5.0 + */ @Override - public int executeUpdate(final String sql) throws SQLException { + public long executeLargeUpdate(final String sql) throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); + setLastUsedInParent(); + try { + return statement.executeLargeUpdate(sql); + } catch (final SQLException e) { + handleException(e); + return 0; } + } + + /** + * @since 2.5.0 + */ + @Override + public long executeLargeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { + checkOpen(); + setLastUsedInParent(); try { - return statement.executeUpdate(sql); + return statement.executeLargeUpdate(sql, autoGeneratedKeys); } catch (final SQLException e) { handleException(e); return 0; } } + /** + * @since 2.5.0 + */ @Override - public int getMaxFieldSize() throws SQLException { + public long executeLargeUpdate(final String sql, final int[] columnIndexes) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - return statement.getMaxFieldSize(); + return statement.executeLargeUpdate(sql, columnIndexes); } catch (final SQLException e) { handleException(e); return 0; } } + /** + * @since 2.5.0 + */ @Override - public void setMaxFieldSize(final int max) throws SQLException { + public long executeLargeUpdate(final String sql, final String[] columnNames) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - statement.setMaxFieldSize(max); + return statement.executeLargeUpdate(sql, columnNames); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public int getMaxRows() throws SQLException { + public ResultSet executeQuery(final String sql) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - return statement.getMaxRows(); + return DelegatingResultSet.wrapResultSet(this, statement.executeQuery(sql)); + } catch (final SQLException e) { + handleException(e); + throw new AssertionError(); + } + } + + @Override + public int executeUpdate(final String sql) throws SQLException { + checkOpen(); + setLastUsedInParent(); + try { + return statement.executeUpdate(sql); } catch (final SQLException e) { handleException(e); return 0; @@ -274,30 +327,35 @@ public class DelegatingStatement extends } @Override - public void setMaxRows(final int max) throws SQLException { + public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - statement.setMaxRows(max); + return statement.executeUpdate(sql, autoGeneratedKeys); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public void setEscapeProcessing(final boolean enable) throws SQLException { + public int executeUpdate(final String sql, final int columnIndexes[]) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - statement.setEscapeProcessing(enable); + return statement.executeUpdate(sql, columnIndexes); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public int getQueryTimeout() throws SQLException { + public int executeUpdate(final String sql, final String columnNames[]) throws SQLException { checkOpen(); + setLastUsedInParent(); try { - return statement.getQueryTimeout(); + return statement.executeUpdate(sql, columnNames); } catch (final SQLException e) { handleException(e); return 0; @@ -305,75 +363,144 @@ public class DelegatingStatement extends } @Override - public void setQueryTimeout(final int seconds) throws SQLException { + protected void finalize() throws Throwable { + // This is required because of statement pooling. The poolable + // statements will always be strongly held by the statement pool. If the + // delegating statements that wrap the poolable statement are not + // strongly held they will be garbage collected but at that point the + // poolable statements need to be returned to the pool else there will + // be a leak of statements from the pool. Closing this statement will + // close all the wrapped statements and return any poolable statements + // to the pool. + close(); + super.finalize(); + } + + @Override + public Connection getConnection() throws SQLException { + checkOpen(); + return getConnectionInternal(); // return the delegating connection that created this + } + + protected DelegatingConnection<?> getConnectionInternal() { + return connection; + } + + /** + * Returns my underlying {@link Statement}. + * + * @return my underlying {@link Statement}. + * @see #getInnermostDelegate + */ + public Statement getDelegate() { + return statement; + } + + @Override + public int getFetchDirection() throws SQLException { checkOpen(); try { - statement.setQueryTimeout(seconds); + return statement.getFetchDirection(); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public void cancel() throws SQLException { + public int getFetchSize() throws SQLException { checkOpen(); try { - statement.cancel(); + return statement.getFetchSize(); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public SQLWarning getWarnings() throws SQLException { + public ResultSet getGeneratedKeys() throws SQLException { checkOpen(); try { - return statement.getWarnings(); + return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys()); } catch (final SQLException e) { handleException(e); throw new AssertionError(); } } + /** + * If my underlying {@link Statement} is not a {@code DelegatingStatement}, returns it, otherwise recursively + * invokes this method on my delegate. + * <p> + * Hence this method will return the first delegate that is not a {@code DelegatingStatement} or {@code null} when + * no non-{@code DelegatingStatement} delegate can be found by traversing this chain. + * </p> + * <p> + * This method is useful when you may have nested {@code DelegatingStatement}s, and you want to make sure to obtain + * a "genuine" {@link Statement}. + * </p> + * + * @return The innermost delegate. + * + * @see #getDelegate + */ + @SuppressWarnings("resource") + public Statement getInnermostDelegate() { + Statement s = statement; + while (s != null && s instanceof DelegatingStatement) { + s = ((DelegatingStatement) s).getDelegate(); + if (this == s) { + return null; + } + } + return s; + } + + /** + * @since 2.5.0 + */ @Override - public void clearWarnings() throws SQLException { + public long getLargeMaxRows() throws SQLException { checkOpen(); try { - statement.clearWarnings(); + return statement.getLargeMaxRows(); } catch (final SQLException e) { handleException(e); + return 0; } } + /** + * @since 2.5.0 + */ @Override - public void setCursorName(final String name) throws SQLException { + public long getLargeUpdateCount() throws SQLException { checkOpen(); try { - statement.setCursorName(name); + return statement.getLargeUpdateCount(); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public boolean execute(final String sql) throws SQLException { + public int getMaxFieldSize() throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } try { - return statement.execute(sql); + return statement.getMaxFieldSize(); } catch (final SQLException e) { handleException(e); - return false; + return 0; } } @Override - public int getUpdateCount() throws SQLException { + public int getMaxRows() throws SQLException { checkOpen(); try { - return statement.getUpdateCount(); + return statement.getMaxRows(); } catch (final SQLException e) { handleException(e); return 0; @@ -392,20 +519,21 @@ public class DelegatingStatement extends } @Override - public void setFetchDirection(final int direction) throws SQLException { + public boolean getMoreResults(final int current) throws SQLException { checkOpen(); try { - statement.setFetchDirection(direction); + return statement.getMoreResults(current); } catch (final SQLException e) { handleException(e); + return false; } } @Override - public int getFetchDirection() throws SQLException { + public int getQueryTimeout() throws SQLException { checkOpen(); try { - return statement.getFetchDirection(); + return statement.getQueryTimeout(); } catch (final SQLException e) { handleException(e); return 0; @@ -413,20 +541,21 @@ public class DelegatingStatement extends } @Override - public void setFetchSize(final int rows) throws SQLException { + public ResultSet getResultSet() throws SQLException { checkOpen(); try { - statement.setFetchSize(rows); + return DelegatingResultSet.wrapResultSet(this, statement.getResultSet()); } catch (final SQLException e) { handleException(e); + throw new AssertionError(); } } @Override - public int getFetchSize() throws SQLException { + public int getResultSetConcurrency() throws SQLException { checkOpen(); try { - return statement.getFetchSize(); + return statement.getResultSetConcurrency(); } catch (final SQLException e) { handleException(e); return 0; @@ -434,10 +563,10 @@ public class DelegatingStatement extends } @Override - public int getResultSetConcurrency() throws SQLException { + public int getResultSetHoldability() throws SQLException { checkOpen(); try { - return statement.getResultSetConcurrency(); + return statement.getResultSetHoldability(); } catch (final SQLException e) { handleException(e); return 0; @@ -456,54 +585,52 @@ public class DelegatingStatement extends } @Override - public void addBatch(final String sql) throws SQLException { + public int getUpdateCount() throws SQLException { checkOpen(); try { - statement.addBatch(sql); + return statement.getUpdateCount(); } catch (final SQLException e) { handleException(e); + return 0; } } @Override - public void clearBatch() throws SQLException { + public SQLWarning getWarnings() throws SQLException { checkOpen(); try { - statement.clearBatch(); + return statement.getWarnings(); } catch (final SQLException e) { handleException(e); + throw new AssertionError(); } } - @Override - public int[] executeBatch() throws SQLException { - checkOpen(); + protected void handleException(final SQLException e) throws SQLException { if (connection != null) { - connection.setLastUsed(); - } - try { - return statement.executeBatch(); - } catch (final SQLException e) { - handleException(e); - throw new AssertionError(); + connection.handleException(e); + } else { + throw e; } } - /** - * Returns a String representation of this object. - * - * @return String + /* + * Note was protected prior to JDBC 4 */ @Override - public String toString() { - return statement == null ? "NULL" : statement.toString(); + public boolean isClosed() throws SQLException { + return closed; + } + + protected boolean isClosedInternal() { + return closed; } @Override - public boolean getMoreResults(final int current) throws SQLException { + public boolean isCloseOnCompletion() throws SQLException { checkOpen(); try { - return statement.getMoreResults(current); + return statement.isCloseOnCompletion(); } catch (final SQLException e) { handleException(e); return false; @@ -511,194 +638,170 @@ public class DelegatingStatement extends } @Override - public ResultSet getGeneratedKeys() throws SQLException { + public boolean isPoolable() throws SQLException { checkOpen(); try { - return DelegatingResultSet.wrapResultSet(this, statement.getGeneratedKeys()); + return statement.isPoolable(); } catch (final SQLException e) { handleException(e); - throw new AssertionError(); + return false; } } @Override - public int executeUpdate(final String sql, final int autoGeneratedKeys) throws SQLException { - checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } - try { - return statement.executeUpdate(sql, autoGeneratedKeys); - } catch (final SQLException e) { - handleException(e); - return 0; + public boolean isWrapperFor(final Class<?> iface) throws SQLException { + if (iface.isAssignableFrom(getClass())) { + return true; + } else if (iface.isAssignableFrom(statement.getClass())) { + return true; + } else { + return statement.isWrapperFor(iface); } } - @Override - public int executeUpdate(final String sql, final int columnIndexes[]) throws SQLException { - checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } - try { - return statement.executeUpdate(sql, columnIndexes); - } catch (final SQLException e) { - handleException(e); - return 0; + /** + * + * @throws SQLException + * thrown by the delegating statement. + * @since 2.4.0 made public, was protected in 2.3.0. + */ + public void passivate() throws SQLException { + if (statement instanceof DelegatingStatement) { + ((DelegatingStatement) statement).passivate(); } } + protected void setClosedInternal(final boolean closed) { + this.closed = closed; + } + @Override - public int executeUpdate(final String sql, final String columnNames[]) throws SQLException { + public void setCursorName(final String name) throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } try { - return statement.executeUpdate(sql, columnNames); + statement.setCursorName(name); } catch (final SQLException e) { handleException(e); - return 0; } } + /** + * Sets my delegate. + * + * @param statement + * my delegate. + */ + public void setDelegate(final Statement statement) { + this.statement = statement; + } + @Override - public boolean execute(final String sql, final int autoGeneratedKeys) throws SQLException { + public void setEscapeProcessing(final boolean enable) throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } try { - return statement.execute(sql, autoGeneratedKeys); + statement.setEscapeProcessing(enable); } catch (final SQLException e) { handleException(e); - return false; } } @Override - public boolean execute(final String sql, final int columnIndexes[]) throws SQLException { + public void setFetchDirection(final int direction) throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } try { - return statement.execute(sql, columnIndexes); + statement.setFetchDirection(direction); } catch (final SQLException e) { handleException(e); - return false; } } @Override - public boolean execute(final String sql, final String columnNames[]) throws SQLException { + public void setFetchSize(final int rows) throws SQLException { checkOpen(); - if (connection != null) { - connection.setLastUsed(); - } try { - return statement.execute(sql, columnNames); + statement.setFetchSize(rows); } catch (final SQLException e) { handleException(e); - return false; } } + /** + * @since 2.5.0 + */ @Override - public int getResultSetHoldability() throws SQLException { + public void setLargeMaxRows(final long max) throws SQLException { checkOpen(); try { - return statement.getResultSetHoldability(); + statement.setLargeMaxRows(max); } catch (final SQLException e) { handleException(e); - return 0; - } - } - - /* - * Note was protected prior to JDBC 4 - */ - @Override - public boolean isClosed() throws SQLException { - return closed; - } - - @Override - public boolean isWrapperFor(final Class<?> iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return true; - } else if (iface.isAssignableFrom(statement.getClass())) { - return true; - } else { - return statement.isWrapperFor(iface); } } - @Override - public <T> T unwrap(final Class<T> iface) throws SQLException { - if (iface.isAssignableFrom(getClass())) { - return iface.cast(this); - } else if (iface.isAssignableFrom(statement.getClass())) { - return iface.cast(statement); - } else { - return statement.unwrap(iface); + private void setLastUsedInParent() { + if (connection != null) { + connection.setLastUsed(); } } @Override - public void setPoolable(final boolean poolable) throws SQLException { + public void setMaxFieldSize(final int max) throws SQLException { checkOpen(); try { - statement.setPoolable(poolable); + statement.setMaxFieldSize(max); } catch (final SQLException e) { handleException(e); } } @Override - public boolean isPoolable() throws SQLException { + public void setMaxRows(final int max) throws SQLException { checkOpen(); try { - return statement.isPoolable(); + statement.setMaxRows(max); } catch (final SQLException e) { handleException(e); - return false; } } @Override - public void closeOnCompletion() throws SQLException { + public void setPoolable(final boolean poolable) throws SQLException { checkOpen(); try { - statement.closeOnCompletion(); + statement.setPoolable(poolable); } catch (final SQLException e) { handleException(e); } } @Override - public boolean isCloseOnCompletion() throws SQLException { + public void setQueryTimeout(final int seconds) throws SQLException { checkOpen(); try { - return statement.isCloseOnCompletion(); + statement.setQueryTimeout(seconds); } catch (final SQLException e) { handleException(e); - return false; } } + /** + * Returns a String representation of this object. + * + * @return String + */ @Override - protected void finalize() throws Throwable { - // This is required because of statement pooling. The poolable - // statements will always be strongly held by the statement pool. If the - // delegating statements that wrap the poolable statement are not - // strongly held they will be garbage collected but at that point the - // poolable statements need to be returned to the pool else there will - // be a leak of statements from the pool. Closing this statement will - // close all the wrapped statements and return any poolable statements - // to the pool. - close(); - super.finalize(); + public String toString() { + return statement == null ? "NULL" : statement.toString(); + } + + @Override + public <T> T unwrap(final Class<T> iface) throws SQLException { + if (iface.isAssignableFrom(getClass())) { + return iface.cast(this); + } else if (iface.isAssignableFrom(statement.getClass())) { + return iface.cast(statement); + } else { + return statement.unwrap(iface); + } } }
Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverConnectionFactory.java Thu Aug 9 16:50:30 2018 @@ -15,6 +15,7 @@ * limitations under the License. */ package org.apache.tomcat.dbcp.dbcp2; + import java.sql.Connection; import java.sql.Driver; import java.sql.SQLException; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/DriverManagerConnectionFactory.java Thu Aug 9 16:50:30 2018 @@ -16,6 +16,7 @@ */ package org.apache.tomcat.dbcp.dbcp2; + import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java Thu Aug 9 16:50:30 2018 @@ -17,7 +17,6 @@ package org.apache.tomcat.dbcp.dbcp2; import java.sql.Connection; -import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; @@ -32,6 +31,105 @@ import org.apache.tomcat.dbcp.dbcp2.Pool public class PStmtKey { /** + * Builder for prepareCall(String sql). + */ + private class PreparedCallSQL implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareCall(sql); + } + } + + /** + * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency). + */ + private class PreparedCallWithResultSetConcurrency implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue()); + } + } + + /** + * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). + */ + private class PreparedCallWithResultSetHoldability implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareCall(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), + resultSetHoldability.intValue()); + } + } + + /** + * Builder for prepareStatement(String sql). + */ + private class PreparedStatementSQL implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql); + } + } + + /** + * Builder for prepareStatement(String sql, int autoGeneratedKeys). + */ + private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql, autoGeneratedKeys.intValue()); + } + } + + /** + * Builder for prepareStatement(String sql, int[] columnIndexes). + */ + private class PreparedStatementWithColumnIndexes implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql, columnIndexes); + } + } + + /** + * Builder for prepareStatement(String sql, String[] columnNames). + */ + private class PreparedStatementWithColumnNames implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql, columnNames); + } + } + + /** + * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency). + */ + private class PreparedStatementWithResultSetConcurrency implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue()); + } + } + + /** + * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). + */ + private class PreparedStatementWithResultSetHoldability implements StatementBuilder { + @Override + public Statement createStatement(final Connection connection) throws SQLException { + return connection.prepareStatement(sql, resultSetType.intValue(), resultSetConcurrency.intValue(), + resultSetHoldability.intValue()); + } + } + + /** + * Interface for Prepared or Callable Statement. + */ + private interface StatementBuilder { + Statement createStatement(Connection connection) throws SQLException; + } + + /** * SQL defining Prepared or Callable Statement */ private final String sql; @@ -54,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>. @@ -79,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); } @@ -96,11 +199,17 @@ public class PStmtKey { * * @param sql * The SQL statement. - * @param catalog - * The catalog. + * @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>. + * @deprecated Use {@link #PStmtKey(String, String, String, int, int)}. */ - public PStmtKey(final String sql, final String catalog) { - this(sql, catalog, StatementType.PREPARED_STATEMENT); + @Deprecated + public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) { + this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); } /** @@ -110,25 +219,11 @@ public class PStmtKey { * The SQL statement. * @param catalog * The catalog. - * @param statementType - * The SQL statement type, prepared or callable. + * @deprecated Use {@link #PStmtKey(String, String, String)}. */ - public PStmtKey(final String sql, final String catalog, final StatementType statementType) { - this.sql = sql; - this.catalog = catalog; - 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(); - } + @Deprecated + public PStmtKey(final String sql, final String catalog) { + this(sql, catalog, StatementType.PREPARED_STATEMENT); } /** @@ -141,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)); } @@ -153,54 +250,17 @@ public class PStmtKey { * The SQL statement. * @param catalog * The catalog. - * @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>. - */ - public PStmtKey(final String sql, final String catalog, final StatementType statementType, - final Integer autoGeneratedKeys) { - this.sql = sql; - this.catalog = catalog; - 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 columnIndexes - * An array of column indexes indicating the columns that should be returned from the inserted row or - * rows. + * @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>. + * @deprecated Use @link {@link #PStmtKey(String, String, String, int, int)}. */ - public PStmtKey(final String sql, final String catalog, final int[] columnIndexes) { - this.sql = sql; - this.catalog = catalog; - 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(); + @Deprecated + public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) { + this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); } /** @@ -210,37 +270,21 @@ public class PStmtKey { * 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. - */ - public PStmtKey(final String sql, final String catalog, final String[] columnNames) { - this.sql = sql; - this.catalog = catalog; - 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 resultSetType - * A result set type; one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, + * 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>. + * <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>. + * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int)}. */ - public PStmtKey(final String sql, final int resultSetType, final int resultSetConcurrency) { - this(sql, null, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); + @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); } /** @@ -251,14 +295,37 @@ public class PStmtKey { * @param catalog * The catalog. * @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>. + * 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. + * @deprecated Use {@link #PStmtKey(String, String, String, int, int, int, PoolingConnection.StatementType)} */ - public PStmtKey(final String sql, final String catalog, final int resultSetType, final int resultSetConcurrency) { - this(sql, catalog, resultSetType, resultSetConcurrency, StatementType.PREPARED_STATEMENT); + @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); + 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(); + } } /** @@ -276,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, PoolingConnection.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; @@ -303,28 +373,180 @@ public class PStmtKey { * The SQL statement. * @param catalog * The catalog. - * @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 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[])}. */ - 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); - } - - /** - * Constructs a key to uniquely identify a prepared statement. + @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); + 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 statementType + * The SQL statement type, prepared or callable. + * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.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; + 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 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>. + * @deprecated Use {@link #PStmtKey(String, String, String, PoolingConnection.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> @@ -336,11 +558,13 @@ public class PStmtKey { * 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 int resultSetType, final int resultSetConcurrency, + 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); @@ -357,88 +581,209 @@ public class PStmtKey { } /** - * Gets the SQL statement. - * - * @return the SQL statement. - */ - public String getSql() { - return sql; - } - - /** - * Gets the result set type, one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, - * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. - * - * @return the result set type. - */ - public Integer getResultSetType() { - return resultSetType; - } - - /** - * Gets the result set concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or - * <code>ResultSet.CONCUR_UPDATABLE</code>. + * Constructs a key to uniquely identify a prepared statement. * - * @return The result set concurrency type. + * @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 Integer getResultSetConcurrency() { - return resultSetConcurrency; + 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(); + } } /** - * Gets the result set holdability, one of the following <code>ResultSet</code> constants: - * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. + * Constructs a key to uniquely identify a prepared statement. * - * @return The result set holdability. + * @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 Integer getResultSetHoldability() { - return resultSetHoldability; + 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(); } /** - * Gets 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>. + * Constructs a key to uniquely identify a prepared statement. * - * @return a flag indicating whether auto-generated keys should be returned. + * @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 Integer getAutoGeneratedKeys() { - return autoGeneratedKeys; + 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(); + } } /** - * Gets an array of column indexes indicating the columns that should be returned from the inserted row or rows. + * Constructs a key to uniquely identify a prepared statement. * - * @return An array of column indexes. + * @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 int[] getColumnIndexes() { - return columnIndexes; + 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; + 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(); + } } /** - * Gets an array of column names indicating the columns that should be returned from the inserted row or rows. + * Constructs a key to uniquely identify a prepared statement. * - * @return An array of column names. - */ - public String[] getColumnNames() { - return columnNames; + * @param sql + * 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(); } /** - * The catalog. + * Constructs a key to uniquely identify a prepared statement. * - * @return The catalog. + * @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[])}. */ - public String getCatalog() { - return catalog; + @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; + this.columnNames = columnNames == null ? null : Arrays.copyOf(columnNames, columnNames.length); + this.resultSetType = null; + this.resultSetConcurrency = null; + this.resultSetHoldability = null; + // create builder + builder = new PreparedStatementWithColumnNames(); } /** - * The SQL statement type. + * Creates a new Statement from the given Connection. * - * @return The SQL statement type. + * @param connection + * The Connection to use to create the statement. + * @return The statement. + * @throws SQLException + * Thrown when there is a problem creating the statement. */ - public StatementType getStmtType() { - return statementType; + public Statement createStatement(final Connection connection) throws SQLException { + if (builder == null) { + throw new IllegalStateException("Prepared statement key is invalid."); + } + return builder.createStatement(connection); } @Override @@ -453,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; @@ -460,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; @@ -467,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; @@ -481,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) { @@ -507,169 +859,140 @@ public class PStmtKey { return true; } - @Override - 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 + Arrays.hashCode(columnIndexes); - result = prime * result + Arrays.hashCode(columnNames); - result = prime * result + statementType.hashCode(); - return result; - } - - @Override - public String toString() { - final StringBuffer buf = new StringBuffer(); - buf.append("PStmtKey: sql="); - buf.append(sql); - buf.append(", catalog="); - buf.append(catalog); - buf.append(", resultSetType="); - buf.append(resultSetType); - buf.append(", resultSetConcurrency="); - buf.append(resultSetConcurrency); - buf.append(", resultSetHoldability="); - buf.append(resultSetHoldability); - buf.append(", autoGeneratedKeys="); - buf.append(autoGeneratedKeys); - buf.append(", columnIndexes="); - buf.append(Arrays.toString(columnIndexes)); - buf.append(", columnNames="); - buf.append(Arrays.toString(columnNames)); - buf.append(", statementType="); - buf.append(statementType); - return buf.toString(); - } - /** - * Creates a new Statement from the given Connection. + * Gets 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>. * - * @param connection - * The Connection to use to create the statement. - * @return The statement. - * @throws SQLException - * Thrown when there is a problem creating the statement. + * @return a flag indicating whether auto-generated keys should be returned. */ - public Statement createStatement(final Connection connection) throws SQLException { - if (builder == null) { - throw new IllegalStateException("Prepared statement key is invalid."); - } - return builder.createStatement(connection); + public Integer getAutoGeneratedKeys() { + return autoGeneratedKeys; } /** - * Interface for Prepared or Callable Statement. + * The catalog. + * + * @return The catalog. */ - private interface StatementBuilder { - public Statement createStatement(Connection connection) throws SQLException; + public String getCatalog() { + return catalog; } /** - * Builder for prepareStatement(String sql). + * Gets an array of column indexes indicating the columns that should be returned from the inserted row or rows. + * + * @return An array of column indexes. */ - private class PreparedStatementSQL implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql); - return statement; - } + public int[] getColumnIndexes() { + return columnIndexes; } /** - * Builder for prepareStatement(String sql, int autoGeneratedKeys). + * Gets an array of column names indicating the columns that should be returned from the inserted row or rows. + * + * @return An array of column names. */ - private class PreparedStatementWithAutoGeneratedKeys implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql, autoGeneratedKeys.intValue()); - return statement; - } + public String[] getColumnNames() { + return columnNames; } /** - * Builder for prepareStatement(String sql, int[] columnIndexes). + * Gets the result set concurrency type; one of <code>ResultSet.CONCUR_READ_ONLY</code> or + * <code>ResultSet.CONCUR_UPDATABLE</code>. + * + * @return The result set concurrency type. */ - private class PreparedStatementWithColumnIndexes implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql, columnIndexes); - return statement; - } + public Integer getResultSetConcurrency() { + return resultSetConcurrency; } /** - * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency). + * Gets the result set holdability, one of the following <code>ResultSet</code> constants: + * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>. + * + * @return The result set holdability. */ - private class PreparedStatementWithResultSetConcurrency implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql, resultSetType.intValue(), - resultSetConcurrency.intValue()); - return statement; - } + public Integer getResultSetHoldability() { + return resultSetHoldability; } /** - * Builder for prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). + * Gets the result set type, one of <code>ResultSet.TYPE_FORWARD_ONLY</code>, + * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>. + * + * @return the result set type. */ - private class PreparedStatementWithResultSetHoldability implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql, resultSetType.intValue(), - resultSetConcurrency.intValue(), resultSetHoldability.intValue()); - return statement; - } + public Integer getResultSetType() { + return resultSetType; } /** - * Builder for prepareStatement(String sql, String[] columnNames). + * The schema. + * + * @return The catalog. */ - private class PreparedStatementWithColumnNames implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareStatement(sql, columnNames); - return statement; - } + public String getSchema() { + return schema; } /** - * Builder for prepareCall(String sql). + * Gets the SQL statement. + * + * @return the SQL statement. */ - private class PreparedCallSQL implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareCall(sql); - return statement; - } + public String getSql() { + return sql; } /** - * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency). + * The SQL statement type. + * + * @return The SQL statement type. */ - private class PreparedCallWithResultSetConcurrency implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareCall(sql, resultSetType.intValue(), - resultSetConcurrency.intValue()); - return statement; - } + public StatementType getStmtType() { + return statementType; } - /** - * Builder for prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability). - */ - private class PreparedCallWithResultSetHoldability implements StatementBuilder { - @Override - public Statement createStatement(final Connection connection) throws SQLException { - final PreparedStatement statement = connection.prepareCall(sql, resultSetType.intValue(), - resultSetConcurrency.intValue(), resultSetHoldability.intValue()); - return statement; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + 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 + ((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; + } + + @Override + public String toString() { + final StringBuffer buf = new StringBuffer(); + buf.append("PStmtKey: sql="); + buf.append(sql); + buf.append(", catalog="); + buf.append(catalog); + buf.append(", schema="); + buf.append(schema); + buf.append(", resultSetType="); + buf.append(resultSetType); + buf.append(", resultSetConcurrency="); + buf.append(resultSetConcurrency); + buf.append(", resultSetHoldability="); + buf.append(resultSetHoldability); + buf.append(", autoGeneratedKeys="); + buf.append(autoGeneratedKeys); + buf.append(", columnIndexes="); + buf.append(Arrays.toString(columnIndexes)); + buf.append(", columnNames="); + buf.append(Arrays.toString(columnNames)); + buf.append(", statementType="); + buf.append(statementType); + return buf.toString(); } } Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java Thu Aug 9 16:50:30 2018 @@ -117,7 +117,7 @@ public class PoolableConnection extends */ public PoolableConnection(final Connection conn, final ObjectPool<PoolableConnection> pool, final ObjectName jmxName) { - this(conn, pool, jmxName, null, false); + this(conn, pool, jmxName, null, true); } @Override Modified: tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java?rev=1837746&r1=1837745&r2=1837746&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/dbcp/dbcp2/PoolableConnectionFactory.java Thu Aug 9 16:50:30 2018 @@ -157,6 +157,17 @@ public class PoolableConnectionFactory i this.defaultCatalog = defaultCatalog; } + /** + * Sets the default "schema" setting for borrowed {@link Connection}s + * + * @param defaultSchema + * the default "schema" setting for borrowed {@link Connection}s + * @since 2.5.0 + */ + public void setDefaultSchema(final String defaultSchema) { + this.defaultSchema = defaultSchema; + } + public void setCacheState(final boolean cacheState) { this.cacheState = cacheState; } @@ -259,6 +270,7 @@ public class PoolableConnectionFactory i * @return true if connections created by this factory will fast fail validation. * @see #setDisconnectionSqlCodes(Collection) * @since 2.1 + * @since 2.5.0 Defaults to true, previous versions defaulted to false. */ public boolean isFastFailValidation() { return fastFailValidation; @@ -312,10 +324,11 @@ public class PoolableConnectionFactory i } else { config.setJmxEnabled(false); } + final PoolingConnection poolingConn = (PoolingConnection) conn; final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> stmtPool = new GenericKeyedObjectPool<>( - (PoolingConnection) conn, config); - ((PoolingConnection) conn).setStatementPool(stmtPool); - ((PoolingConnection) conn).setCacheState(cacheState); + poolingConn, config); + poolingConn.setStatementPool(stmtPool); + poolingConn.setCacheState(cacheState); } // Register this connection with JMX @@ -427,6 +440,9 @@ public class PoolableConnectionFactory i if (defaultCatalog != null && !defaultCatalog.equals(conn.getCatalog())) { conn.setCatalog(defaultCatalog); } + if (defaultSchema != null && !defaultSchema.equals(conn.getSchema())) { + conn.setSchema(defaultSchema); + } conn.setDefaultQueryTimeout(defaultQueryTimeoutSeconds); } @@ -470,7 +486,7 @@ public class PoolableConnectionFactory i private volatile int validationQueryTimeoutSeconds = -1; private Collection<String> connectionInitSqls; private Collection<String> disconnectionSqlCodes; - private boolean fastFailValidation; + private boolean fastFailValidation = true; private volatile ObjectPool<PoolableConnection> pool; private Boolean defaultReadOnly; private Boolean defaultAutoCommit; @@ -478,6 +494,7 @@ public class PoolableConnectionFactory i private boolean rollbackOnReturn = true; private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION; private String defaultCatalog; + private String defaultSchema; private boolean cacheState; private boolean poolStatements; private int maxOpenPreparedStatements = GenericKeyedObjectPoolConfig.DEFAULT_MAX_TOTAL_PER_KEY; --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org