Skip to content

Commit

Permalink
Raise SQLException on methods of a closed Connection
Browse files Browse the repository at this point in the history
Add missed checks on methods of the closed connection.

Closes: #72
Affects: #119, #74
  • Loading branch information
nicktorwald committed Apr 9, 2019
1 parent 06755d5 commit a616415
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 26 deletions.
144 changes: 133 additions & 11 deletions src/main/java/org/tarantool/jdbc/SQLConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.ClientInfoStatus;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
Expand All @@ -29,6 +30,9 @@
import java.sql.Statement;
import java.sql.Struct;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
Expand All @@ -40,10 +44,10 @@
import static org.tarantool.jdbc.SQLDriver.PROP_SOCKET_TIMEOUT;
import static org.tarantool.jdbc.SQLDriver.PROP_USER;

@SuppressWarnings("Since15")
public class SQLConnection implements Connection {

private static final int UNSET_HOLDABILITY = 0;
private static final String PING_QUERY = "SELECT 1";

private final TarantoolConnection connection;

Expand Down Expand Up @@ -91,6 +95,7 @@ public class SQLConnection implements Connection {
* to honor this timeout for the following read/write operations as well.
*
* @return Connected socket.
*
* @throws SQLException if failed.
*/
protected Socket getConnectedSocket() throws SQLException {
Expand Down Expand Up @@ -140,7 +145,9 @@ protected Socket makeSocket() {
* @param user User name.
* @param pass Password.
* @param socket Connected socket.
*
* @return Native tarantool connection.
*
* @throws IOException if failed.
*/
protected TarantoolConnection makeConnection(String user, String pass, Socket socket) throws IOException {
Expand All @@ -161,7 +168,7 @@ public PreparedStatement prepareStatement(String sql) throws SQLException {

@Override
public CallableStatement prepareCall(String sql) throws SQLException {
throw new SQLFeatureNotSupportedException();
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
}

@Override
Expand All @@ -171,25 +178,38 @@ public String nativeSQL(String sql) throws SQLException {

@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
checkNotClosed();
if (autoCommit == false) {
throw new SQLFeatureNotSupportedException();
}
}

@Override
public boolean getAutoCommit() throws SQLException {
checkNotClosed();
return true;
}

@Override
public void commit() throws SQLException {
throw new SQLFeatureNotSupportedException();
checkNotClosed();
if (getAutoCommit()) {
throw new SQLNonTransientException(
"Cannot commit when auto-commit is enabled.",
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
);
}
}

@Override
public void rollback() throws SQLException {
throw new SQLFeatureNotSupportedException();

checkNotClosed();
if (getAutoCommit()) {
throw new SQLNonTransientException(
"Cannot rollback when auto-commit is enabled.",
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
);
}
}

@Override
Expand All @@ -213,43 +233,50 @@ public DatabaseMetaData getMetaData() throws SQLException {

@Override
public void setReadOnly(boolean readOnly) throws SQLException {

checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public boolean isReadOnly() throws SQLException {
checkNotClosed();
return false;
}

@Override
public void setCatalog(String catalog) throws SQLException {
checkNotClosed();
}

@Override
public String getCatalog() throws SQLException {
checkNotClosed();
return null;
}

@Override
public void setTransactionIsolation(int level) throws SQLException {
checkNotClosed();
if (level != Connection.TRANSACTION_NONE) {
throw new SQLFeatureNotSupportedException();
}
}

@Override
public int getTransactionIsolation() throws SQLException {
checkNotClosed();
return Connection.TRANSACTION_NONE;
}

@Override
public SQLWarning getWarnings() throws SQLException {
checkNotClosed();
return null;
}

@Override
public void clearWarnings() throws SQLException {

checkNotClosed();
}

@Override
Expand All @@ -265,16 +292,18 @@ public PreparedStatement prepareStatement(String sql, int resultSetType, int res

@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
throw new SQLFeatureNotSupportedException();
return prepareCall(sql, resultSetType, resultSetConcurrency, getHoldability());
}

@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

Expand All @@ -296,21 +325,43 @@ public int getHoldability() throws SQLException {

@Override
public Savepoint setSavepoint() throws SQLException {
checkNotClosed();
if (getAutoCommit()) {
throw new SQLNonTransientException(
"Cannot set a savepoint when auto-commit is enabled.",
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
);
}
throw new SQLFeatureNotSupportedException();
}

@Override
public Savepoint setSavepoint(String name) throws SQLException {
checkNotClosed();
if (getAutoCommit()) {
throw new SQLNonTransientException(
"Cannot set a savepoint when auto-commit is enabled.",
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
);
}
throw new SQLFeatureNotSupportedException();
}

@Override
public void rollback(Savepoint savepoint) throws SQLException {
checkNotClosed();
if (getAutoCommit()) {
throw new SQLNonTransientException(
"Cannot roll back to a savepoint when auto-commit is enabled.",
SQLStates.IVALID_TRANSACTION_STATE.getSqlState()
);
}
throw new SQLFeatureNotSupportedException();
}

@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

Expand All @@ -336,90 +387,159 @@ public PreparedStatement prepareStatement(String sql,
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public Clob createClob() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public Blob createBlob() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public NClob createNClob() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public SQLXML createSQLXML() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

/**
* {@inheritDoc}
*
* @param timeout temporally ignored param
*
* @return connection activity status
*/
@Override
public boolean isValid(int timeout) throws SQLException {
return true;
}

@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
throw new SQLClientInfoException();
try {
checkNotClosed();
throwUnknownClientProperties(Collections.singleton(name));
} catch (SQLException cause) {
throwUnknownReasonClientProperties("Connection is closed", Collections.singleton(name), cause);
}
}

@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
throw new SQLClientInfoException();
try {
checkNotClosed();
throwUnknownClientProperties(properties.keySet());
} catch (SQLException cause) {
throwUnknownReasonClientProperties("Connection is closed", properties.keySet(), cause);
}
}

/**
* Throws an exception caused by {@code cause} and marks all properties
* as {@link ClientInfoStatus#REASON_UNKNOWN}
*
* @param reason reason mesage
* @param properties client properties
* @param cause original cause
*
* @throws SQLClientInfoException wrapped exception
*/
private void throwUnknownReasonClientProperties(String reason,
Collection<Object> properties,
SQLException cause) throws SQLClientInfoException {
Map<String, ClientInfoStatus> failedProperties = new HashMap<>();
properties.forEach(property -> {
failedProperties.put(property.toString(), ClientInfoStatus.REASON_UNKNOWN);
});
throw new SQLClientInfoException(reason, failedProperties, cause);
}

/**
* Throws exception for unrecognizable properties
*
* @param properties unknown property names
*
* @throws SQLClientInfoException wrapped exception
*/
private void throwUnknownClientProperties(Collection<Object> properties) throws SQLClientInfoException {
Map<String, ClientInfoStatus> failedProperties = new HashMap<>();
properties.forEach(property -> {
failedProperties.put(property.toString(), ClientInfoStatus.REASON_UNKNOWN_PROPERTY);
});
throw new SQLClientInfoException(failedProperties);
}

@Override
public String getClientInfo(String name) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public Properties getClientInfo() throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
checkNotClosed();
throw new SQLFeatureNotSupportedException();
}

@Override
public void setSchema(String schema) throws SQLException {
checkNotClosed();
}

@Override
public String getSchema() throws SQLException {
checkNotClosed();
return null;
}

@Override
public void abort(Executor executor) throws SQLException {
if (isClosed()) {
return;
}
throw new SQLFeatureNotSupportedException();
}

Expand Down Expand Up @@ -544,8 +664,9 @@ private void handleException(Exception e) {
* Checks whether <code>holdability</code> is supported
*
* @param holdability param to be checked
*
* @throws SQLFeatureNotSupportedException param is not supported
* @throws SQLNonTransientException param has invalid value
* @throws SQLNonTransientException param has invalid value
*/
private void checkHoldabilitySupport(int holdability) throws SQLException {
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT
Expand All @@ -562,6 +683,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
*
* @param sql SQL Text.
* @param params Parameters of the SQL statement.
*
* @return Formatted error message.
*/
private static String formatError(String sql, Object... params) {
Expand Down
Loading

0 comments on commit a616415

Please sign in to comment.