Skip to content

Commit

Permalink
feat: expose more methods from Connection in JDBC (#255)
Browse files Browse the repository at this point in the history
* feat: expose more methods from Connection in JDBC

More methods from the Connection API should be exposed in the
Cloud Spanner JDBC Connection interface to make it easier to
execute read-only transactions with specific timestamp bounds.

Towards #253

* clirr: add ignored differences
  • Loading branch information
olavloite committed Dec 5, 2020
1 parent 83e80fc commit 697837c
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 0 deletions.
52 changes: 52 additions & 0 deletions clirr-ignored-differences.xml
Expand Up @@ -42,4 +42,56 @@
<differenceType>8001</differenceType>
<className>com/google/cloud/spanner/jdbc/UnitOfWork$UnitOfWorkState</className>
</difference>

<!-- Expose more methods from Connection API in CloudSpannerJdbcConnection -->
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>com.google.cloud.spanner.connection.AutocommitDmlMode getAutocommitDmlMode()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>java.lang.String getOptimizerVersion()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>com.google.cloud.spanner.TimestampBound getReadOnlyStaleness()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>com.google.cloud.spanner.connection.TransactionMode getTransactionMode()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>boolean isInTransaction()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>boolean isTransactionStarted()</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>void setAutocommitDmlMode(com.google.cloud.spanner.connection.AutocommitDmlMode)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>void setOptimizerVersion(java.lang.String)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>void setReadOnlyStaleness(com.google.cloud.spanner.TimestampBound)</method>
</difference>
<difference>
<differenceType>7012</differenceType>
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
<method>void setTransactionMode(com.google.cloud.spanner.connection.TransactionMode)</method>
</difference>
</differences>
Expand Up @@ -19,6 +19,9 @@
import com.google.cloud.spanner.AbortedException;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.TimestampBound;
import com.google.cloud.spanner.connection.AutocommitDmlMode;
import com.google.cloud.spanner.connection.TransactionMode;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
Expand All @@ -34,6 +37,113 @@
*/
public interface CloudSpannerJdbcConnection extends Connection {

/**
* Sets the transaction mode to use for current transaction. This method may only be called when
* in a transaction, and before the transaction is actually started, i.e. before any statements
* have been executed in the transaction.
*
* @param transactionMode The transaction mode to use for the current transaction.
* <ul>
* <li>{@link TransactionMode#READ_ONLY_TRANSACTION} will create a read-only transaction and
* prevent any changes to written to the database through this transaction. The read
* timestamp to be used will be determined based on the current readOnlyStaleness
* setting of this connection. It is recommended to use {@link
* TransactionMode#READ_ONLY_TRANSACTION} instead of {@link
* TransactionMode#READ_WRITE_TRANSACTION} when possible, as read-only transactions do
* not acquire locks on Cloud Spanner, and read-only transactions never abort.
* <li>{@link TransactionMode#READ_WRITE_TRANSACTION} this value is only allowed when the
* connection is not in read-only mode and will create a read-write transaction. If
* {@link Connection#isRetryAbortsInternally()} is <code>true</code>, each read/write
* transaction will keep track of a running SHA256 checksum for each {@link ResultSet}
* that is returned in order to be able to retry the transaction in case the transaction
* is aborted by Spanner.
* </ul>
*/
void setTransactionMode(TransactionMode transactionMode) throws SQLException;

/**
* @return the transaction mode of the current transaction. This method may only be called when
* the connection is in a transaction.
*/
TransactionMode getTransactionMode() throws SQLException;

/**
* Sets the mode for executing DML statements in autocommit mode for this connection. This setting
* is only used when the connection is in autocommit mode, and may only be set while the
* transaction is in autocommit mode and not in a temporary transaction. The autocommit
* transaction mode is reset to its default value of {@link AutocommitDmlMode#TRANSACTIONAL} when
* autocommit mode is changed on the connection.
*
* @param mode The DML autocommit mode to use
* <ul>
* <li>{@link AutocommitDmlMode#TRANSACTIONAL} DML statements are executed as single
* read-write transaction. After successful execution, the DML statement is guaranteed
* to have been applied exactly once to the database
* <li>{@link AutocommitDmlMode#PARTITIONED_NON_ATOMIC} DML statements are executed as
* partitioned DML transactions. If an error occurs during the execution of the DML
* statement, it is possible that the statement has been applied to some but not all of
* the rows specified in the statement.
* </ul>
*/
void setAutocommitDmlMode(AutocommitDmlMode mode) throws SQLException;

/**
* @return the current {@link AutocommitDmlMode} setting for this connection. This method may only
* be called on a connection that is in autocommit mode and not while in a temporary
* transaction.
*/
AutocommitDmlMode getAutocommitDmlMode() throws SQLException;

/**
* Sets the staleness to use for the current read-only transaction. This method may only be called
* when the transaction mode of the current transaction is {@link
* TransactionMode#READ_ONLY_TRANSACTION} and there is no transaction that has started, or when
* the connection is in read-only and autocommit mode.
*
* @param staleness The staleness to use for the current but not yet started read-only transaction
*/
void setReadOnlyStaleness(TimestampBound staleness) throws SQLException;

/**
* @return the read-only staleness setting for the current read-only transaction. This method may
* only be called when the current transaction is a read-only transaction, or when the
* connection is in read-only and autocommit mode.
*/
TimestampBound getReadOnlyStaleness() throws SQLException;

/**
* Sets the query optimizer version to use for this connection.
*
* @param optimizerVersion The query optimizer version to use. Must be a valid optimizer version
* number, the string <code>LATEST</code> or an empty string. The empty string will instruct
* the connection to use the optimizer version that is defined in the environment variable
* <code>SPANNER_OPTIMIZER_VERSION</code>. If no value is specified in the environment
* variable, the default query optimizer of Cloud Spanner is used.
*/
void setOptimizerVersion(String optimizerVersion) throws SQLException;

/**
* Gets the current query optimizer version of this connection.
*
* @return The query optimizer version that is currently used by this connection.
*/
String getOptimizerVersion() throws SQLException;

/**
* @return <code>true</code> if this connection has a transaction (that has not necessarily
* started). This method will only return false when the {@link Connection} is in autocommit
* mode and no explicit transaction has been started by calling {@link
* Connection#beginTransaction()}. If the {@link Connection} is not in autocommit mode, there
* will always be a transaction.
*/
boolean isInTransaction() throws SQLException;

/**
* @return <code>true</code> if this connection has a transaction that has started. A transaction
* is automatically started by the first statement that is executed in the transaction.
*/
boolean isTransactionStarted() throws SQLException;

/**
* @return the commit {@link Timestamp} of the last read/write transaction. If the last
* transaction was not a read/write transaction, or a read/write transaction that did not
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java
Expand Up @@ -19,8 +19,11 @@
import com.google.api.client.util.Preconditions;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.TimestampBound;
import com.google.cloud.spanner.connection.AutocommitDmlMode;
import com.google.cloud.spanner.connection.ConnectionOptions;
import com.google.cloud.spanner.connection.StatementParser;
import com.google.cloud.spanner.connection.TransactionMode;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import java.sql.Array;
Expand Down Expand Up @@ -74,6 +77,66 @@ public String nativeSQL(String sql) throws SQLException {
.sqlWithNamedParameters;
}

@Override
public void setTransactionMode(TransactionMode mode) throws SQLException {
checkClosed();
getSpannerConnection().setTransactionMode(mode);
}

@Override
public TransactionMode getTransactionMode() throws SQLException {
checkClosed();
return getSpannerConnection().getTransactionMode();
}

@Override
public void setAutocommitDmlMode(AutocommitDmlMode mode) throws SQLException {
checkClosed();
getSpannerConnection().setAutocommitDmlMode(mode);
}

@Override
public AutocommitDmlMode getAutocommitDmlMode() throws SQLException {
checkClosed();
return getSpannerConnection().getAutocommitDmlMode();
}

@Override
public void setReadOnlyStaleness(TimestampBound staleness) throws SQLException {
checkClosed();
getSpannerConnection().setReadOnlyStaleness(staleness);
}

@Override
public TimestampBound getReadOnlyStaleness() throws SQLException {
checkClosed();
return getSpannerConnection().getReadOnlyStaleness();
}

@Override
public void setOptimizerVersion(String optimizerVersion) throws SQLException {
checkClosed();
getSpannerConnection().setOptimizerVersion(optimizerVersion);
}

@Override
public String getOptimizerVersion() throws SQLException {
checkClosed();
return getSpannerConnection().getOptimizerVersion();
}

@Override
public boolean isInTransaction() throws SQLException {
checkClosed();
return getSpannerConnection().isInTransaction();
}

@Override
public boolean isTransactionStarted() throws SQLException {
checkClosed();
return getSpannerConnection().isTransactionStarted();
}

@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
checkClosed();
Expand Down

0 comments on commit 697837c

Please sign in to comment.