Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit 98f01bb

Browse files
authored
feat: auto_batch_dml methods + combination with JDBC batching (#1795)
* feat: auto_batch_dml methods + combination with JDBC batching Adds methods for enabling/disabling auto_batch_dml. Also enables the use of this feature in combination with other JDBC batches. This again allows PreparedStatement#addBatch() and Statement#addBatch(String) to be used in combination with auto_batch_dml. This again makes it usable in combination with frameworks like Hibernate. * test: remove expected error from test * chore: add clirr diffs
1 parent f52a087 commit 98f01bb

6 files changed

Lines changed: 455 additions & 27 deletions

File tree

clirr-ignored-differences.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,36 @@
7676
<differenceType>8001</differenceType>
7777
<className>com/google/cloud/spanner/connection/ConnectionHelper</className>
7878
</difference>
79+
80+
<!-- DML auto batching -->
81+
<difference>
82+
<differenceType>7012</differenceType>
83+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
84+
<method>boolean isAutoBatchDml()</method>
85+
</difference>
86+
<difference>
87+
<differenceType>7012</differenceType>
88+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
89+
<method>void setAutoBatchDml(boolean)</method>
90+
</difference>
91+
<difference>
92+
<differenceType>7012</differenceType>
93+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
94+
<method>long getAutoBatchDmlUpdateCount()</method>
95+
</difference>
96+
<difference>
97+
<differenceType>7012</differenceType>
98+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
99+
<method>void setAutoBatchDmlUpdateCount(long)</method>
100+
</difference>
101+
<difference>
102+
<differenceType>7012</differenceType>
103+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
104+
<method>boolean isAutoBatchDmlUpdateCountVerification()</method>
105+
</difference>
106+
<difference>
107+
<differenceType>7012</differenceType>
108+
<className>com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection</className>
109+
<method>void setAutoBatchDmlUpdateCountVerification(boolean)</method>
110+
</difference>
79111
</differences>

src/main/java/com/google/cloud/spanner/jdbc/CloudSpannerJdbcConnection.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,57 @@ default int getMaxPartitionedParallelism() throws SQLException {
406406
throw new UnsupportedOperationException();
407407
}
408408

409+
/**
410+
* Enables or disables automatic batching of DML statements. When enabled, DML statements that are
411+
* executed on this connection will be buffered in memory instead of actually being executed. The
412+
* buffered DML statements are flushed to Spanner when a statement that cannot be part of a DML
413+
* batch is executed on the connection. This can be a query, a DDL statement with a THEN RETURN
414+
* clause, or a Commit call. The update count that is returned for DML statements that are
415+
* buffered is determined by the value that has been set with {@link
416+
* #setAutoBatchDmlUpdateCount(long)}. The default is 1. The connection verifies that the update
417+
* counts that were returned while buffering DML statements match the actual update counts that
418+
* are returned by Spanner when the batch is executed. This verification can be disabled by
419+
* calling {@link #setAutoBatchDmlUpdateCountVerification(boolean)}.
420+
*/
421+
default void setAutoBatchDml(boolean autoBatchDml) throws SQLException {
422+
throw new UnsupportedOperationException();
423+
}
424+
425+
/** Returns whether automatic DML batching is enabled on this connection. */
426+
default boolean isAutoBatchDml() throws SQLException {
427+
throw new UnsupportedOperationException();
428+
}
429+
430+
/**
431+
* Sets the update count that is returned for DML statements that are buffered during an automatic
432+
* DML batch. This value is only used if {@link #isAutoBatchDml()} is enabled.
433+
*/
434+
default void setAutoBatchDmlUpdateCount(long updateCount) throws SQLException {
435+
throw new UnsupportedOperationException();
436+
}
437+
438+
/**
439+
* Returns the update count that is returned for DML statements that are buffered during an
440+
* automatic DML batch.
441+
*/
442+
default long getAutoBatchDmlUpdateCount() throws SQLException {
443+
throw new UnsupportedOperationException();
444+
}
445+
446+
/**
447+
* Sets whether the update count that is returned by Spanner after executing an automatic DML
448+
* batch should be verified against the update counts that were returned during the buffering of
449+
* those statements.
450+
*/
451+
default void setAutoBatchDmlUpdateCountVerification(boolean verification) throws SQLException {
452+
throw new UnsupportedOperationException();
453+
}
454+
455+
/** Indicates whether the update counts of automatic DML batches should be verified. */
456+
default boolean isAutoBatchDmlUpdateCountVerification() throws SQLException {
457+
throw new UnsupportedOperationException();
458+
}
459+
409460
/**
410461
* @see
411462
* com.google.cloud.spanner.connection.Connection#addTransactionRetryListener(com.google.cloud.spanner.connection.TransactionRetryListener)

src/main/java/com/google/cloud/spanner/jdbc/JdbcConnection.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,36 @@ public int getMaxPartitionedParallelism() throws SQLException {
770770
return get(Connection::getMaxPartitionedParallelism);
771771
}
772772

773+
@Override
774+
public void setAutoBatchDml(boolean autoBatchDml) throws SQLException {
775+
set(Connection::setAutoBatchDml, autoBatchDml);
776+
}
777+
778+
@Override
779+
public boolean isAutoBatchDml() throws SQLException {
780+
return get(Connection::isAutoBatchDml);
781+
}
782+
783+
@Override
784+
public void setAutoBatchDmlUpdateCount(long updateCount) throws SQLException {
785+
set(Connection::setAutoBatchDmlUpdateCount, updateCount);
786+
}
787+
788+
@Override
789+
public long getAutoBatchDmlUpdateCount() throws SQLException {
790+
return get(Connection::getAutoBatchDmlUpdateCount);
791+
}
792+
793+
@Override
794+
public void setAutoBatchDmlUpdateCountVerification(boolean verification) throws SQLException {
795+
set(Connection::setAutoBatchDmlUpdateCountVerification, verification);
796+
}
797+
798+
@Override
799+
public boolean isAutoBatchDmlUpdateCountVerification() throws SQLException {
800+
return get(Connection::isAutoBatchDmlUpdateCountVerification);
801+
}
802+
773803
@SuppressWarnings("deprecation")
774804
private static final class JdbcToSpannerTransactionRetryListener
775805
implements com.google.cloud.spanner.connection.TransactionRetryListener {

src/main/java/com/google/cloud/spanner/jdbc/JdbcStatement.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,6 @@ private BatchType determineStatementBatchType(String sql) throws SQLException {
391391
* client side statement) or if the connection of this statement has an active batch.
392392
*/
393393
void checkAndSetBatchType(String sql) throws SQLException {
394-
checkConnectionHasNoActiveBatch();
395394
BatchType type = determineStatementBatchType(sql);
396395
if (this.currentBatchType == BatchType.NONE) {
397396
this.currentBatchType = type;
@@ -401,15 +400,6 @@ void checkAndSetBatchType(String sql) throws SQLException {
401400
}
402401
}
403402

404-
private void checkConnectionHasNoActiveBatch() throws SQLException {
405-
if (getConnection().getSpannerConnection().isDdlBatchActive()
406-
|| getConnection().getSpannerConnection().isDmlBatchActive()) {
407-
throw JdbcSqlExceptionFactory.of(
408-
"Calling addBatch() is not allowed when a DML or DDL batch has been started on the connection.",
409-
Code.FAILED_PRECONDITION);
410-
}
411-
}
412-
413403
@Override
414404
public void addBatch(String sql) throws SQLException {
415405
checkClosed();
@@ -420,7 +410,6 @@ public void addBatch(String sql) throws SQLException {
420410
@Override
421411
public void clearBatch() throws SQLException {
422412
checkClosed();
423-
checkConnectionHasNoActiveBatch();
424413
batchedStatements.clear();
425414
this.currentBatchType = BatchType.NONE;
426415
}
@@ -436,7 +425,6 @@ public long[] executeLargeBatch() throws SQLException {
436425

437426
private long[] executeBatch(boolean large) throws SQLException {
438427
checkClosed();
439-
checkConnectionHasNoActiveBatch();
440428
StatementTimeout originalTimeout = setTemporaryStatementTimeout();
441429
try {
442430
switch (this.currentBatchType) {

0 commit comments

Comments
 (0)