Skip to content

Commit ece1390

Browse files
chore: Support dml_batch_update_count option in PG dialect (#4142)
* chore: Support dml_batch_update_count option in PG dialect * chore: generate libraries at Wed Oct 8 21:30:02 UTC 2025 * Support in GoogleSQL dialect * Address comments * Fix tests * Update connection property name * Address comments --------- Co-authored-by: cloud-java-bot <[email protected]>
1 parent cf7e99c commit ece1390

File tree

15 files changed

+3379
-226
lines changed

15 files changed

+3379
-226
lines changed

.github/workflows/update_generation_config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
# the branch into which the pull request is merged
2727
base_branch: main
2828
steps:
29-
- uses: actions/checkout@v5
29+
- uses: actions/checkout@v4
3030
with:
3131
fetch-depth: 0
3232
token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static com.google.cloud.spanner.connection.ConnectionProperties.AUTO_BATCH_DML_UPDATE_COUNT;
2626
import static com.google.cloud.spanner.connection.ConnectionProperties.AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION;
2727
import static com.google.cloud.spanner.connection.ConnectionProperties.AUTO_PARTITION_MODE;
28+
import static com.google.cloud.spanner.connection.ConnectionProperties.BATCH_DML_UPDATE_COUNT;
2829
import static com.google.cloud.spanner.connection.ConnectionProperties.DATA_BOOST_ENABLED;
2930
import static com.google.cloud.spanner.connection.ConnectionProperties.DDL_IN_TRANSACTION_MODE;
3031
import static com.google.cloud.spanner.connection.ConnectionProperties.DEFAULT_ISOLATION_LEVEL;
@@ -1607,6 +1608,10 @@ public long getAutoBatchDmlUpdateCount() {
16071608
return getConnectionPropertyValue(AUTO_BATCH_DML_UPDATE_COUNT);
16081609
}
16091610

1611+
long getDmlBatchUpdateCount() {
1612+
return getConnectionPropertyValue(BATCH_DML_UPDATE_COUNT);
1613+
}
1614+
16101615
@Override
16111616
public void setAutoBatchDmlUpdateCountVerification(boolean verification) {
16121617
setConnectionPropertyValue(AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION, verification);
@@ -1617,6 +1622,10 @@ public boolean isAutoBatchDmlUpdateCountVerification() {
16171622
return getConnectionPropertyValue(AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION);
16181623
}
16191624

1625+
void setBatchDmlUpdateCount(long updateCount, boolean local) {
1626+
setConnectionPropertyValue(BATCH_DML_UPDATE_COUNT, updateCount, local);
1627+
}
1628+
16201629
@Override
16211630
public void setDataBoostEnabled(boolean dataBoostEnabled) {
16221631
setConnectionPropertyValue(DATA_BOOST_ENABLED, dataBoostEnabled);
@@ -2340,6 +2349,7 @@ UnitOfWork createNewUnitOfWork(
23402349
.setAutoBatchUpdateCountSupplier(this::getAutoBatchDmlUpdateCount)
23412350
.setAutoBatchUpdateCountVerificationSupplier(
23422351
this::isAutoBatchDmlUpdateCountVerification)
2352+
.setDmlBatchUpdateCountSupplier(this::getDmlBatchUpdateCount)
23432353
.setTransaction(currentUnitOfWork)
23442354
.setStatementTimeout(statementTimeout)
23452355
.withStatementExecutor(statementExecutor)

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ public class ConnectionOptions {
181181
static final boolean DEFAULT_ENABLE_END_TO_END_TRACING = false;
182182
static final boolean DEFAULT_AUTO_BATCH_DML = false;
183183
static final long DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT = 1L;
184+
static final long DEFAULT_BATCH_DML_UPDATE_COUNT = -1L;
184185
static final boolean DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION = true;
185186
private static final String EXPERIMENTAL_HOST_PROJECT_ID = "default";
186187
private static final String DEFAULT_EXPERIMENTAL_HOST_INSTANCE_ID = "default";
@@ -314,6 +315,7 @@ public class ConnectionOptions {
314315
"auto_batch_dml_update_count";
315316
public static final String AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION_PROPERTY_NAME =
316317
"auto_batch_dml_update_count_verification";
318+
public static final String BATCH_DML_UPDATE_COUNT_PROPERTY_NAME = "batch_dml_update_count";
317319

318320
private static final String GUARDED_CONNECTION_PROPERTY_ERROR_MESSAGE =
319321
"%s can only be used if the system property %s has been set to true. "

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperties.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.cloud.spanner.connection.ConnectionOptions.AUTO_BATCH_DML_UPDATE_COUNT_PROPERTY_NAME;
2222
import static com.google.cloud.spanner.connection.ConnectionOptions.AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION_PROPERTY_NAME;
2323
import static com.google.cloud.spanner.connection.ConnectionOptions.AUTO_PARTITION_MODE_PROPERTY_NAME;
24+
import static com.google.cloud.spanner.connection.ConnectionOptions.BATCH_DML_UPDATE_COUNT_PROPERTY_NAME;
2425
import static com.google.cloud.spanner.connection.ConnectionOptions.CHANNEL_PROVIDER_PROPERTY_NAME;
2526
import static com.google.cloud.spanner.connection.ConnectionOptions.CLIENT_CERTIFICATE_PROPERTY_NAME;
2627
import static com.google.cloud.spanner.connection.ConnectionOptions.CLIENT_KEY_PROPERTY_NAME;
@@ -34,6 +35,7 @@
3435
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT;
3536
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION;
3637
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_AUTO_PARTITION_MODE;
38+
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_BATCH_DML_UPDATE_COUNT;
3739
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_CHANNEL_PROVIDER;
3840
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_CLIENT_CERTIFICATE;
3941
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_CLIENT_KEY;
@@ -747,6 +749,15 @@ public class ConnectionProperties {
747749
BOOLEANS,
748750
BooleanConverter.INSTANCE,
749751
Context.USER);
752+
static final ConnectionProperty<Long> BATCH_DML_UPDATE_COUNT =
753+
create(
754+
BATCH_DML_UPDATE_COUNT_PROPERTY_NAME,
755+
"The update count that is returned for DML statements that are executed in an "
756+
+ "explicit DML batch. The default is "
757+
+ DEFAULT_BATCH_DML_UPDATE_COUNT,
758+
DEFAULT_BATCH_DML_UPDATE_COUNT,
759+
LongConverter.INSTANCE,
760+
Context.USER);
750761

751762
static final ImmutableMap<String, ConnectionProperty<?>> CONNECTION_PROPERTIES =
752763
CONNECTION_PROPERTIES_BUILDER.build();

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ StatementResult statementSetPgSessionCharacteristicsTransactionMode(
184184

185185
StatementResult statementRunPartitionedQuery(Statement statement);
186186

187+
StatementResult statementSetBatchDmlUpdateCount(Long updateCount, Boolean local);
188+
187189
StatementResult statementSetAutoBatchDml(Boolean autoBatchDml);
188190

189191
StatementResult statementShowAutoBatchDml();

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_AUTO_BATCH_DML_UPDATE_COUNT;
3030
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION;
3131
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_AUTO_PARTITION_MODE;
32+
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_BATCH_DML_UPDATE_COUNT;
3233
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DATA_BOOST_ENABLED;
3334
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DEFAULT_TRANSACTION_ISOLATION;
3435
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
@@ -726,6 +727,12 @@ public StatementResult statementRunPartitionedQuery(Statement statement) {
726727
ClientSideStatementType.RUN_PARTITIONED_QUERY);
727728
}
728729

730+
@Override
731+
public StatementResult statementSetBatchDmlUpdateCount(Long updateCount, Boolean local) {
732+
getConnection().setBatchDmlUpdateCount(updateCount, local);
733+
return noResult(SET_BATCH_DML_UPDATE_COUNT);
734+
}
735+
729736
@Override
730737
public StatementResult statementSetProtoDescriptors(byte[] protoDescriptors) {
731738
Preconditions.checkNotNull(protoDescriptors);

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DmlBatch.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class DmlBatch extends AbstractBaseUnitOfWork {
5151
private final boolean autoBatch;
5252
private final Supplier<Long> autoBatchUpdateCountSupplier;
5353
private final Supplier<Boolean> verifyUpdateCountsSupplier;
54+
private final Supplier<Long> dmlbatchUpdateCountSupplier;
5455
private final UnitOfWork transaction;
5556
private final String statementTag;
5657
private final List<ParsedStatement> statements = new ArrayList<>();
@@ -61,6 +62,7 @@ static class Builder extends AbstractBaseUnitOfWork.Builder<Builder, DmlBatch> {
6162
private boolean autoBatch;
6263
private Supplier<Long> autoBatchUpdateCountSupplier = Suppliers.ofInstance(1L);
6364
private Supplier<Boolean> verifyUpdateCountsSupplier = Suppliers.ofInstance(Boolean.FALSE);
65+
private Supplier<Long> dmlbatchUpdateCountSupplier = Suppliers.ofInstance(-1L);
6466
private UnitOfWork transaction;
6567
private String statementTag;
6668

@@ -81,6 +83,12 @@ Builder setAutoBatchUpdateCountVerificationSupplier(Supplier<Boolean> verificati
8183
return this;
8284
}
8385

86+
Builder setDmlBatchUpdateCountSupplier(Supplier<Long> dmlbatchUpdateCountSupplier) {
87+
Preconditions.checkNotNull(dmlbatchUpdateCountSupplier);
88+
this.dmlbatchUpdateCountSupplier = dmlbatchUpdateCountSupplier;
89+
return this;
90+
}
91+
8492
Builder setTransaction(UnitOfWork transaction) {
8593
Preconditions.checkNotNull(transaction);
8694
this.transaction = transaction;
@@ -108,6 +116,7 @@ private DmlBatch(Builder builder) {
108116
this.autoBatch = builder.autoBatch;
109117
this.autoBatchUpdateCountSupplier = builder.autoBatchUpdateCountSupplier;
110118
this.verifyUpdateCountsSupplier = builder.verifyUpdateCountsSupplier;
119+
this.dmlbatchUpdateCountSupplier = builder.dmlbatchUpdateCountSupplier;
111120
this.transaction = Preconditions.checkNotNull(builder.transaction);
112121
this.statementTag = builder.statementTag;
113122
}
@@ -193,7 +202,7 @@ public ApiFuture<Void> executeDdlAsync(CallType callType, ParsedStatement ddl) {
193202
long getUpdateCount() {
194203
// Auto-batching returns update count 1 by default, as this is what ORMs normally expect.
195204
// Standard batches return -1 by default, to indicate that the update count is unknown.
196-
return isAutoBatch() ? autoBatchUpdateCountSupplier.get() : -1L;
205+
return isAutoBatch() ? autoBatchUpdateCountSupplier.get() : dmlbatchUpdateCountSupplier.get();
197206
}
198207

199208
@Override

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ enum ClientSideStatementType {
120120
SHOW_AUTO_BATCH_DML,
121121
SET_AUTO_BATCH_DML_UPDATE_COUNT,
122122
SHOW_AUTO_BATCH_DML_UPDATE_COUNT,
123+
SET_BATCH_DML_UPDATE_COUNT,
123124
SET_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION,
124125
SHOW_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION,
125126
SHOW_READ_LOCK_MODE,

google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,27 @@
753753
"converterName": "ClientSideStatementValueConverters$BooleanConverter"
754754
}
755755
},
756+
{
757+
"name": "SET [LOCAL] BATCH_DML_UPDATE_COUNT = <INT64>",
758+
"executorName": "ClientSideStatementSetExecutor",
759+
"resultType": "NO_RESULT",
760+
"statementType": "SET_BATCH_DML_UPDATE_COUNT",
761+
"regex": "(?is)\\A\\s*set\\s+(local\\s+)?batch_dml_update_count\\s*(?:=)\\s*(.*)\\z",
762+
"method": "statementSetBatchDmlUpdateCount",
763+
"exampleStatements": [
764+
"set local batch_dml_update_count = 0",
765+
"set local batch_dml_update_count = 100",
766+
"set batch_dml_update_count = 1",
767+
"set batch_dml_update_count = 100"
768+
],
769+
"examplePrerequisiteStatements": ["set readonly = false", "set autocommit = false"],
770+
"setStatement": {
771+
"propertyName": "BATCH_DML_UPDATE_COUNT",
772+
"separator": "=",
773+
"allowedValues": "(\\d{1,19})",
774+
"converterName": "ClientSideStatementValueConverters$LongConverter"
775+
}
776+
},
756777
{
757778
"name": "SHOW VARIABLE READ_LOCK_MODE",
758779
"executorName": "ClientSideStatementNoParamExecutor",

google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,28 @@
966966
"converterName": "ClientSideStatementValueConverters$LongConverter"
967967
}
968968
},
969+
{
970+
"name": "SET [LOCAL] SPANNER.BATCH_DML_UPDATE_COUNT =|TO <bigint>",
971+
"executorName": "ClientSideStatementSetExecutor",
972+
"resultType": "NO_RESULT",
973+
"statementType": "SET_BATCH_DML_UPDATE_COUNT",
974+
"regex": "(?is)\\A\\s*set\\s+((?:session|local)\\s+)?spanner\\.batch_dml_update_count(?:\\s*=\\s*|\\s+to\\s+)(.*)\\z",
975+
"method": "statementSetBatchDmlUpdateCount",
976+
"exampleStatements": [
977+
"set local spanner.batch_dml_update_count = 0",
978+
"set local spanner.batch_dml_update_count = 100",
979+
"set local spanner.batch_dml_update_count to 1",
980+
"set spanner.batch_dml_update_count to 1",
981+
"set spanner.batch_dml_update_count = 1"
982+
],
983+
"examplePrerequisiteStatements": ["set spanner.readonly = false", "set autocommit = false"],
984+
"setStatement": {
985+
"propertyName": "SPANNER.BATCH_DML_UPDATE_COUNT",
986+
"separator": "(?:=|\\s+TO\\s+)",
987+
"allowedValues": "(\\d{1,19})",
988+
"converterName": "ClientSideStatementValueConverters$LongConverter"
989+
}
990+
},
969991
{
970992
"name": "SET SPANNER.AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION = TRUE|FALSE",
971993
"executorName": "ClientSideStatementSetExecutor",

0 commit comments

Comments
 (0)