diff --git a/.github/workflows/hermetic_library_generation.yaml b/.github/workflows/hermetic_library_generation.yaml
index 4943e3e93ee..46b80edc1c7 100644
--- a/.github/workflows/hermetic_library_generation.yaml
+++ b/.github/workflows/hermetic_library_generation.yaml
@@ -37,7 +37,7 @@ jobs:
with:
fetch-depth: 0
token: ${{ secrets.CLOUD_JAVA_BOT_TOKEN }}
- - uses: googleapis/sdk-platform-java/.github/scripts@v2.48.0
+ - uses: googleapis/sdk-platform-java/.github/scripts@v2.49.0
if: env.SHOULD_RUN == 'true'
with:
base_ref: ${{ github.base_ref }}
diff --git a/.github/workflows/unmanaged_dependency_check.yaml b/.github/workflows/unmanaged_dependency_check.yaml
index c167c82fed8..2b4010cab6f 100644
--- a/.github/workflows/unmanaged_dependency_check.yaml
+++ b/.github/workflows/unmanaged_dependency_check.yaml
@@ -17,6 +17,6 @@ jobs:
# repository
.kokoro/build.sh
- name: Unmanaged dependency check
- uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.38.0
+ uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.39.0
with:
bom-path: google-cloud-spanner-bom/pom.xml
diff --git a/.kokoro/presubmit/graalvm-native-17.cfg b/.kokoro/presubmit/graalvm-native-17.cfg
index 9a49f7df62e..5f84dd393a1 100644
--- a/.kokoro/presubmit/graalvm-native-17.cfg
+++ b/.kokoro/presubmit/graalvm-native-17.cfg
@@ -3,7 +3,7 @@
# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.38.0"
+ value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.39.0"
}
env_vars: {
diff --git a/.kokoro/presubmit/graalvm-native.cfg b/.kokoro/presubmit/graalvm-native.cfg
index e434ee68472..418a399b759 100644
--- a/.kokoro/presubmit/graalvm-native.cfg
+++ b/.kokoro/presubmit/graalvm-native.cfg
@@ -3,7 +3,7 @@
# Configure the docker image for kokoro-trampoline.
env_vars: {
key: "TRAMPOLINE_IMAGE"
- value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.38.0"
+ value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.39.0"
}
env_vars: {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c576408486e..a570d56afaa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [6.80.1](https://github.com/googleapis/java-spanner/compare/v6.80.0...v6.80.1) (2024-10-28)
+
+
+### Dependencies
+
+* Update googleapis/sdk-platform-java action to v2.49.0 ([#3430](https://github.com/googleapis/java-spanner/issues/3430)) ([beb788c](https://github.com/googleapis/java-spanner/commit/beb788c05d099a0c5edeabb7ed63f4a6a7a24c16))
+* Update sdk platform java dependencies ([#3431](https://github.com/googleapis/java-spanner/issues/3431)) ([eef03e9](https://github.com/googleapis/java-spanner/commit/eef03e9e5a5ce9d4fcf9728d6b14630bbb99afce))
+
## [6.80.0](https://github.com/googleapis/java-spanner/compare/v6.79.0...v6.80.0) (2024-10-25)
diff --git a/README.md b/README.md
index 35e60a85ce8..883106b0aca 100644
--- a/README.md
+++ b/README.md
@@ -56,13 +56,13 @@ implementation 'com.google.cloud:google-cloud-spanner'
If you are using Gradle without BOM, add this to your dependencies:
```Groovy
-implementation 'com.google.cloud:google-cloud-spanner:6.80.0'
+implementation 'com.google.cloud:google-cloud-spanner:6.80.1'
```
If you are using SBT, add this to your dependencies:
```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.80.0"
+libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.80.1"
```
## Authentication
@@ -719,7 +719,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner/java11.html
[stability-image]: https://img.shields.io/badge/stability-stable-green
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner.svg
-[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.80.0
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.80.1
[authentication]: https://github.com/googleapis/google-cloud-java#authentication
[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index 84345b34d6c..b6dae243476 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -24,7 +24,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/generation_config.yaml b/generation_config.yaml
index ad36acc0af4..291fc91c39e 100644
--- a/generation_config.yaml
+++ b/generation_config.yaml
@@ -1,5 +1,5 @@
-gapic_generator_version: 2.48.0
-googleapis_commitish: 537fd482f6bb8afb3a146d9b21673a8eb27958bd
+gapic_generator_version: 2.49.0
+googleapis_commitish: 48d30c4966ef9ea31b897e13f75d8f94070cc8e9
libraries_bom_version: 26.49.0
libraries:
- api_shortname: spanner
diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml
index b380542a7bf..08d6202e7f1 100644
--- a/google-cloud-spanner-bom/pom.xml
+++ b/google-cloud-spanner-bom/pom.xml
@@ -3,12 +3,12 @@
4.0.0
com.google.cloud
google-cloud-spanner-bom
- 6.80.0
+ 6.80.1
pom
com.google.cloud
sdk-platform-java-config
- 3.38.0
+ 3.39.0
Google Cloud Spanner BOM
@@ -53,43 +53,43 @@
com.google.cloud
google-cloud-spanner
- 6.80.0
+ 6.80.1
com.google.cloud
google-cloud-spanner
test-jar
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
diff --git a/google-cloud-spanner-executor/pom.xml b/google-cloud-spanner-executor/pom.xml
index 49f3cf946c2..e04c47af445 100644
--- a/google-cloud-spanner-executor/pom.xml
+++ b/google-cloud-spanner-executor/pom.xml
@@ -5,14 +5,14 @@
4.0.0
com.google.cloud
google-cloud-spanner-executor
- 6.80.0
+ 6.80.1
jar
Google Cloud Spanner Executor
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml
index b26900ac62e..e5ab53ce26a 100644
--- a/google-cloud-spanner/pom.xml
+++ b/google-cloud-spanner/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.google.cloud
google-cloud-spanner
- 6.80.0
+ 6.80.1
jar
Google Cloud Spanner
https://github.com/googleapis/java-spanner
@@ -11,7 +11,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
google-cloud-spanner
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java
index 6c869c549fc..c5a09bc3eea 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java
@@ -22,6 +22,7 @@
import com.google.common.collect.ImmutableList;
import com.google.protobuf.ListValue;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -29,6 +30,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Nullable;
/**
@@ -402,20 +404,46 @@ private boolean isFloat32NaN(Value value) {
return value.getType().equals(Type.float32()) && Float.isNaN(value.getFloat32());
}
- static void toProto(Iterable mutations, List out) {
+ /**
+ * Converts the list of mutations to the corresponding protobuf mutations and returns a random
+ * mutation from the available list based on the following heuristics:
+ *
+ *
+ * - 1. Prefer mutations other than INSERT, as INSERT mutations may contain autogenerated
+ * columns whose information is unavailable on the client.
+ *
- If the list only contains INSERT mutations, select the one with the highest number of
+ * values.
+ *
+ */
+ static com.google.spanner.v1.Mutation toProtoAndReturnRandomMutation(
+ Iterable mutations, List out) {
Mutation last = null;
// The mutation currently being built.
com.google.spanner.v1.Mutation.Builder proto = null;
// The "write" (!= DELETE) or "keySet" (==DELETE) for the last mutation encoded, for coalescing.
com.google.spanner.v1.Mutation.Write.Builder write = null;
com.google.spanner.v1.KeySet.Builder keySet = null;
+
+ // Stores all the mutations excluding INSERT mutations.
+ List allMutationsExcludingInsert = new ArrayList<>();
+ // Stores the INSERT mutation with largest number of values.
+ com.google.spanner.v1.Mutation largestInsertMutation =
+ com.google.spanner.v1.Mutation.getDefaultInstance();
+
for (Mutation mutation : mutations) {
if (mutation.operation == Op.DELETE) {
if (last != null && last.operation == Op.DELETE && mutation.table.equals(last.table)) {
mutation.keySet.appendToProto(keySet);
} else {
if (proto != null) {
- out.add(proto.build());
+ com.google.spanner.v1.Mutation builtMutation = proto.build();
+ out.add(builtMutation);
+ // Skip tracking the largest insert mutation if there are mutations other than INSERT.
+ if (allMutationsExcludingInsert.isEmpty()
+ && checkIfInsertMutationWithLargeValue(builtMutation, largestInsertMutation)) {
+ largestInsertMutation = builtMutation;
+ }
+ maybeAddMutationToListExcludingInserts(builtMutation, allMutationsExcludingInsert);
}
proto = com.google.spanner.v1.Mutation.newBuilder();
com.google.spanner.v1.Mutation.Delete.Builder delete =
@@ -437,7 +465,14 @@ static void toProto(Iterable mutations, List mutations, List largestInsertMutation.getInsert().getValuesCount();
+ }
+
+ // Stores all mutations that are not of type INSERT.
+ private static void maybeAddMutationToListExcludingInserts(
+ com.google.spanner.v1.Mutation mutation,
+ List allMutationsExcludingInsert) {
+ if (!mutation.hasInsert()) {
+ allMutationsExcludingInsert.add(mutation);
}
}
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MutationGroup.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MutationGroup.java
index 101ffe48349..67d95290030 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MutationGroup.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MutationGroup.java
@@ -48,7 +48,7 @@ public ImmutableList getMutations() {
static BatchWriteRequest.MutationGroup toProto(final MutationGroup mutationGroup) {
List mutationsProto = new ArrayList<>();
- Mutation.toProto(mutationGroup.getMutations(), mutationsProto);
+ Mutation.toProtoAndReturnRandomMutation(mutationGroup.getMutations(), mutationsProto);
return BatchWriteRequest.MutationGroup.newBuilder().addAllMutations(mutationsProto).build();
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionImpl.java
index 60c9d45d186..5bd31603685 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionImpl.java
@@ -238,7 +238,7 @@ public CommitResponse writeAtLeastOnceWithOptions(
throws SpannerException {
setActive(null);
List mutationsProto = new ArrayList<>();
- Mutation.toProto(mutations, mutationsProto);
+ Mutation.toProtoAndReturnRandomMutation(mutations, mutationsProto);
Options options = Options.fromTransactionOptions(transactionOptions);
final CommitRequest.Builder requestBuilder =
CommitRequest.newBuilder()
@@ -431,19 +431,23 @@ public void close() {
}
}
- ApiFuture beginTransactionAsync(
+ ApiFuture beginTransactionAsync(
Options transactionOptions,
boolean routeToLeader,
Map channelHint,
- ByteString previousTransactionId) {
- final SettableApiFuture res = SettableApiFuture.create();
+ ByteString previousTransactionId,
+ com.google.spanner.v1.Mutation mutation) {
+ final SettableApiFuture res = SettableApiFuture.create();
final ISpan span = tracer.spanBuilder(SpannerImpl.BEGIN_TRANSACTION);
- final BeginTransactionRequest request =
+ BeginTransactionRequest.Builder requestBuilder =
BeginTransactionRequest.newBuilder()
.setSession(getName())
.setOptions(
- createReadWriteTransactionOptions(transactionOptions, previousTransactionId))
- .build();
+ createReadWriteTransactionOptions(transactionOptions, previousTransactionId));
+ if (sessionReference.getIsMultiplexed() && mutation != null) {
+ requestBuilder.setMutationKey(mutation);
+ }
+ final BeginTransactionRequest request = requestBuilder.build();
final ApiFuture requestFuture;
try (IScope ignore = tracer.withSpan(span)) {
requestFuture = spanner.getRpc().beginTransactionAsync(request, channelHint, routeToLeader);
@@ -457,7 +461,7 @@ ApiFuture beginTransactionAsync(
ErrorCode.INTERNAL, "Missing id in transaction\n" + getName());
}
span.end();
- res.set(txn.getId());
+ res.set(txn);
} catch (ExecutionException e) {
span.setStatus(e);
span.end();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java
index 92d9c50aa9e..5eaa54cd050 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java
@@ -289,7 +289,7 @@ void ensureTxn() {
ApiFuture ensureTxnAsync() {
final SettableApiFuture res = SettableApiFuture.create();
if (transactionId == null || isAborted()) {
- createTxnAsync(res);
+ createTxnAsync(res, null);
} else {
span.addAnnotation("Transaction Initialized", "Id", transactionId.toStringUtf8());
txnLogger.log(
@@ -301,20 +301,29 @@ ApiFuture ensureTxnAsync() {
return res;
}
- private void createTxnAsync(final SettableApiFuture res) {
+ private void createTxnAsync(
+ final SettableApiFuture res, com.google.spanner.v1.Mutation mutation) {
span.addAnnotation("Creating Transaction");
- final ApiFuture fut =
+ final ApiFuture fut =
session.beginTransactionAsync(
- options, isRouteToLeader(), getTransactionChannelHint(), getPreviousTransactionId());
+ options,
+ isRouteToLeader(),
+ getTransactionChannelHint(),
+ getPreviousTransactionId(),
+ mutation);
fut.addListener(
() -> {
try {
- transactionId = fut.get();
+ Transaction txn = fut.get();
+ transactionId = txn.getId();
span.addAnnotation("Transaction Creation Done", "Id", transactionId.toStringUtf8());
txnLogger.log(
Level.FINER,
"Started transaction {0}",
txnLogger.isLoggable(Level.FINER) ? transactionId.asReadOnlyByteBuffer() : null);
+ if (txn.hasPrecommitToken()) {
+ onPrecommitToken(txn.getPrecommitToken());
+ }
res.set(null);
} catch (ExecutionException e) {
span.addAnnotation(
@@ -357,13 +366,14 @@ ApiFuture commitAsync() {
close();
List mutationsProto = new ArrayList<>();
+ com.google.spanner.v1.Mutation randomMutation = null;
synchronized (committingLock) {
if (committing) {
throw new IllegalStateException(TRANSACTION_ALREADY_COMMITTED_MESSAGE);
}
committing = true;
if (!mutations.isEmpty()) {
- Mutation.toProto(mutations, mutationsProto);
+ randomMutation = Mutation.toProtoAndReturnRandomMutation(mutations, mutationsProto);
}
}
final SettableApiFuture res = SettableApiFuture.create();
@@ -392,7 +402,7 @@ ApiFuture commitAsync() {
synchronized (lock) {
if (transactionIdFuture == null && transactionId == null && runningAsyncOperations == 0) {
finishOps = SettableApiFuture.create();
- createTxnAsync(finishOps);
+ createTxnAsync(finishOps, randomMutation);
} else {
finishOps = finishedAsyncOperations;
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
index 014ab7e94e3..415bbe6e793 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
@@ -1828,7 +1828,7 @@ private ByteString getTransactionId(Session session, TransactionSelector tx) {
transactionId = null;
break;
case BEGIN:
- transactionId = beginTransaction(session, tx.getBegin()).getId();
+ transactionId = beginTransaction(session, tx.getBegin(), null).getId();
break;
case ID:
Transaction transaction = transactions.get(tx.getId());
@@ -1883,7 +1883,8 @@ public void beginTransaction(
try {
beginTransactionExecutionTime.simulateExecutionTime(
exceptions, stickyGlobalExceptions, freezeLock);
- Transaction transaction = beginTransaction(session, request.getOptions());
+ Transaction transaction =
+ beginTransaction(session, request.getOptions(), request.getMutationKey());
responseObserver.onNext(transaction);
responseObserver.onCompleted();
} catch (StatusRuntimeException t) {
@@ -1893,12 +1894,19 @@ public void beginTransaction(
}
}
- private Transaction beginTransaction(Session session, TransactionOptions options) {
- Transaction.Builder builder =
- Transaction.newBuilder().setId(generateTransactionName(session.getName()));
+ private Transaction beginTransaction(
+ Session session, TransactionOptions options, com.google.spanner.v1.Mutation mutationKey) {
+ ByteString transactionId = generateTransactionName(session.getName());
+ Transaction.Builder builder = Transaction.newBuilder().setId(transactionId);
if (options != null && options.getModeCase() == ModeCase.READ_ONLY) {
setReadTimestamp(options, builder);
}
+ if (session.getMultiplexed()
+ && options.getModeCase() == ModeCase.READ_WRITE
+ && mutationKey != null) {
+ // Mutation only case in a read-write transaction.
+ builder.setPrecommitToken(getTransactionPrecommitToken(transactionId));
+ }
Transaction transaction = builder.build();
transactions.put(transaction.getId(), transaction);
transactionsStarted.add(transaction.getId());
@@ -2005,7 +2013,8 @@ public void commit(CommitRequest request, StreamObserver respons
session,
TransactionOptions.newBuilder()
.setReadWrite(ReadWrite.getDefaultInstance())
- .build());
+ .build(),
+ null);
} else if (request.getTransactionId() != null) {
transaction = transactions.get(request.getTransactionId());
Optional aborted =
@@ -2490,6 +2499,10 @@ Session getSession(String name) {
return null;
}
+ static MultiplexedSessionPrecommitToken getTransactionPrecommitToken(ByteString transactionId) {
+ return getPrecommitToken("TransactionPrecommitToken", transactionId);
+ }
+
static MultiplexedSessionPrecommitToken getResultSetPrecommitToken(ByteString transactionId) {
return getPrecommitToken("ResultSetPrecommitToken", transactionId);
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
index c7d7b697d64..36c527f3842 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
@@ -19,6 +19,7 @@
import static com.google.cloud.spanner.MockSpannerTestUtil.INVALID_UPDATE_STATEMENT;
import static com.google.cloud.spanner.MockSpannerTestUtil.UPDATE_COUNT;
import static com.google.cloud.spanner.MockSpannerTestUtil.UPDATE_STATEMENT;
+import static com.google.cloud.spanner.SpannerApiFutures.get;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -594,10 +595,23 @@ public void testMutationUsingWrite() {
Mutation.newInsertBuilder("FOO").set("ID").to(1L).set("NAME").to("Bar").build()));
assertNotNull(timestamp);
+ List beginTransactionRequests =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertEquals(2, beginTransactionRequests.size());
+ for (BeginTransactionRequest request : beginTransactionRequests) {
+ // Verify that mutation key is set for mutations-only case in read-write transaction.
+ assertTrue(request.hasMutationKey());
+ }
+
List commitRequests = mockSpanner.getRequestsOfType(CommitRequest.class);
assertEquals(2, commitRequests.size());
for (CommitRequest request : commitRequests) {
assertTrue(mockSpanner.getSession(request.getSession()).getMultiplexed());
+ // Verify that the precommit token is set in CommitRequest
+ assertTrue(request.hasPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ request.getPrecommitToken().getPrecommitToken());
}
assertNotNull(client.multiplexedSessionDatabaseClient);
@@ -1083,6 +1097,199 @@ public void testTxnTracksPrecommitTokenWithLatestSeqNo() {
commitRequests.get(0).getPrecommitToken().getPrecommitToken());
}
+ @Test
+ public void testPrecommitTokenForTransactionResponse() {
+ // This test verifies that
+ // 1. A random mutation from the list is set in BeginTransactionRequest.
+ // 2. The precommit token from the Transaction response is correctly tracked
+ // and applied in the CommitRequest. The Transaction response includes a precommit token
+ // only when the read-write transaction consists solely of mutations.
+
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+
+ client
+ .readWriteTransaction()
+ .run(
+ transaction -> {
+ Mutation mutation =
+ Mutation.newInsertBuilder("FOO").set("ID").to(1L).set("NAME").to("Bar").build();
+ transaction.buffer(mutation);
+ return null;
+ });
+
+ // Verify that for mutation only case, a mutation key is set in BeginTransactionRequest.
+ List beginTxnRequest =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertEquals(1L, beginTxnRequest.size());
+ assertTrue(mockSpanner.getSession(beginTxnRequest.get(0).getSession()).getMultiplexed());
+ assertTrue(beginTxnRequest.get(0).hasMutationKey());
+ assertTrue(beginTxnRequest.get(0).getMutationKey().hasInsert());
+
+ // Verify that the latest precommit token is set in the CommitRequest
+ List commitRequests = mockSpanner.getRequestsOfType(CommitRequest.class);
+ assertEquals(1L, commitRequests.size());
+ assertTrue(mockSpanner.getSession(commitRequests.get(0).getSession()).getMultiplexed());
+ assertNotNull(commitRequests.get(0).getPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ commitRequests.get(0).getPrecommitToken().getPrecommitToken());
+ }
+
+ @Test
+ public void testMutationOnlyCaseAborted() {
+ // This test verifies that in the case of mutations-only, when a transaction is retried after an
+ // ABORT, the mutation key is correctly set in the BeginTransaction request.
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+
+ // Force the Commit RPC to return Aborted the first time it is called. The exception is cleared
+ // after the first call, so the retry should succeed.
+ mockSpanner.setCommitExecutionTime(
+ SimulatedExecutionTime.ofException(
+ mockSpanner.createAbortedException(ByteString.copyFromUtf8("test"))));
+ client
+ .readWriteTransaction()
+ .run(
+ transaction -> {
+ Mutation mutation =
+ Mutation.newInsertBuilder("FOO").set("ID").to(1L).set("NAME").to("Bar").build();
+ transaction.buffer(mutation);
+ return null;
+ });
+
+ // Verify that for mutation only case, a mutation key is set in BeginTransactionRequest.
+ List beginTransactionRequests =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertEquals(2L, beginTransactionRequests.size());
+ // Verify the requests are executed using multiplexed sessions
+ for (BeginTransactionRequest request : beginTransactionRequests) {
+ assertTrue(mockSpanner.getSession(request.getSession()).getMultiplexed());
+ assertTrue(request.hasMutationKey());
+ assertTrue(request.getMutationKey().hasInsert());
+ }
+
+ // Verify that the latest precommit token is set in the CommitRequest
+ List commitRequests = mockSpanner.getRequestsOfType(CommitRequest.class);
+ assertEquals(2L, commitRequests.size());
+ for (CommitRequest request : commitRequests) {
+ assertTrue(mockSpanner.getSession(request.getSession()).getMultiplexed());
+ assertNotNull(request.getPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ request.getPrecommitToken().getPrecommitToken());
+ }
+ }
+
+ @Test
+ public void testMutationOnlyUsingTransactionManager() {
+ // Test verifies mutation-only case within a R/W transaction via TransactionManager.
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+
+ try (TransactionManager manager = client.transactionManager()) {
+ TransactionContext transaction = manager.begin();
+ while (true) {
+ try {
+ Mutation mutation =
+ Mutation.newInsertBuilder("FOO").set("ID").to(1L).set("NAME").to("Bar").build();
+ transaction.buffer(mutation);
+ manager.commit();
+ assertNotNull(manager.getCommitTimestamp());
+ break;
+ } catch (AbortedException e) {
+ transaction = manager.resetForRetry();
+ }
+ }
+ }
+
+ // Verify that for mutation only case, a mutation key is set in BeginTransactionRequest.
+ List beginTransactionRequests =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertThat(beginTransactionRequests).hasSize(1);
+ BeginTransactionRequest beginTransaction = beginTransactionRequests.get(0);
+ assertTrue(mockSpanner.getSession(beginTransaction.getSession()).getMultiplexed());
+ assertTrue(beginTransaction.hasMutationKey());
+ assertTrue(beginTransaction.getMutationKey().hasInsert());
+
+ // Verify that the latest precommit token is set in the CommitRequest
+ List commitRequests = mockSpanner.getRequestsOfType(CommitRequest.class);
+ assertThat(commitRequests).hasSize(1);
+ CommitRequest commitRequest = commitRequests.get(0);
+ assertNotNull(commitRequest.getPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ commitRequest.getPrecommitToken().getPrecommitToken());
+ }
+
+ @Test
+ public void testMutationOnlyUsingAsyncRunner() {
+ // Test verifies mutation-only case within a R/W transaction via AsyncRunner.
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+ AsyncRunner runner = client.runAsync();
+ get(
+ runner.runAsync(
+ txn -> {
+ txn.buffer(Mutation.delete("TEST", KeySet.all()));
+ return ApiFutures.immediateFuture(null);
+ },
+ MoreExecutors.directExecutor()));
+
+ // Verify that the mutation key is set in BeginTransactionRequest
+ List beginTransactions =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertThat(beginTransactions).hasSize(1);
+ BeginTransactionRequest beginTransaction = beginTransactions.get(0);
+ assertTrue(beginTransaction.hasMutationKey());
+ assertTrue(beginTransaction.getMutationKey().hasDelete());
+
+ // Verify that the latest precommit token is set in the CommitRequest
+ List commitRequests = mockSpanner.getRequestsOfType(CommitRequest.class);
+ assertThat(commitRequests).hasSize(1);
+ CommitRequest commitRequest = commitRequests.get(0);
+ assertNotNull(commitRequest.getPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ commitRequest.getPrecommitToken().getPrecommitToken());
+ }
+
+ @Test
+ public void testMutationOnlyUsingAsyncTransactionManager() {
+ // Test verifies mutation-only case within a R/W transaction via AsyncTransactionManager.
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+ try (AsyncTransactionManager manager = client.transactionManagerAsync()) {
+ TransactionContextFuture transaction = manager.beginAsync();
+ get(
+ transaction
+ .then(
+ (txn, input) -> {
+ txn.buffer(Mutation.delete("TEST", KeySet.all()));
+ return ApiFutures.immediateFuture(null);
+ },
+ MoreExecutors.directExecutor())
+ .commitAsync());
+ }
+
+ // Verify that the mutation key is set in BeginTransactionRequest
+ List beginTransactions =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class);
+ assertThat(beginTransactions).hasSize(1);
+ BeginTransactionRequest beginTransaction = beginTransactions.get(0);
+ assertTrue(beginTransaction.hasMutationKey());
+ assertTrue(beginTransaction.getMutationKey().hasDelete());
+
+ // Verify that the latest precommit token is set in the CommitRequest
+ List requests = mockSpanner.getRequestsOfType(CommitRequest.class);
+ assertThat(requests).hasSize(1);
+ CommitRequest request = requests.get(0);
+ assertNotNull(request.getPrecommitToken());
+ assertEquals(
+ ByteString.copyFromUtf8("TransactionPrecommitToken"),
+ request.getPrecommitToken().getPrecommitToken());
+ }
+
private void waitForSessionToBeReplaced(DatabaseClientImpl client) {
assertNotNull(client.multiplexedSessionDatabaseClient);
SessionReference sessionReference =
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationGroupTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationGroupTest.java
index 99fcb8b6943..fbf91b9fc16 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationGroupTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationGroupTest.java
@@ -44,7 +44,7 @@ private Mutation getRandomMutation() {
private BatchWriteRequest.MutationGroup getMutationGroupProto(ImmutableList mutations) {
List mutationsProto = new ArrayList<>();
- Mutation.toProto(mutations, mutationsProto);
+ Mutation.toProtoAndReturnRandomMutation(mutations, mutationsProto);
return BatchWriteRequest.MutationGroup.newBuilder().addAllMutations(mutationsProto).build();
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java
index 3f7687482ce..a8ddfe706a8 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java
@@ -19,6 +19,7 @@
import static com.google.common.testing.SerializableTester.reserializeAndAssert;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import com.google.cloud.ByteArray;
import com.google.cloud.Date;
@@ -321,7 +322,7 @@ public void serializationBasic() {
com.google.spanner.v1.Mutation.getDefaultInstance();
proto.add(existingProto);
- Mutation.toProto(mutations, proto);
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
assertThat(proto.size()).isAtLeast(1);
assertThat(proto.get(0)).isSameInstanceAs(existingProto);
@@ -359,7 +360,15 @@ public void toProtoCoalescingChangeOfTable() {
Mutation.newInsertBuilder("T2").set("C").to("V5").build());
List proto = new ArrayList<>();
- Mutation.toProto(mutations, proto);
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+ // Random mutation returned should be INSERT with large number of values
+ MatcherAssert.assertThat(
+ mutation,
+ matchesProto(
+ "insert { table: 'T1' columns: 'C' values { values { string_value: 'V1' } }"
+ + " values { values { string_value: 'V2' } }"
+ + " values { values { string_value: 'V3' } } }"));
assertThat(proto.size()).isEqualTo(2);
MatcherAssert.assertThat(
@@ -386,7 +395,14 @@ public void toProtoCoalescingChangeOfOperation() {
Mutation.newUpdateBuilder("T").set("C").to("V5").build());
List proto = new ArrayList<>();
- Mutation.toProto(mutations, proto);
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+ // Random mutation returned should be of UPDATE operation
+ MatcherAssert.assertThat(
+ mutation,
+ matchesProto(
+ "update { table: 'T' columns: 'C' values { values { string_value: 'V4' } }"
+ + " values { values { string_value: 'V5' } } }"));
assertThat(proto.size()).isEqualTo(2);
MatcherAssert.assertThat(
@@ -413,7 +429,14 @@ public void toProtoCoalescingChangeOfColumn() {
Mutation.newInsertBuilder("T").set("C2").to("V5").build());
List proto = new ArrayList<>();
- Mutation.toProto(mutations, proto);
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+ MatcherAssert.assertThat(
+ mutation,
+ matchesProto(
+ "insert { table: 'T' columns: 'C1' values { values { string_value: 'V1' } }"
+ + " values { values { string_value: 'V2' } }"
+ + " values { values { string_value: 'V3' } } }"));
assertThat(proto.size()).isEqualTo(2);
MatcherAssert.assertThat(
@@ -439,7 +462,10 @@ public void toProtoCoalescingDelete() {
Mutation.delete("T", KeySet.range(KeyRange.closedClosed(Key.of("kc"), Key.of("kd")))));
List proto = new ArrayList<>();
- Mutation.toProto(mutations, proto);
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+ // Random mutation returned should be of DELETE operation
+ assertTrue(mutation.hasDelete());
assertThat(proto.size()).isEqualTo(1);
MatcherAssert.assertThat(
@@ -470,7 +496,9 @@ public void toProtoCoalescingDeleteChanges() {
Mutation.newInsertBuilder("T2").set("C").to("V1").build());
List proto = new ArrayList<>();
- Mutation.toProto(mutations, proto);
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+ assertTrue(mutation.hasDelete());
assertThat(proto.size()).isEqualTo(4);
MatcherAssert.assertThat(
@@ -493,6 +521,22 @@ public void toProtoCoalescingDeleteChanges() {
"insert { table: 'T2', columns: 'C', values { values { string_value: 'V1' } } }"));
}
+ @Test
+ public void toProtoWithEmptyInsertMutations() {
+ List mutations =
+ Arrays.asList(
+ Mutation.newInsertBuilder("T").build(), Mutation.newInsertBuilder("A").build());
+
+ List proto = new ArrayList<>();
+ com.google.spanner.v1.Mutation mutation =
+ Mutation.toProtoAndReturnRandomMutation(mutations, proto);
+
+ // Random mutation returned should be of INSERT operation with empty values
+ MatcherAssert.assertThat(mutation, matchesProto("insert { table: 'T' values { } }"));
+
+ assertThat(proto.size()).isEqualTo(2);
+ }
+
@Test
public void javaSerialization() {
reserializeAndAssert(appendAllTypes(Mutation.newInsertBuilder("test")).build());
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java
index 77369f5371b..40591d17fe8 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java
@@ -319,7 +319,7 @@ public void testMutation() {
.toStringArray(null)
.build());
final List expectedMutations = new ArrayList<>();
- Mutation.toProto(mutations, expectedMutations);
+ Mutation.toProtoAndReturnRandomMutation(mutations, expectedMutations);
databaseClient
.readWriteTransaction()
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java
index c3e8d887ded..00339fd2946 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SessionPoolTest.java
@@ -87,6 +87,7 @@
import com.google.spanner.v1.ExecuteSqlRequest;
import com.google.spanner.v1.ResultSetStats;
import com.google.spanner.v1.RollbackRequest;
+import com.google.spanner.v1.Transaction;
import io.opencensus.metrics.LabelValue;
import io.opencensus.metrics.MetricRegistry;
import io.opencensus.metrics.Metrics;
@@ -1497,7 +1498,7 @@ public void testSessionNotFoundReadWriteTransaction() {
.thenReturn(ApiFutures.immediateFuture(Empty.getDefaultInstance()));
when(closedSession.newTransaction(eq(Options.fromTransactionOptions()), any()))
.thenReturn(closedTransactionContext);
- when(closedSession.beginTransactionAsync(any(), eq(true), any(), any()))
+ when(closedSession.beginTransactionAsync(any(), eq(true), any(), any(), any()))
.thenThrow(sessionNotFound);
when(closedSession.getTracer()).thenReturn(tracer);
TransactionRunnerImpl closedTransactionRunner = new TransactionRunnerImpl(closedSession);
@@ -1513,8 +1514,9 @@ public void testSessionNotFoundReadWriteTransaction() {
final TransactionContextImpl openTransactionContext = mock(TransactionContextImpl.class);
when(openSession.newTransaction(eq(Options.fromTransactionOptions()), any()))
.thenReturn(openTransactionContext);
- when(openSession.beginTransactionAsync(any(), eq(true), any(), any()))
- .thenReturn(ApiFutures.immediateFuture(ByteString.copyFromUtf8("open-txn")));
+ Transaction txn = Transaction.newBuilder().setId(ByteString.copyFromUtf8("open-txn")).build();
+ when(openSession.beginTransactionAsync(any(), eq(true), any(), any(), any()))
+ .thenReturn(ApiFutures.immediateFuture(txn));
when(openSession.getTracer()).thenReturn(tracer);
TransactionRunnerImpl openTransactionRunner = new TransactionRunnerImpl(openSession);
openTransactionRunner.setSpan(span);
diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
index e771e71abb2..d062603d77d 100644
--- a/grpc-google-cloud-spanner-admin-database-v1/pom.xml
+++ b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
grpc-google-cloud-spanner-admin-database-v1
GRPC library for grpc-google-cloud-spanner-admin-database-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
index 51fe501cee2..bfaebfb3718 100644
--- a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
+++ b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
grpc-google-cloud-spanner-admin-instance-v1
GRPC library for grpc-google-cloud-spanner-admin-instance-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/grpc-google-cloud-spanner-executor-v1/pom.xml b/grpc-google-cloud-spanner-executor-v1/pom.xml
index e27a468ce1f..3dc6c424b80 100644
--- a/grpc-google-cloud-spanner-executor-v1/pom.xml
+++ b/grpc-google-cloud-spanner-executor-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.80.0
+ 6.80.1
grpc-google-cloud-spanner-executor-v1
GRPC library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml
index b2a38960dc9..67e58063e72 100644
--- a/grpc-google-cloud-spanner-v1/pom.xml
+++ b/grpc-google-cloud-spanner-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
grpc-google-cloud-spanner-v1
GRPC library for grpc-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/pom.xml b/pom.xml
index 45fa0cc683b..751d20fa5b1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-spanner-parent
pom
- 6.80.0
+ 6.80.1
Google Cloud Spanner Parent
https://github.com/googleapis/java-spanner
@@ -14,7 +14,7 @@
com.google.cloud
sdk-platform-java-config
- 3.38.0
+ 3.39.0
@@ -61,47 +61,47 @@
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
com.google.cloud
google-cloud-spanner
- 6.80.0
+ 6.80.1
diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml
index 744f7b4cf44..4f78204faba 100644
--- a/proto-google-cloud-spanner-admin-database-v1/pom.xml
+++ b/proto-google-cloud-spanner-admin-database-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.80.0
+ 6.80.1
proto-google-cloud-spanner-admin-database-v1
PROTO library for proto-google-cloud-spanner-admin-database-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
index da6d55f4779..cee4154e91f 100644
--- a/proto-google-cloud-spanner-admin-instance-v1/pom.xml
+++ b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.80.0
+ 6.80.1
proto-google-cloud-spanner-admin-instance-v1
PROTO library for proto-google-cloud-spanner-admin-instance-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/proto-google-cloud-spanner-executor-v1/pom.xml b/proto-google-cloud-spanner-executor-v1/pom.xml
index 0b5ce4b88d8..18f8e543f99 100644
--- a/proto-google-cloud-spanner-executor-v1/pom.xml
+++ b/proto-google-cloud-spanner-executor-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.80.0
+ 6.80.1
proto-google-cloud-spanner-executor-v1
Proto library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml
index a5355642bde..8fbe654111a 100644
--- a/proto-google-cloud-spanner-v1/pom.xml
+++ b/proto-google-cloud-spanner-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.80.0
+ 6.80.1
proto-google-cloud-spanner-v1
PROTO library for proto-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.80.0
+ 6.80.1
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 8b76f69773d..d9aa1fec68a 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -32,7 +32,7 @@
com.google.cloud
google-cloud-spanner
- 6.80.0
+ 6.80.1
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 13c21ba4bd8..b3047839aaa 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -192,7 +192,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.5.0
+ 3.6.0
**/SingerProto.java
diff --git a/versions.txt b/versions.txt
index 3c5a3b05694..40ea24a87eb 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,13 +1,13 @@
# Format:
# module:released-version:current-version
-proto-google-cloud-spanner-admin-instance-v1:6.80.0:6.80.0
-proto-google-cloud-spanner-v1:6.80.0:6.80.0
-proto-google-cloud-spanner-admin-database-v1:6.80.0:6.80.0
-grpc-google-cloud-spanner-v1:6.80.0:6.80.0
-grpc-google-cloud-spanner-admin-instance-v1:6.80.0:6.80.0
-grpc-google-cloud-spanner-admin-database-v1:6.80.0:6.80.0
-google-cloud-spanner:6.80.0:6.80.0
-google-cloud-spanner-executor:6.80.0:6.80.0
-proto-google-cloud-spanner-executor-v1:6.80.0:6.80.0
-grpc-google-cloud-spanner-executor-v1:6.80.0:6.80.0
+proto-google-cloud-spanner-admin-instance-v1:6.80.1:6.80.1
+proto-google-cloud-spanner-v1:6.80.1:6.80.1
+proto-google-cloud-spanner-admin-database-v1:6.80.1:6.80.1
+grpc-google-cloud-spanner-v1:6.80.1:6.80.1
+grpc-google-cloud-spanner-admin-instance-v1:6.80.1:6.80.1
+grpc-google-cloud-spanner-admin-database-v1:6.80.1:6.80.1
+google-cloud-spanner:6.80.1:6.80.1
+google-cloud-spanner-executor:6.80.1:6.80.1
+proto-google-cloud-spanner-executor-v1:6.80.1:6.80.1
+grpc-google-cloud-spanner-executor-v1:6.80.1:6.80.1