From a10012371e9625707d5903bec7c665ee47f65272 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Wed, 22 May 2024 17:36:18 +0000
Subject: [PATCH 01/11] chore(main): release 6.67.1-SNAPSHOT (#3119)
:robot: I have created a release *beep* *boop*
---
### Updating meta-information for bleeding-edge SNAPSHOT release.
---
This PR was generated with [Release Please](https://togithub.com/googleapis/release-please). See [documentation](https://togithub.com/googleapis/release-please#release-please).
---
benchmarks/pom.xml | 2 +-
google-cloud-spanner-bom/pom.xml | 18 ++++++++---------
google-cloud-spanner-executor/pom.xml | 4 ++--
google-cloud-spanner/pom.xml | 4 ++--
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
grpc-google-cloud-spanner-executor-v1/pom.xml | 4 ++--
grpc-google-cloud-spanner-v1/pom.xml | 4 ++--
pom.xml | 20 +++++++++----------
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
proto-google-cloud-spanner-v1/pom.xml | 4 ++--
samples/snapshot/pom.xml | 2 +-
versions.txt | 20 +++++++++----------
15 files changed, 51 insertions(+), 51 deletions(-)
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index 4c5d4f6efbd..115d3ccdef9 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -24,7 +24,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml
index 375aafe0817..9aa92fe26ca 100644
--- a/google-cloud-spanner-bom/pom.xml
+++ b/google-cloud-spanner-bom/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.google.cloud
google-cloud-spanner-bom
- 6.67.0
+ 6.67.1-SNAPSHOT
pom
com.google.cloud
@@ -53,43 +53,43 @@
com.google.cloud
google-cloud-spanner
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.cloud
google-cloud-spanner
test-jar
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/google-cloud-spanner-executor/pom.xml b/google-cloud-spanner-executor/pom.xml
index ab7d060a86c..7ef867552a1 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.67.0
+ 6.67.1-SNAPSHOT
jar
Google Cloud Spanner Executor
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml
index ba3a19bd16a..77042788029 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.67.0
+ 6.67.1-SNAPSHOT
jar
Google Cloud Spanner
https://github.com/googleapis/java-spanner
@@ -11,7 +11,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
google-cloud-spanner
diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
index 3141df9325b..28f6a4dc08e 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.67.0
+ 6.67.1-SNAPSHOT
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.67.0
+ 6.67.1-SNAPSHOT
diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
index 543d026ef24..60b07faf891 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.67.0
+ 6.67.1-SNAPSHOT
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.67.0
+ 6.67.1-SNAPSHOT
diff --git a/grpc-google-cloud-spanner-executor-v1/pom.xml b/grpc-google-cloud-spanner-executor-v1/pom.xml
index 314730e3e39..7b6b3782d1a 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.67.0
+ 6.67.1-SNAPSHOT
grpc-google-cloud-spanner-executor-v1
GRPC library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml
index 23522c79c20..c2f8a8e00df 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.67.0
+ 6.67.1-SNAPSHOT
grpc-google-cloud-spanner-v1
GRPC library for grpc-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index 6813b780292..ad44668d9e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-spanner-parent
pom
- 6.67.0
+ 6.67.1-SNAPSHOT
Google Cloud Spanner Parent
https://github.com/googleapis/java-spanner
@@ -61,47 +61,47 @@
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.67.0
+ 6.67.1-SNAPSHOT
com.google.cloud
google-cloud-spanner
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml
index 9d45999d711..792bde57871 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.67.0
+ 6.67.1-SNAPSHOT
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.67.0
+ 6.67.1-SNAPSHOT
diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
index 2e7ea00da31..5e3ae7a6d4f 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.67.0
+ 6.67.1-SNAPSHOT
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.67.0
+ 6.67.1-SNAPSHOT
diff --git a/proto-google-cloud-spanner-executor-v1/pom.xml b/proto-google-cloud-spanner-executor-v1/pom.xml
index f86a9d02d68..b8245be23b3 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.67.0
+ 6.67.1-SNAPSHOT
proto-google-cloud-spanner-executor-v1
Proto library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml
index 81cbf177728..1f5a3e51664 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.67.0
+ 6.67.1-SNAPSHOT
proto-google-cloud-spanner-v1
PROTO library for proto-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 8877cf82b20..2172e8194f0 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -32,7 +32,7 @@
com.google.cloud
google-cloud-spanner
- 6.67.0
+ 6.67.1-SNAPSHOT
diff --git a/versions.txt b/versions.txt
index 30323409a7b..e52916e2f84 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.67.0:6.67.0
-proto-google-cloud-spanner-v1:6.67.0:6.67.0
-proto-google-cloud-spanner-admin-database-v1:6.67.0:6.67.0
-grpc-google-cloud-spanner-v1:6.67.0:6.67.0
-grpc-google-cloud-spanner-admin-instance-v1:6.67.0:6.67.0
-grpc-google-cloud-spanner-admin-database-v1:6.67.0:6.67.0
-google-cloud-spanner:6.67.0:6.67.0
-google-cloud-spanner-executor:6.67.0:6.67.0
-proto-google-cloud-spanner-executor-v1:6.67.0:6.67.0
-grpc-google-cloud-spanner-executor-v1:6.67.0:6.67.0
+proto-google-cloud-spanner-admin-instance-v1:6.67.0:6.67.1-SNAPSHOT
+proto-google-cloud-spanner-v1:6.67.0:6.67.1-SNAPSHOT
+proto-google-cloud-spanner-admin-database-v1:6.67.0:6.67.1-SNAPSHOT
+grpc-google-cloud-spanner-v1:6.67.0:6.67.1-SNAPSHOT
+grpc-google-cloud-spanner-admin-instance-v1:6.67.0:6.67.1-SNAPSHOT
+grpc-google-cloud-spanner-admin-database-v1:6.67.0:6.67.1-SNAPSHOT
+google-cloud-spanner:6.67.0:6.67.1-SNAPSHOT
+google-cloud-spanner-executor:6.67.0:6.67.1-SNAPSHOT
+proto-google-cloud-spanner-executor-v1:6.67.0:6.67.1-SNAPSHOT
+grpc-google-cloud-spanner-executor-v1:6.67.0:6.67.1-SNAPSHOT
From b93850f224e6a3a2e926cec4044249e22ed9a42b Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Thu, 23 May 2024 10:18:13 +0530
Subject: [PATCH 02/11] chore: update dependency versions in java templates
(#1964) (#3102)
* chore: update dependency versions in java templates
* update other templates
Source-Link: https://github.com/googleapis/synthtool/commit/0b86c72fe652dd7e52ba05a63f61bc1399ad5d65
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e
Co-authored-by: Owl Bot
---
.github/.OwlBot.lock.yaml | 4 ++--
.github/workflows/approve-readme.yaml | 2 +-
.github/workflows/renovate_config_check.yaml | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 6983bb26347..5db36a5f7d8 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:25b384ee1674eda3984ec41c15b514a63bbeb5eda4d57c73c7e6f5adef2fd2f1
-# created: 2024-04-05T19:12:34.133475268Z
+ digest: sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e
+# created: 2024-05-09T16:31:37.168667071Z
diff --git a/.github/workflows/approve-readme.yaml b/.github/workflows/approve-readme.yaml
index f5fc7d5169e..59f00b8eb6e 100644
--- a/.github/workflows/approve-readme.yaml
+++ b/.github/workflows/approve-readme.yaml
@@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'googleapis' && github.head_ref == 'autosynth-readme'
steps:
- - uses: actions/github-script@v6
+ - uses: actions/github-script@v7
with:
github-token: ${{secrets.YOSHI_APPROVER_TOKEN}}
script: |
diff --git a/.github/workflows/renovate_config_check.yaml b/.github/workflows/renovate_config_check.yaml
index 87d8eb2be8c..7c5ec7865e1 100644
--- a/.github/workflows/renovate_config_check.yaml
+++ b/.github/workflows/renovate_config_check.yaml
@@ -14,7 +14,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: '20'
From 0345ff96892aec9179febebcd3679f7e8a2c3e50 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 23 May 2024 07:18:52 +0200
Subject: [PATCH 03/11] chore(deps): update dependency
com.google.cloud:libraries-bom to v26.39.0 (#3077)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* chore(deps): update dependency com.google.cloud:libraries-bom to v26.39.0
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---------
Co-authored-by: Owl Bot
---
README.md | 2 +-
samples/native-image/pom.xml | 2 +-
samples/snippets/pom.xml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 038867956ae..cdfaf9f988e 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file:
com.google.cloud
libraries-bom
- 26.37.0
+ 26.39.0
pom
import
diff --git a/samples/native-image/pom.xml b/samples/native-image/pom.xml
index 8cf8cc752e1..6f181ef814e 100644
--- a/samples/native-image/pom.xml
+++ b/samples/native-image/pom.xml
@@ -29,7 +29,7 @@
com.google.cloud
libraries-bom
- 26.37.0
+ 26.39.0
pom
import
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index fc8c0052157..3a58a2a23d7 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -34,7 +34,7 @@
com.google.cloud
libraries-bom
- 26.37.0
+ 26.39.0
pom
import
From ddebbbbeef976f61f23cdd66c5f7c1f412e2f9bd Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Thu, 23 May 2024 07:24:16 +0200
Subject: [PATCH 04/11] deps: update dependency
org.graalvm.buildtools:native-maven-plugin to v0.10.2 (#3117)
---
samples/native-image/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/native-image/pom.xml b/samples/native-image/pom.xml
index 6f181ef814e..2d8ace4b6a0 100644
--- a/samples/native-image/pom.xml
+++ b/samples/native-image/pom.xml
@@ -131,7 +131,7 @@
org.graalvm.buildtools
native-maven-plugin
- 0.10.1
+ 0.10.2
true
com.example.spanner.NativeImageSpannerSample
From dfd9c4b9c5426b3e77d87dbbc5f6b5827c60408a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Thu, 23 May 2024 08:13:37 +0200
Subject: [PATCH 05/11] chore: add exclude_txn_from_change_streams option to
Connection API (#3104)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* chore: add exclude_txn_from_change_streams option to Connection API
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
* fix: add support for PDML
---------
Co-authored-by: Owl Bot
---
.../clirr-ignored-differences.xml | 12 +
.../connection/AbstractBaseUnitOfWork.java | 9 +
.../cloud/spanner/connection/Connection.java | 16 +
.../spanner/connection/ConnectionImpl.java | 62 +-
.../ConnectionStatementExecutor.java | 4 +
.../ConnectionStatementExecutorImpl.java | 17 +
.../connection/ReadWriteTransaction.java | 6 +
.../connection/SingleUseTransaction.java | 20 +-
.../spanner/connection/StatementResult.java | 2 +
.../connection/ClientSideStatements.json | 24 +
.../connection/PG_ClientSideStatements.json | 24 +
...udeTxnFromChangeStreamsMockServerTest.java | 236 ++++
.../connection/ClientSideStatementsTest.sql | 599 +++++++++
.../ConnectionImplGeneratedSqlScriptTest.sql | 224 +--
.../postgresql/ClientSideStatementsTest.sql | 1197 +++++++++++++++++
.../ConnectionImplGeneratedSqlScriptTest.sql | 224 +--
16 files changed, 2435 insertions(+), 241 deletions(-)
create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ExcludeTxnFromChangeStreamsMockServerTest.java
diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index e659fd125ce..8b4c75ad385 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -676,4 +676,16 @@
boolean isEnableExtendedTracing()
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ boolean isExcludeTxnFromChangeStreams()
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ void setExcludeTxnFromChangeStreams(boolean)
+
+
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
index 698e20dca26..ec9e7a636ed 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
@@ -73,6 +73,7 @@ abstract class AbstractBaseUnitOfWork implements UnitOfWork {
private final StatementExecutor statementExecutor;
private final StatementTimeout statementTimeout;
protected final String transactionTag;
+ protected final boolean excludeTxnFromChangeStreams;
protected final RpcPriority rpcPriority;
protected final Span span;
@@ -107,6 +108,8 @@ abstract static class Builder, T extends AbstractBaseUni
private StatementExecutor statementExecutor;
private StatementTimeout statementTimeout = new StatementTimeout();
private String transactionTag;
+
+ private boolean excludeTxnFromChangeStreams;
private RpcPriority rpcPriority;
private Span span;
@@ -134,6 +137,11 @@ B setTransactionTag(@Nullable String tag) {
return self();
}
+ B setExcludeTxnFromChangeStreams(boolean excludeTxnFromChangeStreams) {
+ this.excludeTxnFromChangeStreams = excludeTxnFromChangeStreams;
+ return self();
+ }
+
B setRpcPriority(@Nullable RpcPriority rpcPriority) {
this.rpcPriority = rpcPriority;
return self();
@@ -152,6 +160,7 @@ B setSpan(@Nullable Span span) {
this.statementExecutor = builder.statementExecutor;
this.statementTimeout = builder.statementTimeout;
this.transactionTag = builder.transactionTag;
+ this.excludeTxnFromChangeStreams = builder.excludeTxnFromChangeStreams;
this.rpcPriority = builder.rpcPriority;
this.span = Preconditions.checkNotNull(builder.span);
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
index e1a4415ea49..59a919ec9c8 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
@@ -387,6 +387,22 @@ default String getStatementTag() {
throw new UnsupportedOperationException();
}
+ /**
+ * Sets whether the next transaction should be excluded from all change streams with the DDL
+ * option `allow_txn_exclusion=true`
+ */
+ default void setExcludeTxnFromChangeStreams(boolean excludeTxnFromChangeStreams) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns true if the next transaction should be excluded from all change streams with the DDL
+ * option `allow_txn_exclusion=true`
+ */
+ default boolean isExcludeTxnFromChangeStreams() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @return true if this connection will automatically retry read/write transactions
* that abort. This method may only be called when the connection is in read/write
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
index e4afc501b51..c4e33b14b6b 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
@@ -269,6 +269,8 @@ static UnitOfWorkType of(TransactionMode transactionMode) {
private String transactionTag;
private String statementTag;
+ private boolean excludeTxnFromChangeStreams;
+
private Duration maxCommitDelay;
/** Create a connection and register it in the SpannerPool. */
@@ -743,6 +745,24 @@ public void setStatementTag(String tag) {
this.statementTag = tag;
}
+ @Override
+ public boolean isExcludeTxnFromChangeStreams() {
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ ConnectionPreconditions.checkState(!isDdlBatchActive(), "This connection is in a DDL batch");
+ return excludeTxnFromChangeStreams;
+ }
+
+ @Override
+ public void setExcludeTxnFromChangeStreams(boolean excludeTxnFromChangeStreams) {
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ ConnectionPreconditions.checkState(
+ !isBatchActive(), "Cannot set exclude_txn_from_change_streams while in a batch");
+ ConnectionPreconditions.checkState(
+ !isTransactionStarted(),
+ "exclude_txn_from_change_streams cannot be set after the transaction has started");
+ this.excludeTxnFromChangeStreams = excludeTxnFromChangeStreams;
+ }
+
/**
* Throws an {@link SpannerException} with code {@link ErrorCode#FAILED_PRECONDITION} if the
* current state of this connection does not allow changing the setting for retryAbortsInternally.
@@ -899,6 +919,7 @@ private void setDefaultTransactionOptions() {
: UnitOfWorkType.READ_WRITE_TRANSACTION;
batchMode = BatchMode.NONE;
transactionTag = null;
+ excludeTxnFromChangeStreams = false;
} else {
popUnitOfWorkFromTransactionStack();
}
@@ -1768,22 +1789,29 @@ UnitOfWork createNewUnitOfWork(
if (isInternalMetadataQuery
|| (isAutocommit() && !isInTransaction() && !isInBatch())
|| forceSingleUse) {
- return SingleUseTransaction.newBuilder()
- .setInternalMetadataQuery(isInternalMetadataQuery)
- .setDdlClient(ddlClient)
- .setDatabaseClient(dbClient)
- .setBatchClient(batchClient)
- .setReadOnly(isReadOnly())
- .setReadOnlyStaleness(readOnlyStaleness)
- .setAutocommitDmlMode(autocommitDmlMode)
- .setReturnCommitStats(returnCommitStats)
- .setMaxCommitDelay(maxCommitDelay)
- .setStatementTimeout(statementTimeout)
- .withStatementExecutor(statementExecutor)
- .setSpan(
- createSpanForUnitOfWork(
- statementType == StatementType.DDL ? DDL_STATEMENT : SINGLE_USE_TRANSACTION))
- .build();
+ SingleUseTransaction singleUseTransaction =
+ SingleUseTransaction.newBuilder()
+ .setInternalMetadataQuery(isInternalMetadataQuery)
+ .setDdlClient(ddlClient)
+ .setDatabaseClient(dbClient)
+ .setBatchClient(batchClient)
+ .setReadOnly(isReadOnly())
+ .setReadOnlyStaleness(readOnlyStaleness)
+ .setAutocommitDmlMode(autocommitDmlMode)
+ .setReturnCommitStats(returnCommitStats)
+ .setExcludeTxnFromChangeStreams(excludeTxnFromChangeStreams)
+ .setMaxCommitDelay(maxCommitDelay)
+ .setStatementTimeout(statementTimeout)
+ .withStatementExecutor(statementExecutor)
+ .setSpan(
+ createSpanForUnitOfWork(
+ statementType == StatementType.DDL ? DDL_STATEMENT : SINGLE_USE_TRANSACTION))
+ .build();
+ if (!isInternalMetadataQuery && !forceSingleUse) {
+ // Reset the transaction options after starting a single-use transaction.
+ setDefaultTransactionOptions();
+ }
+ return singleUseTransaction;
} else {
switch (getUnitOfWorkType()) {
case READ_ONLY_TRANSACTION:
@@ -1810,6 +1838,7 @@ UnitOfWork createNewUnitOfWork(
.setStatementTimeout(statementTimeout)
.withStatementExecutor(statementExecutor)
.setTransactionTag(transactionTag)
+ .setExcludeTxnFromChangeStreams(excludeTxnFromChangeStreams)
.setRpcPriority(rpcPriority)
.setSpan(createSpanForUnitOfWork(READ_WRITE_TRANSACTION))
.build();
@@ -1822,6 +1851,7 @@ UnitOfWork createNewUnitOfWork(
.setStatementTimeout(statementTimeout)
.withStatementExecutor(statementExecutor)
.setStatementTag(statementTag)
+ .setExcludeTxnFromChangeStreams(excludeTxnFromChangeStreams)
.setRpcPriority(rpcPriority)
.setSpan(createSpanForUnitOfWork(DML_BATCH))
.build();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
index cc4c53275b3..2fb63d9db3b 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
@@ -99,6 +99,10 @@ StatementResult statementSetDelayTransactionStartUntilFirstWrite(
StatementResult statementShowTransactionTag();
+ StatementResult statementSetExcludeTxnFromChangeStreams(Boolean excludeTxnFromChangeStreams);
+
+ StatementResult statementShowExcludeTxnFromChangeStreams();
+
StatementResult statementBeginTransaction();
StatementResult statementBeginPgTransaction(PgTransactionMode transactionMode);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
index ec0ca4f4ac3..28cb2c8ae91 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
@@ -29,6 +29,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DEFAULT_TRANSACTION_ISOLATION;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_DIRECTED_READ;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_COMMIT_DELAY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_PARTITIONED_PARALLELISM;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_PARTITIONS;
@@ -52,6 +53,7 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DATA_BOOST_ENABLED;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DELAY_TRANSACTION_START_UNTIL_FIRST_WRITE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_DIRECTED_READ;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_EXCLUDE_TXN_FROM_CHANGE_STREAMS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_COMMIT_DELAY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_PARTITIONED_PARALLELISM;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_PARTITIONS;
@@ -409,6 +411,21 @@ public StatementResult statementShowTransactionTag() {
SHOW_TRANSACTION_TAG);
}
+ @Override
+ public StatementResult statementSetExcludeTxnFromChangeStreams(
+ Boolean excludeTxnFromChangeStreams) {
+ getConnection().setExcludeTxnFromChangeStreams(excludeTxnFromChangeStreams);
+ return noResult(SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS);
+ }
+
+ @Override
+ public StatementResult statementShowExcludeTxnFromChangeStreams() {
+ return resultSet(
+ String.format("%sEXCLUDE_TXN_FROM_CHANGE_STREAMS", getNamespace(connection.getDialect())),
+ getConnection().isExcludeTxnFromChangeStreams(),
+ SHOW_EXCLUDE_TXN_FROM_CHANGE_STREAMS);
+ }
+
@Override
public StatementResult statementBeginTransaction() {
getConnection().beginTransaction();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadWriteTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadWriteTransaction.java
index 19c91ac1945..0c55d90a9a3 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadWriteTransaction.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadWriteTransaction.java
@@ -251,6 +251,9 @@ private TransactionOption[] extractOptions(Builder builder) {
if (this.transactionTag != null) {
numOptions++;
}
+ if (this.excludeTxnFromChangeStreams) {
+ numOptions++;
+ }
if (this.rpcPriority != null) {
numOptions++;
}
@@ -265,6 +268,9 @@ private TransactionOption[] extractOptions(Builder builder) {
if (this.transactionTag != null) {
options[index++] = Options.tag(this.transactionTag);
}
+ if (this.excludeTxnFromChangeStreams) {
+ options[index++] = Options.excludeTxnFromChangeStreams();
+ }
if (this.rpcPriority != null) {
options[index++] = Options.priority(this.rpcPriority);
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
index 7dfa46a5977..05c05ae9e16 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
@@ -55,6 +55,7 @@
import com.google.spanner.v1.SpannerGrpc;
import io.opentelemetry.context.Scope;
import java.time.Duration;
+import java.util.Arrays;
import java.util.concurrent.Callable;
/**
@@ -497,6 +498,9 @@ private TransactionRunner createWriteTransaction() {
if (returnCommitStats) {
numOptions++;
}
+ if (excludeTxnFromChangeStreams) {
+ numOptions++;
+ }
if (maxCommitDelay != null) {
numOptions++;
}
@@ -511,6 +515,9 @@ private TransactionRunner createWriteTransaction() {
if (returnCommitStats) {
options[index++] = Options.commitStats();
}
+ if (excludeTxnFromChangeStreams) {
+ options[index++] = Options.excludeTxnFromChangeStreams();
+ }
if (maxCommitDelay != null) {
options[index++] = Options.maxCommitDelay(maxCommitDelay);
}
@@ -580,10 +587,21 @@ private ApiFuture analyzeTransactionalUpdateAsync(
private ApiFuture executePartitionedUpdateAsync(
CallType callType, final ParsedStatement update, final UpdateOption... options) {
+ final UpdateOption[] effectiveOptions;
+ if (excludeTxnFromChangeStreams) {
+ if (options.length == 0) {
+ effectiveOptions = new UpdateOption[] {Options.excludeTxnFromChangeStreams()};
+ } else {
+ effectiveOptions = Arrays.copyOf(options, options.length + 1);
+ effectiveOptions[effectiveOptions.length - 1] = Options.excludeTxnFromChangeStreams();
+ }
+ } else {
+ effectiveOptions = options;
+ }
Callable callable =
() -> {
try {
- Long res = dbClient.executePartitionedUpdate(update.getStatement(), options);
+ Long res = dbClient.executePartitionedUpdate(update.getStatement(), effectiveOptions);
state = UnitOfWorkState.COMMITTED;
return res;
} catch (Throwable t) {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
index 77f544a046f..8488276340d 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
@@ -79,6 +79,8 @@ enum ClientSideStatementType {
SET_STATEMENT_TAG,
SHOW_TRANSACTION_TAG,
SET_TRANSACTION_TAG,
+ SHOW_EXCLUDE_TXN_FROM_CHANGE_STREAMS,
+ SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS,
BEGIN,
COMMIT,
ROLLBACK,
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
index da2f79b844e..a1dbe4566c5 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
@@ -149,6 +149,15 @@
"method": "statementShowTransactionTag",
"exampleStatements": ["show variable transaction_tag"]
},
+ {
+ "name": "SHOW VARIABLE EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "executorName": "ClientSideStatementNoParamExecutor",
+ "resultType": "RESULT_SET",
+ "statementType": "SHOW_EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "regex": "(?is)\\A\\s*show\\s+variable\\s+exclude_txn_from_change_streams\\s*\\z",
+ "method": "statementShowExcludeTxnFromChangeStreams",
+ "exampleStatements": ["show variable exclude_txn_from_change_streams"]
+ },
{
"name": "SHOW VARIABLE RPC_PRIORITY",
"executorName": "ClientSideStatementNoParamExecutor",
@@ -497,6 +506,21 @@
"converterName": "ClientSideStatementValueConverters$StringValueConverter"
}
},
+ {
+ "name": "SET EXCLUDE_TXN_FROM_CHANGE_STREAMS = TRUE|FALSE",
+ "executorName": "ClientSideStatementSetExecutor",
+ "resultType": "NO_RESULT",
+ "statementType": "SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "regex": "(?is)\\A\\s*set\\s+exclude_txn_from_change_streams\\s*(?:=)\\s*(.*)\\z",
+ "method": "statementSetExcludeTxnFromChangeStreams",
+ "exampleStatements": ["set exclude_txn_from_change_streams = true", "set exclude_txn_from_change_streams = false"],
+ "setStatement": {
+ "propertyName": "EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "separator": "=",
+ "allowedValues": "(TRUE|FALSE)",
+ "converterName": "ClientSideStatementValueConverters$BooleanConverter"
+ }
+ },
{
"name": "SET RPC_PRIORITY = 'HIGH'|'MEDIUM'|'LOW'|'NULL'",
"executorName": "ClientSideStatementSetExecutor",
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
index f641f7be0d9..396a36c7a54 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
@@ -149,6 +149,15 @@
"method": "statementShowTransactionTag",
"exampleStatements": ["show spanner.transaction_tag","show variable spanner.transaction_tag"]
},
+ {
+ "name": "SHOW [VARIABLE] SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "executorName": "ClientSideStatementNoParamExecutor",
+ "resultType": "RESULT_SET",
+ "statementType": "SHOW_EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "regex": "(?is)\\A\\s*show\\s+(?:variable\\s+)?spanner\\.exclude_txn_from_change_streams\\s*\\z",
+ "method": "statementShowExcludeTxnFromChangeStreams",
+ "exampleStatements": ["show spanner.exclude_txn_from_change_streams","show variable spanner.exclude_txn_from_change_streams"]
+ },
{
"name": "SHOW [VARIABLE] SPANNER.RPC_PRIORITY",
"executorName": "ClientSideStatementNoParamExecutor",
@@ -679,6 +688,21 @@
"converterName": "ClientSideStatementValueConverters$StringValueConverter"
}
},
+ {
+ "name": "SET SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS =|TO TRUE|FALSE",
+ "executorName": "ClientSideStatementSetExecutor",
+ "resultType": "NO_RESULT",
+ "statementType": "SET_EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "regex": "(?is)\\A\\s*set\\s+spanner\\.exclude_txn_from_change_streams(?:\\s*=\\s*|\\s+to\\s+)(.*)\\z",
+ "method": "statementSetReturnCommitStats",
+ "exampleStatements": ["set spanner.exclude_txn_from_change_streams = true", "set spanner.exclude_txn_from_change_streams = false", "set spanner.exclude_txn_from_change_streams to true", "set spanner.exclude_txn_from_change_streams to false"],
+ "setStatement": {
+ "propertyName": "SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS",
+ "separator": "(?:=|\\s+TO\\s+)",
+ "allowedValues": "(TRUE|FALSE)",
+ "converterName": "ClientSideStatementValueConverters$BooleanConverter"
+ }
+ },
{
"name": "SET SPANNER.RPC_PRIORITY =|TO 'HIGH'|'MEDIUM'|'LOW'|'NULL'",
"executorName": "ClientSideStatementSetExecutor",
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ExcludeTxnFromChangeStreamsMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ExcludeTxnFromChangeStreamsMockServerTest.java
new file mode 100644
index 00000000000..5fc8fc7cfef
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ExcludeTxnFromChangeStreamsMockServerTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.ResultSet;
+import com.google.cloud.spanner.SpannerException;
+import com.google.cloud.spanner.Statement;
+import com.google.common.collect.ImmutableList;
+import com.google.spanner.v1.BeginTransactionRequest;
+import com.google.spanner.v1.ExecuteBatchDmlRequest;
+import com.google.spanner.v1.ExecuteSqlRequest;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ExcludeTxnFromChangeStreamsMockServerTest extends AbstractMockServerTest {
+
+ @After
+ public void clearRequests() {
+ mockSpanner.clearRequests();
+ }
+
+ @Test
+ public void testAutoCommit_includedByDefault() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.executeUpdate(INSERT_STATEMENT);
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertFalse(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testAutoCommitUpdate() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeUpdate(INSERT_STATEMENT);
+
+ // Verify that the setting is reset after executing a transaction.
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testAutoCommitBatchDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeBatchUpdate(ImmutableList.of(INSERT_STATEMENT, INSERT_STATEMENT));
+
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
+ ExecuteBatchDmlRequest request =
+ mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testAutoCommitUpdateReturning() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeQuery(INSERT_RETURNING_STATEMENT);
+
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testPartitionedDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeUpdate(INSERT_STATEMENT);
+
+ // Verify that the setting is reset after executing a transaction.
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ BeginTransactionRequest request =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0);
+ assertTrue(request.hasOptions());
+ assertTrue(request.getOptions().hasPartitionedDml());
+ assertTrue(request.getOptions().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testTransaction_includedByDefault() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.commit();
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertFalse(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testTransactionUpdate() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.commit();
+
+ // Verify that the setting is reset after executing a transaction.
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testTransactionBatchDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeBatchUpdate(ImmutableList.of(INSERT_STATEMENT, INSERT_STATEMENT));
+ connection.commit();
+
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
+ ExecuteBatchDmlRequest request =
+ mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testTransactionUpdateReturning() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.setExcludeTxnFromChangeStreams(true);
+ connection.executeQuery(INSERT_RETURNING_STATEMENT);
+ connection.commit();
+
+ assertFalse(connection.isExcludeTxnFromChangeStreams());
+ }
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.hasTransaction());
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getTransaction().getBegin().getExcludeTxnFromChangeStreams());
+ }
+
+ @Test
+ public void testSqlStatements() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+
+ connection.execute(Statement.of("set exclude_txn_from_change_streams = true"));
+ assertTrue(connection.isExcludeTxnFromChangeStreams());
+
+ try (ResultSet resultSet =
+ connection
+ .execute(Statement.of("show variable exclude_txn_from_change_streams"))
+ .getResultSet()) {
+ assertTrue(resultSet.next());
+ assertTrue(resultSet.getBoolean("EXCLUDE_TXN_FROM_CHANGE_STREAMS"));
+ assertFalse(resultSet.next());
+ }
+
+ connection.setAutocommit(false);
+ connection.execute(Statement.of("set exclude_txn_from_change_streams = true"));
+ assertTrue(connection.isExcludeTxnFromChangeStreams());
+ connection.execute(INSERT_STATEMENT);
+ assertThrows(
+ SpannerException.class,
+ () -> connection.execute(Statement.of("set exclude_txn_from_change_streams=false")));
+ }
+ }
+}
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
index 30aed342903..4b6aec5b965 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
@@ -3591,6 +3591,205 @@ NEW_CONNECTION;
@EXPECT EXCEPTION UNIMPLEMENTED
show variable/-transaction_tag;
NEW_CONNECTION;
+show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+SHOW VARIABLE EXCLUDE_TXN_FROM_CHANGE_STREAMS;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+
+
+
+show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams
+
+;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show
+variable
+exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable%exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable_exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable&exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable$exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable@exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable!exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable*exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable(exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams);
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable)exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable+exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-#exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable\exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable?exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-/exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/#exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-show variable exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable exclude_txn_from_change_streams/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/-exclude_txn_from_change_streams;
+NEW_CONNECTION;
show variable rpc_priority;
NEW_CONNECTION;
SHOW VARIABLE RPC_PRIORITY;
@@ -18416,6 +18615,406 @@ set autocommit = false;
@EXPECT EXCEPTION INVALID_ARGUMENT
set/-transaction_tag='test_tag';
NEW_CONNECTION;
+set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+SET EXCLUDE_TXN_FROM_CHANGE_STREAMS = TRUE;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+ set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+ set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+
+
+
+set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true ;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true ;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true
+
+;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set
+exclude_txn_from_change_streams
+=
+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =%true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =_true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =&true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =$true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =@true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =!true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =*true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =(true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =)true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =\true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =?true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = true/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/-true;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+SET EXCLUDE_TXN_FROM_CHANGE_STREAMS = FALSE;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+ set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+ set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+
+
+
+set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false ;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false ;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false
+
+;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set
+exclude_txn_from_change_streams
+=
+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =%false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =_false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =&false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =$false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =@false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =!false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =*false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =(false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =)false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =\false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =?false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =-/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams = false/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set exclude_txn_from_change_streams =/-false;
+NEW_CONNECTION;
set rpc_priority='HIGH';
NEW_CONNECTION;
SET RPC_PRIORITY='HIGH';
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql
index 84275c3d5c3..d9e8e244f0d 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql
@@ -160,15 +160,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.519000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.519000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.894000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.519000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -510,15 +510,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.630000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.630000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.008000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.630000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -950,8 +950,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.728000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.728000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -961,7 +961,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.111000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.728000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1462,8 +1462,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.831000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.831000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -1473,7 +1473,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.217000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.831000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1876,15 +1876,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.915000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.915000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.318000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.915000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.985000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.388000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.985000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2600,13 +2600,13 @@ SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.063000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.472000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.063000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2910,14 +2910,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.138000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.138000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.543000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.138000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -3245,15 +3245,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.214000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.214000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.630000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.214000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.295000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.295000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -3672,7 +3672,7 @@ START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.713000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.295000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.358000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.778000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.358000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4438,13 +4438,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.419000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.833000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.419000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.475000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.475000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.892000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.475000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5288,15 +5288,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.540000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.540000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.959000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.540000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5641,15 +5641,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.596000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.596000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.012000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.596000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6088,8 +6088,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.654000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.654000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -6099,7 +6099,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.073000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.654000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6607,8 +6607,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.737000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.737000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -6618,7 +6618,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.152000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.737000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7023,15 +7023,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.805000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.805000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.223000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.805000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.862000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.285000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.862000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7756,13 +7756,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.930000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.350000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.930000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8075,14 +8075,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.994000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.994000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.415000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.994000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8392,13 +8392,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.043000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.468000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.043000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -8753,8 +8753,8 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.101000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.101000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.517000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.101000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9197,8 +9197,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.160000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.160000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -9206,8 +9206,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.575000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.160000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.160000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -9593,15 +9593,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.228000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.228000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.641000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.228000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9952,15 +9952,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.296000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.296000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.691000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.296000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.296000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -10320,15 +10320,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.354000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.354000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.768000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.354000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.354000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -10718,16 +10718,16 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.414000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.414000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.829000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.414000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.414000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11110,15 +11110,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.473000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.473000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.886000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.473000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.473000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11448,14 +11448,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.529000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.529000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.946000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.529000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.529000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11778,15 +11778,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.577000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.577000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.999000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.577000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.577000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12193,8 +12193,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.630000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.630000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12202,8 +12202,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.050000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.630000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.630000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12586,15 +12586,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.801000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.801000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.106000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.801000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
@@ -12932,15 +12932,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.877000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.877000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.157000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.877000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.877000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -13287,15 +13287,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.967000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.967000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.213000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.967000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.967000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -13612,14 +13612,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:27.025000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:27.025000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.269000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:27.025000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:27.025000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql
index 5ffa722385d..0f2c0368412 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql
@@ -7167,6 +7167,403 @@ NEW_CONNECTION;
@EXPECT EXCEPTION UNIMPLEMENTED
show variable/-spanner.transaction_tag;
NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+SHOW SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+
+
+
+show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams
+
+;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show
+spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show%spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show_spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show&spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show$spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show@spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show!spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show*spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show(spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show)spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show-spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show+spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show-#spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show/spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show\spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show?spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show-/spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show/#spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-show spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show spanner.exclude_txn_from_change_streams/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+show/-spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+SHOW VARIABLE SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+ show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+
+
+
+show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams ;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams
+
+;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+show
+variable
+spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable%spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable_spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable&spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable$spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable@spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable!spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable*spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable(spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams);
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable)spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable+spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-#spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable\spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable?spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-/spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/#spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-show variable spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable spanner.exclude_txn_from_change_streams/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/-spanner.exclude_txn_from_change_streams;
+NEW_CONNECTION;
show spanner.rpc_priority;
NEW_CONNECTION;
SHOW SPANNER.RPC_PRIORITY;
@@ -70783,6 +71180,806 @@ set autocommit = false;
@EXPECT EXCEPTION INVALID_ARGUMENT
set spanner.transaction_tag to/-'test_tag';
NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+SET SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS = TRUE;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+
+
+
+set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true
+
+;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+set
+spanner.exclude_txn_from_change_streams
+=
+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =%true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =_true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =&true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =$true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =@true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =!true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =*true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =(true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =)true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =\true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =?true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.exclude_txn_from_change_streams = true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = true/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/-true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+SET SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS = FALSE;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+
+
+
+set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false
+
+;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+set
+spanner.exclude_txn_from_change_streams
+=
+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =%false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =_false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =&false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =$false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =@false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =!false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =*false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =(false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =)false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =\false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =?false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =-/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.exclude_txn_from_change_streams = false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams = false/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams =/-false;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+SET SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS TO TRUE;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+
+
+
+set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true
+
+;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+set
+spanner.exclude_txn_from_change_streams
+to
+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to%true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to_true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to&true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to$true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to@true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to!true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to*true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to(true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to)true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to+true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to\true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to?true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-/true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/#true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.exclude_txn_from_change_streams to true;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to true/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/-true;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+SET SPANNER.EXCLUDE_TXN_FROM_CHANGE_STREAMS TO FALSE;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+ set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+
+
+
+set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false ;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false
+
+;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+set
+spanner.exclude_txn_from_change_streams
+to
+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to%false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to_false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to&false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to$false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to@false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to!false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to*false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to(false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false);
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to)false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to+false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to\false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to?false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to-/false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/#false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.exclude_txn_from_change_streams to false;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to false/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.exclude_txn_from_change_streams to/-false;
+NEW_CONNECTION;
set spanner.rpc_priority='HIGH';
NEW_CONNECTION;
SET SPANNER.RPC_PRIORITY='HIGH';
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql
index e35ae5f3c3c..5f6ecd2b3a1 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql
@@ -160,15 +160,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.581000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.581000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:32.957000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.581000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -510,15 +510,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.679000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.679000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.060000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.679000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -950,8 +950,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.784000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.784000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -961,7 +961,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.165000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.784000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1462,8 +1462,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.878000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.878000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -1473,7 +1473,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.275000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.878000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1876,15 +1876,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:24.948000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:24.948000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.351000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:24.948000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.022000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.428000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.022000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2600,13 +2600,13 @@ SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.103000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.509000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.103000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2910,14 +2910,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.167000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.167000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.575000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.167000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -3245,15 +3245,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.262000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.262000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.662000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.262000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.328000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.328000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -3672,7 +3672,7 @@ START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.747000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.328000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.390000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.806000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.390000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4438,13 +4438,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.445000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.861000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.445000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.511000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.511000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.927000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.511000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5288,15 +5288,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.565000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.565000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:33.985000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.565000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5641,15 +5641,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.623000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.623000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.041000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.623000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6088,8 +6088,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.692000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.692000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -6099,7 +6099,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.108000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.692000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6607,8 +6607,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.774000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.774000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -6618,7 +6618,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.191000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.774000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7023,15 +7023,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.833000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:25.833000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.254000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.833000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.894000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.318000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.894000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7756,13 +7756,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:25.964000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.384000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:25.964000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8075,14 +8075,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.019000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.019000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.443000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.019000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8392,13 +8392,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.075000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.492000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.075000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -8753,8 +8753,8 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.126000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.126000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.542000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.126000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9197,8 +9197,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.197000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.197000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -9206,8 +9206,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.611000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.197000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.197000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -9593,15 +9593,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.251000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.251000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.665000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.251000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9952,15 +9952,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.324000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.324000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.719000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.324000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.324000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -10320,15 +10320,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.385000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.385000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.800000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.385000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.385000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -10718,16 +10718,16 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.443000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.443000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.857000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.443000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.443000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11110,15 +11110,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.502000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.502000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.918000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.502000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.502000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11448,14 +11448,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.553000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.553000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:34.974000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.553000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.553000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11778,15 +11778,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.601000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.601000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.024000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.601000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.601000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12193,8 +12193,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.697000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.697000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12202,8 +12202,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.080000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.697000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.697000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12586,15 +12586,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.836000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.836000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.129000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.836000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
@@ -12932,15 +12932,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.919000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.919000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.184000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.919000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.919000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -13287,15 +13287,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:26.997000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:26.997000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.242000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:26.997000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:26.997000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -13612,14 +13612,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-05-13T09:04:27.050000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-05-13T09:04:27.050000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-04-22T15:43:35.293000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-05-13T09:04:27.050000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-05-13T09:04:27.050000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
From dee7cdabe74058434e4d630846f066dc82fdf512 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Thu, 23 May 2024 08:14:02 +0200
Subject: [PATCH 06/11] feat: allow DML batches in transactions to execute
analyzeUpdate (#3114)
Executing analyzeUpdate in a DML Batch inside a transaction should
be possible, as the parent transaction can be used for that.
---
.../connection/AbstractBaseUnitOfWork.java | 2 --
.../AbstractMultiUseTransaction.java | 2 +-
.../cloud/spanner/connection/DdlBatch.java | 2 +-
.../cloud/spanner/connection/DmlBatch.java | 11 +++---
.../connection/SingleUseTransaction.java | 2 +-
.../cloud/spanner/connection/UnitOfWork.java | 3 ++
.../connection/AnalyzeStatementsTest.java | 34 +++++++++++++++++--
7 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
index ec9e7a636ed..ef624ea8416 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractBaseUnitOfWork.java
@@ -176,8 +176,6 @@ private Void endUnitOfWorkSpan() {
return null;
}
- abstract boolean isSingleUse();
-
/**
* Returns a descriptive name for the type of transaction / unit of work. This is used in error
* messages.
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractMultiUseTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractMultiUseTransaction.java
index f84f379e79a..ca78c3e5aea 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractMultiUseTransaction.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractMultiUseTransaction.java
@@ -96,7 +96,7 @@ public String toString() {
}
@Override
- boolean isSingleUse() {
+ public boolean isSingleUse() {
return false;
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
index ca5da153f6a..f21c7e2cdeb 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
@@ -97,7 +97,7 @@ private DdlBatch(Builder builder) {
}
@Override
- boolean isSingleUse() {
+ public boolean isSingleUse() {
return false;
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DmlBatch.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DmlBatch.java
index 1551a186e7f..fde3c609cb3 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DmlBatch.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DmlBatch.java
@@ -78,12 +78,12 @@ static Builder newBuilder() {
private DmlBatch(Builder builder) {
super(builder);
- this.transaction = builder.transaction;
+ this.transaction = Preconditions.checkNotNull(builder.transaction);
this.statementTag = builder.statementTag;
}
@Override
- boolean isSingleUse() {
+ public boolean isSingleUse() {
return false;
}
@@ -174,8 +174,11 @@ public ApiFuture executeUpdateAsync(
@Override
public ApiFuture analyzeUpdateAsync(
CallType callType, ParsedStatement update, AnalyzeMode analyzeMode, UpdateOption... options) {
- throw SpannerExceptionFactory.newSpannerException(
- ErrorCode.FAILED_PRECONDITION, "Analyzing updates is not allowed for DML batches.");
+ if (transaction.isSingleUse()) {
+ throw SpannerExceptionFactory.newSpannerException(
+ ErrorCode.FAILED_PRECONDITION, "Analyzing updates is not allowed for DML batches.");
+ }
+ return transaction.analyzeUpdateAsync(callType, update, analyzeMode, options);
}
@Override
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
index 05c05ae9e16..3eeffae47b0 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
@@ -180,7 +180,7 @@ private SingleUseTransaction(Builder builder) {
}
@Override
- boolean isSingleUse() {
+ public boolean isSingleUse() {
return true;
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/UnitOfWork.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/UnitOfWork.java
index 1c8bc6a29c0..577cd39d201 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/UnitOfWork.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/UnitOfWork.java
@@ -77,6 +77,9 @@ public boolean isActive() {
/** @return true if this unit of work is still active. */
boolean isActive();
+ /** Returns true if this transaction can only be used for a single statement. */
+ boolean isSingleUse();
+
/**
* Commits the changes in this unit of work to the database. For read-only transactions, this only
* closes the {@link ReadContext}. This method will throw a {@link SpannerException} if called for
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AnalyzeStatementsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AnalyzeStatementsTest.java
index 3adb50b170f..6f76963fef7 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AnalyzeStatementsTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AnalyzeStatementsTest.java
@@ -355,8 +355,9 @@ public void testAnalyzeUpdateStatementDdlBatch() {
}
@Test
- public void testAnalyzeUpdateDmlBatch() {
+ public void testAnalyzeUpdateDmlBatch_AutoCommit() {
try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
connection.startBatchDml();
SpannerException exception =
@@ -371,8 +372,23 @@ public void testAnalyzeUpdateDmlBatch() {
}
@Test
- public void testAnalyzeUpdateStatementDmlBatch() {
+ public void testAnalyzeUpdateDmlBatch_Transactional() {
try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.startBatchDml();
+
+ assertNotNull(connection.analyzeUpdate(PLAN_UPDATE, QueryAnalyzeMode.PLAN));
+ assertEquals(-1L, connection.executeUpdate(INSERT_STATEMENT));
+ connection.runBatch();
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ }
+ }
+
+ @Test
+ public void testAnalyzeUpdateStatementDmlBatch_AutoCommit() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
connection.startBatchDml();
SpannerException exception =
@@ -385,4 +401,18 @@ public void testAnalyzeUpdateStatementDmlBatch() {
assertEquals(0, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
}
+
+ @Test
+ public void testAnalyzeUpdateStatementDmlBatch_Transactional() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(false);
+ connection.startBatchDml();
+
+ connection.analyzeUpdateStatement(PLAN_UPDATE, QueryAnalyzeMode.PLAN);
+ assertEquals(-1L, connection.executeUpdate(INSERT_STATEMENT));
+ connection.runBatch();
+
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ }
+ }
}
From ae93c5774f70155f4f068ad6e8ec9e03fedc3158 Mon Sep 17 00:00:00 2001
From: Mend Renovate
Date: Fri, 24 May 2024 05:56:22 +0200
Subject: [PATCH 07/11] chore(deps): update dependency
com.google.cloud:google-cloud-spanner to v6.67.0 (#3120)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* chore(deps): update dependency com.google.cloud:google-cloud-spanner to v6.67.0
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---------
Co-authored-by: Owl Bot
---
README.md | 8 ++++----
benchmarks/pom.xml | 2 +-
samples/install-without-bom/pom.xml | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
index cdfaf9f988e..ba3bc5d59c7 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ If you are using Maven without the BOM, add this to your dependencies:
com.google.cloud
google-cloud-spanner
- 6.66.0
+ 6.67.0
```
@@ -57,13 +57,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.66.0'
+implementation 'com.google.cloud:google-cloud-spanner:6.67.0'
```
If you are using SBT, add this to your dependencies:
```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.66.0"
+libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.67.0"
```
@@ -671,7 +671,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.66.0
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.67.0
[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 115d3ccdef9..1b75952769b 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -92,7 +92,7 @@
com.google.cloud
google-cloud-spanner
- 6.66.0
+ 6.67.0
commons-cli
diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml
index 2999cbebb48..fecfbdc5d5e 100644
--- a/samples/install-without-bom/pom.xml
+++ b/samples/install-without-bom/pom.xml
@@ -33,7 +33,7 @@
com.google.cloud
google-cloud-spanner
- 6.66.0
+ 6.67.0
From 7e7c814045dc84aaa57e7c716b0221e6cb19bcd1 Mon Sep 17 00:00:00 2001
From: Sri Harsha CH <57220027+harshachinta@users.noreply.github.com>
Date: Fri, 24 May 2024 17:09:10 +0530
Subject: [PATCH 08/11] feat(spanner): add support for Proto Columns in
Connection API (#3123)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: Support for Proto Messages & Enums (#2155)
* feat: Importing Proto Changes
Commit will be reverted, once PROTO changes are available publicly.
* feat: Proto Message Implementation
* feat: Adding support for enum
* feat: Code refactoring
Adding default implementation for newly added methods
ByteArray compatability changes for Proto Messages
* docs: Adding Java docs for all the newly added methods.
* test: Sample Proto & Generated classes for unit test
* feat: Adding bytes/proto & int64/enum compatability
Adding Additional check for ChecksumResultSet
* test: Adding unit tests
* test: Adding unit tests for ValueBinder.java
* feat: refactoring to add support for getValue & other minor changes
* feat: Minor refactoring
1. Adding docs and formatting the code.
2. Adding additional methods for enum and message which accepts descriptors.
* feat: Adding bytes/message & int64/enum compatability in Value
* refactor: Minor refactoring
* feat: Adding Proto Array Implementation
* test: Implementing unit tests for array of protos and enums
* refactor: adding clirr ignores
* feat: Adding support for enum as Primary Key
* feat: Code Review Changes, minor refactoring and adding docs
* feat: Addressing review comments
-Modified Docs/Comments
-Minor Refactoring
* refactor: Using Column instead of column to avoid test failures
* feat: Minor refactoring
-code review comments
-adding function docs
* samples: Adding samples for updating & querying Proto messages & enums (#2211)
* samples: Adding samples for updating & querying Proto messages & enums
* style: linting
* style: linting
* docs: Adding function and class doc
* test: Proto Column Integration tests (#2212)
* test: Adding Integration tests for Proto Messages & Enums
* test: Adding additional test for Parameterized Queries, Primary Keys & Invalid Wire type errors.
* style: Formatting
* style: Formatting
* test: Updating instance and db name
* test: Adding inter compatability check while writing data
* Configured jitpack.yml to use OpenJDK 11 (#2218)
Co-authored-by: Pavol Juhos
* feat: add support for Proto Columns DDL (#2277)
* feat: add code changes and tests for Proto columns DDL support
* feat: add auto generated code
* feat: code changes and tests for Proto columns DDL support
* feat: add descriptors file
* feat: code refactoring
* feat: Integration tests and code refactoring
* feat: code refactoring
* feat: unit tests and clirr differences
* feat: lint changes
* feat: code refactor
* feat: code refactoring
* feat: code refactoring
* feat: code refactoring
* feat: add java docs to new methods
* feat: lint formatting
* feat: lint formatting changes
* feat: lint formatting
* feat: lint formatting
* feat: test exception cases
* feat: code refactoring
* feat: add java docs and refactoring
* feat: add java docs
* feat: java docs refactor
* feat: remove overload method setProtoDescriptors that accepts file path as input to avoid unexpected issues
* feat: remove updateDdl method overload to update proto descriptor
* teat: update pom file to run tests on cloud-devel region temporarily to validate main branch update
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
* fix: revert host changes in pom.xml file
* feat: add support for Proto Columns to Connection API
* feat: add client side statement support for proto descriptor
* feat: update existing unit tests to include proto descriptorss argument
* feat: code refactor for client side statements
* feat: add unit tests
* feat: code refactoring for file path client statement
* test: add integration test for DDL
* fix: comment refactoring
* feat: move proto descriptor file read logic to ConnectionImpl file to fix autogenerated client side statement tests
* feat: add autogenerated test for new proto columns client side statements
* feat: add unit tests to verify proto descriptor set via filepath
* feat: add review comments
* feat: add client side statement to show proto descriptors file path
* fix: remove proto descriptors file extension validation
* feat: comment refactor
* feat: address review comments
* feat: update tests and revert autogenerated code
* chore: revert autogenerated coee
* chore: revert autogenerated code
* chore: revert autogenerated code
* chore: lint format
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
* chore: regenerate descriptors file
* chore: update schema
* chore: update base64 value for protodescriptor
* chore: update copyright year
---------
Co-authored-by: Gaurav Purohit
Co-authored-by: Pavol Juhos
Co-authored-by: Owl Bot
---
.../clirr-ignored-differences.xml | 28 +-
.../java/com/google/cloud/spanner/Type.java | 4 +-
.../ClientSideStatementValueConverters.java | 44 +
.../cloud/spanner/connection/Connection.java | 20 +
.../spanner/connection/ConnectionImpl.java | 70 +-
.../ConnectionStatementExecutor.java | 8 +
.../ConnectionStatementExecutorImpl.java | 34 +
.../cloud/spanner/connection/DdlBatch.java | 10 +-
.../cloud/spanner/connection/DdlClient.java | 27 +-
.../connection/SingleUseTransaction.java | 10 +-
.../spanner/connection/StatementResult.java | 4 +
.../connection/StatementResultImpl.java | 18 +
.../connection/ClientSideStatements.json | 50 ++
.../connection/ConnectionImplTest.java | 105 ++-
.../ConnectionStatementExecutorTest.java | 25 +
.../spanner/connection/DdlBatchTest.java | 83 +-
.../spanner/connection/DdlClientTests.java | 49 +-
.../ProtoDescriptorsConverterTest.java | 64 ++
.../ProtoDescriptorsFileConverterTest.java | 46 +
.../connection/SingleUseTransactionTest.java | 69 +-
.../connection/StatementResultImplTest.java | 31 +
.../connection/ClientSideStatementsTest.sql | 794 ++++++++++++++++++
.../cloud/spanner/connection/ITDdlTest.sql | 43 +-
23 files changed, 1587 insertions(+), 49 deletions(-)
create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsConverterTest.java
create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsFileConverterTest.java
diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index 8b4c75ad385..b591c0378de 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -337,6 +337,12 @@
com/google/cloud/spanner/spi/v1/GapicSpannerRpc
com.google.cloud.spanner.spi.v1.SpannerRpc$StreamingCall read(com.google.spanner.v1.ReadRequest, com.google.cloud.spanner.spi.v1.SpannerRpc$ResultStreamConsumer, java.util.Map)
+
+ 7005
+ com/google/cloud/spanner/spi/v1/GapicSpannerRpc
+ com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(java.lang.String, java.lang.Iterable, java.lang.String)
+ com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(com.google.cloud.spanner.Database, java.lang.Iterable, java.lang.String)
+
7005
com/google/cloud/spanner/spi/v1/GapicSpannerRpc
@@ -387,6 +393,12 @@
com/google/cloud/spanner/spi/v1/SpannerRpc
com.google.cloud.spanner.spi.v1.SpannerRpc$StreamingCall read(com.google.spanner.v1.ReadRequest, com.google.cloud.spanner.spi.v1.SpannerRpc$ResultStreamConsumer, java.util.Map)
+
+ 7005
+ com/google/cloud/spanner/spi/v1/SpannerRpc
+ com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(java.lang.String, java.lang.Iterable, java.lang.String)
+ com.google.api.gax.longrunning.OperationFuture updateDatabaseDdl(com.google.cloud.spanner.Database, java.lang.Iterable, java.lang.String)
+
7005
com/google/cloud/spanner/spi/v1/SpannerRpc
@@ -656,7 +668,7 @@
com/google/cloud/spanner/connection/Connection
com.google.cloud.spanner.Spanner getSpanner()
-
+
7012
@@ -668,7 +680,7 @@
com/google/cloud/spanner/connection/Connection
com.google.cloud.spanner.connection.DdlInTransactionMode getDdlInTransactionMode()
-
+
7012
@@ -688,4 +700,16 @@
void setExcludeTxnFromChangeStreams(boolean)
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ byte[] getProtoDescriptors()
+
+
+ 7012
+ com/google/cloud/spanner/connection/Connection
+ void setProtoDescriptors(byte[])
+
+
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Type.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Type.java
index 4d93a9bfb02..748cb7f87ec 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Type.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Type.java
@@ -147,7 +147,7 @@ public static Type pgOid() {
/**
* To get the descriptor for the {@code PROTO} type.
*
- * @param protoTypeFqn Proto fully qualified name (ex: "spanner.examples.music.SingerInfo").
+ * @param protoTypeFqn Proto fully qualified name (ex: "examples.spanner.music.SingerInfo").
*/
public static Type proto(String protoTypeFqn) {
return new Type(Code.PROTO, protoTypeFqn);
@@ -156,7 +156,7 @@ public static Type proto(String protoTypeFqn) {
/**
* To get the descriptor for the {@code ENUM} type.
*
- * @param protoTypeFqn Proto ENUM fully qualified name (ex: "spanner.examples.music.Genre")
+ * @param protoTypeFqn Proto ENUM fully qualified name (ex: "examples.spanner.music.Genre")
*/
public static Type protoEnum(String protoTypeFqn) {
return new Type(Code.ENUM, protoTypeFqn);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementValueConverters.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementValueConverters.java
index 6be277777a6..4e4053249d2 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementValueConverters.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementValueConverters.java
@@ -26,10 +26,12 @@
import com.google.cloud.spanner.connection.PgTransactionMode.IsolationLevel;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
import com.google.protobuf.Duration;
import com.google.protobuf.util.Durations;
import com.google.spanner.v1.DirectedReadOptions;
import com.google.spanner.v1.RequestOptions.Priority;
+import java.util.Base64;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
@@ -563,4 +565,46 @@ public String convert(String value) {
return value.substring(7).trim();
}
}
+
+ /** Converter for converting Base64 encoded string to byte[] */
+ static class ProtoDescriptorsConverter implements ClientSideStatementValueConverter {
+
+ public ProtoDescriptorsConverter(String allowedValues) {}
+
+ @Override
+ public Class getParameterClass() {
+ return byte[].class;
+ }
+
+ @Override
+ public byte[] convert(String value) {
+ if (value == null || value.length() == 0 || value.equalsIgnoreCase("null")) {
+ return null;
+ }
+ try {
+ return Base64.getDecoder().decode(value);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+ }
+
+ /** Converter for converting String that take in file path as input to String */
+ static class ProtoDescriptorsFileConverter implements ClientSideStatementValueConverter {
+
+ public ProtoDescriptorsFileConverter(String allowedValues) {}
+
+ @Override
+ public Class getParameterClass() {
+ return String.class;
+ }
+
+ @Override
+ public String convert(String filePath) {
+ if (Strings.isNullOrEmpty(filePath)) {
+ return null;
+ }
+ return filePath;
+ }
+ }
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
index 59a919ec9c8..0178be3b289 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/Connection.java
@@ -47,6 +47,7 @@
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
/**
* Internal connection API for Google Cloud Spanner. This interface may introduce breaking changes
@@ -403,6 +404,25 @@ default boolean isExcludeTxnFromChangeStreams() {
throw new UnsupportedOperationException();
}
+ /**
+ * Sets the proto descriptors to use for the next DDL statement (single or batch) that will be
+ * executed. The proto descriptor is automatically cleared after the statement is executed.
+ *
+ * @param protoDescriptors The proto descriptors to use with the next DDL statement (single or
+ * batch) that will be executed on this connection.
+ */
+ default void setProtoDescriptors(@Nonnull byte[] protoDescriptors) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @return The proto descriptor that will be used with the next DDL statement (single or batch)
+ * that is executed on this connection.
+ */
+ default byte[] getProtoDescriptors() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @return true if this connection will automatically retry read/write transactions
* that abort. This method may only be called when the connection is in read/write
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
index c4e33b14b6b..c0cbc8c22d5 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionImpl.java
@@ -22,6 +22,7 @@
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.GaxProperties;
+import com.google.cloud.ByteArray;
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.AsyncResultSet;
import com.google.cloud.spanner.BatchClient;
@@ -65,6 +66,9 @@
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@@ -81,6 +85,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.threeten.bp.Instant;
@@ -113,7 +118,7 @@ private LeakedConnectionException() {
}
}
- private volatile LeakedConnectionException leakedException;;
+ private volatile LeakedConnectionException leakedException;
private final SpannerPool spannerPool;
private AbstractStatementParser statementParser;
/**
@@ -268,10 +273,11 @@ static UnitOfWorkType of(TransactionMode transactionMode) {
private String transactionTag;
private String statementTag;
-
private boolean excludeTxnFromChangeStreams;
private Duration maxCommitDelay;
+ private byte[] protoDescriptors;
+ private String protoDescriptorsFilePath;
/** Create a connection and register it in the SpannerPool. */
ConnectionImpl(ConnectionOptions options) {
@@ -353,6 +359,7 @@ public Spanner getSpanner() {
private DdlClient createDdlClient() {
return DdlClient.newBuilder()
.setDatabaseAdminClient(spanner.getDatabaseAdminClient())
+ .setProjectId(options.getProjectId())
.setInstanceId(options.getInstanceId())
.setDatabaseName(options.getDatabaseName())
.build();
@@ -763,6 +770,52 @@ public void setExcludeTxnFromChangeStreams(boolean excludeTxnFromChangeStreams)
this.excludeTxnFromChangeStreams = excludeTxnFromChangeStreams;
}
+ @Override
+ public byte[] getProtoDescriptors() {
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ if (this.protoDescriptors == null && this.protoDescriptorsFilePath != null) {
+ // Read from file if filepath is valid
+ try {
+ File protoDescriptorsFile = new File(this.protoDescriptorsFilePath);
+ if (!protoDescriptorsFile.isFile()) {
+ throw SpannerExceptionFactory.newSpannerException(
+ ErrorCode.INVALID_ARGUMENT,
+ String.format(
+ "File %s is not a valid proto descriptors file", this.protoDescriptorsFilePath));
+ }
+ InputStream pdStream = new FileInputStream(protoDescriptorsFile);
+ this.protoDescriptors = ByteArray.copyFrom(pdStream).toByteArray();
+ } catch (Exception exception) {
+ throw SpannerExceptionFactory.newSpannerException(exception);
+ }
+ }
+ return this.protoDescriptors;
+ }
+
+ @Override
+ public void setProtoDescriptors(@Nonnull byte[] protoDescriptors) {
+ Preconditions.checkNotNull(protoDescriptors);
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ ConnectionPreconditions.checkState(
+ !isBatchActive(), "Proto descriptors cannot be set when a batch is active");
+ this.protoDescriptors = protoDescriptors;
+ this.protoDescriptorsFilePath = null;
+ }
+
+ void setProtoDescriptorsFilePath(@Nonnull String protoDescriptorsFilePath) {
+ Preconditions.checkNotNull(protoDescriptorsFilePath);
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ ConnectionPreconditions.checkState(
+ !isBatchActive(), "Proto descriptors file path cannot be set when a batch is active");
+ this.protoDescriptorsFilePath = protoDescriptorsFilePath;
+ this.protoDescriptors = null;
+ }
+
+ String getProtoDescriptorsFilePath() {
+ ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG);
+ return this.protoDescriptorsFilePath;
+ }
+
/**
* Throws an {@link SpannerException} with code {@link ErrorCode#FAILED_PRECONDITION} if the
* current state of this connection does not allow changing the setting for retryAbortsInternally.
@@ -1806,6 +1859,7 @@ UnitOfWork createNewUnitOfWork(
.setSpan(
createSpanForUnitOfWork(
statementType == StatementType.DDL ? DDL_STATEMENT : SINGLE_USE_TRANSACTION))
+ .setProtoDescriptors(getProtoDescriptors())
.build();
if (!isInternalMetadataQuery && !forceSingleUse) {
// Reset the transaction options after starting a single-use transaction.
@@ -1862,6 +1916,7 @@ UnitOfWork createNewUnitOfWork(
.setStatementTimeout(statementTimeout)
.withStatementExecutor(statementExecutor)
.setSpan(createSpanForUnitOfWork(DDL_BATCH))
+ .setProtoDescriptors(getProtoDescriptors())
.build();
default:
}
@@ -1885,7 +1940,11 @@ private void popUnitOfWorkFromTransactionStack() {
}
private ApiFuture executeDdlAsync(CallType callType, ParsedStatement ddl) {
- return getOrStartDdlUnitOfWork().executeDdlAsync(callType, ddl);
+ ApiFuture result = getOrStartDdlUnitOfWork().executeDdlAsync(callType, ddl);
+ // reset proto descriptors after executing a DDL statement
+ this.protoDescriptors = null;
+ this.protoDescriptorsFilePath = null;
+ return result;
}
@Override
@@ -1985,6 +2044,11 @@ public ApiFuture runBatchAsync() {
}
return ApiFutures.immediateFuture(new long[0]);
} finally {
+ if (isDdlBatchActive()) {
+ // reset proto descriptors after executing a DDL batch
+ this.protoDescriptors = null;
+ this.protoDescriptorsFilePath = null;
+ }
this.batchMode = BatchMode.NONE;
setDefaultTransactionOptions();
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
index 2fb63d9db3b..0abebabf84d 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java
@@ -138,6 +138,14 @@ StatementResult statementSetPgSessionCharacteristicsTransactionMode(
StatementResult statementShowTransactionIsolationLevel();
+ StatementResult statementSetProtoDescriptors(byte[] protoDescriptors);
+
+ StatementResult statementSetProtoDescriptorsFilePath(String filePath);
+
+ StatementResult statementShowProtoDescriptors();
+
+ StatementResult statementShowProtoDescriptorsFilePath();
+
StatementResult statementExplain(String sql);
StatementResult statementShowDataBoostEnabled();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
index 28cb2c8ae91..412dcce8916 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java
@@ -35,6 +35,8 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_MAX_PARTITIONS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_OPTIMIZER_STATISTICS_PACKAGE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_OPTIMIZER_VERSION;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_PROTO_DESCRIPTORS;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_PROTO_DESCRIPTORS_FILE_PATH;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_READONLY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_READ_ONLY_STALENESS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SET_RETRY_ABORTS_INTERNALLY;
@@ -59,6 +61,8 @@
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_MAX_PARTITIONS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_STATISTICS_PACKAGE;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_OPTIMIZER_VERSION;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_PROTO_DESCRIPTORS;
+import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_PROTO_DESCRIPTORS_FILE_PATH;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_READONLY;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_READ_ONLY_STALENESS;
import static com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType.SHOW_READ_TIMESTAMP;
@@ -637,6 +641,36 @@ public StatementResult statementRunPartitionedQuery(Statement statement) {
ClientSideStatementType.RUN_PARTITIONED_QUERY);
}
+ @Override
+ public StatementResult statementSetProtoDescriptors(byte[] protoDescriptors) {
+ Preconditions.checkNotNull(protoDescriptors);
+ getConnection().setProtoDescriptors(protoDescriptors);
+ return noResult(SET_PROTO_DESCRIPTORS);
+ }
+
+ @Override
+ public StatementResult statementSetProtoDescriptorsFilePath(String filePath) {
+ Preconditions.checkNotNull(filePath);
+ getConnection().setProtoDescriptorsFilePath(filePath);
+ return noResult(SET_PROTO_DESCRIPTORS_FILE_PATH);
+ }
+
+ @Override
+ public StatementResult statementShowProtoDescriptors() {
+ return resultSet(
+ String.format("%sPROTO_DESCRIPTORS", getNamespace(connection.getDialect())),
+ getConnection().getProtoDescriptors(),
+ SHOW_PROTO_DESCRIPTORS);
+ }
+
+ @Override
+ public StatementResult statementShowProtoDescriptorsFilePath() {
+ return resultSet(
+ String.format("%sPROTO_DESCRIPTORS_FILE_PATH", getNamespace(connection.getDialect())),
+ getConnection().getProtoDescriptorsFilePath(),
+ SHOW_PROTO_DESCRIPTORS_FILE_PATH);
+ }
+
private String processQueryPlan(PlanNode planNode) {
StringBuilder planNodeDescription = new StringBuilder(" : { ");
com.google.protobuf.Struct metadata = planNode.getMetadata();
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
index f21c7e2cdeb..4c8a0542696 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlBatch.java
@@ -59,10 +59,12 @@ class DdlBatch extends AbstractBaseUnitOfWork {
private final DatabaseClient dbClient;
private final List statements = new ArrayList<>();
private UnitOfWorkState state = UnitOfWorkState.STARTED;
+ private final byte[] protoDescriptors;
static class Builder extends AbstractBaseUnitOfWork.Builder {
private DdlClient ddlClient;
private DatabaseClient dbClient;
+ private byte[] protoDescriptors;
private Builder() {}
@@ -78,6 +80,11 @@ Builder setDatabaseClient(DatabaseClient client) {
return this;
}
+ Builder setProtoDescriptors(byte[] protoDescriptors) {
+ this.protoDescriptors = protoDescriptors;
+ return this;
+ }
+
@Override
DdlBatch build() {
Preconditions.checkState(ddlClient != null, "No DdlClient specified");
@@ -94,6 +101,7 @@ private DdlBatch(Builder builder) {
super(builder);
this.ddlClient = builder.ddlClient;
this.dbClient = builder.dbClient;
+ this.protoDescriptors = builder.protoDescriptors;
}
@Override
@@ -227,7 +235,7 @@ public ApiFuture runBatchAsync(CallType callType) {
() -> {
try {
OperationFuture operation =
- ddlClient.executeDdl(statements);
+ ddlClient.executeDdl(statements, protoDescriptors);
try {
// Wait until the operation has finished.
getWithStatementTimeout(operation, RUN_BATCH_STATEMENT);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java
index fedf60d7a91..7bce1ab78cd 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java
@@ -19,6 +19,7 @@
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
+import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Dialect;
import com.google.cloud.spanner.ErrorCode;
import com.google.cloud.spanner.SpannerExceptionFactory;
@@ -35,11 +36,13 @@
*/
class DdlClient {
private final DatabaseAdminClient dbAdminClient;
+ private final String projectId;
private final String instanceId;
private final String databaseName;
static class Builder {
private DatabaseAdminClient dbAdminClient;
+ private String projectId;
private String instanceId;
private String databaseName;
@@ -51,6 +54,13 @@ Builder setDatabaseAdminClient(DatabaseAdminClient client) {
return this;
}
+ Builder setProjectId(String projectId) {
+ Preconditions.checkArgument(
+ !Strings.isNullOrEmpty(projectId), "Empty projectId is not allowed");
+ this.projectId = projectId;
+ return this;
+ }
+
Builder setInstanceId(String instanceId) {
Preconditions.checkArgument(
!Strings.isNullOrEmpty(instanceId), "Empty instanceId is not allowed");
@@ -67,6 +77,7 @@ Builder setDatabaseName(String name) {
DdlClient build() {
Preconditions.checkState(dbAdminClient != null, "No DatabaseAdminClient specified");
+ Preconditions.checkState(!Strings.isNullOrEmpty(projectId), "No ProjectId specified");
Preconditions.checkState(!Strings.isNullOrEmpty(instanceId), "No InstanceId specified");
Preconditions.checkArgument(
!Strings.isNullOrEmpty(databaseName), "No database name specified");
@@ -80,6 +91,7 @@ static Builder newBuilder() {
private DdlClient(Builder builder) {
this.dbAdminClient = builder.dbAdminClient;
+ this.projectId = builder.projectId;
this.instanceId = builder.instanceId;
this.databaseName = builder.databaseName;
}
@@ -92,17 +104,24 @@ OperationFuture executeCreateDatabase(
}
/** Execute a single DDL statement. */
- OperationFuture executeDdl(String ddl) {
- return executeDdl(Collections.singletonList(ddl));
+ OperationFuture executeDdl(String ddl, byte[] protoDescriptors) {
+ return executeDdl(Collections.singletonList(ddl), protoDescriptors);
}
/** Execute a list of DDL statements as one operation. */
- OperationFuture executeDdl(List statements) {
+ OperationFuture executeDdl(
+ List statements, byte[] protoDescriptors) {
if (statements.stream().anyMatch(DdlClient::isCreateDatabaseStatement)) {
throw SpannerExceptionFactory.newSpannerException(
ErrorCode.INVALID_ARGUMENT, "CREATE DATABASE is not supported in a DDL batch");
}
- return dbAdminClient.updateDatabaseDdl(instanceId, databaseName, statements, null);
+ Database.Builder dbBuilder =
+ dbAdminClient.newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseName));
+ if (protoDescriptors != null) {
+ dbBuilder.setProtoDescriptors(protoDescriptors);
+ }
+ Database db = dbBuilder.build();
+ return dbAdminClient.updateDatabaseDdl(db, statements, null);
}
/** Returns true if the statement is a `CREATE DATABASE ...` statement. */
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
index 3eeffae47b0..44f20ccdbd8 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SingleUseTransaction.java
@@ -84,6 +84,7 @@ class SingleUseTransaction extends AbstractBaseUnitOfWork {
private final boolean returnCommitStats;
private final Duration maxCommitDelay;
private final boolean internalMetdataQuery;
+ private final byte[] protoDescriptors;
private volatile SettableApiFuture readTimestamp = null;
private volatile TransactionRunner writeTransaction;
private boolean used = false;
@@ -99,6 +100,7 @@ static class Builder extends AbstractBaseUnitOfWork.Builder executeDdlAsync(CallType callType, final ParsedStatement
ddlClient.executeCreateDatabase(
ddl.getSqlWithoutComments(), dbClient.getDialect());
} else {
- operation = ddlClient.executeDdl(ddl.getSqlWithoutComments());
+ operation = ddlClient.executeDdl(ddl.getSqlWithoutComments(), protoDescriptors);
}
getWithStatementTimeout(operation, ddl);
state = UnitOfWorkState.COMMITTED;
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
index 8488276340d..3ddf32ca5fe 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResult.java
@@ -107,6 +107,10 @@ enum ClientSideStatementType {
PARTITION,
RUN_PARTITION,
RUN_PARTITIONED_QUERY,
+ SET_PROTO_DESCRIPTORS,
+ SET_PROTO_DESCRIPTORS_FILE_PATH,
+ SHOW_PROTO_DESCRIPTORS,
+ SHOW_PROTO_DESCRIPTORS_FILE_PATH
}
/**
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResultImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResultImpl.java
index 58a1f7ae1c0..ee5032463cd 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResultImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementResultImpl.java
@@ -18,6 +18,7 @@
import static com.google.cloud.spanner.SpannerApiFutures.get;
+import com.google.cloud.ByteArray;
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.ResultSets;
@@ -147,6 +148,23 @@ static StatementResult resultSet(
clientSideStatementType);
}
+ /**
+ * Convenience method for creating a {@link StatementResult} containing a {@link ResultSet} with
+ * one BYTES column and one row that is created by a {@link ClientSideStatement}.
+ */
+ static StatementResult resultSet(
+ String name, byte[] values, ClientSideStatementType clientSideStatementType) {
+ return of(
+ ResultSets.forRows(
+ Type.struct(StructField.of(name, Type.bytes())),
+ Collections.singletonList(
+ Struct.newBuilder()
+ .set(name)
+ .to(values != null ? ByteArray.copyFrom(values) : null)
+ .build())),
+ clientSideStatementType);
+ }
+
/** {@link StatementResult} containing no results. */
static StatementResult noResult() {
return new StatementResultImpl((ClientSideStatementType) null);
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
index a1dbe4566c5..d0c2f7f3a6a 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
@@ -669,6 +669,56 @@
"allowedValues": "(\\d{1,9})",
"converterName": "ClientSideStatementValueConverters$NonNegativeIntegerConverter"
}
+ },
+ {
+ "name": "SET PROTO_DESCRIPTORS = ''",
+ "executorName": "ClientSideStatementSetExecutor",
+ "resultType": "NO_RESULT",
+ "statementType": "SET_PROTO_DESCRIPTORS",
+ "regex": "(?is)\\A\\s*set\\s+proto_descriptors\\s*(?:=)\\s*(.*)\\z",
+ "method": "statementSetProtoDescriptors",
+ "exampleStatements": ["set proto_descriptors='protodescriptorsbase64'"],
+ "setStatement": {
+ "propertyName": "PROTO_DESCRIPTORS",
+ "separator": "=",
+ "allowedValues": "'((\\S+)|())'",
+ "converterName": "ClientSideStatementValueConverters$ProtoDescriptorsConverter"
+ }
+ },
+ {
+ "name": "SET PROTO_DESCRIPTORS_FILE_PATH = ''",
+ "executorName": "ClientSideStatementSetExecutor",
+ "resultType": "NO_RESULT",
+ "statementType": "SET_PROTO_DESCRIPTORS_FILE_PATH",
+ "regex": "(?is)\\A\\s*set\\s+proto_descriptors_file_path\\s*(?:=)\\s*(.*)\\z",
+ "method": "statementSetProtoDescriptorsFilePath",
+ "exampleStatements": ["set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'"],
+ "setStatement": {
+ "propertyName": "PROTO_DESCRIPTORS_FILE_PATH",
+ "separator": "=",
+ "allowedValues": "'((\\S+)|())'",
+ "converterName": "ClientSideStatementValueConverters$ProtoDescriptorsFileConverter"
+ }
+ },
+ {
+ "name": "SHOW VARIABLE PROTO_DESCRIPTORS",
+ "executorName": "ClientSideStatementNoParamExecutor",
+ "resultType": "RESULT_SET",
+ "statementType": "SHOW_PROTO_DESCRIPTORS",
+ "regex": "(?is)\\A\\s*show\\s+variable\\s+proto_descriptors\\s*\\z",
+ "method": "statementShowProtoDescriptors",
+ "exampleStatements": ["show variable proto_descriptors"]
+ },
+ {
+ "name": "SHOW VARIABLE PROTO_DESCRIPTORS_FILE_PATH",
+ "executorName": "ClientSideStatementNoParamExecutor",
+ "resultType": "RESULT_SET",
+ "statementType": "SHOW_PROTO_DESCRIPTORS_FILE_PATH",
+ "regex": "(?is)\\A\\s*show\\s+variable\\s+proto_descriptors_file_path\\s*\\z",
+ "method": "statementShowProtoDescriptorsFilePath",
+ "exampleStatements": [
+ "show variable proto_descriptors_file_path"
+ ]
}
]
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
index a14f91a4815..299205bafc6 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
@@ -25,6 +25,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -32,6 +33,7 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.anyString;
@@ -77,9 +79,11 @@
import com.google.cloud.spanner.connection.UnitOfWork.CallType;
import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState;
import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
import com.google.spanner.v1.ResultSetStats;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -220,8 +224,8 @@ private static DdlClient createDefaultMockDdlClient() {
UpdateDatabaseDdlMetadata metadata = UpdateDatabaseDdlMetadata.getDefaultInstance();
ApiFuture futureMetadata = ApiFutures.immediateFuture(metadata);
when(operation.getMetadata()).thenReturn(futureMetadata);
- when(ddlClient.executeDdl(anyString())).thenCallRealMethod();
- when(ddlClient.executeDdl(anyList())).thenReturn(operation);
+ when(ddlClient.executeDdl(anyString(), isNull())).thenCallRealMethod();
+ when(ddlClient.executeDdl(anyList(), isNull())).thenReturn(operation);
return ddlClient;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -1925,4 +1929,101 @@ private void assertThrowResultNotAllowed(
.contains(
"Only statements that return a result of one of the following types are allowed"));
}
+
+ @Test
+ public void testProtoDescriptorsAlwaysAllowed() {
+ ConnectionOptions connectionOptions = mock(ConnectionOptions.class);
+ when(connectionOptions.isAutocommit()).thenReturn(true);
+ SpannerPool spannerPool = mock(SpannerPool.class);
+ DdlClient ddlClient = mock(DdlClient.class);
+ DatabaseClient dbClient = mock(DatabaseClient.class);
+ when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL);
+ final UnitOfWork unitOfWork = mock(UnitOfWork.class);
+ final String protoDescriptorsFilePath =
+ "src/test/resources/com/google/cloud/spanner/descriptors.pb";
+ when(unitOfWork.executeDdlAsync(any(), any(ParsedStatement.class)))
+ .thenReturn(ApiFutures.immediateFuture(null));
+ when(unitOfWork.executeQueryAsync(
+ any(), any(ParsedStatement.class), any(AnalyzeMode.class), Mockito.any()))
+ .thenReturn(ApiFutures.immediateFuture(mock(ResultSet.class)));
+ try (ConnectionImpl connection =
+ new ConnectionImpl(
+ connectionOptions, spannerPool, ddlClient, dbClient, mock(BatchClient.class)) {
+ @Override
+ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork(
+ StatementType statementType, boolean isInternalMetadataQuery) {
+ return unitOfWork;
+ }
+ }) {
+ byte[] protoDescriptors;
+ try {
+ InputStream in =
+ ConnectionImplTest.class
+ .getClassLoader()
+ .getResourceAsStream("com/google/cloud/spanner/descriptors.pb");
+ assertNotNull(in);
+ protoDescriptors = ByteStreams.toByteArray(in);
+ } catch (Exception e) {
+ throw SpannerExceptionFactory.newSpannerException(e);
+ }
+
+ assertTrue(connection.isAutocommit());
+
+ assertNull(connection.getProtoDescriptors());
+ connection.setProtoDescriptors(protoDescriptors);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+
+ connection.setAutocommit(false);
+
+ connection.setProtoDescriptors(protoDescriptors);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+
+ // proto descriptor should reset after executing a DDL statement
+ connection.setProtoDescriptors(protoDescriptors);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("CREATE PROTO BUNDLE (examples.spanner.music.SingerInfo)"));
+ assertNull(connection.getProtoDescriptors());
+
+ // proto descriptor should not reset if the statement is not a DDL statement
+ connection.setProtoDescriptors(protoDescriptors);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("SELECT FOO FROM BAR"));
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+
+ // proto descriptor file path should reset after executing a DDL statement
+ connection.setProtoDescriptorsFilePath(protoDescriptorsFilePath);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("CREATE PROTO BUNDLE (examples.spanner.music.SingerInfo)"));
+ assertNull(connection.getProtoDescriptors());
+ assertNull(connection.getProtoDescriptorsFilePath());
+
+ // proto descriptor file path should not reset if the statement is not a DDL statement
+ connection.setProtoDescriptorsFilePath(protoDescriptorsFilePath);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("SELECT FOO FROM BAR"));
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ assertEquals(protoDescriptorsFilePath, connection.getProtoDescriptorsFilePath());
+
+ // test proto descriptor file path as input
+ connection.setProtoDescriptorsFilePath(protoDescriptorsFilePath);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("CREATE PROTO BUNDLE (examples.spanner.music.SingerInfo)"));
+ assertNull(connection.getProtoDescriptors());
+
+ // proto descriptor set through file path should overwrite the proto descriptor set from
+ // byte[]
+ connection.setProtoDescriptors("protoDescriptors".getBytes());
+ connection.setProtoDescriptorsFilePath(protoDescriptorsFilePath);
+ assertArrayEquals(protoDescriptors, connection.getProtoDescriptors());
+ connection.execute(Statement.of("CREATE PROTO BUNDLE (examples.spanner.music.SingerInfo)"));
+ assertNull(connection.getProtoDescriptors());
+
+ // proto descriptor set through byte[] should overwrite the proto descriptor from file path
+ connection.setProtoDescriptorsFilePath(protoDescriptorsFilePath);
+ connection.setProtoDescriptors("protoDescriptors".getBytes());
+ assertArrayEquals("protoDescriptors".getBytes(), connection.getProtoDescriptors());
+ connection.execute(Statement.of("CREATE PROTO BUNDLE (examples.spanner.music.SingerInfo)"));
+ assertNull(connection.getProtoDescriptors());
+ }
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorTest.java
index bf7822e3285..3e883c377fe 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorTest.java
@@ -252,4 +252,29 @@ public void testStatementSetPgTransactionModeNoOp() {
verify(connection, never()).setTransactionMode(TransactionMode.READ_ONLY_TRANSACTION);
verify(connection, never()).setTransactionMode(TransactionMode.READ_WRITE_TRANSACTION);
}
+
+ @Test
+ public void testStatementSetProtoDescriptors() {
+ subject.statementSetProtoDescriptors("protoDescriptor".getBytes());
+ verify(connection).setProtoDescriptors("protoDescriptor".getBytes());
+ }
+
+ @Test
+ public void testStatementSetProtoDescriptorsFilePath() {
+ String filePath = "com/google/cloud/spanner/descriptors.pb";
+ subject.statementSetProtoDescriptorsFilePath(filePath);
+ verify(connection).setProtoDescriptorsFilePath(filePath);
+ }
+
+ @Test
+ public void testStatementGetProtoDescriptors() {
+ subject.statementShowProtoDescriptors();
+ verify(connection).getProtoDescriptors();
+ }
+
+ @Test
+ public void testStatementGetProtoDescriptorsFilePath() {
+ subject.statementShowProtoDescriptorsFilePath();
+ verify(connection).getProtoDescriptorsFilePath();
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlBatchTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlBatchTest.java
index 74cc925ee85..b6a12567101 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlBatchTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlBatchTest.java
@@ -21,9 +21,12 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.argThat;
@@ -48,10 +51,12 @@
import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType;
import com.google.cloud.spanner.connection.UnitOfWork.CallType;
import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState;
+import com.google.common.io.ByteStreams;
import com.google.protobuf.Timestamp;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
import io.grpc.Status;
import io.opentelemetry.api.trace.Span;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -108,8 +113,8 @@ private DdlClient createDefaultMockDdlClient(
ApiFuture metadataFuture =
ApiFutures.immediateFuture(metadataBuilder.build());
when(operation.getMetadata()).thenReturn(metadataFuture);
- when(ddlClient.executeDdl(anyString())).thenReturn(operation);
- when(ddlClient.executeDdl(anyList())).thenReturn(operation);
+ when(ddlClient.executeDdl(anyString(), any())).thenReturn(operation);
+ when(ddlClient.executeDdl(anyList(), any())).thenReturn(operation);
return ddlClient;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -253,7 +258,7 @@ public void testGetStateAndIsActive() {
DdlClient client = mock(DdlClient.class);
SpannerException exception = mock(SpannerException.class);
when(exception.getErrorCode()).thenReturn(ErrorCode.FAILED_PRECONDITION);
- doThrow(exception).when(client).executeDdl(anyList());
+ doThrow(exception).when(client).executeDdl(anyList(), isNull());
batch = createSubject(client);
assertThat(batch.getState(), is(UnitOfWorkState.STARTED));
assertThat(batch.isActive(), is(true));
@@ -299,8 +304,8 @@ public void testRunBatch() {
DdlBatch batch = createSubject(client);
get(batch.runBatchAsync(CallType.SYNC));
assertThat(batch.getState(), is(UnitOfWorkState.RAN));
- verify(client, never()).executeDdl(anyString());
- verify(client, never()).executeDdl(argThat(isEmptyListOfStrings()));
+ verify(client, never()).executeDdl(anyString(), isNull());
+ verify(client, never()).executeDdl(argThat(isEmptyListOfStrings()), isNull());
ParsedStatement statement = mock(ParsedStatement.class);
when(statement.getType()).thenReturn(StatementType.DDL);
@@ -311,14 +316,14 @@ public void testRunBatch() {
batch = createSubject(client);
batch.executeDdlAsync(CallType.SYNC, statement);
get(batch.runBatchAsync(CallType.SYNC));
- verify(client).executeDdl(argThat(isListOfStringsWithSize(1)));
+ verify(client).executeDdl(argThat(isListOfStringsWithSize(1)), isNull());
client = createDefaultMockDdlClient();
batch = createSubject(client);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.executeDdlAsync(CallType.SYNC, statement);
get(batch.runBatchAsync(CallType.SYNC));
- verify(client).executeDdl(argThat(isListOfStringsWithSize(2)));
+ verify(client).executeDdl(argThat(isListOfStringsWithSize(2)), isNull());
assertThat(batch.getState(), is(UnitOfWorkState.RAN));
boolean exception = false;
try {
@@ -364,7 +369,48 @@ public void testRunBatch() {
}
assertThat(exception, is(true));
assertThat(batch.getState(), is(UnitOfWorkState.RUN_FAILED));
- verify(client).executeDdl(argThat(isListOfStringsWithSize(2)));
+ verify(client).executeDdl(argThat(isListOfStringsWithSize(2)), isNull());
+
+ // verify when protoDescriptors is null
+ client = createDefaultMockDdlClient();
+ batch =
+ DdlBatch.newBuilder()
+ .setDdlClient(client)
+ .setDatabaseClient(mock(DatabaseClient.class))
+ .withStatementExecutor(new StatementExecutor())
+ .setSpan(Span.getInvalid())
+ .setProtoDescriptors(null)
+ .build();
+ batch.executeDdlAsync(CallType.SYNC, statement);
+ batch.executeDdlAsync(CallType.SYNC, statement);
+ get(batch.runBatchAsync(CallType.SYNC));
+ verify(client).executeDdl(argThat(isListOfStringsWithSize(2)), isNull());
+
+ // verify when protoDescriptors is not null
+ byte[] protoDescriptors;
+ try {
+ InputStream in =
+ DdlBatchTest.class
+ .getClassLoader()
+ .getResourceAsStream("com/google/cloud/spanner/descriptors.pb");
+ assertNotNull(in);
+ protoDescriptors = ByteStreams.toByteArray(in);
+ } catch (Exception e) {
+ throw SpannerExceptionFactory.newSpannerException(e);
+ }
+ client = createDefaultMockDdlClient();
+ batch =
+ DdlBatch.newBuilder()
+ .setDdlClient(client)
+ .setDatabaseClient(mock(DatabaseClient.class))
+ .withStatementExecutor(new StatementExecutor())
+ .setSpan(Span.getInvalid())
+ .setProtoDescriptors(protoDescriptors)
+ .build();
+ batch.executeDdlAsync(CallType.SYNC, statement);
+ batch.executeDdlAsync(CallType.SYNC, statement);
+ get(batch.runBatchAsync(CallType.SYNC));
+ verify(client).executeDdl(argThat(isListOfStringsWithSize(2)), any(byte[].class));
}
@Test
@@ -383,7 +429,8 @@ public void testUpdateCount() throws InterruptedException, ExecutionException {
OperationFuture operationFuture = mock(OperationFuture.class);
when(operationFuture.get()).thenReturn(null);
when(operationFuture.getMetadata()).thenReturn(metadataFuture);
- when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture);
+ when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull()))
+ .thenReturn(operationFuture);
DdlBatch batch =
DdlBatch.newBuilder()
.withStatementExecutor(new StatementExecutor())
@@ -422,7 +469,8 @@ public void testFailedUpdateCount() throws InterruptedException, ExecutionExcept
new ExecutionException(
"ddl statement failed", Status.INVALID_ARGUMENT.asRuntimeException()));
when(operationFuture.getMetadata()).thenReturn(metadataFuture);
- when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture);
+ when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull()))
+ .thenReturn(operationFuture);
DdlBatch batch =
DdlBatch.newBuilder()
.withStatementExecutor(new StatementExecutor())
@@ -465,7 +513,8 @@ public void testFailedAfterFirstStatement() throws InterruptedException, Executi
new ExecutionException(
"ddl statement failed", Status.INVALID_ARGUMENT.asRuntimeException()));
when(operationFuture.getMetadata()).thenReturn(metadataFuture);
- when(client.executeDdl(argThat(isListOfStringsWithSize(2)))).thenReturn(operationFuture);
+ when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull()))
+ .thenReturn(operationFuture);
DdlBatch batch =
DdlBatch.newBuilder()
.withStatementExecutor(new StatementExecutor())
@@ -497,8 +546,8 @@ public void testAbort() {
DdlBatch batch = createSubject(client);
batch.abortBatch();
assertThat(batch.getState(), is(UnitOfWorkState.ABORTED));
- verify(client, never()).executeDdl(anyString());
- verify(client, never()).executeDdl(anyList());
+ verify(client, never()).executeDdl(anyString(), isNull());
+ verify(client, never()).executeDdl(anyList(), isNull());
ParsedStatement statement = mock(ParsedStatement.class);
when(statement.getType()).thenReturn(StatementType.DDL);
@@ -509,21 +558,21 @@ public void testAbort() {
batch = createSubject(client);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.abortBatch();
- verify(client, never()).executeDdl(anyList());
+ verify(client, never()).executeDdl(anyList(), isNull());
client = createDefaultMockDdlClient();
batch = createSubject(client);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.abortBatch();
- verify(client, never()).executeDdl(anyList());
+ verify(client, never()).executeDdl(anyList(), isNull());
client = createDefaultMockDdlClient();
batch = createSubject(client);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.executeDdlAsync(CallType.SYNC, statement);
batch.abortBatch();
- verify(client, never()).executeDdl(anyList());
+ verify(client, never()).executeDdl(anyList(), isNull());
boolean exception = false;
try {
get(batch.runBatchAsync(CallType.SYNC));
@@ -534,7 +583,7 @@ public void testAbort() {
exception = true;
}
assertThat(exception, is(true));
- verify(client, never()).executeDdl(anyList());
+ verify(client, never()).executeDdl(anyList(), isNull());
}
@Test
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java
index d46e4dca592..c61635fce23 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java
@@ -17,17 +17,25 @@
package com.google.cloud.spanner.connection;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.api.gax.longrunning.OperationFuture;
+import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
+import com.google.cloud.spanner.DatabaseId;
+import com.google.cloud.spanner.SpannerExceptionFactory;
+import com.google.common.io.ByteStreams;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -39,11 +47,13 @@
@RunWith(JUnit4.class)
public class DdlClientTests {
+ private final String projectId = "test-project";
private final String instanceId = "test-instance";
private final String databaseId = "test-database";
private DdlClient createSubject(DatabaseAdminClient client) {
return DdlClient.newBuilder()
+ .setProjectId(projectId)
.setInstanceId(instanceId)
.setDatabaseName(databaseId)
.setDatabaseAdminClient(client)
@@ -52,21 +62,48 @@ private DdlClient createSubject(DatabaseAdminClient client) {
@Test
public void testExecuteDdl() throws InterruptedException, ExecutionException {
+ byte[] protoDescriptors;
+ try {
+ InputStream in =
+ DdlBatchTest.class
+ .getClassLoader()
+ .getResourceAsStream("com/google/cloud/spanner/descriptors.pb");
+ assertNotNull(in);
+ protoDescriptors = ByteStreams.toByteArray(in);
+ } catch (Exception e) {
+ throw SpannerExceptionFactory.newSpannerException(e);
+ }
+
DatabaseAdminClient client = mock(DatabaseAdminClient.class);
+ Database database = mock(Database.class);
+ Database.Builder databaseBuilder = mock(Database.Builder.class);
@SuppressWarnings("unchecked")
OperationFuture operation = mock(OperationFuture.class);
+
when(operation.get()).thenReturn(null);
- when(client.updateDatabaseDdl(eq(instanceId), eq(databaseId), anyList(), isNull()))
- .thenReturn(operation);
+ when(client.newDatabaseBuilder((DatabaseId.of(projectId, instanceId, databaseId))))
+ .thenReturn(databaseBuilder);
+ when(databaseBuilder.setProtoDescriptors(protoDescriptors)).thenReturn(databaseBuilder);
+ when(databaseBuilder.build()).thenReturn(database);
+ when(client.updateDatabaseDdl(eq(database), anyList(), isNull())).thenReturn(operation);
+
DdlClient subject = createSubject(client);
String ddl = "CREATE TABLE FOO";
- subject.executeDdl(ddl);
- verify(client).updateDatabaseDdl(instanceId, databaseId, Collections.singletonList(ddl), null);
+ subject.executeDdl(ddl, null);
+ verify(databaseBuilder, never()).setProtoDescriptors(any(byte[].class));
+ verify(client).updateDatabaseDdl(database, Collections.singletonList(ddl), null);
subject = createSubject(client);
List ddlList = Arrays.asList("CREATE TABLE FOO", "DROP TABLE FOO");
- subject.executeDdl(ddlList);
- verify(client).updateDatabaseDdl(instanceId, databaseId, ddlList, null);
+ subject.executeDdl(ddlList, null);
+ verify(databaseBuilder, never()).setProtoDescriptors(any(byte[].class));
+ verify(client).updateDatabaseDdl(database, ddlList, null);
+
+ subject = createSubject(client);
+ ddlList = Arrays.asList("CREATE PROTO BUNDLE", "CREATE TABLE FOO");
+ subject.executeDdl(ddlList, protoDescriptors);
+ verify(databaseBuilder).setProtoDescriptors(protoDescriptors);
+ verify(client).updateDatabaseDdl(database, ddlList, null);
}
@Test
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsConverterTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsConverterTest.java
new file mode 100644
index 00000000000..766bc987d37
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsConverterTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.SpannerExceptionFactory;
+import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException;
+import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.ProtoDescriptorsConverter;
+import com.google.common.io.ByteStreams;
+import java.io.InputStream;
+import java.util.Base64;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ProtoDescriptorsConverterTest {
+ @Test
+ public void testConvert() throws CompileException {
+ String allowedValues =
+ ReadOnlyStalenessConverterTest.getAllowedValues(
+ ProtoDescriptorsConverter.class, Dialect.GOOGLE_STANDARD_SQL);
+ assertNotNull(allowedValues);
+ ProtoDescriptorsConverter converter = new ProtoDescriptorsConverter(allowedValues);
+
+ byte[] protoDescriptors;
+ try {
+ InputStream in =
+ ProtoDescriptorsConverterTest.class
+ .getClassLoader()
+ .getResourceAsStream("com/google/cloud/spanner/descriptors.pb");
+ assertNotNull(in);
+ protoDescriptors = ByteStreams.toByteArray(in);
+ } catch (Exception e) {
+ throw SpannerExceptionFactory.newSpannerException(e);
+ }
+
+ assertNull(converter.convert(""));
+ assertNull(converter.convert("null"));
+ assertNull(converter.convert(null));
+ assertNull(converter.convert("random string"));
+
+ assertArrayEquals(
+ converter.convert(Base64.getEncoder().encodeToString(protoDescriptors)), protoDescriptors);
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsFileConverterTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsFileConverterTest.java
new file mode 100644
index 00000000000..29e4a2b591b
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ProtoDescriptorsFileConverterTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException;
+import com.google.cloud.spanner.connection.ClientSideStatementValueConverters.ProtoDescriptorsFileConverter;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class ProtoDescriptorsFileConverterTest {
+ @Test
+ public void testConvert() throws CompileException {
+ String allowedValues =
+ ReadOnlyStalenessConverterTest.getAllowedValues(
+ ProtoDescriptorsFileConverter.class, Dialect.GOOGLE_STANDARD_SQL);
+ assertNotNull(allowedValues);
+ ProtoDescriptorsFileConverter converter = new ProtoDescriptorsFileConverter(allowedValues);
+
+ assertNull(converter.convert(""));
+ assertNull(converter.convert(null));
+
+ String filePath = "com/google/cloud/spanner/descriptors.pb";
+ assertEquals(converter.convert(filePath), filePath);
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
index 0ab419f294b..1fd6d6bd7e2 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyList;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
@@ -57,9 +58,11 @@
import com.google.cloud.spanner.connection.StatementExecutor.StatementTimeout;
import com.google.cloud.spanner.connection.UnitOfWork.CallType;
import com.google.common.base.Preconditions;
+import com.google.common.io.ByteStreams;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
import com.google.spanner.v1.ResultSetStats;
import io.opentelemetry.api.trace.Span;
+import java.io.InputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
@@ -301,8 +304,8 @@ private DdlClient createDefaultMockDdlClient() {
final OperationFuture operation =
mock(OperationFuture.class);
when(operation.get()).thenReturn(null);
- when(ddlClient.executeDdl(anyString())).thenCallRealMethod();
- when(ddlClient.executeDdl(anyList())).thenReturn(operation);
+ when(ddlClient.executeDdl(anyString(), any())).thenCallRealMethod();
+ when(ddlClient.executeDdl(anyList(), any())).thenReturn(operation);
return ddlClient;
} catch (Exception e) {
throw new RuntimeException(e);
@@ -316,7 +319,8 @@ private SingleUseTransaction createSubject() {
TimestampBound.strong(),
AutocommitDmlMode.TRANSACTIONAL,
CommitBehavior.SUCCEED,
- 0L);
+ 0L,
+ null);
}
private SingleUseTransaction createSubject(AutocommitDmlMode dmlMode) {
@@ -326,7 +330,8 @@ private SingleUseTransaction createSubject(AutocommitDmlMode dmlMode) {
TimestampBound.strong(),
dmlMode,
CommitBehavior.SUCCEED,
- 0L);
+ 0L,
+ null);
}
private SingleUseTransaction createSubject(CommitBehavior commitBehavior) {
@@ -336,7 +341,8 @@ private SingleUseTransaction createSubject(CommitBehavior commitBehavior) {
TimestampBound.strong(),
AutocommitDmlMode.TRANSACTIONAL,
commitBehavior,
- 0L);
+ 0L,
+ null);
}
private SingleUseTransaction createDdlSubject(DdlClient ddlClient) {
@@ -346,7 +352,20 @@ private SingleUseTransaction createDdlSubject(DdlClient ddlClient) {
TimestampBound.strong(),
AutocommitDmlMode.TRANSACTIONAL,
CommitBehavior.SUCCEED,
- 0L);
+ 0L,
+ null);
+ }
+
+ private SingleUseTransaction createProtoDescriptorsSubject(
+ DdlClient ddlClient, byte[] protoDescriptors) {
+ return createSubject(
+ ddlClient,
+ false,
+ TimestampBound.strong(),
+ AutocommitDmlMode.TRANSACTIONAL,
+ CommitBehavior.SUCCEED,
+ 0L,
+ protoDescriptors);
}
private SingleUseTransaction createReadOnlySubject(TimestampBound staleness) {
@@ -356,7 +375,8 @@ private SingleUseTransaction createReadOnlySubject(TimestampBound staleness) {
staleness,
AutocommitDmlMode.TRANSACTIONAL,
CommitBehavior.SUCCEED,
- 0L);
+ 0L,
+ null);
}
private SingleUseTransaction createSubject(
@@ -365,7 +385,8 @@ private SingleUseTransaction createSubject(
TimestampBound staleness,
AutocommitDmlMode dmlMode,
final CommitBehavior commitBehavior,
- long timeout) {
+ long timeout,
+ byte[] protoDescriptors) {
DatabaseClient dbClient = mock(DatabaseClient.class);
com.google.cloud.spanner.ReadOnlyTransaction singleUse =
new SimpleReadOnlyTransaction(staleness);
@@ -454,6 +475,7 @@ public TransactionRunner allowNestedTransaction() {
timeout == 0L ? nullTimeout() : timeout(timeout, TimeUnit.MILLISECONDS))
.withStatementExecutor(executor)
.setSpan(Span.getInvalid())
+ .setProtoDescriptors(protoDescriptors)
.build();
}
@@ -541,7 +563,34 @@ public void testExecuteDdl() {
DdlClient ddlClient = createDefaultMockDdlClient();
SingleUseTransaction subject = createDdlSubject(ddlClient);
get(subject.executeDdlAsync(CallType.SYNC, ddl));
- verify(ddlClient).executeDdl(sql);
+ verify(ddlClient).executeDdl(sql, null);
+ }
+
+ @Test
+ public void testExecuteDdlWithProtoDescriptors() {
+ String sql = "CREATE TABLE FOO";
+ ParsedStatement ddl = createParsedDdl(sql);
+ DdlClient ddlClient = createDefaultMockDdlClient();
+ // verify when protoDescriptors value is null
+ SingleUseTransaction subject = createProtoDescriptorsSubject(ddlClient, null);
+ get(subject.executeDdlAsync(CallType.SYNC, ddl));
+ verify(ddlClient).executeDdl(sql, null);
+
+ // verify when protoDescriptors value is not null
+ byte[] protoDescriptors;
+ try {
+ InputStream in =
+ SingleUseTransactionTest.class
+ .getClassLoader()
+ .getResourceAsStream("com/google/cloud/spanner/descriptors.pb");
+ assertNotNull(in);
+ protoDescriptors = ByteStreams.toByteArray(in);
+ } catch (Exception e) {
+ throw SpannerExceptionFactory.newSpannerException(e);
+ }
+ subject = createProtoDescriptorsSubject(ddlClient, protoDescriptors);
+ get(subject.executeDdlAsync(CallType.SYNC, ddl));
+ verify(ddlClient).executeDdl(sql, protoDescriptors);
}
@Test
@@ -735,7 +784,7 @@ public void testMultiUse() {
DdlClient ddlClient = createDefaultMockDdlClient();
SingleUseTransaction subject = createDdlSubject(ddlClient);
get(subject.executeDdlAsync(CallType.SYNC, ddl));
- verify(ddlClient).executeDdl(sql);
+ verify(ddlClient).executeDdl(sql, null);
try {
get(subject.executeDdlAsync(CallType.SYNC, ddl));
fail("missing expected exception");
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementResultImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementResultImplTest.java
index c28d3b75b95..0a55ff2c420 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementResultImplTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementResultImplTest.java
@@ -21,9 +21,13 @@
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
+import com.google.cloud.ByteArray;
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.ErrorCode;
import com.google.cloud.spanner.ResultSet;
@@ -154,6 +158,18 @@ public void testStringResultSetGetResultSet() {
assertThat(subject.getResultSet().next(), is(true));
assertThat(subject.getResultSet().getString("foo"), is(equalTo("bar")));
assertThat(subject.getResultSet().next(), is(false));
+
+ subject =
+ StatementResultImpl.resultSet(
+ "path", "descriptors.pb", ClientSideStatementType.SHOW_PROTO_DESCRIPTORS_FILE_PATH);
+ assertThat(subject.getResultType(), is(equalTo(ResultType.RESULT_SET)));
+ assertThat(
+ subject.getClientSideStatementType(),
+ is(equalTo(ClientSideStatementType.SHOW_PROTO_DESCRIPTORS_FILE_PATH)));
+ assertThat(subject.getResultSet(), is(notNullValue()));
+ assertThat(subject.getResultSet().next(), is(true));
+ assertThat(subject.getResultSet().getString("path"), is(equalTo("descriptors.pb")));
+ assertThat(subject.getResultSet().next(), is(false));
}
@Test
@@ -190,4 +206,19 @@ public void testTimestampResultSetGetResultSet() {
is(equalTo(Timestamp.ofTimeSecondsAndNanos(10L, 10))));
assertThat(subject.getResultSet().next(), is(false));
}
+
+ @Test
+ public void testBytesResultSetGetResultSet() {
+ StatementResult subject =
+ StatementResultImpl.resultSet(
+ "foo", "protoDescriptors".getBytes(), ClientSideStatementType.SHOW_PROTO_DESCRIPTORS);
+ assertEquals(subject.getResultType(), ResultType.RESULT_SET);
+ assertEquals(
+ subject.getClientSideStatementType(), ClientSideStatementType.SHOW_PROTO_DESCRIPTORS);
+ assertNotNull(subject.getResultSet());
+ assertTrue(subject.getResultSet().next());
+ assertEquals(
+ subject.getResultSet().getBytes("foo"), ByteArray.copyFrom("protoDescriptors".getBytes()));
+ assertFalse(subject.getResultSet().next());
+ }
}
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
index 4b6aec5b965..a098a275462 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
@@ -23196,3 +23196,797 @@ set max_partitioned_parallelism = 10/-;
NEW_CONNECTION;
@EXPECT EXCEPTION INVALID_ARGUMENT
set max_partitioned_parallelism =/-10;
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+SET PROTO_DESCRIPTORS='PROTODESCRIPTORSBASE64';
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+ set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+ set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+
+
+
+set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64' ;
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64' ;
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64'
+
+;
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+set
+proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64' bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set%proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set_proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set&proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set$proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set@proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set!proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set*proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set(proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64');
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set)proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set+proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-#proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set\proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set?proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-/proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/#proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors='protodescriptorsbase64'/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/-proto_descriptors='protodescriptorsbase64';
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+SET PROTO_DESCRIPTORS_FILE_PATH='SRC/TEST/RESOURCES/COM/GOOGLE/CLOUD/SPANNER/DESCRIPTORS.PB';
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+ set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+ set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+
+
+
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb' ;
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb' ;
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'
+
+;
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+set
+proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb' bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set%proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set_proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set&proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set$proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set@proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set!proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set*proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set(proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb');
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set)proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set+proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-#proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set\proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set?proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-/proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/#proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb'/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/-proto_descriptors_file_path='src/test/resources/com/google/cloud/spanner/descriptors.pb';
+NEW_CONNECTION;
+show variable proto_descriptors;
+NEW_CONNECTION;
+SHOW VARIABLE PROTO_DESCRIPTORS;
+NEW_CONNECTION;
+show variable proto_descriptors;
+NEW_CONNECTION;
+ show variable proto_descriptors;
+NEW_CONNECTION;
+ show variable proto_descriptors;
+NEW_CONNECTION;
+
+
+
+show variable proto_descriptors;
+NEW_CONNECTION;
+show variable proto_descriptors ;
+NEW_CONNECTION;
+show variable proto_descriptors ;
+NEW_CONNECTION;
+show variable proto_descriptors
+
+;
+NEW_CONNECTION;
+show variable proto_descriptors;
+NEW_CONNECTION;
+show variable proto_descriptors;
+NEW_CONNECTION;
+show
+variable
+proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable%proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable_proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable&proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable$proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable@proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable!proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable*proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable(proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors);
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable)proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable+proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-#proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable\proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable?proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-/proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/#proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-show variable proto_descriptors;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/-proto_descriptors;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+SHOW VARIABLE PROTO_DESCRIPTORS_FILE_PATH;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+ show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+ show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+
+
+
+show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path ;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path ;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path
+
+;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+show
+variable
+proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable%proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable_proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable&proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable$proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable@proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable!proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable*proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable(proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path);
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable)proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable+proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-#proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable\proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable?proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable-/proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/#proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-show variable proto_descriptors_file_path;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable proto_descriptors_file_path/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION UNIMPLEMENTED
+show variable/-proto_descriptors_file_path;
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ITDdlTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ITDdlTest.sql
index 2dea0423151..2efc59ed36e 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ITDdlTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ITDdlTest.sql
@@ -127,7 +127,7 @@ WHERE TABLE_NAME='VALID_MULTIPLE_DDL_IN_DDL_BATCH_1' OR TABLE_NAME='VALID_MULTIP
NEW_CONNECTION;
-/*
+/*
* Do a test that shows that a DDL batch might only execute some of the statements,
* for example if data in a table prevents a unique index from being created.
*/
@@ -187,3 +187,44 @@ RUN BATCH;
START BATCH DDL;
ABORT BATCH;
+
+NEW_CONNECTION;
+-- Set proto descriptors using relative path to the descriptors.pb file. This gets applied for next DDL statement
+SET PROTO_DESCRIPTORS_FILE_PATH = 'src/test/resources/com/google/cloud/spanner/descriptors.pb';
+-- Check if Proto descriptors is set
+@EXPECT RESULT_SET 'PROTO_DESCRIPTORS_FILE_PATH'
+SHOW VARIABLE PROTO_DESCRIPTORS_FILE_PATH;
+
+CREATE PROTO BUNDLE (examples.spanner.music.Genre);
+-- Check if Proto descriptors is reset to null
+@EXPECT RESULT_SET 'PROTO_DESCRIPTORS',null
+SHOW VARIABLE PROTO_DESCRIPTORS;
+@EXPECT RESULT_SET 'PROTO_DESCRIPTORS_FILE_PATH',null
+SHOW VARIABLE PROTO_DESCRIPTORS_FILE_PATH;
+
+-- Set Proto Descriptor as base64 string. This gets applied to all statements in next DDL batch
+SET PROTO_DESCRIPTORS = 'CvYCCgxzaW5nZXIucHJvdG8SFmV4YW1wbGVzLnNwYW5uZXIubXVzaWMi6gEKClNpbmdlckluZm8SIAoJc2luZ2VyX2lkGAEgASgDSABSCHNpbmdlcklkiAEBEiIKCmJpcnRoX2RhdGUYAiABKAlIAVIJYmlydGhEYXRliAEBEiUKC25hdGlvbmFsaXR5GAMgASgJSAJSC25hdGlvbmFsaXR5iAEBEjgKBWdlbnJlGAQgASgOMh0uZXhhbXBsZXMuc3Bhbm5lci5tdXNpYy5HZW5yZUgDUgVnZW5yZYgBAUIMCgpfc2luZ2VyX2lkQg0KC19iaXJ0aF9kYXRlQg4KDF9uYXRpb25hbGl0eUIICgZfZ2VucmUqLgoFR2VucmUSBwoDUE9QEAASCAoESkFaWhABEggKBEZPTEsQAhIICgRST0NLEANCKQoYY29tLmdvb2dsZS5jbG91ZC5zcGFubmVyQgtTaW5nZXJQcm90b1AAYgZwcm90bzM=';
+
+@EXPECT RESULT_SET 'PROTO_DESCRIPTORS'
+SHOW VARIABLE PROTO_DESCRIPTORS;
+
+START BATCH DDL;
+ALTER PROTO BUNDLE INSERT (examples.spanner.music.SingerInfo);
+CREATE TABLE Singers (
+ SingerId INT64 NOT NULL,
+ FirstName STRING(1024),
+ LastName STRING(1024),
+ SingerInfo examples.spanner.music.SingerInfo,
+ SingerGenre examples.spanner.music.Genre
+) PRIMARY KEY (SingerId);
+-- Run the batch
+RUN BATCH;
+
+-- Check if Proto descriptors is reset to null
+@EXPECT RESULT_SET 'PROTO_DESCRIPTORS',null
+SHOW VARIABLE PROTO_DESCRIPTORS;
+-- Check that the table is created
+@EXPECT RESULT_SET
+SELECT COUNT(*) AS ACTUAL, 1 AS EXPECTED
+FROM INFORMATION_SCHEMA.TABLES
+WHERE TABLE_NAME='Singers';
From 39902c384f3f7f9438252cbee287f2428faf1440 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?=
Date: Mon, 27 May 2024 07:18:22 +0200
Subject: [PATCH 09/11] fix: allow getMetadata() calls before calling next()
(#3111)
* fix: allow getMetadata() calls before calling next()
Calling getMetadata() on a MergedResultSet should be allowed without
first calling next() in order to be consistent with other ResultSets
that are returned by the Connection API.
* fix: remove unnecessary partitions
---
.../spanner/connection/MergedResultSet.java | 38 +++++++-
.../PartitionedQueryMockServerTest.java | 88 +++++++++++++++++++
2 files changed, 122 insertions(+), 4 deletions(-)
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/MergedResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/MergedResultSet.java
index 36451bc8f40..fcbc49f346d 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/MergedResultSet.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/MergedResultSet.java
@@ -18,6 +18,7 @@
import static com.google.common.base.Preconditions.checkState;
+import com.google.cloud.spanner.ErrorCode;
import com.google.cloud.spanner.ForwardingStructReader;
import com.google.cloud.spanner.ResultSet;
import com.google.cloud.spanner.SpannerException;
@@ -30,6 +31,7 @@
import com.google.spanner.v1.ResultSetStats;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
@@ -47,15 +49,18 @@ static class PartitionExecutor implements Runnable {
private final Connection connection;
private final String partitionId;
private final LinkedBlockingDeque queue;
+ private final CountDownLatch metadataAvailableLatch;
private final AtomicBoolean shouldStop = new AtomicBoolean();
PartitionExecutor(
Connection connection,
String partitionId,
- LinkedBlockingDeque queue) {
+ LinkedBlockingDeque queue,
+ CountDownLatch metadataAvailableLatch) {
this.connection = Preconditions.checkNotNull(connection);
this.partitionId = Preconditions.checkNotNull(partitionId);
this.queue = queue;
+ this.metadataAvailableLatch = Preconditions.checkNotNull(metadataAvailableLatch);
}
@Override
@@ -68,6 +73,7 @@ public void run() {
queue.put(
PartitionExecutorResult.dataAndMetadata(
row, resultSet.getType(), resultSet.getMetadata()));
+ metadataAvailableLatch.countDown();
first = false;
} else {
queue.put(PartitionExecutorResult.data(row));
@@ -82,9 +88,11 @@ public void run() {
queue.put(
PartitionExecutorResult.typeAndMetadata(
resultSet.getType(), resultSet.getMetadata()));
+ metadataAvailableLatch.countDown();
}
} catch (Throwable exception) {
putWithoutInterruptPropagation(PartitionExecutorResult.exception(exception));
+ metadataAvailableLatch.countDown();
} finally {
// Emit a special 'finished' result to ensure that the row producer is not blocked on a
// queue that never receives any more results. This ensures that we can safely block on
@@ -215,6 +223,7 @@ private static class RowProducerImpl implements RowProducer {
private final AtomicInteger finishedCounter;
private final LinkedBlockingDeque queue;
private ResultSetMetadata metadata;
+ private final CountDownLatch metadataAvailableLatch = new CountDownLatch(1);
private Type type;
private Struct currentRow;
private Throwable exception;
@@ -243,7 +252,7 @@ private static class RowProducerImpl implements RowProducer {
this.finishedCounter = new AtomicInteger(partitions.size());
for (String partition : partitions) {
PartitionExecutor partitionExecutor =
- new PartitionExecutor(connection, partition, this.queue);
+ new PartitionExecutor(connection, partition, this.queue, this.metadataAvailableLatch);
this.partitionExecutors.add(partitionExecutor);
this.executor.submit(partitionExecutor);
}
@@ -310,8 +319,27 @@ public Struct get() {
return currentRow;
}
+ private PartitionExecutorResult getFirstResult() {
+ try {
+ metadataAvailableLatch.await();
+ } catch (InterruptedException interruptedException) {
+ throw SpannerExceptionFactory.propagateInterrupt(interruptedException);
+ }
+ PartitionExecutorResult result = queue.peek();
+ if (result == null) {
+ throw SpannerExceptionFactory.newSpannerException(
+ ErrorCode.FAILED_PRECONDITION, "Thread-unsafe access to ResultSet");
+ }
+ if (result.exception != null) {
+ throw SpannerExceptionFactory.asSpannerException(result.exception);
+ }
+ return result;
+ }
+
public ResultSetMetadata getMetadata() {
- checkState(metadata != null, "next() call required");
+ if (metadata == null) {
+ return getFirstResult().metadata;
+ }
return metadata;
}
@@ -326,7 +354,9 @@ public int getParallelism() {
}
public Type getType() {
- checkState(type != null, "next() call required");
+ if (type == null) {
+ return getFirstResult().type;
+ }
return type;
}
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
index 95bb4fb8fa0..655ca0de586 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
@@ -417,6 +417,94 @@ public void testRunEmptyPartitionedQuery() {
assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class));
}
+ @Test
+ public void testGetMetadataWithoutNextCall() {
+ int generatedRowCount = 1;
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(generatedRowCount);
+ Statement statement =
+ Statement.newBuilder("select * from random_table where active=@active")
+ .bind("active")
+ .to(true)
+ .build();
+ mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
+
+ int maxPartitions = 1;
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ try (PartitionedQueryResultSet resultSet =
+ connection.runPartitionedQuery(
+ statement, PartitionOptions.newBuilder().setMaxPartitions(maxPartitions).build())) {
+ assertNotNull(resultSet.getMetadata());
+ assertEquals(24, resultSet.getMetadata().getRowType().getFieldsCount());
+ assertNotNull(resultSet.getType());
+ assertEquals(24, resultSet.getType().getStructFields().size());
+
+ assertTrue(resultSet.next());
+ assertNotNull(resultSet.getMetadata());
+ assertEquals(24, resultSet.getMetadata().getRowType().getFieldsCount());
+ assertNotNull(resultSet.getType());
+ assertEquals(24, resultSet.getType().getStructFields().size());
+
+ assertFalse(resultSet.next());
+ }
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class));
+ }
+
+ @Test
+ public void testGetMetadataWithoutNextCallOnEmptyResultSet() {
+ int generatedRowCount = 0;
+ RandomResultSetGenerator generator = new RandomResultSetGenerator(generatedRowCount);
+ Statement statement =
+ Statement.newBuilder("select * from random_table where active=@active")
+ .bind("active")
+ .to(true)
+ .build();
+ mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
+
+ int maxPartitions = 1;
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ try (PartitionedQueryResultSet resultSet =
+ connection.runPartitionedQuery(
+ statement, PartitionOptions.newBuilder().setMaxPartitions(maxPartitions).build())) {
+ assertNotNull(resultSet.getMetadata());
+ assertEquals(24, resultSet.getMetadata().getRowType().getFieldsCount());
+ assertNotNull(resultSet.getType());
+ assertEquals(24, resultSet.getType().getStructFields().size());
+
+ assertFalse(resultSet.next());
+ }
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class));
+ }
+
+ @Test
+ public void testGetMetadataWithoutNextCallOnResultSetWithError() {
+ Statement statement =
+ Statement.newBuilder("select * from random_table where active=@active")
+ .bind("active")
+ .to(true)
+ .build();
+ mockSpanner.putStatementResult(
+ StatementResult.exception(statement, Status.NOT_FOUND.asRuntimeException()));
+
+ int maxPartitions = 1;
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ try (PartitionedQueryResultSet resultSet =
+ connection.runPartitionedQuery(
+ statement, PartitionOptions.newBuilder().setMaxPartitions(maxPartitions).build())) {
+ assertThrows(SpannerException.class, resultSet::getMetadata);
+ assertThrows(SpannerException.class, resultSet::getType);
+ }
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ assertEquals(1, mockSpanner.countRequestsOfType(PartitionQueryRequest.class));
+ }
+
@Test
public void testRunPartitionedQueryUsingSql() {
int generatedRowCount = 20;
From 7d5a52c19a4b8028b78fc64a10f1ba6127fa6ffe Mon Sep 17 00:00:00 2001
From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com>
Date: Mon, 27 May 2024 14:45:41 +0530
Subject: [PATCH 10/11] feat: [java] allow passing libraries_bom_version from
env (#1967) (#3112)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: [java] allow passing libraries_bom_version from env (#1967)
* feat: [java] allow passing libraries_bom_version from env
* reformat
Source-Link: https://github.com/googleapis/synthtool/commit/e36d2f164ca698f0264fb6f79ddc4b0fa024a940
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:31aa2ef27b071c2e7844b0eb1d5a24254daff06615b1b138b994dd6345c0b0ea
* 🦉 Updates from OwlBot post-processor
See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md
---------
Co-authored-by: Owl Bot
Co-authored-by: rahul2393
---
.github/.OwlBot.lock.yaml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml
index 5db36a5f7d8..f817c5f4499 100644
--- a/.github/.OwlBot.lock.yaml
+++ b/.github/.OwlBot.lock.yaml
@@ -13,5 +13,5 @@
# limitations under the License.
docker:
image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest
- digest: sha256:68ba5f5164a4b55529d358bb262feaa000536a0c62980727dd05a91bbb47ea5e
-# created: 2024-05-09T16:31:37.168667071Z
+ digest: sha256:31aa2ef27b071c2e7844b0eb1d5a24254daff06615b1b138b994dd6345c0b0ea
+# created: 2024-05-17T15:15:57.6714113Z
From adee81b396c2004c261f2329d65e45114be0f9f9 Mon Sep 17 00:00:00 2001
From: "release-please[bot]"
<55107282+release-please[bot]@users.noreply.github.com>
Date: Mon, 27 May 2024 16:16:42 +0530
Subject: [PATCH 11/11] chore(main): release 6.68.0 (#3121)
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
---
CHANGELOG.md | 19 ++++++++++++++++++
benchmarks/pom.xml | 2 +-
google-cloud-spanner-bom/pom.xml | 18 ++++++++---------
google-cloud-spanner-executor/pom.xml | 4 ++--
google-cloud-spanner/pom.xml | 4 ++--
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
grpc-google-cloud-spanner-executor-v1/pom.xml | 4 ++--
grpc-google-cloud-spanner-v1/pom.xml | 4 ++--
pom.xml | 20 +++++++++----------
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
.../pom.xml | 4 ++--
proto-google-cloud-spanner-v1/pom.xml | 4 ++--
samples/snapshot/pom.xml | 2 +-
versions.txt | 20 +++++++++----------
16 files changed, 70 insertions(+), 51 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f689e6160e6..df2d86a1349 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
# Changelog
+## [6.68.0](https://github.com/googleapis/java-spanner/compare/v6.67.0...v6.68.0) (2024-05-27)
+
+
+### Features
+
+* [java] allow passing libraries_bom_version from env ([#1967](https://github.com/googleapis/java-spanner/issues/1967)) ([#3112](https://github.com/googleapis/java-spanner/issues/3112)) ([7d5a52c](https://github.com/googleapis/java-spanner/commit/7d5a52c19a4b8028b78fc64a10f1ba6127fa6ffe))
+* Allow DML batches in transactions to execute analyzeUpdate ([#3114](https://github.com/googleapis/java-spanner/issues/3114)) ([dee7cda](https://github.com/googleapis/java-spanner/commit/dee7cdabe74058434e4d630846f066dc82fdf512))
+* **spanner:** Add support for Proto Columns in Connection API ([#3123](https://github.com/googleapis/java-spanner/issues/3123)) ([7e7c814](https://github.com/googleapis/java-spanner/commit/7e7c814045dc84aaa57e7c716b0221e6cb19bcd1))
+
+
+### Bug Fixes
+
+* Allow getMetadata() calls before calling next() ([#3111](https://github.com/googleapis/java-spanner/issues/3111)) ([39902c3](https://github.com/googleapis/java-spanner/commit/39902c384f3f7f9438252cbee287f2428faf1440))
+
+
+### Dependencies
+
+* Update dependency org.graalvm.buildtools:native-maven-plugin to v0.10.2 ([#3117](https://github.com/googleapis/java-spanner/issues/3117)) ([ddebbbb](https://github.com/googleapis/java-spanner/commit/ddebbbbeef976f61f23cdd66c5f7c1f412e2f9bd))
+
## [6.67.0](https://github.com/googleapis/java-spanner/compare/v6.66.0...v6.67.0) (2024-05-22)
diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml
index 1b75952769b..5d9d436fc21 100644
--- a/benchmarks/pom.xml
+++ b/benchmarks/pom.xml
@@ -24,7 +24,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml
index 9aa92fe26ca..75f97b7fc25 100644
--- a/google-cloud-spanner-bom/pom.xml
+++ b/google-cloud-spanner-bom/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.google.cloud
google-cloud-spanner-bom
- 6.67.1-SNAPSHOT
+ 6.68.0
pom
com.google.cloud
@@ -53,43 +53,43 @@
com.google.cloud
google-cloud-spanner
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.cloud
google-cloud-spanner
test-jar
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/google-cloud-spanner-executor/pom.xml b/google-cloud-spanner-executor/pom.xml
index 7ef867552a1..fab27c91baf 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.67.1-SNAPSHOT
+ 6.68.0
jar
Google Cloud Spanner Executor
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml
index 77042788029..511ccc8eec2 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.67.1-SNAPSHOT
+ 6.68.0
jar
Google Cloud Spanner
https://github.com/googleapis/java-spanner
@@ -11,7 +11,7 @@
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
google-cloud-spanner
diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
index 28f6a4dc08e..6629f05bde2 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.67.1-SNAPSHOT
+ 6.68.0
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.67.1-SNAPSHOT
+ 6.68.0
diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
index 60b07faf891..fa42a386394 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.67.1-SNAPSHOT
+ 6.68.0
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.67.1-SNAPSHOT
+ 6.68.0
diff --git a/grpc-google-cloud-spanner-executor-v1/pom.xml b/grpc-google-cloud-spanner-executor-v1/pom.xml
index 7b6b3782d1a..1194a147482 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.67.1-SNAPSHOT
+ 6.68.0
grpc-google-cloud-spanner-executor-v1
GRPC library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml
index c2f8a8e00df..aae151f72da 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.67.1-SNAPSHOT
+ 6.68.0
grpc-google-cloud-spanner-v1
GRPC library for grpc-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/pom.xml b/pom.xml
index ad44668d9e5..36916f0f0c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-spanner-parent
pom
- 6.67.1-SNAPSHOT
+ 6.68.0
Google Cloud Spanner Parent
https://github.com/googleapis/java-spanner
@@ -61,47 +61,47 @@
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.67.1-SNAPSHOT
+ 6.68.0
com.google.cloud
google-cloud-spanner
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml
index 792bde57871..e946d3a99af 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.67.1-SNAPSHOT
+ 6.68.0
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.67.1-SNAPSHOT
+ 6.68.0
diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
index 5e3ae7a6d4f..df8c9c5f2e0 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.67.1-SNAPSHOT
+ 6.68.0
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.67.1-SNAPSHOT
+ 6.68.0
diff --git a/proto-google-cloud-spanner-executor-v1/pom.xml b/proto-google-cloud-spanner-executor-v1/pom.xml
index b8245be23b3..4c6e9d2ba25 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.67.1-SNAPSHOT
+ 6.68.0
proto-google-cloud-spanner-executor-v1
Proto library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml
index 1f5a3e51664..c265c8f14bb 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.67.1-SNAPSHOT
+ 6.68.0
proto-google-cloud-spanner-v1
PROTO library for proto-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index 2172e8194f0..7ab1684582d 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -32,7 +32,7 @@
com.google.cloud
google-cloud-spanner
- 6.67.1-SNAPSHOT
+ 6.68.0
diff --git a/versions.txt b/versions.txt
index e52916e2f84..c956d228a61 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.67.0:6.67.1-SNAPSHOT
-proto-google-cloud-spanner-v1:6.67.0:6.67.1-SNAPSHOT
-proto-google-cloud-spanner-admin-database-v1:6.67.0:6.67.1-SNAPSHOT
-grpc-google-cloud-spanner-v1:6.67.0:6.67.1-SNAPSHOT
-grpc-google-cloud-spanner-admin-instance-v1:6.67.0:6.67.1-SNAPSHOT
-grpc-google-cloud-spanner-admin-database-v1:6.67.0:6.67.1-SNAPSHOT
-google-cloud-spanner:6.67.0:6.67.1-SNAPSHOT
-google-cloud-spanner-executor:6.67.0:6.67.1-SNAPSHOT
-proto-google-cloud-spanner-executor-v1:6.67.0:6.67.1-SNAPSHOT
-grpc-google-cloud-spanner-executor-v1:6.67.0:6.67.1-SNAPSHOT
+proto-google-cloud-spanner-admin-instance-v1:6.68.0:6.68.0
+proto-google-cloud-spanner-v1:6.68.0:6.68.0
+proto-google-cloud-spanner-admin-database-v1:6.68.0:6.68.0
+grpc-google-cloud-spanner-v1:6.68.0:6.68.0
+grpc-google-cloud-spanner-admin-instance-v1:6.68.0:6.68.0
+grpc-google-cloud-spanner-admin-database-v1:6.68.0:6.68.0
+google-cloud-spanner:6.68.0:6.68.0
+google-cloud-spanner-executor:6.68.0:6.68.0
+proto-google-cloud-spanner-executor-v1:6.68.0:6.68.0
+grpc-google-cloud-spanner-executor-v1:6.68.0:6.68.0