Skip to content

Commit 6a5b11f

Browse files
chore: Support dml_batch_update_count option in PG dialect
1 parent c12d18d commit 6a5b11f

File tree

9 files changed

+91
-1
lines changed

9 files changed

+91
-1
lines changed

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
@@ -31,6 +31,7 @@
3131
import static com.google.cloud.spanner.connection.ConnectionProperties.DEFAULT_SEQUENCE_KIND;
3232
import static com.google.cloud.spanner.connection.ConnectionProperties.DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
3333
import static com.google.cloud.spanner.connection.ConnectionProperties.DIRECTED_READ;
34+
import static com.google.cloud.spanner.connection.ConnectionProperties.DML_BATCH_UPDATE_COUNT;
3435
import static com.google.cloud.spanner.connection.ConnectionProperties.KEEP_TRANSACTION_ALIVE;
3536
import static com.google.cloud.spanner.connection.ConnectionProperties.MAX_COMMIT_DELAY;
3637
import static com.google.cloud.spanner.connection.ConnectionProperties.MAX_PARTITIONED_PARALLELISM;
@@ -1607,6 +1608,10 @@ public long getAutoBatchDmlUpdateCount() {
16071608
return getConnectionPropertyValue(AUTO_BATCH_DML_UPDATE_COUNT);
16081609
}
16091610

1611+
long getDmlBatchUpdateCount() {
1612+
return getConnectionPropertyValue(DML_BATCH_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 setDmlBatchUpdateCount(long updateCount, boolean local) {
1626+
setConnectionPropertyValue(DML_BATCH_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
@@ -178,6 +178,7 @@ public class ConnectionOptions {
178178
static final boolean DEFAULT_ENABLE_END_TO_END_TRACING = false;
179179
static final boolean DEFAULT_AUTO_BATCH_DML = false;
180180
static final long DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT = 1L;
181+
static final long DEFAULT_DML_BATCH_UPDATE_COUNT = -1L;
181182
static final boolean DEFAULT_AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION = true;
182183
private static final String EXPERIMENTAL_HOST_PROJECT_ID = "default";
183184
private static final String DEFAULT_EXPERIMENTAL_HOST_INSTANCE_ID = "default";
@@ -308,6 +309,7 @@ public class ConnectionOptions {
308309
"auto_batch_dml_update_count";
309310
public static final String AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION_PROPERTY_NAME =
310311
"auto_batch_dml_update_count_verification";
312+
public static final String DML_BATCH_UPDATE_COUNT_PROPERTY_NAME = "dml_batch_update_count";
311313

312314
private static final String GUARDED_CONNECTION_PROPERTY_ERROR_MESSAGE =
313315
"%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: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_DDL_IN_TRANSACTION_MODE;
4444
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_DEFAULT_SEQUENCE_KIND;
4545
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
46+
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_DML_BATCH_UPDATE_COUNT;
4647
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_ENABLE_API_TRACING;
4748
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_ENABLE_END_TO_END_TRACING;
4849
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_ENABLE_EXTENDED_TRACING;
@@ -72,6 +73,7 @@
7273
import static com.google.cloud.spanner.connection.ConnectionOptions.DEFAULT_USE_VIRTUAL_THREADS;
7374
import static com.google.cloud.spanner.connection.ConnectionOptions.DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE_NAME;
7475
import static com.google.cloud.spanner.connection.ConnectionOptions.DIALECT_PROPERTY_NAME;
76+
import static com.google.cloud.spanner.connection.ConnectionOptions.DML_BATCH_UPDATE_COUNT_PROPERTY_NAME;
7577
import static com.google.cloud.spanner.connection.ConnectionOptions.ENABLE_API_TRACING_PROPERTY_NAME;
7678
import static com.google.cloud.spanner.connection.ConnectionOptions.ENABLE_END_TO_END_TRACING_PROPERTY_NAME;
7779
import static com.google.cloud.spanner.connection.ConnectionOptions.ENABLE_EXTENDED_TRACING_PROPERTY_NAME;
@@ -728,6 +730,16 @@ public class ConnectionProperties {
728730
BOOLEANS,
729731
BooleanConverter.INSTANCE,
730732
Context.USER);
733+
static final ConnectionProperty<Long> DML_BATCH_UPDATE_COUNT =
734+
create(
735+
DML_BATCH_UPDATE_COUNT_PROPERTY_NAME,
736+
"DML statements that are executed in batch when "
737+
+ " 'start batch dml' statement is executed. This property determines"
738+
+ " the update count that is returned for these DML statements. The default is "
739+
+ DEFAULT_DML_BATCH_UPDATE_COUNT,
740+
DEFAULT_DML_BATCH_UPDATE_COUNT,
741+
LongConverter.INSTANCE,
742+
Context.USER);
731743

732744
static final ImmutableMap<String, ConnectionProperty<?>> CONNECTION_PROPERTIES =
733745
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 statementSetDmlBatchUpdateCount(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
@@ -33,6 +33,7 @@
3333
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DEFAULT_TRANSACTION_ISOLATION;
3434
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
3535
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DIRECTED_READ;
36+
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DML_BATCH_UPDATE_COUNT;
3637
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS;
3738
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_KEEP_TRANSACTION_ALIVE;
3839
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_COMMIT_DELAY;
@@ -726,6 +727,12 @@ public StatementResult statementRunPartitionedQuery(Statement statement) {
726727
ClientSideStatementType.RUN_PARTITIONED_QUERY);
727728
}
728729

730+
@Override
731+
public StatementResult statementSetDmlBatchUpdateCount(Long updateCount, Boolean local) {
732+
getConnection().setDmlBatchUpdateCount(updateCount, local);
733+
return noResult(SET_DML_BATCH_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: 9 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,11 @@ Builder setAutoBatchUpdateCountVerificationSupplier(Supplier<Boolean> verificati
8183
return this;
8284
}
8385

86+
Builder setDmlBatchUpdateCountSupplier(Supplier<Long> dmlbatchUpdateCountSupplier) {
87+
this.dmlbatchUpdateCountSupplier = dmlbatchUpdateCountSupplier;
88+
return this;
89+
}
90+
8491
Builder setTransaction(UnitOfWork transaction) {
8592
Preconditions.checkNotNull(transaction);
8693
this.transaction = transaction;
@@ -108,6 +115,7 @@ private DmlBatch(Builder builder) {
108115
this.autoBatch = builder.autoBatch;
109116
this.autoBatchUpdateCountSupplier = builder.autoBatchUpdateCountSupplier;
110117
this.verifyUpdateCountsSupplier = builder.verifyUpdateCountsSupplier;
118+
this.dmlbatchUpdateCountSupplier = builder.dmlbatchUpdateCountSupplier;
111119
this.transaction = Preconditions.checkNotNull(builder.transaction);
112120
this.statementTag = builder.statementTag;
113121
}
@@ -193,7 +201,7 @@ public ApiFuture<Void> executeDdlAsync(CallType callType, ParsedStatement ddl) {
193201
long getUpdateCount() {
194202
// Auto-batching returns update count 1 by default, as this is what ORMs normally expect.
195203
// Standard batches return -1 by default, to indicate that the update count is unknown.
196-
return isAutoBatch() ? autoBatchUpdateCountSupplier.get() : -1L;
204+
return isAutoBatch() ? autoBatchUpdateCountSupplier.get() : dmlbatchUpdateCountSupplier.get();
197205
}
198206

199207
@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_DML_BATCH_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/PG_ClientSideStatements.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,25 @@
966966
"converterName": "ClientSideStatementValueConverters$LongConverter"
967967
}
968968
},
969+
{
970+
"name": "SET LOCAL SPANNER.DML_BATCH_UPDATE_COUNT =|TO <bigint>",
971+
"executorName": "ClientSideStatementSetExecutor",
972+
"resultType": "NO_RESULT",
973+
"statementType": "SET_DML_BATCH_UPDATE_COUNT",
974+
"regex": "(?is)\\A\\s*set\\s+((?:session|local)\\s+)?spanner\\.dml_batch_update_count(?:\\s*=\\s*|\\s+to\\s+)(.*)\\z",
975+
"method": "statementSetDmlBatchUpdateCount",
976+
"exampleStatements": [
977+
"set local spanner.dml_batch_update_count = 0",
978+
"set local spanner.dml_batch_update_count = 100",
979+
"set local spanner.dml_batch_update_count to 1"
980+
],
981+
"setStatement": {
982+
"propertyName": "SPANNER.DML_BATCH_UPDATE_COUNT",
983+
"separator": "(?:=|\\s+TO\\s+)",
984+
"allowedValues": "(\\d{1,19})",
985+
"converterName": "ClientSideStatementValueConverters$LongConverter"
986+
}
987+
},
969988
{
970989
"name": "SET SPANNER.AUTO_BATCH_DML_UPDATE_COUNT_VERIFICATION = TRUE|FALSE",
971990
"executorName": "ClientSideStatementSetExecutor",

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828
import com.google.cloud.spanner.AsyncResultSet;
2929
import com.google.cloud.spanner.AsyncResultSet.CallbackResponse;
3030
import com.google.cloud.spanner.AsyncResultSet.ReadyCallback;
31+
import com.google.cloud.spanner.Dialect;
3132
import com.google.cloud.spanner.ErrorCode;
3233
import com.google.cloud.spanner.ForceCloseSpannerFunction;
34+
import com.google.cloud.spanner.MockSpannerServiceImpl;
3335
import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime;
3436
import com.google.cloud.spanner.Mutation;
3537
import com.google.cloud.spanner.ResultSet;
@@ -48,6 +50,7 @@
4850
import com.google.spanner.v1.CommitRequest;
4951
import com.google.spanner.v1.ExecuteBatchDmlRequest;
5052
import com.google.spanner.v1.ExecuteSqlRequest;
53+
import java.util.Arrays;
5154
import java.util.List;
5255
import java.util.concurrent.ExecutorService;
5356
import java.util.concurrent.Executors;
@@ -336,6 +339,32 @@ public void testAutocommitRunBatch() {
336339
}
337340
}
338341

342+
@Test
343+
public void testDmlBatchUpdateCount() {
344+
SpannerPool.closeSpannerPool();
345+
mockSpanner.putStatementResult(
346+
MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.POSTGRESQL));
347+
try {
348+
try (Connection connection = createConnection()) {
349+
connection.execute(Statement.of("set local spanner.dml_batch_update_count = 1"));
350+
connection.execute(Statement.of("START BATCH DML"));
351+
List<Statement> statements = Arrays.asList(INSERT_STATEMENT, INSERT_STATEMENT);
352+
long[] updateCounts = connection.executeBatchUpdate(statements);
353+
assertThat(updateCounts).asList().containsExactly(1L, 1L);
354+
}
355+
try (Connection connection = createConnection()) {
356+
connection.execute(Statement.of("START BATCH DML"));
357+
List<Statement> statements = Arrays.asList(INSERT_STATEMENT, INSERT_STATEMENT);
358+
long[] updateCounts = connection.executeBatchUpdate(statements);
359+
assertThat(updateCounts).asList().containsExactly(-1L, -1L);
360+
}
361+
} finally {
362+
SpannerPool.closeSpannerPool();
363+
mockSpanner.putStatementResult(
364+
MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL));
365+
}
366+
}
367+
339368
@Test
340369
public void testAutocommitRunBatchAsync() {
341370
try (Connection connection = createConnection()) {

0 commit comments

Comments
 (0)