From 290022ab5a6fbde98c21e8f3276ae3f15567d95c Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Mon, 7 Feb 2022 22:06:45 +0000 Subject: [PATCH 01/19] chore: enable auto release in java (#1349) (#1670) * chore: fix auto-release * chore: remove codecov.yml * chore: update license headers for yaml files Source-Link: https://github.com/googleapis/synthtool/commit/5b777277a01a93e7f10c9279521e807b934e78d4 Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 --- .github/.OwlBot.lock.yaml | 2 +- .github/workflows/approve-readme.yaml | 15 +++++++++++++++ .github/workflows/auto-release.yaml | 19 +++++++++++++++++-- .github/workflows/ci.yaml | 15 +++++++++++++++ .kokoro/build.bat | 15 +++++++++++++++ README.md | 4 ++-- 6 files changed, 65 insertions(+), 5 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index 8807efcad4b..a8ddd81ae94 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:7c853edc4136ae8f19f9d46d4569d38de2e446db2eea057f32e412bdba255846 + digest: sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 diff --git a/.github/workflows/approve-readme.yaml b/.github/workflows/approve-readme.yaml index c5132427982..1bb18232761 100644 --- a/.github/workflows/approve-readme.yaml +++ b/.github/workflows/approve-readme.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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. +# Github action job to test core java library features on +# downstream client libraries before they are released. on: pull_request: name: auto-merge-readme diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml index 59c7cadde31..2ba3082bee2 100644 --- a/.github/workflows/auto-release.yaml +++ b/.github/workflows/auto-release.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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. +# Github action job to test core java library features on +# downstream client libraries before they are released. on: pull_request: name: auto-release @@ -16,8 +31,8 @@ jobs: return; } - // only approve PRs like "chore: release " - if ( !context.payload.pull_request.title.startsWith("chore: release") ) { + // only approve PRs like "chore(main): release " + if ( !context.payload.pull_request.title.startsWith("chore(main): release") ) { return; } diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 05de1f60dcf..6b5e56aaacd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,3 +1,18 @@ +# Copyright 2022 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. +# Github action job to test core java library features on +# downstream client libraries before they are released. on: push: branches: diff --git a/.kokoro/build.bat b/.kokoro/build.bat index 05826ad93fe..cc602c9eba8 100644 --- a/.kokoro/build.bat +++ b/.kokoro/build.bat @@ -1,3 +1,18 @@ :: See documentation in type-shell-output.bat +# Copyright 2022 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. +# Github action job to test core java library features on +# downstream client libraries before they are released. "C:\Program Files\Git\bin\bash.exe" %~dp0build.sh diff --git a/README.md b/README.md index 6779605fedc..2b8bdddb056 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,13 @@ implementation 'com.google.cloud:google-cloud-spanner' If you are using Gradle without BOM, add this to your dependencies ```Groovy -implementation 'com.google.cloud:google-cloud-spanner:6.17.4' +implementation 'com.google.cloud:google-cloud-spanner:6.18.0' ``` If you are using SBT, add this to your dependencies ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.17.4" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.18.0" ``` ## Authentication From 989523990b4e303af5b1d6b612d6dee8c690e32e Mon Sep 17 00:00:00 2001 From: "gcf-owl-bot[bot]" <78513119+gcf-owl-bot[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 00:50:51 +0000 Subject: [PATCH 02/19] chore: update auto-release script to fix breaking changes in v5 (#1350) (#1671) Source-Link: https://github.com/googleapis/synthtool/commit/53a58c23eb4decb3a17fab07388d42799e158b5f Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-java:latest@sha256:3c950ed12391ebaffd1ee66d0374766a1c50144ebe6a7a0042300b2e6bb5856b --- .github/.OwlBot.lock.yaml | 2 +- .github/workflows/auto-release.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/.OwlBot.lock.yaml b/.github/.OwlBot.lock.yaml index a8ddd81ae94..9786771c434 100644 --- a/.github/.OwlBot.lock.yaml +++ b/.github/.OwlBot.lock.yaml @@ -13,4 +13,4 @@ # limitations under the License. docker: image: gcr.io/cloud-devrel-public-resources/owlbot-java:latest - digest: sha256:ebc2104854c5b81c6fd72ca79400a2e20e0d510c5e0654fd1a19e5c9be160ca6 + digest: sha256:3c950ed12391ebaffd1ee66d0374766a1c50144ebe6a7a0042300b2e6bb5856b diff --git a/.github/workflows/auto-release.yaml b/.github/workflows/auto-release.yaml index 2ba3082bee2..18e23230d98 100644 --- a/.github/workflows/auto-release.yaml +++ b/.github/workflows/auto-release.yaml @@ -37,7 +37,7 @@ jobs: } // only approve PRs with pom.xml and versions.txt changes - const filesPromise = github.pulls.listFiles.endpoint({ + const filesPromise = github.rest.pulls.listFiles.endpoint({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, @@ -69,7 +69,7 @@ jobs: return; } - const promise = github.pulls.list.endpoint({ + const promise = github.rest.pulls.list.endpoint({ owner: context.repo.owner, repo: context.repo.repo, state: 'open' @@ -86,7 +86,7 @@ jobs: } // approve release PR - await github.pulls.createReview({ + await github.rest.pulls.createReview({ owner: context.repo.owner, repo: context.repo.repo, body: 'Rubber stamped release!', @@ -95,7 +95,7 @@ jobs: }); // attach kokoro:force-run and automerge labels - await github.issues.addLabels({ + await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, From fc0679df7fc7b3b8dd58bcbea8c78a95aa16218a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 8 Feb 2022 01:25:05 +0000 Subject: [PATCH 03/19] chore(main): release 6.18.1-SNAPSHOT (#1665) :robot: I have created a release *beep* *boop* --- ### Updating meta-information for bleeding-edge SNAPSHOT release. --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --- google-cloud-spanner-bom/pom.xml | 18 +++++++++--------- google-cloud-spanner/pom.xml | 4 ++-- .../pom.xml | 4 ++-- .../pom.xml | 4 ++-- grpc-google-cloud-spanner-v1/pom.xml | 4 ++-- pom.xml | 16 ++++++++-------- .../pom.xml | 4 ++-- .../pom.xml | 4 ++-- proto-google-cloud-spanner-v1/pom.xml | 4 ++-- samples/snapshot/pom.xml | 2 +- versions.txt | 14 +++++++------- 11 files changed, 39 insertions(+), 39 deletions(-) diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml index 14e39747f65..fd6d24c6208 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.18.0 + 6.18.1-SNAPSHOT pom com.google.cloud @@ -53,43 +53,43 @@ com.google.cloud google-cloud-spanner - 6.18.0 + 6.18.1-SNAPSHOT com.google.cloud google-cloud-spanner test-jar - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc proto-google-cloud-spanner-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.18.0 + 6.18.1-SNAPSHOT diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 76bea85ee73..62276e23e79 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.18.0 + 6.18.1-SNAPSHOT jar Google Cloud Spanner https://github.com/googleapis/java-spanner @@ -11,7 +11,7 @@ com.google.cloud google-cloud-spanner-parent - 6.18.0 + 6.18.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 df6507267ae..81396931682 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.18.0 + 6.18.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.18.0 + 6.18.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 265693ff83d..54e2993a612 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.18.0 + 6.18.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.18.0 + 6.18.1-SNAPSHOT diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml index c82e975c726..13407ad03ba 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.18.0 + 6.18.1-SNAPSHOT grpc-google-cloud-spanner-v1 GRPC library for grpc-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.18.0 + 6.18.1-SNAPSHOT diff --git a/pom.xml b/pom.xml index 5194c127a0c..fef11a346d1 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-spanner-parent pom - 6.18.0 + 6.18.1-SNAPSHOT Google Cloud Spanner Parent https://github.com/googleapis/java-spanner @@ -62,37 +62,37 @@ com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc proto-google-cloud-spanner-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.18.0 + 6.18.1-SNAPSHOT com.google.cloud google-cloud-spanner - 6.18.0 + 6.18.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 5527b946790..ffbaef0f38c 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.18.0 + 6.18.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.18.0 + 6.18.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 3df1e39b291..2bee0aa10e2 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.18.0 + 6.18.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.18.0 + 6.18.1-SNAPSHOT diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml index 4229203912a..0b061fb01dd 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.18.0 + 6.18.1-SNAPSHOT proto-google-cloud-spanner-v1 PROTO library for proto-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.18.0 + 6.18.1-SNAPSHOT diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index f5f1481c143..dd9886843c0 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -31,7 +31,7 @@ com.google.cloud google-cloud-spanner - 6.18.0 + 6.18.1-SNAPSHOT diff --git a/versions.txt b/versions.txt index 122a4b35372..cb5830abe5e 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -proto-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.0 -proto-google-cloud-spanner-v1:6.18.0:6.18.0 -proto-google-cloud-spanner-admin-database-v1:6.18.0:6.18.0 -grpc-google-cloud-spanner-v1:6.18.0:6.18.0 -grpc-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.0 -grpc-google-cloud-spanner-admin-database-v1:6.18.0:6.18.0 -google-cloud-spanner:6.18.0:6.18.0 +proto-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.1-SNAPSHOT +proto-google-cloud-spanner-v1:6.18.0:6.18.1-SNAPSHOT +proto-google-cloud-spanner-admin-database-v1:6.18.0:6.18.1-SNAPSHOT +grpc-google-cloud-spanner-v1:6.18.0:6.18.1-SNAPSHOT +grpc-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.1-SNAPSHOT +grpc-google-cloud-spanner-admin-database-v1:6.18.0:6.18.1-SNAPSHOT +google-cloud-spanner:6.18.0:6.18.1-SNAPSHOT From 69f24c0f47fa86caedceb10f95d6a5cd61274898 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Feb 2022 18:32:40 +0100 Subject: [PATCH 04/19] build(deps): update dependency org.apache.maven.plugins:maven-project-info-reports-plugin to v3.2.1 (#1669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-project-info-reports-plugin](https://maven.apache.org/plugins/) | `3.1.2` -> `3.2.1` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.1/compatibility-slim/3.1.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-project-info-reports-plugin/3.2.1/confidence-slim/3.1.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index fef11a346d1..04d8911de0c 100644 --- a/pom.xml +++ b/pom.xml @@ -159,7 +159,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.1.2 + 3.2.1 From 2aef87b759366fc58dfdf3d16283270ddc30a11b Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Feb 2022 18:42:52 +0100 Subject: [PATCH 05/19] build(deps): update dependency com.google.cloud:google-cloud-shared-config to v1.2.7 (#1672) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-shared-config](https://togithub.com/googleapis/java-shared-config) | `1.2.6` -> `1.2.7` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/compatibility-slim/1.2.6)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-shared-config/1.2.7/confidence-slim/1.2.6)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-shared-config ### [`v1.2.7`](https://togithub.com/googleapis/java-shared-config/blob/HEAD/CHANGELOG.md#​127-httpsgithubcomgoogleapisjava-shared-configcomparev126v127-2022-02-04) [Compare Source](https://togithub.com/googleapis/java-shared-config/compare/v1.2.6...v1.2.7)
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- google-cloud-spanner-bom/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml index fd6d24c6208..4a35fe5707a 100644 --- a/google-cloud-spanner-bom/pom.xml +++ b/google-cloud-spanner-bom/pom.xml @@ -8,7 +8,7 @@ com.google.cloud google-cloud-shared-config - 1.2.6 + 1.2.7 Google Cloud Spanner BOM diff --git a/pom.xml b/pom.xml index 04d8911de0c..f634da99bd4 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.google.cloud google-cloud-shared-config - 1.2.6 + 1.2.7 From 1211bfa1c6fc132f21e49542fbaac37160ba98dd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 8 Feb 2022 19:44:41 +0100 Subject: [PATCH 06/19] chore(deps): update dependency com.google.cloud:google-cloud-spanner to v6.18.0 (#1668) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-spanner](https://togithub.com/googleapis/java-spanner) | `6.17.4` -> `6.18.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner/6.18.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner/6.18.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner/6.18.0/compatibility-slim/6.17.4)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-spanner/6.18.0/confidence-slim/6.17.4)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-spanner ### [`v6.18.0`](https://togithub.com/googleapis/java-spanner/blob/HEAD/CHANGELOG.md#​6180-httpsgithubcomgoogleapisjava-spannercomparev6174v6180-2022-02-03) [Compare Source](https://togithub.com/googleapis/java-spanner/compare/v6.17.4...v6.18.0) ##### Features - add database dialect ([#​1657](https://togithub.com/googleapis/java-spanner/issues/1657)) ([269f090](https://togithub.com/googleapis/java-spanner/commit/269f090805b366fcd7a7163a6602268b4d143aa4)) - Updating readme with new gfe latency metrics ([#​1630](https://togithub.com/googleapis/java-spanner/issues/1630)) ([d02601a](https://togithub.com/googleapis/java-spanner/commit/d02601ac73a1b9ab580480c4370ba26260996d8c)) ##### Dependencies - **java:** update actions/github-script action to v5 ([#​1339](https://togithub.com/googleapis/java-spanner/issues/1339)) ([#​1659](https://togithub.com/googleapis/java-spanner/issues/1659)) ([203b346](https://togithub.com/googleapis/java-spanner/commit/203b346e748b78e56aad2246c3970593a7584825)) - update actions/github-script action to v5 ([#​1658](https://togithub.com/googleapis/java-spanner/issues/1658)) ([a2f3790](https://togithub.com/googleapis/java-spanner/commit/a2f3790c35ecc960b50979caa12f6355f397c127)) - update dependency com.google.cloud:google-cloud-monitoring to v3.2.1 ([#​1637](https://togithub.com/googleapis/java-spanner/issues/1637)) ([73c9434](https://togithub.com/googleapis/java-spanner/commit/73c94349b56710adc788c3a8440648e7f66f228b)) - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.7.0 ([#​1662](https://togithub.com/googleapis/java-spanner/issues/1662)) ([ece31c0](https://togithub.com/googleapis/java-spanner/commit/ece31c0d873ee537b167792dcbe9dc62d783a52d)) - update opencensus.version to v0.31.0 ([#​1661](https://togithub.com/googleapis/java-spanner/issues/1661)) ([1e86a3a](https://togithub.com/googleapis/java-spanner/commit/1e86a3a4542e6744cb1d8a8dbca36218c147c9f0)) ##### [6.17.4](https://www.github.com/googleapis/java-spanner/compare/v6.17.3...v6.17.4) (2022-01-07) ##### Dependencies - update dependency com.google.cloud:google-cloud-shared-dependencies to v2.6.0 ([#​1632](https://www.togithub.com/googleapis/java-spanner/issues/1632)) ([c7d4d4d](https://www.github.com/googleapis/java-spanner/commit/c7d4d4d833e9027642a870e5f03cf768c02216e3)) - update dependency com.google.cloud:google-cloud-trace to v2.1.1 ([#​1633](https://www.togithub.com/googleapis/java-spanner/issues/1633)) ([4607c21](https://www.github.com/googleapis/java-spanner/commit/4607c21518a13fd9e48a8876bbfa9f587dbe1823)) ##### [6.17.3](https://www.github.com/googleapis/java-spanner/compare/v6.17.2...v6.17.3) (2021-12-17) ##### Bug Fixes - re-adds test-jar to bom definition ([#​1596](https://www.togithub.com/googleapis/java-spanner/issues/1596)) ([5accdcd](https://www.github.com/googleapis/java-spanner/commit/5accdcdb163a4f434ba1b47ac4f1ecba92be6f67)) ##### Dependencies - bump OpenCensus API to 0.30.0 ([#​1598](https://www.togithub.com/googleapis/java-spanner/issues/1598)) ([b953363](https://www.github.com/googleapis/java-spanner/commit/b953363c531cd2cd7e831d546a30b3bbfab54268)) ##### [6.17.2](https://www.github.com/googleapis/java-spanner/compare/v6.17.1...v6.17.2) (2021-12-15) ##### Dependencies - update opencensus.version to v0.29.0 ([#​1589](https://www.togithub.com/googleapis/java-spanner/issues/1589)) ([7abf7ff](https://www.github.com/googleapis/java-spanner/commit/7abf7ff9b339eaef499313be17c7cabc169246fb)) ##### [6.17.1](https://www.github.com/googleapis/java-spanner/compare/v6.17.0...v6.17.1) (2021-12-08) ##### Dependencies - update dependency com.google.cloud:google-cloud-trace to v2.1.0 ([#​1574](https://www.togithub.com/googleapis/java-spanner/issues/1574)) ([eaf2831](https://www.github.com/googleapis/java-spanner/commit/eaf28318f0a8eb5dc3795865de438f1d0e7bd982))
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- README.md | 2 +- samples/install-without-bom/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2b8bdddb056..1b1889c1c0e 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ If you are using Maven without BOM, add this to your dependencies: com.google.cloud google-cloud-spanner - 6.17.4 + 6.18.0 ``` diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 5cad27a5839..c4b4f7ae89e 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -32,7 +32,7 @@ com.google.cloud google-cloud-spanner - 6.17.4 + 6.18.0 From f6a8a03952a4634783c8a239c63ab97a4987d2d5 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Feb 2022 00:24:57 +0100 Subject: [PATCH 07/19] chore(deps): update dependency com.google.cloud:libraries-bom to v24.3.0 (#1674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:libraries-bom](https://cloud.google.com/java/docs/bom) ([source](https://togithub.com/GoogleCloudPlatform/cloud-opensource-java)) | `24.2.0` -> `24.3.0` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/compatibility-slim/24.2.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:libraries-bom/24.3.0/confidence-slim/24.2.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Renovate will not automatically rebase this PR, because other commits have been found. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- README.md | 4 ++-- samples/snippets/pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b1889c1c0e..01de91c7245 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 - 24.2.0 + 24.3.0 pom import @@ -49,7 +49,7 @@ If you are using Maven without BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies ```Groovy -implementation platform('com.google.cloud:libraries-bom:24.2.0') +implementation platform('com.google.cloud:libraries-bom:24.3.0') implementation 'com.google.cloud:google-cloud-spanner' ``` diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index a40c65a2a16..2104201819c 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -33,7 +33,7 @@ com.google.cloud libraries-bom - 24.2.0 + 24.3.0 pom import From 4f46635577f0e754ce271e4aba338b84d34f57dd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Feb 2022 01:28:51 +0100 Subject: [PATCH 08/19] deps: update dependency com.google.cloud:google-cloud-trace to v2.1.2 (#1664) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-trace](https://togithub.com/googleapis/java-core) | `2.1.1` -> `2.1.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-trace/2.1.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-trace/2.1.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-trace/2.1.2/compatibility-slim/2.1.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-trace/2.1.2/confidence-slim/2.1.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-core ### [`v2.1.2`](https://togithub.com/googleapis/java-core/blob/HEAD/CHANGELOG.md#​212-httpswwwgithubcomgoogleapisjava-corecomparev211v212-2021-08-31) [Compare Source](https://togithub.com/googleapis/java-core/compare/v2.1.1...v2.1.2)
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index c4b4f7ae89e..593f8a95b7d 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -22,7 +22,7 @@ 1.8 UTF-8 0.31.0 - 2.1.1 + 2.1.2 3.2.1
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index dd9886843c0..67342008b75 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -22,7 +22,7 @@ 1.8 UTF-8 0.31.0 - 2.1.1 + 2.1.2 3.2.1 From 8ea22205ea1361012b8f237af9150f320b41cc23 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Wed, 9 Feb 2022 02:10:43 +0100 Subject: [PATCH 09/19] deps: update dependency com.google.cloud:google-cloud-monitoring to v3.2.2 (#1666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.cloud:google-cloud-monitoring](https://togithub.com/googleapis/java-monitoring) | `3.2.1` -> `3.2.2` | [![age](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-monitoring/3.2.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-monitoring/3.2.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-monitoring/3.2.2/compatibility-slim/3.2.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/com.google.cloud:google-cloud-monitoring/3.2.2/confidence-slim/3.2.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
googleapis/java-monitoring ### [`v3.2.2`](https://togithub.com/googleapis/java-monitoring/blob/HEAD/CHANGELOG.md#​322-httpsgithubcomgoogleapisjava-monitoringcomparev321v322-2022-02-03) [Compare Source](https://togithub.com/googleapis/java-monitoring/compare/v3.2.1...v3.2.2)
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- samples/install-without-bom/pom.xml | 2 +- samples/snapshot/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/install-without-bom/pom.xml b/samples/install-without-bom/pom.xml index 593f8a95b7d..e5dd0274f39 100644 --- a/samples/install-without-bom/pom.xml +++ b/samples/install-without-bom/pom.xml @@ -23,7 +23,7 @@ UTF-8 0.31.0 2.1.2 - 3.2.1 + 3.2.2 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 67342008b75..aa087e6ca9c 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -23,7 +23,7 @@ UTF-8 0.31.0 2.1.2 - 3.2.1 + 3.2.2 From 5f156f2efdb4726679766b385d500a030c24e477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 10 Feb 2022 18:47:19 +0100 Subject: [PATCH 10/19] feat: PostgreSQL dialect databases (#1673) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: PostgreSQL dialect databases * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix: add clirr differences * fix: do not join type names for every invocation * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * fix: revert to showing column index * test: add parameterization for ITBatchReadTest * test: parameterize BatchReadTest and skip unsupported tests Co-authored-by: Owl Bot --- .../clirr-ignored-differences.xml | 13 + .../cloud/spanner/AbstractResultSet.java | 34 +- .../cloud/spanner/AbstractStructReader.java | 37 +- .../com/google/cloud/spanner/Database.java | 1 + .../spanner/DatabaseAdminClientImpl.java | 9 +- .../google/cloud/spanner/DatabaseInfo.java | 34 +- .../com/google/cloud/spanner/Dialect.java | 83 + .../com/google/cloud/spanner/Mutation.java | 4 +- .../google/cloud/spanner/SpannerOptions.java | 33 + .../java/com/google/cloud/spanner/Struct.java | 4 + .../java/com/google/cloud/spanner/Type.java | 66 +- .../java/com/google/cloud/spanner/Value.java | 159 + .../com/google/cloud/spanner/ValueBinder.java | 5 + .../connection/AbstractBaseUnitOfWork.java | 2 +- .../AbstractMultiUseTransaction.java | 2 +- ...rser.java => AbstractStatementParser.java} | 329 +- .../spanner/connection/ChecksumResultSet.java | 12 +- .../cloud/spanner/connection/Connection.java | 6 + .../spanner/connection/ConnectionImpl.java | 14 +- .../spanner/connection/ConnectionOptions.java | 72 +- .../cloud/spanner/connection/DdlBatch.java | 20 +- .../cloud/spanner/connection/DmlBatch.java | 4 +- .../spanner/connection/FailedBatchUpdate.java | 6 +- .../cloud/spanner/connection/FailedQuery.java | 2 +- .../spanner/connection/FailedUpdate.java | 2 +- .../connection/PostgreSQLStatementParser.java | 256 + .../connection/ReadOnlyTransaction.java | 2 +- .../connection/ReadWriteTransaction.java | 48 +- .../connection/RetriableBatchUpdate.java | 6 +- .../spanner/connection/RetriableUpdate.java | 2 +- .../connection/SingleUseTransaction.java | 18 +- .../cloud/spanner/connection/SpannerPool.java | 15 +- .../connection/SpannerStatementParser.java | 249 + .../StatementExecutionInterceptor.java | 2 +- .../spanner/connection/StatementExecutor.java | 2 +- .../cloud/spanner/connection/UnitOfWork.java | 2 +- .../cloud/spanner/spi/v1/GapicSpannerRpc.java | 34 +- .../spanner/testing/RemoteSpannerHelper.java | 32 +- .../AbstractStructReaderTypesTest.java | 14 + .../spanner/DatabaseAdminClientImplTest.java | 12 +- .../google/cloud/spanner/DatabaseTest.java | 82 +- .../com/google/cloud/spanner/DialectTest.java | 95 + .../cloud/spanner/MockSpannerServiceImpl.java | 131 +- .../google/cloud/spanner/MutationTest.java | 68 +- .../google/cloud/spanner/PgNumericTest.java | 372 + .../cloud/spanner/SpannerOptionsTest.java | 3 + .../com/google/cloud/spanner/StructTest.java | 27 + .../com/google/cloud/spanner/TypeTest.java | 95 +- .../google/cloud/spanner/ValueBinderTest.java | 11 + .../com/google/cloud/spanner/ValueTest.java | 182 + .../AbstractConnectionImplTest.java | 2 +- .../connection/AbstractSqlScriptTest.java | 57 + .../connection/AbstractSqlScriptVerifier.java | 13 +- .../connection/ClientSideStatementsTest.java | 29 +- .../ConnectionImplAutocommitReadOnlyTest.java | 2 +- ...ConnectionImplAutocommitReadWriteTest.java | 2 +- .../ConnectionImplGeneratedSqlScriptTest.java | 23 +- .../connection/ConnectionImplTest.java | 87 +- ...nnectionImplTransactionalReadOnlyTest.java | 2 +- ...nectionImplTransactionalReadWriteTest.java | 2 +- .../connection/ConnectionOptionsTest.java | 76 + ...nnectionStatementWithNoParametersTest.java | 23 +- ...nnectionStatementWithOneParameterTest.java | 23 +- .../spanner/connection/DdlBatchTest.java | 27 +- .../spanner/connection/DmlBatchTest.java | 11 +- .../connection/ITAbstractSpannerTest.java | 2 +- .../connection/ReadOnlyTransactionTest.java | 4 +- .../connection/ReadWriteTransactionTest.java | 4 +- .../SetReadOnlyStalenessSqlScriptTest.java | 23 +- .../SetStatementTimeoutSqlScriptTest.java | 23 +- .../connection/SingleUseTransactionTest.java | 4 +- .../spanner/connection/SqlScriptVerifier.java | 6 + .../connection/StatementParserTest.java | 978 +- .../connection/TestChannelProvider.java | 26 + .../spanner/it/DialectTestParameter.java | 50 + .../cloud/spanner/it/ITBatchReadTest.java | 143 +- .../google/cloud/spanner/it/ITDMLTest.java | 99 +- .../it/ITDatabaseAdminDialectAwareTest.java | 120 + .../cloud/spanner/it/ITDatabaseAdminTest.java | 73 +- .../cloud/spanner/it/ITLargeReadTest.java | 74 +- .../cloud/spanner/it/ITPgNumericTest.java | 472 + .../google/cloud/spanner/it/ITQueryTest.java | 361 +- .../google/cloud/spanner/it/ITReadTest.java | 123 +- .../cloud/spanner/it/ITResultSetGetValue.java | 226 +- .../spanner/it/ITTransactionManagerTest.java | 58 +- .../google/cloud/spanner/it/ITWriteTest.java | 126 +- .../cloud/spanner/it/slow/ITBackupTest.java | 11 + .../spanner/spi/v1/GapicSpannerRpcTest.java | 38 +- .../connection/ClientSideStatementsTest.sql | 1110 +- .../ConnectionImplGeneratedSqlScriptTest.sql | 10464 ++++++++-------- .../connection/PostgreSQLCommentsTest.sql | 187 + 91 files changed, 11073 insertions(+), 6824 deletions(-) create mode 100644 google-cloud-spanner/clirr-ignored-differences.xml create mode 100644 google-cloud-spanner/src/main/java/com/google/cloud/spanner/Dialect.java rename google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/{StatementParser.java => AbstractStatementParser.java} (57%) create mode 100644 google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/PostgreSQLStatementParser.java create mode 100644 google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerStatementParser.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/DialectTest.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptTest.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TestChannelProvider.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/DialectTestParameter.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminDialectAwareTest.java create mode 100644 google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITPgNumericTest.java create mode 100644 google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/PostgreSQLCommentsTest.sql diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml new file mode 100644 index 00000000000..c750b2a7f40 --- /dev/null +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -0,0 +1,13 @@ + + + + + 7012 + com/google/cloud/spanner/connection/Connection + com.google.cloud.spanner.Dialect getDialect() + + + 8001 + com/google/cloud/spanner/connection/StatementParser + + diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java index 54bfc3f5453..6143386293d 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractResultSet.java @@ -375,6 +375,9 @@ private Object writeReplace() { case NUMERIC: builder.set(fieldName).to((BigDecimal) value); break; + case PG_NUMERIC: + builder.set(fieldName).to((String) value); + break; case STRING: builder.set(fieldName).to((String) value); break; @@ -391,7 +394,8 @@ private Object writeReplace() { builder.set(fieldName).to((Date) value); break; case ARRAY: - switch (fieldType.getArrayElementType().getCode()) { + final Type elementType = fieldType.getArrayElementType(); + switch (elementType.getCode()) { case BOOL: builder.set(fieldName).toBoolArray((Iterable) value); break; @@ -404,6 +408,9 @@ private Object writeReplace() { case NUMERIC: builder.set(fieldName).toNumericArray((Iterable) value); break; + case PG_NUMERIC: + builder.set(fieldName).toPgNumericArray((Iterable) value); + break; case STRING: builder.set(fieldName).toStringArray((Iterable) value); break; @@ -420,13 +427,10 @@ private Object writeReplace() { builder.set(fieldName).toDateArray((Iterable) value); break; case STRUCT: - builder - .set(fieldName) - .toStructArray(fieldType.getArrayElementType(), (Iterable) value); + builder.set(fieldName).toStructArray(elementType, (Iterable) value); break; default: - throw new AssertionError( - "Unhandled array type code: " + fieldType.getArrayElementType()); + throw new AssertionError("Unhandled array type code: " + elementType); } break; case STRUCT: @@ -484,7 +488,11 @@ private static Object decodeValue(Type fieldType, com.google.protobuf.Value prot case FLOAT64: return valueProtoToFloat64(proto); case NUMERIC: + checkType(fieldType, proto, KindCase.STRING_VALUE); return new BigDecimal(proto.getStringValue()); + case PG_NUMERIC: + checkType(fieldType, proto, KindCase.STRING_VALUE); + return proto.getStringValue(); case STRING: case JSON: checkType(fieldType, proto, KindCase.STRING_VALUE); @@ -549,6 +557,10 @@ static Object decodeArrayValue(Type elementType, ListValue listValue) { } return list; } + case PG_NUMERIC: + return Lists.transform( + listValue.getValuesList(), + input -> input.getKindCase() == KindCase.NULL_VALUE ? null : input.getStringValue()); case STRING: case JSON: return Lists.transform( @@ -695,6 +707,8 @@ protected Value getValueInternal(int columnIndex) { return Value.int64(isNull ? null : getLongInternal(columnIndex)); case NUMERIC: return Value.numeric(isNull ? null : getBigDecimalInternal(columnIndex)); + case PG_NUMERIC: + return Value.pgNumeric(isNull ? null : getStringInternal(columnIndex)); case FLOAT64: return Value.float64(isNull ? null : getDoubleInternal(columnIndex)); case STRING: @@ -708,13 +722,16 @@ protected Value getValueInternal(int columnIndex) { case STRUCT: return Value.struct(isNull ? null : getStructInternal(columnIndex)); case ARRAY: - switch (columnType.getArrayElementType().getCode()) { + final Type elementType = columnType.getArrayElementType(); + switch (elementType.getCode()) { case BOOL: return Value.boolArray(isNull ? null : getBooleanListInternal(columnIndex)); case INT64: return Value.int64Array(isNull ? null : getLongListInternal(columnIndex)); case NUMERIC: return Value.numericArray(isNull ? null : getBigDecimalListInternal(columnIndex)); + case PG_NUMERIC: + return Value.pgNumericArray(isNull ? null : getStringListInternal(columnIndex)); case FLOAT64: return Value.float64Array(isNull ? null : getDoubleListInternal(columnIndex)); case STRING: @@ -727,8 +744,7 @@ protected Value getValueInternal(int columnIndex) { return Value.dateArray(isNull ? null : getDateListInternal(columnIndex)); case STRUCT: return Value.structArray( - columnType.getArrayElementType(), - isNull ? null : getStructListInternal(columnIndex)); + elementType, isNull ? null : getStructListInternal(columnIndex)); default: throw new IllegalArgumentException( "Invalid array value type " + this.type.getArrayElementType()); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java index 185ab03eef6..d9038466a46 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractStructReader.java @@ -22,6 +22,7 @@ import com.google.cloud.Date; import com.google.cloud.Timestamp; import java.math.BigDecimal; +import java.util.Arrays; import java.util.List; /** @@ -159,14 +160,19 @@ public BigDecimal getBigDecimal(String columnName) { @Override public String getString(int columnIndex) { - checkNonNullOfType(columnIndex, Type.string(), columnIndex); + checkNonNullOfTypes( + columnIndex, + Arrays.asList(Type.string(), Type.pgNumeric()), + columnIndex, + "STRING, NUMERIC"); return getStringInternal(columnIndex); } @Override public String getString(String columnName) { int columnIndex = getColumnIndex(columnName); - checkNonNullOfType(columnIndex, Type.string(), columnName); + checkNonNullOfTypes( + columnIndex, Arrays.asList(Type.string(), Type.pgNumeric()), columnName, "STRING, NUMERIC"); return getStringInternal(columnIndex); } @@ -327,14 +333,22 @@ public List getBigDecimalList(String columnName) { @Override public List getStringList(int columnIndex) { - checkNonNullOfType(columnIndex, Type.array(Type.string()), columnIndex); + checkNonNullOfTypes( + columnIndex, + Arrays.asList(Type.array(Type.string()), Type.array(Type.pgNumeric())), + columnIndex, + "ARRAY, ARRAY"); return getStringListInternal(columnIndex); } @Override public List getStringList(String columnName) { int columnIndex = getColumnIndex(columnName); - checkNonNullOfType(columnIndex, Type.array(Type.string()), columnName); + checkNonNullOfTypes( + columnIndex, + Arrays.asList(Type.array(Type.string()), Type.array(Type.pgNumeric())), + columnName, + "ARRAY, ARRAY"); return getStringListInternal(columnIndex); } @@ -429,6 +443,21 @@ private void checkNonNullOfType(int columnIndex, Type expectedType, Object colum checkNonNull(columnIndex, columnNameForError); } + private void checkNonNullOfTypes( + int columnIndex, + List expectedTypes, + Object columnNameForError, + String expectedTypeNames) { + Type actualType = getColumnType(columnIndex); + checkState( + expectedTypes.contains(actualType), + "Column %s is not of correct type: expected one of [%s] but was %s", + columnNameForError, + expectedTypeNames, + actualType); + checkNonNull(columnIndex, columnNameForError); + } + private void checkNonNullArrayOfStruct(int columnIndex, Object columnNameForError) { Type actualType = getColumnType(columnIndex); checkState( diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Database.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Database.java index 30d5017272c..eb3afdca705 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Database.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Database.java @@ -188,6 +188,7 @@ static Database fromProto( .setEarliestVersionTime(Timestamp.fromProto(proto.getEarliestVersionTime())) .setEncryptionConfig(CustomerManagedEncryption.fromProtoOrNull(proto.getEncryptionConfig())) .setDefaultLeader(proto.getDefaultLeader()) + .setDialect(Dialect.fromProto(proto.getDatabaseDialect())) .setProto(proto) .build(); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java index 4d79ed517da..52df8701556 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseAdminClientImpl.java @@ -23,7 +23,6 @@ import com.google.cloud.Policy; import com.google.cloud.Policy.DefaultMarshaller; import com.google.cloud.Timestamp; -import com.google.cloud.spanner.DatabaseInfo.State; import com.google.cloud.spanner.Options.ListOption; import com.google.cloud.spanner.SpannerImpl.PageFetcher; import com.google.cloud.spanner.spi.v1.SpannerRpc; @@ -281,14 +280,18 @@ public Backup fromProto(com.google.spanner.admin.database.v1.Backup proto) { public OperationFuture createDatabase( String instanceId, String databaseId, Iterable statements) throws SpannerException { return createDatabase( - new Database(DatabaseId.of(projectId, instanceId, databaseId), State.UNSPECIFIED, this), + newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) + .build(), statements); } @Override public OperationFuture createDatabase( Database database, Iterable statements) throws SpannerException { - String createStatement = "CREATE DATABASE `" + database.getId().getDatabase() + "`"; + final Dialect dialect = Preconditions.checkNotNull(database.getDialect()); + final String createStatement = + dialect.createDatabaseStatementFor(database.getId().getDatabase()); OperationFuture rawOperationFuture = rpc.createDatabase( diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java index b58769bcb54..565517e3419 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseInfo.java @@ -54,6 +54,10 @@ public Builder setDefaultLeader(String defaultLeader) { throw new UnsupportedOperationException("Unimplemented"); } + public Builder setDialect(Dialect dialect) { + throw new UnsupportedOperationException("Unimplemented"); + } + abstract Builder setProto(com.google.spanner.admin.database.v1.Database proto); /** Builds the database from this builder. */ @@ -69,6 +73,7 @@ abstract static class BuilderImpl extends Builder { private Timestamp earliestVersionTime; private CustomerManagedEncryption encryptionConfig; private String defaultLeader; + private Dialect dialect = Dialect.GOOGLE_STANDARD_SQL; private com.google.spanner.admin.database.v1.Database proto; BuilderImpl(DatabaseId id) { @@ -84,6 +89,7 @@ abstract static class BuilderImpl extends Builder { this.earliestVersionTime = other.earliestVersionTime; this.encryptionConfig = other.encryptionConfig; this.defaultLeader = other.defaultLeader; + this.dialect = other.dialect; this.proto = other.proto; } @@ -129,6 +135,12 @@ public Builder setDefaultLeader(String defaultLeader) { return this; } + @Override + public Builder setDialect(Dialect dialect) { + this.dialect = dialect; + return this; + } + @Override Builder setProto(@Nullable com.google.spanner.admin.database.v1.Database proto) { this.proto = proto; @@ -156,6 +168,7 @@ public enum State { private final Timestamp earliestVersionTime; private final CustomerManagedEncryption encryptionConfig; private final String defaultLeader; + private final Dialect dialect; private final com.google.spanner.admin.database.v1.Database proto; public DatabaseInfo(DatabaseId id, State state) { @@ -167,6 +180,7 @@ public DatabaseInfo(DatabaseId id, State state) { this.earliestVersionTime = null; this.encryptionConfig = null; this.defaultLeader = null; + this.dialect = null; this.proto = null; } @@ -179,6 +193,7 @@ public DatabaseInfo(DatabaseId id, State state) { this.earliestVersionTime = builder.earliestVersionTime; this.encryptionConfig = builder.encryptionConfig; this.defaultLeader = builder.defaultLeader; + this.dialect = builder.dialect; this.proto = builder.proto; } @@ -239,6 +254,14 @@ public Timestamp getEarliestVersionTime() { return defaultLeader; } + /** + * The dialect that is used by the database. It can be one of the values as specified in {@link + * Dialect#values()}. + */ + public @Nullable Dialect getDialect() { + return dialect; + } + /** Returns the raw proto instance that was used to construct this {@link Database}. */ public @Nullable com.google.spanner.admin.database.v1.Database getProto() { return proto; @@ -260,7 +283,8 @@ public boolean equals(Object o) { && Objects.equals(versionRetentionPeriod, that.versionRetentionPeriod) && Objects.equals(earliestVersionTime, that.earliestVersionTime) && Objects.equals(encryptionConfig, that.encryptionConfig) - && Objects.equals(defaultLeader, that.defaultLeader); + && Objects.equals(defaultLeader, that.defaultLeader) + && Objects.equals(dialect, that.dialect); } @Override @@ -273,13 +297,14 @@ public int hashCode() { versionRetentionPeriod, earliestVersionTime, encryptionConfig, - defaultLeader); + defaultLeader, + dialect); } @Override public String toString() { return String.format( - "Database[%s, %s, %s, %s, %s, %s, %s, %s]", + "Database[%s, %s, %s, %s, %s, %s, %s, %s, %s]", id.getName(), state, createTime, @@ -287,6 +312,7 @@ public String toString() { versionRetentionPeriod, earliestVersionTime, encryptionConfig, - defaultLeader); + defaultLeader, + dialect); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Dialect.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Dialect.java new file mode 100644 index 00000000000..ba7186d8047 --- /dev/null +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Dialect.java @@ -0,0 +1,83 @@ +/* + * Copyright 2022 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; + +import com.google.common.collect.ImmutableMap; +import com.google.spanner.admin.database.v1.DatabaseDialect; +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +public enum Dialect { + GOOGLE_STANDARD_SQL { + @Override + public String createDatabaseStatementFor(String databaseName) { + return "CREATE DATABASE `" + databaseName + "`"; + } + + @Override + public DatabaseDialect toProto() { + return DatabaseDialect.GOOGLE_STANDARD_SQL; + } + }, + POSTGRESQL { + @Override + public String createDatabaseStatementFor(String databaseName) { + return "CREATE DATABASE \"" + databaseName + "\""; + } + + @Override + public DatabaseDialect toProto() { + return DatabaseDialect.POSTGRESQL; + } + }; + + private static final Map protoToDialect = + ImmutableMap.of( + DatabaseDialect.DATABASE_DIALECT_UNSPECIFIED, Dialect.GOOGLE_STANDARD_SQL, + DatabaseDialect.GOOGLE_STANDARD_SQL, Dialect.GOOGLE_STANDARD_SQL, + DatabaseDialect.POSTGRESQL, Dialect.POSTGRESQL); + + public abstract String createDatabaseStatementFor(String databaseName); + + public abstract DatabaseDialect toProto(); + + public static Dialect fromProto(DatabaseDialect databaseDialect) { + final Dialect dialect = protoToDialect.get(databaseDialect); + if (dialect == null) { + throw new IllegalArgumentException( + String.format( + "Invalid dialect: %s. Dialect must be one of [%s]", + databaseDialect, + protoToDialect.keySet().stream() + .map(DatabaseDialect::name) + .collect(Collectors.joining(", ")))); + } + return dialect; + } + + public static Dialect fromName(String name) { + try { + return Dialect.valueOf(name); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException( + String.format( + "Invalid dialect: %s. Dialect must be one of %s", + name, Arrays.toString(Dialect.values()))); + } + } +} diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java index dd043653566..73995a20df8 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Mutation.java @@ -385,7 +385,9 @@ private boolean areValuesEqual(List values, List otherValues) { } private boolean isNaN(Value value) { - return !value.isNull() && value.getType() == Type.float64() && Double.isNaN(value.getFloat64()); + return !value.isNull() + && value.getType().equals(Type.float64()) + && Double.isNaN(value.getFloat64()); } static void toProto(Iterable mutations, List out) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java index 5d1a51390d7..14f07314e8f 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java @@ -125,6 +125,7 @@ public class SpannerOptions extends ServiceOptions { private final CallCredentialsProvider callCredentialsProvider; private final CloseableExecutorProvider asyncExecutorProvider; private final String compressorName; + private final Dialect dialect; /** * Interface that can be used to provide {@link CallCredentials} instead of {@link Credentials} to @@ -592,6 +593,7 @@ private SpannerOptions(Builder builder) { callCredentialsProvider = builder.callCredentialsProvider; asyncExecutorProvider = builder.asyncExecutorProvider; compressorName = builder.compressorName; + dialect = builder.dialect; } /** @@ -691,6 +693,7 @@ public static class Builder private CloseableExecutorProvider asyncExecutorProvider; private String compressorName; private String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST"); + private Dialect dialect = Dialect.GOOGLE_STANDARD_SQL; private Builder() { // Manually set retry and polling settings that work. @@ -745,6 +748,7 @@ private Builder() { this.channelProvider = options.channelProvider; this.channelConfigurator = options.channelConfigurator; this.interceptorProvider = options.interceptorProvider; + this.dialect = options.dialect; } @Override @@ -764,6 +768,20 @@ protected Set getAllowedClientLibTokens() { /** * Sets the {@code ChannelProvider}. {@link GapicSpannerRpc} would create a default one if none * is provided. + * + *

Setting a custom {@link TransportChannelProvider} also overrides any other settings that + * affect the default channel provider. These must be set manually on the custom {@link + * TransportChannelProvider} instead of on {@link SpannerOptions}. The settings of {@link + * SpannerOptions} that have no effect if you set a custom {@link TransportChannelProvider} are: + * + *

    + *
  1. {@link #setChannelConfigurator(ApiFunction)} + *
  2. {@link #setHost(String)} + *
  3. {@link #setNumChannels(int)} + *
  4. {@link #setInterceptorProvider(GrpcInterceptorProvider)} + *
  5. {@link #setDialect(Dialect)} + *
  6. {@link #setHeaderProvider(com.google.api.gax.rpc.HeaderProvider)} + *
*/ public Builder setChannelProvider(TransportChannelProvider channelProvider) { this.channelProvider = channelProvider; @@ -1121,6 +1139,17 @@ public Builder setEmulatorHost(String emulatorHost) { return this; } + /** + * Sets the {@link Dialect} to use with Cloud Spanner. The default is {@link + * Dialect#GOOGLE_STANDARD_SQL}. + */ + public Builder setDialect(Dialect dialect) { + Preconditions.checkNotNull(dialect); + this.dialect = dialect; + return this; + } + + @SuppressWarnings("rawtypes") @Override public SpannerOptions build() { // Set the host of emulator has been set. @@ -1247,6 +1276,10 @@ public String getCompressorName() { return compressorName; } + public Dialect getDialect() { + return dialect; + } + /** Returns the default query options to use for the specific database. */ public QueryOptions getDefaultQueryOptions(DatabaseId databaseId) { // Use the specific query options for the database if any have been specified. These have diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Struct.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Struct.java index 9a437f2be31..c986767d3a0 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Struct.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Struct.java @@ -349,6 +349,8 @@ private Object getAsObject(int columnIndex) { return getDoubleInternal(columnIndex); case NUMERIC: return getBigDecimalInternal(columnIndex); + case PG_NUMERIC: + return getStringInternal(columnIndex); case STRING: return getStringInternal(columnIndex); case JSON: @@ -371,6 +373,8 @@ private Object getAsObject(int columnIndex) { return getDoubleListInternal(columnIndex); case NUMERIC: return getBigDecimalListInternal(columnIndex); + case PG_NUMERIC: + return getStringListInternal(columnIndex); case STRING: return getStringListInternal(columnIndex); case JSON: 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 4a78eca4674..15305e0cdab 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 @@ -17,16 +17,20 @@ package com.google.cloud.spanner; import static com.google.common.base.Preconditions.checkArgument; +import static com.google.spanner.v1.TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.spanner.v1.TypeAnnotationCode; import com.google.spanner.v1.TypeCode; import java.io.Serializable; +import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import java.util.TreeMap; import javax.annotation.Nullable; @@ -45,6 +49,7 @@ public final class Type implements Serializable { private static final Type TYPE_INT64 = new Type(Code.INT64, null, null); private static final Type TYPE_FLOAT64 = new Type(Code.FLOAT64, null, null); private static final Type TYPE_NUMERIC = new Type(Code.NUMERIC, null, null); + private static final Type TYPE_PG_NUMERIC = new Type(Code.PG_NUMERIC, null, null); private static final Type TYPE_STRING = new Type(Code.STRING, null, null); private static final Type TYPE_JSON = new Type(Code.JSON, null, null); private static final Type TYPE_BYTES = new Type(Code.BYTES, null, null); @@ -54,6 +59,7 @@ public final class Type implements Serializable { private static final Type TYPE_ARRAY_INT64 = new Type(Code.ARRAY, TYPE_INT64, null); private static final Type TYPE_ARRAY_FLOAT64 = new Type(Code.ARRAY, TYPE_FLOAT64, null); private static final Type TYPE_ARRAY_NUMERIC = new Type(Code.ARRAY, TYPE_NUMERIC, null); + private static final Type TYPE_ARRAY_PG_NUMERIC = new Type(Code.ARRAY, TYPE_PG_NUMERIC, null); private static final Type TYPE_ARRAY_STRING = new Type(Code.ARRAY, TYPE_STRING, null); private static final Type TYPE_ARRAY_JSON = new Type(Code.ARRAY, TYPE_JSON, null); private static final Type TYPE_ARRAY_BYTES = new Type(Code.ARRAY, TYPE_BYTES, null); @@ -89,6 +95,14 @@ public static Type numeric() { return TYPE_NUMERIC; } + /** + * Returns the descriptor for the {@code NUMERIC} type with the {@code PG_NUMERIC} type + * annotation. + */ + public static Type pgNumeric() { + return Type.TYPE_PG_NUMERIC; + } + /** * Returns the descriptor for the {@code STRING} type: a variable-length Unicode character string. */ @@ -134,6 +148,8 @@ public static Type array(Type elementType) { return TYPE_ARRAY_FLOAT64; case NUMERIC: return TYPE_ARRAY_NUMERIC; + case PG_NUMERIC: + return TYPE_ARRAY_PG_NUMERIC; case STRING: return TYPE_ARRAY_STRING; case JSON: @@ -189,6 +205,7 @@ public enum Code { BOOL(TypeCode.BOOL), INT64(TypeCode.INT64), NUMERIC(TypeCode.NUMERIC), + PG_NUMERIC(TypeCode.NUMERIC, TypeAnnotationCode.PG_NUMERIC), FLOAT64(TypeCode.FLOAT64), STRING(TypeCode.STRING), JSON(TypeCode.JSON), @@ -198,31 +215,51 @@ public enum Code { ARRAY(TypeCode.ARRAY), STRUCT(TypeCode.STRUCT); - private static final Map protoToCode; + private static final Map, Code> protoToCode; static { - ImmutableMap.Builder builder = ImmutableMap.builder(); + ImmutableMap.Builder, Code> builder = + ImmutableMap.builder(); for (Code code : Code.values()) { - builder.put(code.protoCode(), code); + builder.put(new SimpleEntry<>(code.getTypeCode(), code.getTypeAnnotationCode()), code); } protoToCode = builder.build(); } - private final TypeCode protoCode; + private final TypeCode typeCode; + private final TypeAnnotationCode typeAnnotationCode; + + Code(TypeCode typeCode) { + this(typeCode, TYPE_ANNOTATION_CODE_UNSPECIFIED); + } + + Code(TypeCode typeCode, TypeAnnotationCode typeAnnotationCode) { + this.typeCode = typeCode; + this.typeAnnotationCode = typeAnnotationCode; + } - Code(TypeCode protoCode) { - this.protoCode = protoCode; + TypeCode getTypeCode() { + return typeCode; } - TypeCode protoCode() { - return protoCode; + TypeAnnotationCode getTypeAnnotationCode() { + return typeAnnotationCode; } - static Code fromProtoCode(TypeCode protoCode) { - Code code = protoToCode.get(protoCode); - checkArgument(code != null, "Invalid code: %s", protoCode); + static Code fromProto(TypeCode typeCode, TypeAnnotationCode typeAnnotationCode) { + Code code = protoToCode.get(new SimpleEntry<>(typeCode, typeAnnotationCode)); + checkArgument(code != null, "Invalid code: %s<%s>", typeCode, typeAnnotationCode); return code; } + + @Override + public String toString() { + if (typeAnnotationCode == TYPE_ANNOTATION_CODE_UNSPECIFIED) { + return typeCode.toString(); + } else { + return typeCode.toString() + "<" + typeAnnotationCode.toString() + ">"; + } + } } /** Describes an individual field in a {@code STRUCT type}. */ @@ -379,7 +416,8 @@ public int hashCode() { com.google.spanner.v1.Type toProto() { com.google.spanner.v1.Type.Builder proto = com.google.spanner.v1.Type.newBuilder(); - proto.setCode(code.protoCode()); + proto.setCode(code.getTypeCode()); + proto.setTypeAnnotation(code.getTypeAnnotationCode()); if (code == Code.ARRAY) { proto.setArrayElementType(arrayElementType.toProto()); } else if (code == Code.STRUCT) { @@ -392,7 +430,7 @@ com.google.spanner.v1.Type toProto() { } static Type fromProto(com.google.spanner.v1.Type proto) { - Code type = Code.fromProtoCode(proto.getCode()); + Code type = Code.fromProto(proto.getCode(), proto.getTypeAnnotation()); switch (type) { case BOOL: return bool(); @@ -402,6 +440,8 @@ static Type fromProto(com.google.spanner.v1.Type proto) { return float64(); case NUMERIC: return numeric(); + case PG_NUMERIC: + return pgNumeric(); case STRING: return string(); case JSON: diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java index 090c636b59d..38b4361d755 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java @@ -35,6 +35,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -72,6 +73,9 @@ public abstract class Value implements Serializable { */ public static final Timestamp COMMIT_TIMESTAMP = Timestamp.ofTimeMicroseconds(0L); + /** Constant to specify a PG Numeric NaN value. */ + public static final String NAN = "NaN"; + private static final int MAX_DEBUG_STRING_LENGTH = 36; private static final String ELLIPSIS = "..."; private static final String NULL_STRING = "NULL"; @@ -157,6 +161,21 @@ public static Value numeric(@Nullable BigDecimal v) { return new NumericImpl(v == null, v); } + /** + * Returns a {@code PG NUMERIC} value. This value has flexible precision and scale which is + * specified in the Database DDL. This value also supports {@code NaNs}, which can be specified + * with {@code Value.pgNumeric(Value.NAN)} or simply as {@code Value.pgNumeric("NaN")}. + * + *

Note that this flavour of numeric is different than Spanner numerics ({@link + * Value#numeric(BigDecimal)}). It should be used only for handling numerics in the PostgreSQL + * dialect. + * + * @param v the value, which may be null + */ + public static Value pgNumeric(@Nullable String v) { + return new PgNumericImpl(v == null, v); + } + /** * Returns a {@code STRING} value. * @@ -338,6 +357,17 @@ public static Value numericArray(@Nullable Iterable v) { return new NumericArrayImpl(v == null, v == null ? null : immutableCopyOf(v)); } + /** + * Returns an {@code ARRAY} value. + * + * @param v the source of element values. This may be {@code null} to produce a value for which + * {@code isNull()} is {@code true}. Individual elements may also be {@code null}. Individual + * elements may be {@code "NaN"} or {@link Value#NAN}. + */ + public static Value pgNumericArray(@Nullable Iterable v) { + return new PgNumericArrayImpl(v == null, v == null ? null : immutableCopyOf(v)); + } + /** * Returns an {@code ARRAY} value. * @@ -1232,6 +1262,65 @@ void valueToString(StringBuilder b) { } } + private static class PgNumericImpl extends AbstractObjectValue { + private BigDecimal valueAsBigDecimal; + private NumberFormatException bigDecimalConversionError; + private Double valueAsDouble; + private NumberFormatException doubleConversionError; + + private PgNumericImpl(boolean isNull, String value) { + super(isNull, Type.pgNumeric(), value); + } + + @Override + public String getString() { + checkType(Type.pgNumeric()); + checkNotNull(); + return value; + } + + @Override + public BigDecimal getNumeric() { + checkType(Type.pgNumeric()); + checkNotNull(); + if (bigDecimalConversionError != null) { + throw bigDecimalConversionError; + } + if (valueAsBigDecimal == null) { + try { + valueAsBigDecimal = new BigDecimal(value); + } catch (NumberFormatException e) { + bigDecimalConversionError = e; + throw e; + } + } + return valueAsBigDecimal; + } + + @Override + public double getFloat64() { + checkType(Type.pgNumeric()); + checkNotNull(); + if (doubleConversionError != null) { + throw doubleConversionError; + } + if (valueAsDouble == null) { + try { + valueAsDouble = Double.parseDouble(value); + } catch (NumberFormatException e) { + doubleConversionError = e; + throw e; + } + } + return valueAsDouble; + } + + @Override + void valueToString(StringBuilder b) { + b.append(value); + } + } + private abstract static class PrimitiveArrayImpl extends AbstractValue { private final BitSet nulls; @@ -1580,6 +1669,72 @@ void appendElement(StringBuilder b, BigDecimal element) { } } + private static class PgNumericArrayImpl extends AbstractArrayValue { + + private List valuesAsBigDecimal; + private NumberFormatException bigDecimalConversionError; + private List valuesAsDouble; + private NumberFormatException doubleConversionError; + + private PgNumericArrayImpl(boolean isNull, @Nullable List values) { + super(isNull, Type.pgNumeric(), values); + } + + @Override + public List getStringArray() { + checkType(getType()); + checkNotNull(); + return value; + } + + @Override + public List getNumericArray() { + checkType(getType()); + checkNotNull(); + if (bigDecimalConversionError != null) { + throw bigDecimalConversionError; + } + if (valuesAsBigDecimal == null) { + try { + valuesAsBigDecimal = + value.stream() + .map(v -> v == null ? null : new BigDecimal(v)) + .collect(Collectors.toList()); + } catch (NumberFormatException e) { + bigDecimalConversionError = e; + throw e; + } + } + return valuesAsBigDecimal; + } + + @Override + public List getFloat64Array() { + checkType(getType()); + checkNotNull(); + if (doubleConversionError != null) { + throw doubleConversionError; + } + if (valuesAsDouble == null) { + try { + valuesAsDouble = + value.stream() + .map(v -> v == null ? null : Double.valueOf(v)) + .collect(Collectors.toList()); + } catch (NumberFormatException e) { + doubleConversionError = e; + throw e; + } + } + return valuesAsDouble; + } + + @Override + void appendElement(StringBuilder b, String element) { + b.append(element); + } + } + private static class StructImpl extends AbstractObjectValue { // Constructor for non-NULL struct values. @@ -1631,6 +1786,8 @@ private Value getValue(int fieldIndex) { return Value.float64(value.getDouble(fieldIndex)); case NUMERIC: return Value.numeric(value.getBigDecimal(fieldIndex)); + case PG_NUMERIC: + return Value.pgNumeric(value.getString(fieldIndex)); case DATE: return Value.date(value.getDate(fieldIndex)); case TIMESTAMP: @@ -1655,6 +1812,8 @@ private Value getValue(int fieldIndex) { return Value.float64Array(value.getDoubleList(fieldIndex)); case NUMERIC: return Value.numericArray(value.getBigDecimalList(fieldIndex)); + case PG_NUMERIC: + return Value.pgNumericArray(value.getStringList(fieldIndex)); case DATE: return Value.dateArray(value.getDateList(fieldIndex)); case TIMESTAMP: diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ValueBinder.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ValueBinder.java index 07dd246e7b4..cdca5d84a25 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ValueBinder.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ValueBinder.java @@ -173,6 +173,11 @@ public R toNumericArray(@Nullable Iterable values) { return handle(Value.numericArray(values)); } + /** Binds to {@code Value.pgNumericArray(values)} */ + public R toPgNumericArray(@Nullable Iterable values) { + return handle(Value.pgNumericArray(values)); + } + /** Binds to {@code Value.stringArray(values)} */ public R toStringArray(@Nullable Iterable values) { return handle(Value.stringArray(values)); 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 a21c4880ecb..e9117287853 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 @@ -27,8 +27,8 @@ import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.StatementExecutor.StatementTimeout; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.MoreExecutors; 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 ac3c7cb86a1..88dabb7763b 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 @@ -23,7 +23,7 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.common.base.Preconditions; import com.google.spanner.v1.SpannerGrpc; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java similarity index 57% rename from google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementParser.java rename to google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java index f3822177f04..62cee4e26e1 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementParser.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java @@ -17,18 +17,23 @@ package com.google.cloud.spanner.connection; import com.google.api.core.InternalApi; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.Callable; /** * Internal class for the Spanner Connection API. @@ -37,12 +42,92 @@ * the type of statement, allowing the connection API to know which method on Spanner should be * called. The parser does not validate the validity of statements, except for {@link * ClientSideStatement}s. This means that an invalid DML statement could be accepted by the {@link - * StatementParser} and sent to Spanner, and Spanner will then reject it with some error message. + * AbstractStatementParser} and sent to Spanner, and Spanner will then reject it with some error + * message. */ @InternalApi -public class StatementParser { - /** Singleton instance of {@link StatementParser}. */ - public static final StatementParser INSTANCE = new StatementParser(); +public abstract class AbstractStatementParser { + private static final Object lock = new Object(); + private static final Map INSTANCES = new HashMap<>(); + private static final ImmutableMap> + KNOWN_PARSER_CLASSES = + ImmutableMap.of( + Dialect.GOOGLE_STANDARD_SQL, + SpannerStatementParser.class, + Dialect.POSTGRESQL, + PostgreSQLStatementParser.class); + private static final String GSQL_STATEMENT = "/*GSQL*/"; + + /* Checks if the SQL statement starts with /*GSQL*/ + private boolean isGoogleSql(String sql) { + return sql.startsWith(GSQL_STATEMENT); + } + + /** Get an instance of {@link AbstractStatementParser} for the specified dialect. */ + public static AbstractStatementParser getInstance(Dialect dialect) { + synchronized (lock) { + if (!INSTANCES.containsKey(dialect)) { + try { + Class clazz = KNOWN_PARSER_CLASSES.get(dialect); + if (clazz == null) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INTERNAL, "There is no known statement parser for dialect " + dialect); + } + INSTANCES.put(dialect, clazz.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INTERNAL, + "Could not instantiate statement parser for dialect " + dialect.name(), + e); + } + } + return INSTANCES.get(dialect); + } + } + + /** + * The following fixed pre-parsed statements are used internally by the Connection API. These do + * not need to be parsed using a specific dialect, as they are equal for all dialects, and + * pre-parsing them avoids the need to repeatedly parse statements that are used internally. + */ + + /** Begins a transaction. */ + static final ParsedStatement BEGIN_STATEMENT = + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL).parse(Statement.of("BEGIN")); + + /** + * Create a COMMIT statement to use with the {@link #commit()} method to allow it to be cancelled, + * time out or retried. + * + *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, + * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout + * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link + * #commit()} method is called directly, we do not have a {@link ParsedStatement}, and the method + * uses this statement instead in order to use the same logic as the other statements. + */ + static final ParsedStatement COMMIT_STATEMENT = + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("COMMIT")); + + /** The {@link Statement} and {@link Callable} for rollbacks */ + static final ParsedStatement ROLLBACK_STATEMENT = + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("ROLLBACK")); + + /** + * Create a RUN BATCH statement to use with the {@link #executeBatchUpdate(Iterable)} method to + * allow it to be cancelled, time out or retried. + * + *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, + * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout + * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link + * #executeBatchUpdate(Iterable)} method is called, we do not have one {@link ParsedStatement}, + * and the method uses this statement instead in order to use the same logic as the other + * statements. + */ + static final ParsedStatement RUN_BATCH_STATEMENT = + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("RUN BATCH")); /** The type of statement that has been recognized by the parser. */ enum StatementType { @@ -213,13 +298,14 @@ ClientSideStatement getClientSideStatement() { } } - private static final Set ddlStatements = ImmutableSet.of("CREATE", "DROP", "ALTER"); - private static final Set selectStatements = ImmutableSet.of("SELECT", "WITH"); - private static final Set dmlStatements = ImmutableSet.of("INSERT", "UPDATE", "DELETE"); + static final Set ddlStatements = ImmutableSet.of("CREATE", "DROP", "ALTER"); + static final Set selectStatements = ImmutableSet.of("SELECT", "WITH", "SHOW"); + static final Set dmlStatements = ImmutableSet.of("INSERT", "UPDATE", "DELETE"); + private final Dialect dialect; private final Set statements; - /** Private constructor for singleton instance. */ - private StatementParser() { + AbstractStatementParser(Dialect dialect) { + this.dialect = dialect; try { statements = Collections.unmodifiableSet(ClientSideStatements.INSTANCE.getCompiledStatements()); @@ -299,6 +385,8 @@ public boolean isDdlStatement(String sql) { @InternalApi public boolean isQuery(String sql) { // Skip any query hints at the beginning of the query. + // We only do this if we actually know that it starts with a hint to prevent unnecessary + // re-assigning the exact same sql string. if (sql.startsWith("@")) { sql = removeStatementHint(sql); } @@ -323,12 +411,23 @@ public boolean isUpdateStatement(String sql) { return statementStartsWith(sql, dmlStatements); } + protected abstract boolean supportsExplain(); + private boolean statementStartsWith(String sql, Iterable checkStatements) { Preconditions.checkNotNull(sql); - String[] tokens = sql.split("\\s+", 2); - if (tokens.length > 0) { + String[] tokens; + if (isGoogleSql(sql)) { + tokens = sql.substring(GSQL_STATEMENT.length()).split("\\s+", 2); + } else { + tokens = sql.split("\\s+", 2); + } + int checkIndex = 0; + if (supportsExplain() && tokens[0].equalsIgnoreCase("EXPLAIN")) { + checkIndex = 1; + } + if (tokens.length > checkIndex) { for (String check : checkStatements) { - if (tokens[0].equalsIgnoreCase(check)) { + if (tokens[checkIndex].equalsIgnoreCase(check)) { return true; } } @@ -336,149 +435,95 @@ private boolean statementStartsWith(String sql, Iterable checkStatements return false; } + static final char SINGLE_QUOTE = '\''; + static final char DOUBLE_QUOTE = '"'; + static final char BACKTICK_QUOTE = '`'; + static final char HYPHEN = '-'; + static final char DASH = '#'; + static final char SLASH = '/'; + static final char ASTERIKS = '*'; + static final char DOLLAR = '$'; + /** - * Removes comments from and trims the given sql statement. Spanner supports three types of - * comments: - * - *

    - *
  • Single line comments starting with '--' - *
  • Single line comments starting with '#' - *
  • Multi line comments between '/*' and '*/' - *
- * - * Reference: https://cloud.google.com/spanner/docs/lexical#comments + * Removes comments from and trims the given sql statement using the dialect of this parser. * * @param sql The sql statement to remove comments from and to trim. * @return the sql statement without the comments and leading and trailing spaces. */ @InternalApi - public static String removeCommentsAndTrim(String sql) { - Preconditions.checkNotNull(sql); - final char SINGLE_QUOTE = '\''; - final char DOUBLE_QUOTE = '"'; - final char BACKTICK_QUOTE = '`'; - final char HYPHEN = '-'; - final char DASH = '#'; - final char SLASH = '/'; - final char ASTERISK = '*'; - boolean isInQuoted = false; - boolean isInSingleLineComment = false; - boolean isInMultiLineComment = false; - char startQuote = 0; - boolean lastCharWasEscapeChar = false; - boolean isTripleQuoted = false; - StringBuilder res = new StringBuilder(sql.length()); - int index = 0; - while (index < sql.length()) { - char c = sql.charAt(index); - if (isInQuoted) { - if ((c == '\n' || c == '\r') && !isTripleQuoted) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); - } else if (c == startQuote) { - if (lastCharWasEscapeChar) { - lastCharWasEscapeChar = false; - } else if (isTripleQuoted) { - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isInQuoted = false; - startQuote = 0; - isTripleQuoted = false; - res.append(c).append(c); - index += 2; - } - } else { - isInQuoted = false; - startQuote = 0; - } - } else if (c == '\\') { - lastCharWasEscapeChar = true; - } else { - lastCharWasEscapeChar = false; - } - res.append(c); - } else { - // We are not in a quoted string. - if (isInSingleLineComment) { - if (c == '\n') { - isInSingleLineComment = false; - // Include the line feed in the result. - res.append(c); - } - } else if (isInMultiLineComment) { - if (sql.length() > index + 1 && c == ASTERISK && sql.charAt(index + 1) == SLASH) { - isInMultiLineComment = false; - index++; - } + abstract String removeCommentsAndTrimInternal(String sql); + + @InternalApi + public String removeCommentsAndTrim(String sql) { + switch (dialect) { + case POSTGRESQL: + if (isGoogleSql(sql.trim())) { + return GSQL_STATEMENT + + INSTANCES.get(Dialect.GOOGLE_STANDARD_SQL).removeCommentsAndTrimInternal(sql); } else { - if (c == DASH - || (sql.length() > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN)) { - // This is a single line comment. - isInSingleLineComment = true; - } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERISK) { - isInMultiLineComment = true; - index++; - } else { - if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { - isInQuoted = true; - startQuote = c; - // Check whether it is a triple-quote. - if (sql.length() > index + 2 - && sql.charAt(index + 1) == startQuote - && sql.charAt(index + 2) == startQuote) { - isTripleQuoted = true; - res.append(c).append(c); - index += 2; - } - } - res.append(c); - } + return removeCommentsAndTrimInternal(sql); } - } - index++; - } - if (isInQuoted) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + case GOOGLE_STANDARD_SQL: + return removeCommentsAndTrimInternal(sql); + default: + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INTERNAL, "Unknown dialect: " + dialect); } - if (res.length() > 0 && res.charAt(res.length() - 1) == ';') { - res.deleteCharAt(res.length() - 1); - } - return res.toString().trim(); } /** Removes any statement hints at the beginning of the statement. */ - static String removeStatementHint(String sql) { - // Valid statement hints at the beginning of a query statement can only contain a fixed set of - // possible values. Although it is possible to add a @{FORCE_INDEX=...} as a statement hint, the - // only allowed value is _BASE_TABLE. This means that we can safely assume that the statement - // hint will not contain any special characters, for example a closing curly brace or one of the - // keywords SELECT, UPDATE, DELETE, WITH, and that we can keep the check simple by just - // searching for the first occurrence of a keyword that should be preceded by a closing curly - // brace at the end of the statement hint. - int startStatementHintIndex = sql.indexOf('{'); - // Statement hints are allowed for both queries and DML statements. - int startQueryIndex = -1; - String upperCaseSql = sql.toUpperCase(); - Set selectAndDmlStatements = - Sets.union(selectStatements, dmlStatements).immutableCopy(); - for (String keyword : selectAndDmlStatements) { - startQueryIndex = upperCaseSql.indexOf(keyword); - if (startQueryIndex > -1) { - break; - } + abstract String removeStatementHint(String sql); + + /** Parameter information with positional parameters translated to named parameters. */ + @InternalApi + public static class ParametersInfo { + public final int numberOfParameters; + public final String sqlWithNamedParameters; + + ParametersInfo(int numberOfParameters, String sqlWithNamedParameters) { + this.numberOfParameters = numberOfParameters; + this.sqlWithNamedParameters = sqlWithNamedParameters; + } + } + + /** + * Converts all positional parameters (?) in the given sql string into named parameters. The + * parameters are named @p1, @p2, etc. This method is used when converting a JDBC statement that + * uses positional parameters to a Cloud Spanner {@link Statement} instance that requires named + * parameters. The input SQL string may not contain any comments. There is an exception case if + * the statement starts with a GSQL comment which forces it to be interpreted as a GoogleSql + * statement. + * + * @param sql The sql string without comments that should be converted + * @return A {@link ParametersInfo} object containing a string with named parameters instead of + * positional parameters and the number of parameters. + * @throws SpannerException If the input sql string contains an unclosed string/byte literal. + */ + @InternalApi + abstract ParametersInfo convertPositionalParametersToNamedParametersInternal( + char paramChar, String sql); + + @InternalApi + public ParametersInfo convertPositionalParametersToNamedParameters(char paramChar, String sql) { + if (dialect == Dialect.POSTGRESQL && isGoogleSql(sql.trim())) { + return INSTANCES + .get(Dialect.GOOGLE_STANDARD_SQL) + .convertPositionalParametersToNamedParametersInternal(paramChar, sql); + } else { + return INSTANCES + .get(dialect) + .convertPositionalParametersToNamedParametersInternal(paramChar, sql); } - if (startQueryIndex > -1) { - int endStatementHintIndex = sql.substring(0, startQueryIndex).lastIndexOf('}'); - if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex) { - // Looks like an invalid statement hint. Just ignore at this point and let the caller handle - // the invalid query. - return sql; + } + + /** Convenience method that is used to estimate the number of parameters in a SQL statement. */ + static int countOccurrencesOf(char c, String string) { + int res = 0; + for (int i = 0; i < string.length(); i++) { + if (string.charAt(i) == c) { + res++; } - return removeCommentsAndTrim(sql.substring(endStatementHintIndex + 1)); } - // Seems invalid, just return the original statement. - return sql; + return res; } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ChecksumResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ChecksumResultSet.java index ba8f5950ae3..2c01396083e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ChecksumResultSet.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ChecksumResultSet.java @@ -26,8 +26,8 @@ import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.Type.Code; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.hash.Funnel; @@ -236,6 +236,9 @@ public void funnel(Struct row, PrimitiveSink into) { case NUMERIC: funnelValue(type, row.getBigDecimal(i), into); break; + case PG_NUMERIC: + funnelValue(type, row.getString(i), into); + break; case INT64: funnelValue(type, row.getLong(i), into); break; @@ -291,6 +294,12 @@ private void funnelArray( funnelValue(Code.NUMERIC, value, into); } break; + case PG_NUMERIC: + into.putInt(row.getStringList(columnIndex).size()); + for (String value : row.getStringList(columnIndex)) { + funnelValue(Code.STRING, value, into); + } + break; case INT64: into.putInt(row.getLongList(columnIndex).size()); for (Long value : row.getLongList(columnIndex)) { @@ -358,6 +367,7 @@ private void funnelValue(Code type, T value, PrimitiveSink into) { case INT64: into.putLong((Long) value); break; + case PG_NUMERIC: case STRING: case JSON: String stringValue = (String) value; 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 f7d8e18e911..9c74e5b9ca1 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 @@ -23,6 +23,7 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.AsyncResultSet; import com.google.cloud.spanner.CommitResponse; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.Options.QueryOption; @@ -1098,6 +1099,11 @@ default RpcPriority getRPCPriority() { */ void bufferedWrite(Iterable mutations); + /** The {@link Dialect} that is used by this {@link Connection}. */ + default Dialect getDialect() { + throw new UnsupportedOperationException("Not implemented"); + } + /** * This query option is used internally to indicate that a query is executed by the library itself * to fetch metadata. These queries are specifically allowed to be executed even when a DDL batch 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 df8caa0ff85..9cea3810a98 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 @@ -24,6 +24,7 @@ import com.google.cloud.spanner.AsyncResultSet; import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.Options; @@ -39,9 +40,9 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TimestampBound.Mode; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.StatementExecutor.StatementTimeout; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; @@ -82,7 +83,7 @@ private LeakedConnectionException() { private volatile LeakedConnectionException leakedException = new LeakedConnectionException(); private final SpannerPool spannerPool; - private final StatementParser parser = StatementParser.INSTANCE; + private final AbstractStatementParser parser; /** * The {@link ConnectionStatementExecutor} is responsible for translating parsed {@link * ClientSideStatement}s into actual method calls on this {@link ConnectionImpl}. I.e. the {@link @@ -220,6 +221,7 @@ static UnitOfWorkType of(TransactionMode transactionMode) { this.statementExecutor = new StatementExecutor(options.getStatementExecutionInterceptors()); this.spannerPool = SpannerPool.INSTANCE; this.options = options; + this.parser = AbstractStatementParser.getInstance(options.getDialect()); this.spanner = spannerPool.getSpanner(options, this); if (options.isAutoConfigEmulator()) { EmulatorUtil.maybeCreateInstanceAndDatabase(spanner, options.getDatabaseId()); @@ -249,6 +251,7 @@ static UnitOfWorkType of(TransactionMode transactionMode) { this.statementExecutor = new StatementExecutor(Collections.emptyList()); this.spannerPool = spannerPool; this.options = options; + this.parser = AbstractStatementParser.getInstance(options.getDialect()); this.spanner = spannerPool.getSpanner(options, this); this.ddlClient = ddlClient; this.dbClient = dbClient; @@ -319,6 +322,11 @@ LeakedConnectionException getLeakedException() { return leakedException; } + @Override + public Dialect getDialect() { + return options.getDialect(); + } + @Override public boolean isClosed() { return closed; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java index 47c2bad9789..eb6a430f6d0 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.connection; import com.google.api.core.InternalApi; +import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.Credentials; import com.google.auth.oauth2.AccessToken; import com.google.auth.oauth2.GoogleCredentials; @@ -24,6 +25,7 @@ import com.google.cloud.NoCredentials; import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Options.RpcPriority; import com.google.cloud.spanner.SessionPoolOptions; @@ -35,6 +37,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -156,12 +159,14 @@ public String[] getValidValues() { private static final String DEFAULT_MIN_SESSIONS = null; private static final String DEFAULT_MAX_SESSIONS = null; private static final String DEFAULT_NUM_CHANNELS = null; + private static final String DEFAULT_CHANNEL_PROVIDER = null; private static final String DEFAULT_USER_AGENT = null; private static final String DEFAULT_OPTIMIZER_VERSION = ""; private static final String DEFAULT_OPTIMIZER_STATISTICS_PACKAGE = ""; private static final RpcPriority DEFAULT_RPC_PRIORITY = null; private static final boolean DEFAULT_RETURN_COMMIT_STATS = false; private static final boolean DEFAULT_LENIENT = false; + private static final String DEFAULT_DIALECT = Dialect.GOOGLE_STANDARD_SQL.name(); private static final String PLAIN_TEXT_PROTOCOL = "http:"; private static final String HOST_PROTOCOL = "https:"; @@ -189,6 +194,8 @@ public String[] getValidValues() { public static final String MAX_SESSIONS_PROPERTY_NAME = "maxSessions"; /** Name of the 'numChannels' connection property. */ public static final String NUM_CHANNELS_PROPERTY_NAME = "numChannels"; + /** Name of the 'channelProvider' connection property. */ + public static final String CHANNEL_PROVIDER_PROPERTY_NAME = "channelProvider"; /** Custom user agent string is only for other Google libraries. */ private static final String USER_AGENT_PROPERTY_NAME = "userAgent"; /** Query optimizer version to use for a connection. */ @@ -200,6 +207,8 @@ public String[] getValidValues() { public static final String LENIENT_PROPERTY_NAME = "lenient"; /** Name of the 'rpcPriority' connection property. */ public static final String RPC_PRIORITY_NAME = "rpcPriority"; + /** Dialect to use for a connection. */ + private static final String DIALECT_PROPERTY_NAME = "dialect"; /** All valid connection properties. */ public static final Set VALID_PROPERTIES = @@ -236,6 +245,9 @@ public String[] getValidValues() { ConnectionProperty.createStringProperty( NUM_CHANNELS_PROPERTY_NAME, "The number of gRPC channels to use to communicate with Cloud Spanner. The default is 4."), + ConnectionProperty.createStringProperty( + CHANNEL_PROVIDER_PROPERTY_NAME, + "The name of the channel provider class. The name must reference an implementation of ExternalChannelProvider. If this property is not set, the connection will use the default grpc channel provider."), ConnectionProperty.createBooleanProperty( USE_PLAIN_TEXT_PROPERTY_NAME, "Use a plain text communication channel (i.e. non-TLS) for communicating with the server (true/false). Set this value to true for communication with the Cloud Spanner emulator.", @@ -259,7 +271,9 @@ public String[] getValidValues() { DEFAULT_LENIENT), ConnectionProperty.createStringProperty( RPC_PRIORITY_NAME, - "Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH.")))); + "Sets the priority for all RPC invocations from this connection (HIGH/MEDIUM/LOW). The default is HIGH."), + ConnectionProperty.createStringProperty( + DIALECT_PROPERTY_NAME, "Sets the dialect to use for this connection.")))); private static final Set INTERNAL_PROPERTIES = Collections.unmodifiableSet( @@ -311,6 +325,15 @@ interface SpannerOptionsConfigurator { void configure(SpannerOptions.Builder options); } + /** + * {@link ExternalChannelProvider} can be used for to specify an external channel provider. This + * is needed if you require different certificates than those provided by the standard grpc + * channel provider. + */ + public interface ExternalChannelProvider { + TransportChannelProvider getChannelProvider(String host, int port); + } + /** Builder for {@link ConnectionOptions} instances. */ public static class Builder { private String uri; @@ -491,10 +514,12 @@ public static Builder newBuilder() { private final Credentials credentials; private final SessionPoolOptions sessionPoolOptions; private final Integer numChannels; + private final String channelProvider; private final Integer minSessions; private final Integer maxSessions; private final String userAgent; private final QueryOptions queryOptions; + private final Dialect dialect; private final boolean returnCommitStats; private final boolean autoConfigEmulator; private final RpcPriority rpcPriority; @@ -538,6 +563,14 @@ private ConnectionOptions(Builder builder) { queryOptionsBuilder.setOptimizerStatisticsPackage(parseOptimizerStatisticsPackage(this.uri)); this.queryOptions = queryOptionsBuilder.build(); this.returnCommitStats = parseReturnCommitStats(this.uri); + + try { + this.dialect = Dialect.fromName(parseDialect(uri)); + } catch (IllegalArgumentException e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, e.getMessage(), e); + } + this.autoConfigEmulator = parseAutoConfigEmulator(this.uri); this.usePlainText = this.autoConfigEmulator || parseUsePlainText(this.uri); this.host = determineHost(matcher, autoConfigEmulator, usePlainText); @@ -569,6 +602,7 @@ private ConnectionOptions(Builder builder) { parseIntegerProperty(MAX_SESSIONS_PROPERTY_NAME, parseMaxSessions(builder.uri)); this.numChannels = parseIntegerProperty(NUM_CHANNELS_PROPERTY_NAME, parseNumChannels(builder.uri)); + this.channelProvider = parseChannelProvider(builder.uri); String projectId = matcher.group(Builder.PROJECT_GROUP); if (Builder.DEFAULT_PROJECT_ID_PLACEHOLDER.equalsIgnoreCase(projectId)) { @@ -699,6 +733,12 @@ static String parseNumChannels(String uri) { return value != null ? value : DEFAULT_NUM_CHANNELS; } + @VisibleForTesting + static String parseChannelProvider(String uri) { + String value = parseUriProperty(uri, CHANNEL_PROVIDER_PROPERTY_NAME); + return value != null ? value : DEFAULT_CHANNEL_PROVIDER; + } + @VisibleForTesting static String parseUserAgent(String uri) { String value = parseUriProperty(uri, USER_AGENT_PROPERTY_NAME); @@ -740,6 +780,12 @@ static RpcPriority parseRPCPriority(String uri) { return value != null ? RpcPriority.valueOf(value) : DEFAULT_RPC_PRIORITY; } + @VisibleForTesting + static String parseDialect(String uri) { + String value = parseUriProperty(uri, DIALECT_PROPERTY_NAME); + return value != null ? value.toUpperCase() : DEFAULT_DIALECT; + } + @VisibleForTesting static String parseUriProperty(String uri, String property) { Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); @@ -845,6 +891,25 @@ public Integer getNumChannels() { return numChannels; } + /** Calls the getChannelProvider() method from the supplied class. */ + public TransportChannelProvider getChannelProvider() { + if (channelProvider == null) { + return null; + } + try { + URL url = new URL(host); + ExternalChannelProvider provider = + ExternalChannelProvider.class.cast(Class.forName(channelProvider).newInstance()); + return provider.getChannelProvider(url.getHost(), url.getPort()); + } catch (Exception e) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + String.format( + "%s : Failed to create channel with external provider: %s", + e.toString(), channelProvider)); + } + } + /** The host and port number that this {@link ConnectionOptions} will connect to */ public String getHost() { return host; @@ -905,6 +970,11 @@ public String getWarnings() { return warnings; } + /** The dialect to use for connections created by this {@link ConnectionOptions}. */ + public Dialect getDialect() { + return dialect; + } + /** Use http instead of https. Only valid for (local) test servers. */ boolean isUsePlainText() { return usePlainText; 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 675b6e3a955..6d34c76fde8 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 @@ -16,6 +16,8 @@ package com.google.cloud.spanner.connection; +import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT; + import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.api.gax.longrunning.OperationFuture; @@ -29,10 +31,9 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.Connection.InternalMetadataQuery; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.spanner.admin.database.v1.DatabaseAdminGrpc; @@ -210,15 +211,6 @@ public ApiFuture writeAsync(Iterable mutations) { ErrorCode.FAILED_PRECONDITION, "Writing mutations is not allowed for DDL batches."); } - /** - * Create a {@link ParsedStatement} that we can use as input for the generic execute method when - * the {@link #runBatch()} method is executed. This method uses the generic execute method that - * allows statements to be cancelled and to timeout, which requires the input to be a {@link - * ParsedStatement}. - */ - private static final ParsedStatement RUN_BATCH = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - @Override public ApiFuture runBatchAsync() { ConnectionPreconditions.checkState( @@ -235,7 +227,7 @@ public ApiFuture runBatchAsync() { ddlClient.executeDdl(statements); try { // Wait until the operation has finished. - getWithStatementTimeout(operation, RUN_BATCH); + getWithStatementTimeout(operation, RUN_BATCH_STATEMENT); long[] updateCounts = new long[statements.size()]; Arrays.fill(updateCounts, 1L); state = UnitOfWorkState.RAN; @@ -252,7 +244,7 @@ public ApiFuture runBatchAsync() { }; this.state = UnitOfWorkState.RUNNING; return executeStatementAsync( - RUN_BATCH, callable, DatabaseAdminGrpc.getUpdateDatabaseDdlMethod()); + RUN_BATCH_STATEMENT, callable, DatabaseAdminGrpc.getUpdateDatabaseDdlMethod()); } long[] extractUpdateCounts(OperationFuture operation) { 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 d7bf7302434..d2224f98ad3 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 @@ -29,8 +29,8 @@ import com.google.cloud.spanner.Options.UpdateOption; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.MoreExecutors; import java.util.ArrayList; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedBatchUpdate.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedBatchUpdate.java index 6721e9b6eca..42f270d9f85 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedBatchUpdate.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedBatchUpdate.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.connection; +import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT; + import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; @@ -53,9 +55,7 @@ public void retry(AbortedException aborted) throws AbortedException { transaction .getStatementExecutor() .invokeInterceptors( - ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, - StatementExecutionStep.RETRY_STATEMENT, - transaction); + RUN_BATCH_STATEMENT, StatementExecutionStep.RETRY_STATEMENT, transaction); try { transaction.getReadContext().batchUpdate(statements); } catch (AbortedException e) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedQuery.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedQuery.java index 4a1e1b005ce..d64c4b9401f 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedQuery.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedQuery.java @@ -21,8 +21,8 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.base.Preconditions; import java.util.Objects; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedUpdate.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedUpdate.java index 836185fabeb..5c184e20d3b 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedUpdate.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/FailedUpdate.java @@ -19,8 +19,8 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.base.Preconditions; import java.util.Objects; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/PostgreSQLStatementParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/PostgreSQLStatementParser.java new file mode 100644 index 00000000000..0b29bec5333 --- /dev/null +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/PostgreSQLStatementParser.java @@ -0,0 +1,256 @@ +/* + * Copyright 2020 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 com.google.api.core.InternalApi; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.common.base.Preconditions; + +@InternalApi +public class PostgreSQLStatementParser extends AbstractStatementParser { + PostgreSQLStatementParser() { + super(Dialect.POSTGRESQL); + } + + /** + * Indicates whether the parser supports the {@code EXPLAIN} clause. The PostgreSQL parser does + * not support it. + */ + @Override + protected boolean supportsExplain() { + return false; + } + + /** + * Removes comments from and trims the given sql statement. PostgreSQL supports two types of + * comments: + * + *
    + *
  • Single line comments starting with '--' + *
  • Multi line comments between '/*' and '*/'. Nested comments are supported and all + * comments, including the nested comments, must be terminated. + *
+ * + * Reference: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-COMMENTS + * + * @param sql The sql statement to remove comments from and to trim. + * @return the sql statement without the comments and leading and trailing spaces. + */ + @InternalApi + @Override + String removeCommentsAndTrimInternal(String sql) { + Preconditions.checkNotNull(sql); + String currentTag = null; + boolean isInQuoted = false; + boolean isInSingleLineComment = false; + int multiLineCommentLevel = 0; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + StringBuilder res = new StringBuilder(sql.length()); + int index = 0; + while (index < sql.length()) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && startQuote != DOLLAR) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } else if (c == startQuote) { + if (c == DOLLAR) { + // Check if this is the end of the current dollar quoted string. + String tag = parseDollarQuotedString(sql, index + 1); + if (tag != null && tag.equals(currentTag)) { + index += tag.length() + 1; + res.append(c); + res.append(tag); + isInQuoted = false; + startQuote = 0; + } + } else if (lastCharWasEscapeChar) { + lastCharWasEscapeChar = false; + } else if (sql.length() > index + 1 && sql.charAt(index + 1) == startQuote) { + // This is an escaped quote (e.g. 'foo''bar') + res.append(c); + index++; + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + res.append(c); + } else { + // We are not in a quoted string. + if (isInSingleLineComment) { + if (c == '\n') { + isInSingleLineComment = false; + // Include the line feed in the result. + res.append(c); + } + } else if (multiLineCommentLevel > 0) { + if (sql.length() > index + 1 && c == ASTERIKS && sql.charAt(index + 1) == SLASH) { + multiLineCommentLevel--; + index++; + } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERIKS) { + multiLineCommentLevel++; + index++; + } + } else { + // Check for -- which indicates the start of a single-line comment. + if (sql.length() > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN) { + // This is a single line comment. + isInSingleLineComment = true; + } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERIKS) { + multiLineCommentLevel++; + index++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE) { + isInQuoted = true; + startQuote = c; + } else if (c == DOLLAR) { + currentTag = parseDollarQuotedString(sql, index + 1); + if (currentTag != null) { + isInQuoted = true; + startQuote = DOLLAR; + index += currentTag.length() + 1; + res.append(c); + res.append(currentTag); + } + } + res.append(c); + } + } + } + index++; + } + if (isInQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } + if (multiLineCommentLevel > 0) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, + "SQL statement contains an unterminated block comment: " + sql); + } + if (res.length() > 0 && res.charAt(res.length() - 1) == ';') { + res.deleteCharAt(res.length() - 1); + } + return res.toString().trim(); + } + + String parseDollarQuotedString(String sql, int index) { + // Look ahead to the next dollar sign (if any). Everything in between is the quote tag. + StringBuilder tag = new StringBuilder(); + while (index < sql.length()) { + char c = sql.charAt(index); + if (c == DOLLAR) { + return tag.toString(); + } + if (!Character.isJavaIdentifierPart(c)) { + break; + } + tag.append(c); + index++; + } + return null; + } + + /** PostgreSQL does not support statement hints. */ + @Override + String removeStatementHint(String sql) { + return sql; + } + + @InternalApi + @Override + ParametersInfo convertPositionalParametersToNamedParametersInternal(char paramChar, String sql) { + Preconditions.checkNotNull(sql); + final String namedParamPrefix = "$"; + String currentTag = null; + boolean isInQuoted = false; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + StringBuilder named = new StringBuilder(sql.length() + countOccurrencesOf(paramChar, sql)); + int index = 0; + int paramIndex = 1; + while (index < sql.length()) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && startQuote != DOLLAR) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } else if (c == startQuote) { + if (c == DOLLAR) { + // Check if this is the end of the current dollar quoted string. + String tag = parseDollarQuotedString(sql, index + 1); + if (tag != null && tag.equals(currentTag)) { + index += tag.length() + 1; + named.append(c); + named.append(tag); + isInQuoted = false; + startQuote = 0; + } + } else if (lastCharWasEscapeChar) { + lastCharWasEscapeChar = false; + } else if (sql.length() > index + 1 && sql.charAt(index + 1) == startQuote) { + // This is an escaped quote (e.g. 'foo''bar') + named.append(c); + index++; + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + named.append(c); + } else { + if (c == paramChar) { + named.append(namedParamPrefix + paramIndex); + paramIndex++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE) { + isInQuoted = true; + startQuote = c; + } else if (c == DOLLAR) { + currentTag = parseDollarQuotedString(sql, index + 1); + if (currentTag != null) { + isInQuoted = true; + startQuote = DOLLAR; + index += currentTag.length() + 1; + named.append(c); + named.append(currentTag); + } + } + named.append(c); + } + } + index++; + } + if (isInQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } + return new ParametersInfo(paramIndex - 1, named.toString()); + } +} diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadOnlyTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadOnlyTransaction.java index 1e1fa0cba86..f4731336674 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadOnlyTransaction.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ReadOnlyTransaction.java @@ -28,7 +28,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.common.base.Preconditions; /** 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 45b49de19b3..822eb3b0169 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 @@ -17,6 +17,10 @@ package com.google.cloud.spanner.connection; import static com.google.cloud.spanner.SpannerApiFutures.get; +import static com.google.cloud.spanner.connection.AbstractStatementParser.BEGIN_STATEMENT; +import static com.google.cloud.spanner.connection.AbstractStatementParser.COMMIT_STATEMENT; +import static com.google.cloud.spanner.connection.AbstractStatementParser.ROLLBACK_STATEMENT; +import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT; import static com.google.common.base.Preconditions.checkNotNull; import com.google.api.core.ApiFuture; @@ -40,7 +44,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TransactionContext; import com.google.cloud.spanner.TransactionManager; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.TransactionRetryListener.RetryResult; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; @@ -203,9 +207,6 @@ public boolean isReadOnly() { return false; } - private static final ParsedStatement BEGIN_STATEMENT = - StatementParser.INSTANCE.parse(Statement.of("BEGIN")); - @Override void checkValidTransaction() { checkValidState(); @@ -453,20 +454,6 @@ public void onSuccess(Long result) {} return res; } - /** - * Create a RUN BATCH statement to use with the {@link #executeBatchUpdate(Iterable)} method to - * allow it to be cancelled, time out or retried. - * - *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, - * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout - * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link - * #executeBatchUpdate(Iterable)} method is called, we do not have one {@link ParsedStatement}, - * and the method uses this statement instead in order to use the same logic as the other - * statements. - */ - static final ParsedStatement EXECUTE_BATCH_UPDATE_STATEMENT = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - @Override public ApiFuture executeBatchUpdateAsync( Iterable updates, final UpdateOption... options) { @@ -484,7 +471,7 @@ public ApiFuture executeBatchUpdateAsync( if (retryAbortsInternally) { res = executeStatementAsync( - EXECUTE_BATCH_UPDATE_STATEMENT, + RUN_BATCH_STATEMENT, () -> { checkTimedOut(); return runWithRetry( @@ -492,7 +479,7 @@ public ApiFuture executeBatchUpdateAsync( try { getStatementExecutor() .invokeInterceptors( - EXECUTE_BATCH_UPDATE_STATEMENT, + RUN_BATCH_STATEMENT, StatementExecutionStep.EXECUTE_STATEMENT, ReadWriteTransaction.this); long[] updateCounts = @@ -513,7 +500,7 @@ public ApiFuture executeBatchUpdateAsync( } else { res = executeStatementAsync( - EXECUTE_BATCH_UPDATE_STATEMENT, + RUN_BATCH_STATEMENT, () -> { checkTimedOut(); checkAborted(); @@ -548,19 +535,6 @@ public ApiFuture writeAsync(Iterable mutations) { return ApiFutures.immediateFuture(null); } - /** - * Create a COMMIT statement to use with the {@link #commit()} method to allow it to be cancelled, - * time out or retried. - * - *

{@link ReadWriteTransaction} uses the generic methods {@link #executeAsync(ParsedStatement, - * Callable)} and {@link #runWithRetry(Callable)} to allow statements to be cancelled, to timeout - * and to be retried. These methods require a {@link ParsedStatement} as input. When the {@link - * #commit()} method is called directly, we do not have a {@link ParsedStatement}, and the method - * uses this statement instead in order to use the same logic as the other statements. - */ - private static final ParsedStatement COMMIT_STATEMENT = - StatementParser.INSTANCE.parse(Statement.of("COMMIT")); - private final Callable commitCallable = new Callable() { @Override @@ -861,10 +835,6 @@ private void invokeTransactionRetryListenersOnFinish(RetryResult result) { } } - /** The {@link Statement} and {@link Callable} for rollbacks */ - private final ParsedStatement rollbackStatement = - StatementParser.INSTANCE.parse(Statement.of("ROLLBACK")); - private final Callable rollbackCallable = new Callable() { @Override @@ -890,7 +860,7 @@ public ApiFuture rollbackAsync() { state = UnitOfWorkState.ROLLED_BACK; if (txContextFuture != null && state != UnitOfWorkState.ABORTED) { return executeStatementAsync( - rollbackStatement, rollbackCallable, SpannerGrpc.getRollbackMethod()); + ROLLBACK_STATEMENT, rollbackCallable, SpannerGrpc.getRollbackMethod()); } else { return ApiFutures.immediateFuture(null); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableBatchUpdate.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableBatchUpdate.java index ad2e2b2950f..194200faae2 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableBatchUpdate.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableBatchUpdate.java @@ -16,6 +16,8 @@ package com.google.cloud.spanner.connection; +import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT; + import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.Options.UpdateOption; import com.google.cloud.spanner.SpannerException; @@ -55,9 +57,7 @@ public void retry(AbortedException aborted) throws AbortedException { transaction .getStatementExecutor() .invokeInterceptors( - ReadWriteTransaction.EXECUTE_BATCH_UPDATE_STATEMENT, - StatementExecutionStep.RETRY_STATEMENT, - transaction); + RUN_BATCH_STATEMENT, StatementExecutionStep.RETRY_STATEMENT, transaction); newCount = transaction.getReadContext().batchUpdate(statements, options); } catch (AbortedException e) { // Just re-throw the AbortedException and let the retry logic determine whether another try diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableUpdate.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableUpdate.java index 060a1aa61de..3818bdd739c 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableUpdate.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/RetriableUpdate.java @@ -20,8 +20,8 @@ import com.google.cloud.spanner.Options.UpdateOption; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ReadWriteTransaction.RetriableStatement; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.base.Preconditions; /** 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 aca72d09680..f34e6f72e71 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 @@ -16,6 +16,9 @@ package com.google.cloud.spanner.connection; +import static com.google.cloud.spanner.connection.AbstractStatementParser.COMMIT_STATEMENT; +import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT; + import com.google.api.core.ApiFuture; import com.google.api.core.SettableApiFuture; import com.google.api.gax.longrunning.OperationFuture; @@ -33,11 +36,10 @@ import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; -import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TransactionRunner; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; @@ -304,9 +306,6 @@ public ApiFuture executeUpdateAsync(ParsedStatement update, UpdateOption.. return res; } - private final ParsedStatement executeBatchUpdateStatement = - StatementParser.INSTANCE.parse(Statement.of("RUN BATCH")); - @Override public ApiFuture executeBatchUpdateAsync( Iterable updates, UpdateOption... options) { @@ -417,12 +416,9 @@ private ApiFuture executeTransactionalBatchUpdateAsync( }); }; return executeStatementAsync( - executeBatchUpdateStatement, callable, SpannerGrpc.getExecuteBatchDmlMethod()); + RUN_BATCH_STATEMENT, callable, SpannerGrpc.getExecuteBatchDmlMethod()); } - private final ParsedStatement commitStatement = - StatementParser.INSTANCE.parse(Statement.of("COMMIT")); - @Override public ApiFuture writeAsync(final Iterable mutations) { Preconditions.checkNotNull(mutations); @@ -447,7 +443,7 @@ public ApiFuture writeAsync(final Iterable mutations) { throw t; } }; - return executeStatementAsync(commitStatement, callable, SpannerGrpc.getCommitMethod()); + return executeStatementAsync(COMMIT_STATEMENT, callable, SpannerGrpc.getCommitMethod()); } @Override diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java index 3d433adf87d..479b10df2e5 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.connection; import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SessionPoolOptions; import com.google.cloud.spanner.Spanner; @@ -152,6 +153,7 @@ static class SpannerPoolKey { private final Integer numChannels; private final boolean usePlainText; private final String userAgent; + private final Dialect dialect; @VisibleForTesting static SpannerPoolKey of(ConnectionOptions options) { @@ -169,6 +171,7 @@ private SpannerPoolKey(ConnectionOptions options) { this.numChannels = options.getNumChannels(); this.usePlainText = options.isUsePlainText(); this.userAgent = options.getUserAgent(); + this.dialect = options.getDialect(); } @Override @@ -183,7 +186,8 @@ public boolean equals(Object o) { && Objects.equals(this.sessionPoolOptions, other.sessionPoolOptions) && Objects.equals(this.numChannels, other.numChannels) && Objects.equals(this.usePlainText, other.usePlainText) - && Objects.equals(this.userAgent, other.userAgent); + && Objects.equals(this.userAgent, other.userAgent) + && Objects.equals(this.dialect, other.dialect); } @Override @@ -195,7 +199,8 @@ public int hashCode() { this.sessionPoolOptions, this.numChannels, this.usePlainText, - this.userAgent); + this.userAgent, + this.dialect); } } @@ -321,11 +326,15 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) { .setClientLibToken(MoreObjects.firstNonNull(key.userAgent, CONNECTION_API_CLIENT_LIB_TOKEN)) .setHost(key.host) .setProjectId(key.projectId) - .setCredentials(options.getCredentials()); + .setCredentials(options.getCredentials()) + .setDialect(options.getDialect()); builder.setSessionPoolOption(key.sessionPoolOptions); if (key.numChannels != null) { builder.setNumChannels(key.numChannels); } + if (options.getChannelProvider() != null) { + builder.setChannelProvider(options.getChannelProvider()); + } if (key.usePlainText) { // Credentials may not be sent over a plain text channel. builder.setCredentials(NoCredentials.getInstance()); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerStatementParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerStatementParser.java new file mode 100644 index 00000000000..a9c7624f273 --- /dev/null +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerStatementParser.java @@ -0,0 +1,249 @@ +/* + * Copyright 2022 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 com.google.api.core.InternalApi; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerExceptionFactory; +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; +import java.util.Set; + +@InternalApi +public class SpannerStatementParser extends AbstractStatementParser { + + public SpannerStatementParser() { + super(Dialect.GOOGLE_STANDARD_SQL); + } + + /** + * Indicates whether the parser supports the {@code EXPLAIN} clause. The Spanner parser does + * support it. + */ + @Override + protected boolean supportsExplain() { + return true; + } + + /** + * Removes comments from and trims the given sql statement. Spanner supports three types of + * comments: + * + *

    + *
  • Single line comments starting with '--' + *
  • Single line comments starting with '#' + *
  • Multi line comments between '/*' and '*/' + *
+ * + * Reference: https://cloud.google.com/spanner/docs/lexical#comments + * + * @param sql The sql statement to remove comments from and to trim. + * @return the sql statement without the comments and leading and trailing spaces. + */ + @InternalApi + @Override + String removeCommentsAndTrimInternal(String sql) { + Preconditions.checkNotNull(sql); + boolean isInQuoted = false; + boolean isInSingleLineComment = false; + boolean isInMultiLineComment = false; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + boolean isTripleQuoted = false; + StringBuilder res = new StringBuilder(sql.length()); + int index = 0; + while (index < sql.length()) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && !isTripleQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } else if (c == startQuote) { + if (lastCharWasEscapeChar) { + // TODO: Is this correct inside of a triple-quoted string? + lastCharWasEscapeChar = false; + } else if (isTripleQuoted) { + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isInQuoted = false; + startQuote = 0; + isTripleQuoted = false; + res.append(c).append(c); + index += 2; + } + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + res.append(c); + } else { + // We are not in a quoted string. + if (isInSingleLineComment) { + if (c == '\n') { + isInSingleLineComment = false; + // Include the line feed in the result. + res.append(c); + } + } else if (isInMultiLineComment) { + if (sql.length() > index + 1 && c == ASTERIKS && sql.charAt(index + 1) == SLASH) { + isInMultiLineComment = false; + index++; + } + } else { + if (c == DASH + || (sql.length() > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN)) { + // This is a single line comment. + isInSingleLineComment = true; + } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERIKS) { + isInMultiLineComment = true; + index++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { + isInQuoted = true; + startQuote = c; + // Check whether it is a triple-quote. + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isTripleQuoted = true; + res.append(c).append(c); + index += 2; + } + } + res.append(c); + } + } + } + index++; + } + if (isInQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } + if (res.length() > 0 && res.charAt(res.length() - 1) == ';') { + res.deleteCharAt(res.length() - 1); + } + return res.toString().trim(); + } + + /** Removes any statement hints at the beginning of the statement. */ + @Override + String removeStatementHint(String sql) { + // Valid statement hints at the beginning of a query statement can only contain a fixed set of + // possible values. Although it is possible to add a @{FORCE_INDEX=...} as a statement hint, the + // only allowed value is _BASE_TABLE. This means that we can safely assume that the statement + // hint will not contain any special characters, for example a closing curly brace or one of the + // keywords SELECT, UPDATE, DELETE, WITH, and that we can keep the check simple by just + // searching for the first occurrence of a keyword that should be preceded by a closing curly + // brace at the end of the statement hint. + int startStatementHintIndex = sql.indexOf('{'); + // Statement hints are allowed for both queries and DML statements. + int startQueryIndex = -1; + String upperCaseSql = sql.toUpperCase(); + Set selectAndDmlStatements = + Sets.union(selectStatements, dmlStatements).immutableCopy(); + for (String keyword : selectAndDmlStatements) { + startQueryIndex = upperCaseSql.indexOf(keyword); + if (startQueryIndex > -1) { + break; + } + } + if (startQueryIndex > -1) { + int endStatementHintIndex = sql.substring(0, startQueryIndex).lastIndexOf('}'); + if (startStatementHintIndex == -1 || startStatementHintIndex > endStatementHintIndex) { + // Looks like an invalid statement hint. Just ignore at this point and let the caller handle + // the invalid query. + return sql; + } + return removeCommentsAndTrim(sql.substring(endStatementHintIndex + 1)); + } + // Seems invalid, just return the original statement. + return sql; + } + + @InternalApi + @Override + ParametersInfo convertPositionalParametersToNamedParametersInternal(char paramChar, String sql) { + final char SINGLE_QUOTE = '\''; + final char DOUBLE_QUOTE = '"'; + final char BACKTICK_QUOTE = '`'; + boolean isInQuoted = false; + char startQuote = 0; + boolean lastCharWasEscapeChar = false; + boolean isTripleQuoted = false; + int paramIndex = 1; + StringBuilder named = new StringBuilder(sql.length() + countOccurrencesOf(paramChar, sql)); + for (int index = 0; index < sql.length(); index++) { + char c = sql.charAt(index); + if (isInQuoted) { + if ((c == '\n' || c == '\r') && !isTripleQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } else if (c == startQuote) { + if (lastCharWasEscapeChar) { + lastCharWasEscapeChar = false; + } else if (isTripleQuoted) { + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isInQuoted = false; + startQuote = 0; + isTripleQuoted = false; + } + } else { + isInQuoted = false; + startQuote = 0; + } + } else if (c == '\\') { + lastCharWasEscapeChar = true; + } else { + lastCharWasEscapeChar = false; + } + named.append(c); + } else { + if (c == paramChar) { + named.append("@p" + paramIndex); + paramIndex++; + } else { + if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE || c == BACKTICK_QUOTE) { + isInQuoted = true; + startQuote = c; + // check whether it is a triple-quote + if (sql.length() > index + 2 + && sql.charAt(index + 1) == startQuote + && sql.charAt(index + 2) == startQuote) { + isTripleQuoted = true; + } + } + named.append(c); + } + } + } + if (isInQuoted) { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.INVALID_ARGUMENT, "SQL statement contains an unclosed literal: " + sql); + } + return new ParametersInfo(paramIndex - 1, named.toString()); + } +} diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutionInterceptor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutionInterceptor.java index 159edc3e3d4..a2eaa99a5cb 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutionInterceptor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutionInterceptor.java @@ -17,7 +17,7 @@ package com.google.cloud.spanner.connection; import com.google.cloud.spanner.ResultSet; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; /** Interface for interceptors that are invoked before a statement is executed. */ interface StatementExecutionInterceptor { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutor.java index 821ebb1f288..438fc749fdc 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/StatementExecutor.java @@ -18,8 +18,8 @@ import com.google.api.core.ApiFuture; import com.google.api.core.ListenableFutureToApiFuture; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ReadOnlyStalenessUtil.DurationValueGetter; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.util.concurrent.ListeningExecutorService; 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 0bf6fff9f27..cf68f4ddaf3 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 @@ -27,7 +27,7 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.TransactionContext; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.spanner.v1.ResultSetStats; import java.util.concurrent.ExecutionException; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java index 4558559faa2..98a7e0927f3 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java @@ -175,6 +175,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; @@ -187,6 +189,8 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nullable; import org.threeten.bp.Duration; @@ -578,18 +582,19 @@ private static void maybeEnableGrpcGcpExtension( } private static HeaderProvider headerProviderWithUserAgentFrom(HeaderProvider headerProvider) { + final Optional> existingUserAgentEntry = + headerProvider.getHeaders().entrySet().stream() + .filter(entry -> entry.getKey().equalsIgnoreCase(USER_AGENT_KEY)) + .findFirst(); + final String existingUserAgentValue = existingUserAgentEntry.map(Entry::getValue).orElse(null); + final String userAgent = + Stream.of(existingUserAgentValue, DEFAULT_USER_AGENT) + .filter(Objects::nonNull) + .collect(Collectors.joining(" ")); + final Map headersWithUserAgent = new HashMap<>(headerProvider.getHeaders()); - String userAgent = null; - for (Entry entry : headersWithUserAgent.entrySet()) { - if (entry.getKey().equalsIgnoreCase(USER_AGENT_KEY)) { - userAgent = entry.getValue(); - headersWithUserAgent.remove(entry.getKey()); - break; - } - } - headersWithUserAgent.put( - USER_AGENT_KEY, - userAgent == null ? DEFAULT_USER_AGENT : userAgent + " " + DEFAULT_USER_AGENT); + existingUserAgentEntry.ifPresent(entry -> headersWithUserAgent.remove(entry.getKey())); + headersWithUserAgent.put(USER_AGENT_KEY, userAgent); return FixedHeaderProvider.create(headersWithUserAgent); } @@ -1045,9 +1050,7 @@ public OperationFuture createDatabase( Iterable additionalStatements, com.google.cloud.spanner.Database databaseInfo) throws SpannerException { - final String databaseId = - createDatabaseStatement.substring( - "CREATE DATABASE `".length(), createDatabaseStatement.length() - 1); + final String databaseId = databaseInfo.getId().getDatabase(); CreateDatabaseRequest.Builder requestBuilder = CreateDatabaseRequest.newBuilder() .setParent(instanceName) @@ -1057,6 +1060,9 @@ public OperationFuture createDatabase( requestBuilder.setEncryptionConfig( EncryptionConfigProtoMapper.encryptionConfig(databaseInfo.getEncryptionConfig())); } + if (databaseInfo.getDialect() != null) { + requestBuilder.setDatabaseDialect(databaseInfo.getDialect().toProto()); + } final CreateDatabaseRequest request = requestBuilder.build(); OperationFutureCallable callable = diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/testing/RemoteSpannerHelper.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/testing/RemoteSpannerHelper.java index f6021b2a7d6..b3e9abf0740 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/testing/RemoteSpannerHelper.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/testing/RemoteSpannerHelper.java @@ -20,14 +20,18 @@ import com.google.cloud.spanner.BatchClient; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.InstanceId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.SpannerOptions; +import com.google.common.collect.Iterables; import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; @@ -93,7 +97,7 @@ public InstanceId getInstanceId() { * accordingly. */ public Database createTestDatabase(String... statements) throws SpannerException { - return createTestDatabase(Arrays.asList(statements)); + return createTestDatabase(Dialect.GOOGLE_STANDARD_SQL, Arrays.asList(statements)); } /** @@ -115,14 +119,28 @@ public String getUniqueBackupId() { * DATABASE ...} statement should not be included; an appropriate name will be chosen and the * statement generated accordingly. */ - public Database createTestDatabase(Iterable statements) throws SpannerException { + public Database createTestDatabase(Dialect dialect, Iterable statements) + throws SpannerException { String dbId = getUniqueDatabaseId(); + Database databaseToCreate = + client + .getDatabaseAdminClient() + .newDatabaseBuilder( + DatabaseId.of(instanceId.getProject(), instanceId.getInstance(), dbId)) + .setDialect(dialect) + .build(); try { + Iterable ddlStatements = + dialect == Dialect.POSTGRESQL ? Collections.emptyList() : statements; OperationFuture op = - client - .getDatabaseAdminClient() - .createDatabase(instanceId.getInstance(), dbId, statements); + client.getDatabaseAdminClient().createDatabase(databaseToCreate, ddlStatements); Database db = op.get(); + if (dialect == Dialect.POSTGRESQL && Iterables.size(statements) > 0) { + client + .getDatabaseAdminClient() + .updateDatabaseDdl(instanceId.getInstance(), dbId, statements, null) + .get(); + } logger.log(Level.FINE, "Created test database {0}", db.getId()); dbs.add(db); return db; @@ -131,6 +149,10 @@ public Database createTestDatabase(Iterable statements) throws SpannerEx } } + public Database createTestDatabase(Iterable statements) throws SpannerException { + return createTestDatabase(Dialect.GOOGLE_STANDARD_SQL, statements); + } + /** Deletes all the databases created via {@code createTestDatabase}. Shuts down the client. */ public void cleanUp() { // Drop all the databases we created explicitly. diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java index 7bb8bb51943..10167ddc9d0 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractStructReaderTypesTest.java @@ -200,6 +200,13 @@ public static Collection parameters() { "getBigDecimal", Collections.singletonList("getValue") }, + { + Type.pgNumeric(), + "getStringInternal", + "1.23", + "getString", + Collections.singletonList("getValue") + }, { Type.string(), "getStringInternal", @@ -284,6 +291,13 @@ public static Collection parameters() { "getBigDecimalList", Collections.singletonList("getValue") }, + { + Type.array(Type.pgNumeric()), + "getStringListInternal", + Arrays.asList("1.23", "2.34"), + "getStringList", + Collections.singletonList("getValue") + }, { Type.array(Type.string()), "getStringListInternal", diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java index 4d44861b75b..44a531d4a34 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientImplTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner; import static com.google.common.truth.Truth.assertThat; +import static com.google.spanner.admin.database.v1.DatabaseDialect.GOOGLE_STANDARD_SQL; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -46,6 +47,7 @@ import com.google.spanner.admin.database.v1.CreateBackupMetadata; import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import com.google.spanner.admin.database.v1.Database; +import com.google.spanner.admin.database.v1.DatabaseDialect; import com.google.spanner.admin.database.v1.EncryptionInfo; import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; @@ -77,6 +79,7 @@ public class DatabaseAdminClientImplTest { private static final String KMS_KEY_NAME = "projects/my-project/locations/some-location/keyRings/my-keyring/cryptoKeys/my-key"; private static final String KMS_KEY_VERSION = "1"; + private static final DatabaseDialect DIALECT = GOOGLE_STANDARD_SQL; @Mock SpannerRpc rpc; DatabaseAdminClientImpl client; @@ -93,6 +96,7 @@ private Database getDatabaseProto() { .setState(Database.State.READY) .setEarliestVersionTime(EARLIEST_VERSION_TIME.toProto()) .setVersionRetentionPeriod(VERSION_RETENTION_PERIOD) + .setDatabaseDialect(DIALECT) .build(); } @@ -161,8 +165,11 @@ public void createDatabase() throws Exception { INSTANCE_NAME, "CREATE DATABASE `" + DB_ID + "`", Collections.emptyList(), - new com.google.cloud.spanner.Database( - DatabaseId.of(DB_NAME), State.UNSPECIFIED, client))) + client + .newDatabaseBuilder(DatabaseId.of(DB_NAME)) + .setState(State.UNSPECIFIED) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) + .build())) .thenReturn(rawOperationFuture); OperationFuture op = client.createDatabase(INSTANCE_ID, DB_ID, Collections.emptyList()); @@ -176,6 +183,7 @@ public void createEncryptedDatabase() throws Exception { client .newDatabaseBuilder(DatabaseId.of(DB_NAME)) .setEncryptionConfig(EncryptionConfigs.customerManagedEncryption(KMS_KEY_NAME)) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) .build(); OperationFuture rawOperationFuture = diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java index d1e8d2e31f5..bd09d131a61 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseTest.java @@ -19,6 +19,7 @@ import static com.google.cloud.spanner.DatabaseInfo.State.CREATING; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -31,6 +32,7 @@ import com.google.cloud.spanner.encryption.EncryptionConfigs; import com.google.rpc.Code; import com.google.rpc.Status; +import com.google.spanner.admin.database.v1.DatabaseDialect; import com.google.spanner.admin.database.v1.EncryptionInfo; import java.util.Collections; import java.util.List; @@ -63,6 +65,7 @@ public class DatabaseTest { .setKmsKeyVersion(KMS_KEY_VERSION) .build()); private static final String DEFAULT_LEADER = "default-leader"; + private static final DatabaseDialect DEFAULT_DIALECT = DatabaseDialect.GOOGLE_STANDARD_SQL; @Mock DatabaseAdminClient dbClient; @@ -100,15 +103,42 @@ public void listDatabaseOperations() { } @Test - public void fromProto() { - Database db = createDatabase(); - assertEquals(NAME, db.getId().getName()); - assertEquals(CREATING, db.getState()); - assertEquals(VERSION_RETENTION_PERIOD, db.getVersionRetentionPeriod()); - assertEquals(EARLIEST_VERSION_TIME, db.getEarliestVersionTime()); + public void testFromProto() { + final Database database = createDatabase(); + assertEquals(NAME, database.getId().getName()); + assertEquals(CREATING, database.getState()); + assertEquals(VERSION_RETENTION_PERIOD, database.getVersionRetentionPeriod()); + assertEquals(EARLIEST_VERSION_TIME, database.getEarliestVersionTime()); assertEquals( - EncryptionConfigs.customerManagedEncryption(KMS_KEY_NAME), db.getEncryptionConfig()); - assertEquals(DEFAULT_LEADER, db.getDefaultLeader()); + EncryptionConfigs.customerManagedEncryption(KMS_KEY_NAME), database.getEncryptionConfig()); + assertEquals(DEFAULT_LEADER, database.getDefaultLeader()); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, database.getDialect()); + } + + @Test + public void testUnspecifiedDialectDefaultsToGoogleStandardSqlDialect() { + final Database database = + Database.fromProto( + defaultProtoDatabase() + .toBuilder() + .setDatabaseDialect(DatabaseDialect.DATABASE_DIALECT_UNSPECIFIED) + .build(), + dbClient); + + assertEquals(Dialect.GOOGLE_STANDARD_SQL, database.getDialect()); + } + + @Test + public void testUnrecognizedDialectThrowsException() { + assertThrows( + IllegalArgumentException.class, + () -> + Database.fromProto( + defaultProtoDatabase() + .toBuilder() + .setDatabaseDialect(DatabaseDialect.UNRECOGNIZED) + .build(), + dbClient)); } @Test @@ -137,6 +167,17 @@ public void testBuildWithDefaultLeader() { assertEquals(DEFAULT_LEADER, db.getDefaultLeader()); } + @Test + public void testBuildWithDatabaseDialect() { + final Database database = + dbClient + .newDatabaseBuilder(DatabaseId.of("my-project", "my-instance", "my-database")) + .setDialect(Dialect.GOOGLE_STANDARD_SQL) + .build(); + + assertEquals(Dialect.GOOGLE_STANDARD_SQL, database.getDialect()); + } + @Test public void getIAMPolicy() { Database database = @@ -177,16 +218,19 @@ public void testEqualsAndHashCode() { } private Database createDatabase() { - com.google.spanner.admin.database.v1.Database proto = - com.google.spanner.admin.database.v1.Database.newBuilder() - .setName(NAME) - .setState(com.google.spanner.admin.database.v1.Database.State.CREATING) - .setEarliestVersionTime(EARLIEST_VERSION_TIME.toProto()) - .setVersionRetentionPeriod(VERSION_RETENTION_PERIOD) - .setEncryptionConfig(ENCRYPTION_CONFIG) - .addAllEncryptionInfo(ENCRYPTION_INFOS) - .setDefaultLeader(DEFAULT_LEADER) - .build(); - return Database.fromProto(proto, dbClient); + return Database.fromProto(defaultProtoDatabase(), dbClient); + } + + private com.google.spanner.admin.database.v1.Database defaultProtoDatabase() { + return com.google.spanner.admin.database.v1.Database.newBuilder() + .setName(NAME) + .setState(com.google.spanner.admin.database.v1.Database.State.CREATING) + .setEarliestVersionTime(EARLIEST_VERSION_TIME.toProto()) + .setVersionRetentionPeriod(VERSION_RETENTION_PERIOD) + .setEncryptionConfig(ENCRYPTION_CONFIG) + .addAllEncryptionInfo(ENCRYPTION_INFOS) + .setDefaultLeader(DEFAULT_LEADER) + .setDatabaseDialect(DEFAULT_DIALECT) + .build(); } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DialectTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DialectTest.java new file mode 100644 index 00000000000..01c0bc38fc9 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DialectTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2022 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import com.google.spanner.admin.database.v1.DatabaseDialect; +import org.junit.Test; + +public class DialectTest { + + @Test + public void testCreateDatabaseStatementForGoogleStandardSQLDialect() { + assertEquals( + "CREATE DATABASE `my-database`", + Dialect.GOOGLE_STANDARD_SQL.createDatabaseStatementFor("my-database")); + } + + @Test + public void testCreateDatabaseStatementForPostgreSQLDialect() { + assertEquals( + "CREATE DATABASE \"my-database\"", + Dialect.POSTGRESQL.createDatabaseStatementFor("my-database")); + } + + @Test + public void testGoogleStandardSQLDialectToProto() { + assertEquals(DatabaseDialect.GOOGLE_STANDARD_SQL, Dialect.GOOGLE_STANDARD_SQL.toProto()); + } + + @Test + public void testPostgreSQLToProto() { + assertEquals(DatabaseDialect.POSTGRESQL, Dialect.POSTGRESQL.toProto()); + } + + @Test + public void testFromGoogleStandardSQLDialectProto() { + assertEquals( + Dialect.GOOGLE_STANDARD_SQL, Dialect.fromProto(DatabaseDialect.GOOGLE_STANDARD_SQL)); + } + + @Test + public void testFromUnspecifiedDialectProto() { + assertEquals( + Dialect.GOOGLE_STANDARD_SQL, + Dialect.fromProto(DatabaseDialect.DATABASE_DIALECT_UNSPECIFIED)); + } + + @Test + public void testFromPostgreSQLDialectProto() { + assertEquals(Dialect.POSTGRESQL, Dialect.fromProto(DatabaseDialect.POSTGRESQL)); + } + + @Test + public void testFromUnrecognizedDialectProto() { + assertThrows( + IllegalArgumentException.class, () -> Dialect.fromProto(DatabaseDialect.UNRECOGNIZED)); + } + + @Test + public void testFromNullDialectProto() { + assertThrows( + IllegalArgumentException.class, () -> Dialect.fromProto(DatabaseDialect.UNRECOGNIZED)); + } + + @Test + public void testFromGoogleStandardSQLDialectName() { + assertEquals(Dialect.GOOGLE_STANDARD_SQL, Dialect.fromName("GOOGLE_STANDARD_SQL")); + } + + @Test + public void testFromPostgreSQLDialectName() { + assertEquals(Dialect.POSTGRESQL, Dialect.fromName("POSTGRESQL")); + } + + @Test + public void testFromInvalidDialectName() { + assertThrows(IllegalArgumentException.class, () -> Dialect.fromName("INVALID")); + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java index 4ebe92798ec..a307e23db22 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java @@ -71,6 +71,7 @@ import com.google.spanner.v1.TransactionOptions.ReadWrite; import com.google.spanner.v1.TransactionSelector; import com.google.spanner.v1.Type; +import com.google.spanner.v1.TypeAnnotationCode; import com.google.spanner.v1.TypeCode; import io.grpc.Metadata; import io.grpc.ServerServiceDefinition; @@ -79,6 +80,7 @@ import io.grpc.protobuf.ProtoUtils; import io.grpc.protobuf.lite.ProtoLiteUtils; import io.grpc.stub.StreamObserver; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -1176,84 +1178,99 @@ private Statement buildStatement( String sql, Map paramTypes, com.google.protobuf.Struct params) { Statement.Builder builder = Statement.newBuilder(sql); for (Entry entry : paramTypes.entrySet()) { - com.google.protobuf.Value value = params.getFieldsOrThrow(entry.getKey()); + final String fieldName = entry.getKey(); + final Type fieldType = entry.getValue(); + final Type elementType = fieldType.getArrayElementType(); + com.google.protobuf.Value value = params.getFieldsOrThrow(fieldName); if (value.getKindCase() == KindCase.NULL_VALUE) { - switch (entry.getValue().getCode()) { + switch (fieldType.getCode()) { case ARRAY: - switch (entry.getValue().getArrayElementType().getCode()) { + switch (elementType.getCode()) { case BOOL: - builder.bind(entry.getKey()).toBoolArray((Iterable) null); + builder.bind(fieldName).toBoolArray((Iterable) null); break; case BYTES: - builder.bind(entry.getKey()).toBytesArray(null); + builder.bind(fieldName).toBytesArray(null); break; case DATE: - builder.bind(entry.getKey()).toDateArray(null); + builder.bind(fieldName).toDateArray(null); break; case FLOAT64: - builder.bind(entry.getKey()).toFloat64Array((Iterable) null); + builder.bind(fieldName).toFloat64Array((Iterable) null); break; case INT64: - builder.bind(entry.getKey()).toInt64Array((Iterable) null); + builder.bind(fieldName).toInt64Array((Iterable) null); break; case STRING: - builder.bind(entry.getKey()).toStringArray(null); + builder.bind(fieldName).toStringArray(null); + break; + case NUMERIC: + if (elementType.getTypeAnnotation() == TypeAnnotationCode.PG_NUMERIC) { + builder.bind(fieldName).toPgNumericArray(null); + } else { + builder.bind(fieldName).toNumericArray(null); + } break; case TIMESTAMP: - builder.bind(entry.getKey()).toTimestampArray(null); + builder.bind(fieldName).toTimestampArray(null); break; case JSON: - builder.bind(entry.getKey()).toJsonArray(null); + builder.bind(fieldName).toJsonArray(null); break; case STRUCT: case TYPE_CODE_UNSPECIFIED: case UNRECOGNIZED: default: throw new IllegalArgumentException( - "Unknown or invalid array parameter type: " - + entry.getValue().getArrayElementType().getCode()); + "Unknown or invalid array parameter type: " + elementType.getCode()); } break; case BOOL: - builder.bind(entry.getKey()).to((Boolean) null); + builder.bind(fieldName).to((Boolean) null); break; case BYTES: - builder.bind(entry.getKey()).to((ByteArray) null); + builder.bind(fieldName).to((ByteArray) null); break; case DATE: - builder.bind(entry.getKey()).to((Date) null); + builder.bind(fieldName).to((Date) null); break; case FLOAT64: - builder.bind(entry.getKey()).to((Double) null); + builder.bind(fieldName).to((Double) null); break; case INT64: - builder.bind(entry.getKey()).to((Long) null); + builder.bind(fieldName).to((Long) null); break; case STRING: - builder.bind(entry.getKey()).to((String) null); + builder.bind(fieldName).to((String) null); + break; + case NUMERIC: + if (fieldType.getTypeAnnotation() == TypeAnnotationCode.PG_NUMERIC) { + builder.bind(fieldName).to(Value.pgNumeric(null)); + } else { + builder.bind(fieldName).to((BigDecimal) null); + } break; case STRUCT: - builder.bind(entry.getKey()).to((Struct) null); + builder.bind(fieldName).to((Struct) null); break; case TIMESTAMP: - builder.bind(entry.getKey()).to((com.google.cloud.Timestamp) null); + builder.bind(fieldName).to((com.google.cloud.Timestamp) null); break; case JSON: - builder.bind(entry.getKey()).to(Value.json((String) null)); + builder.bind(fieldName).to(Value.json(null)); break; case TYPE_CODE_UNSPECIFIED: case UNRECOGNIZED: default: - throw new IllegalArgumentException( - "Unknown parameter type: " + entry.getValue().getCode()); + throw new IllegalArgumentException("Unknown parameter type: " + fieldType.getCode()); } } else { - switch (entry.getValue().getCode()) { + switch (fieldType.getCode()) { case ARRAY: - switch (entry.getValue().getArrayElementType().getCode()) { + switch (elementType.getCode()) { case BOOL: builder - .bind(entry.getKey()) + .bind(fieldName) .toBoolArray( (Iterable) GrpcStruct.decodeArrayValue( @@ -1261,7 +1278,7 @@ private Statement buildStatement( break; case BYTES: builder - .bind(entry.getKey()) + .bind(fieldName) .toBytesArray( (Iterable) GrpcStruct.decodeArrayValue( @@ -1269,7 +1286,7 @@ private Statement buildStatement( break; case DATE: builder - .bind(entry.getKey()) + .bind(fieldName) .toDateArray( (Iterable) GrpcStruct.decodeArrayValue( @@ -1277,7 +1294,7 @@ private Statement buildStatement( break; case FLOAT64: builder - .bind(entry.getKey()) + .bind(fieldName) .toFloat64Array( (Iterable) GrpcStruct.decodeArrayValue( @@ -1285,7 +1302,7 @@ private Statement buildStatement( break; case INT64: builder - .bind(entry.getKey()) + .bind(fieldName) .toInt64Array( (Iterable) GrpcStruct.decodeArrayValue( @@ -1293,15 +1310,32 @@ private Statement buildStatement( break; case STRING: builder - .bind(entry.getKey()) + .bind(fieldName) .toStringArray( (Iterable) GrpcStruct.decodeArrayValue( com.google.cloud.spanner.Type.string(), value.getListValue())); break; + case NUMERIC: + if (elementType.getTypeAnnotation() == TypeAnnotationCode.PG_NUMERIC) { + builder + .bind(fieldName) + .toPgNumericArray( + (Iterable) + GrpcStruct.decodeArrayValue( + com.google.cloud.spanner.Type.pgNumeric(), value.getListValue())); + } else { + builder + .bind(fieldName) + .toNumericArray( + (Iterable) + GrpcStruct.decodeArrayValue( + com.google.cloud.spanner.Type.numeric(), value.getListValue())); + } + break; case TIMESTAMP: builder - .bind(entry.getKey()) + .bind(fieldName) .toTimestampArray( (Iterable) GrpcStruct.decodeArrayValue( @@ -1309,7 +1343,7 @@ private Statement buildStatement( break; case JSON: builder - .bind(entry.getKey()) + .bind(fieldName) .toJsonArray( (Iterable) GrpcStruct.decodeArrayValue( @@ -1320,43 +1354,48 @@ private Statement buildStatement( case UNRECOGNIZED: default: throw new IllegalArgumentException( - "Unknown or invalid array parameter type: " - + entry.getValue().getArrayElementType().getCode()); + "Unknown or invalid array parameter type: " + elementType.getCode()); } break; case BOOL: - builder.bind(entry.getKey()).to(value.getBoolValue()); + builder.bind(fieldName).to(value.getBoolValue()); break; case BYTES: - builder.bind(entry.getKey()).to(ByteArray.fromBase64(value.getStringValue())); + builder.bind(fieldName).to(ByteArray.fromBase64(value.getStringValue())); break; case DATE: - builder.bind(entry.getKey()).to(Date.parseDate(value.getStringValue())); + builder.bind(fieldName).to(Date.parseDate(value.getStringValue())); break; case FLOAT64: - builder.bind(entry.getKey()).to(value.getNumberValue()); + builder.bind(fieldName).to(value.getNumberValue()); break; case INT64: - builder.bind(entry.getKey()).to(Long.valueOf(value.getStringValue())); + builder.bind(fieldName).to(Long.valueOf(value.getStringValue())); break; case STRING: - builder.bind(entry.getKey()).to(value.getStringValue()); + builder.bind(fieldName).to(value.getStringValue()); + break; + case NUMERIC: + if (fieldType.getTypeAnnotation() == TypeAnnotationCode.PG_NUMERIC) { + builder.bind(fieldName).to(Value.pgNumeric(value.getStringValue())); + } else { + builder.bind(fieldName).to(new BigDecimal(value.getStringValue())); + } break; case STRUCT: throw new IllegalArgumentException("Struct parameters not (yet) supported"); case TIMESTAMP: builder - .bind(entry.getKey()) + .bind(fieldName) .to(com.google.cloud.Timestamp.parseTimestamp(value.getStringValue())); break; case JSON: - builder.bind(entry.getKey()).to(Value.json(value.getStringValue())); + builder.bind(fieldName).to(Value.json(value.getStringValue())); break; case TYPE_CODE_UNSPECIFIED: case UNRECOGNIZED: default: - throw new IllegalArgumentException( - "Unknown parameter type: " + entry.getValue().getCode()); + throw new IllegalArgumentException("Unknown parameter type: " + fieldType.getCode()); } } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java index 372b2de3034..eb96334b509 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MutationTest.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.testing.EqualsTester; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -512,54 +513,99 @@ private Mutation.WriteBuilder appendAllTypes(Mutation.WriteBuilder builder) { .to(true) .set("boolNull") .to((Boolean) null) + .set("boolValue") + .to(Value.bool(false)) .set("int") .to(42) .set("intNull") .to((Long) null) + .set("intValue") + .to(Value.int64(1L)) .set("float") .to(42.1) .set("floatNull") .to((Double) null) + .set("floatValue") + .to(Value.float64(10D)) .set("string") .to("str") .set("stringNull") .to((String) null) + .set("stringValue") + .to(Value.string("strValue")) + .set("bigDecimal") + .to(BigDecimal.valueOf(123, 2)) + .set("bigDecimalNull") + .to((BigDecimal) null) + .set("bigDecimalValueAsNumeric") + .to(Value.numeric(BigDecimal.TEN)) + .set("pgNumericValue") + .to(Value.pgNumeric("4.2")) + .set("timestamp") + .to(Timestamp.MAX_VALUE) + .set("timestampNull") + .to((Timestamp) null) + .set("timestampValue") + .to(Value.timestamp(Timestamp.MIN_VALUE)) + .set("date") + .to(Date.fromYearMonthDay(2017, 4, 17)) + .set("dateNull") + .to((Date) null) + .set("dateValue") + .to(Value.date(Date.fromYearMonthDay(2021, 1, 2))) .set("boolArr") .toBoolArray(new boolean[] {true, false}) .set("boolArrNull") .toBoolArray((boolean[]) null) + .set("boolArrValue") + .to(Value.boolArray(ImmutableList.of(false, true))) .set("intArr") .toInt64Array(new long[] {1, 2, 3}) .set("intArrNull") .toInt64Array((long[]) null) + .set("intArrValue") + .to(Value.int64Array(ImmutableList.of(1L, 2L))) .set("floatArr") .toFloat64Array(new double[] {1.1, 2.2, 3.3}) .set("floatArrNull") .toFloat64Array((double[]) null) - .set("nullStr") - .to((String) null) - .set("timestamp") - .to(Timestamp.MAX_VALUE) - .set("timestampNull") - .to((Timestamp) null) - .set("date") - .to(Date.fromYearMonthDay(2017, 4, 17)) - .set("dateNull") - .to((Date) null) + .set("floatArrValue") + .to(Value.float64Array(ImmutableList.of(10.1D, 10.2D, 10.3D))) .set("stringArr") .toStringArray(ImmutableList.of("one", "two")) .set("stringArrNull") .toStringArray(null) + .set("stringArrValue") + .to(Value.stringArray(ImmutableList.of("uno", "dos"))) + .set("numericArr") + .toNumericArray(ImmutableList.of(BigDecimal.ONE, BigDecimal.TEN)) + .set("numericArrNull") + .toNumericArray(null) + .set("numericArrValue") + .to(Value.numericArray(ImmutableList.of(BigDecimal.ZERO, BigDecimal.valueOf(234, 2)))) + .set("pgNumericArr") + .toPgNumericArray(ImmutableList.of("1.23", "2.34")) + .set("pgNumericArrNull") + .toPgNumericArray(null) + .set("pgNumericArrValue") + .to(Value.pgNumericArray(ImmutableList.of("10.20", "20.30"))) .set("timestampArr") .toTimestampArray(ImmutableList.of(Timestamp.MAX_VALUE, Timestamp.MAX_VALUE)) .set("timestampArrNull") .toTimestampArray(null) + .set("timestampArrValue") + .to(Value.timestampArray(ImmutableList.of(Timestamp.MIN_VALUE, Timestamp.MAX_VALUE))) .set("dateArr") .toDateArray( ImmutableList.of( Date.fromYearMonthDay(2017, 4, 17), Date.fromYearMonthDay(2017, 4, 18))) .set("dateArrNull") - .toDateArray(null); + .toDateArray(null) + .set("dateArrValue") + .to( + Value.dateArray( + ImmutableList.of( + Date.fromYearMonthDay(2021, 1, 2), Date.fromYearMonthDay(2022, 2, 3)))); } static Matcher matchesProto(String expected) { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java new file mode 100644 index 00000000000..77369f5371b --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/PgNumericTest.java @@ -0,0 +1,372 @@ +/* + * Copyright 2022 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult; +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.ListValue; +import com.google.protobuf.NullValue; +import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteSqlRequest; +import com.google.spanner.v1.ResultSetMetadata; +import com.google.spanner.v1.StructType; +import com.google.spanner.v1.StructType.Field; +import com.google.spanner.v1.TypeAnnotationCode; +import com.google.spanner.v1.TypeCode; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Server; +import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class PgNumericTest { + + private static final String PROJECT = "my-project"; + private static final String INSTANCE = "my-instance"; + private static final String DATABASE = "database"; + private static final ResultSetMetadata RESULT_SET_METADATA = + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("PgNumeric") + .setType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC) + .build())) + .addFields( + Field.newBuilder() + .setName("PgNumericArray") + .setType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.ARRAY) + .setArrayElementType( + com.google.spanner.v1.Type.newBuilder() + .setCode(TypeCode.NUMERIC) + .setTypeAnnotation(TypeAnnotationCode.PG_NUMERIC)) + .build())) + .build()) + .build(); + private static MockSpannerServiceImpl mockSpanner; + private static InetSocketAddress address; + private static Server server; + private Spanner spanner; + private DatabaseClient databaseClient; + + @BeforeClass + public static void beforeClass() throws Exception { + mockSpanner = new MockSpannerServiceImpl(); + mockSpanner.setAbortProbability(0.0D); + + address = new InetSocketAddress("localhost", 0); + server = NettyServerBuilder.forAddress(address).addService(mockSpanner).build().start(); + } + + @AfterClass + public static void afterClass() throws Exception { + server.shutdown(); + server.awaitTermination(); + } + + @Before + public void setUp() throws Exception { + final String endpoint = address.getHostString() + ":" + server.getPort(); + spanner = + SpannerOptions.newBuilder() + .setProjectId(PROJECT) + .setChannelConfigurator(ManagedChannelBuilder::usePlaintext) + .setHost("https://" + endpoint) + .setCredentials(NoCredentials.getInstance()) + .setSessionPoolOption(SessionPoolOptions.newBuilder().setFailOnSessionLeak().build()) + .build() + .getService(); + databaseClient = spanner.getDatabaseClient(DatabaseId.of(PROJECT, INSTANCE, DATABASE)); + } + + @After + public void tearDown() throws Exception { + spanner.close(); + mockSpanner.removeAllExecutionTimes(); + mockSpanner.reset(); + } + + @Test + public void testQueryNoNullsAsStrings() { + final Statement statement = + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 0"); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues(com.google.protobuf.Value.newBuilder().setStringValue("1.23")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("2.34")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("3.45")) + .build())) + .build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = + databaseClient + .singleUse() + .executeQuery( + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 0"))) { + resultSet.next(); + + assertEquals("1.23", resultSet.getString("PgNumeric")); + assertEquals("1.23", resultSet.getString(0)); + assertEquals(Arrays.asList("2.34", "3.45"), resultSet.getStringList("PgNumericArray")); + assertEquals(Arrays.asList("2.34", "3.45"), resultSet.getStringList(1)); + } + } + + @Test + public void testQueryNoNullsAsValues() { + final Statement statement = + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 0"); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues(com.google.protobuf.Value.newBuilder().setStringValue("1.23")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("2.34")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("3.45")) + .build())) + .build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = databaseClient.singleUse().executeQuery(statement)) { + resultSet.next(); + + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("PgNumeric")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue(0)); + assertEquals( + Value.pgNumericArray(Arrays.asList("2.34", "3.45")), + resultSet.getValue("PgNumericArray")); + assertEquals(Value.pgNumericArray(Arrays.asList("2.34", "3.45")), resultSet.getValue(1)); + } + } + + @Test + public void testQueryNullElements() { + final Statement statement = + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 3"); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE)) + .addValues( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("1.23")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE)) + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("2.34")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE)) + .build())) + .build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = databaseClient.singleUse().executeQuery(statement)) { + resultSet.next(); + + assertEquals( + Value.pgNumericArray(Arrays.asList("1.23", null, "2.34", null)), + resultSet.getValue("PgNumericArray")); + assertEquals( + Value.pgNumericArray(Arrays.asList("1.23", null, "2.34", null)), resultSet.getValue(1)); + } + } + + @Test + public void testQueryNaNs() { + final Statement statement = + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 2"); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues(com.google.protobuf.Value.newBuilder().setStringValue("NaN")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("NaN")) + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue("NaN")) + .build())) + .build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = databaseClient.singleUse().executeQuery(statement)) { + resultSet.next(); + + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("PgNumeric")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue(0)); + assertEquals( + Value.pgNumericArray(Arrays.asList("NaN", "NaN")), resultSet.getValue("PgNumericArray")); + assertEquals(Value.pgNumericArray(Arrays.asList("NaN", "NaN")), resultSet.getValue(1)); + } + } + + @Test + public void testQueryNulls() { + final Statement statement = + Statement.of("SELECT PgNumeric, PgNumericArray FROM Table WHERE Id = 1"); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE)) + .addValues( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE)) + .build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = databaseClient.singleUse().executeQuery(statement)) { + resultSet.next(); + + assertTrue(resultSet.isNull("PgNumeric")); + assertTrue(resultSet.isNull(0)); + assertTrue(resultSet.isNull("PgNumericArray")); + assertTrue(resultSet.isNull(1)); + } + } + + @Test + public void testMutation() { + final List mutations = + Collections.singletonList( + Mutation.newInsertBuilder("Table") + .set("PgNumeric") + .to("1.23") + .set("PgNumericNull") + .to((String) null) + .set("PgNumericNaN") + .to("NaN") + .set("PgNumericValue") + .to(Value.pgNumeric("2.34")) + .set("PgNumericArray") + .toStringArray(Arrays.asList("2.34", null, "3.45")) + .set("PgNumericArrayNull") + .toStringArray(null) + .build()); + final List expectedMutations = new ArrayList<>(); + Mutation.toProto(mutations, expectedMutations); + + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer(mutations); + return null; + }); + + final List requests = mockSpanner.getRequestsOfType(CommitRequest.class); + final CommitRequest request = requests.get(0); + assertEquals(1, requests.size()); + assertEquals(expectedMutations, request.getMutationsList()); + } + + @Test + public void testParameterizedStatement() { + final Statement statement = + Statement.newBuilder("SELECT * FROM Table WHERE PgNumeric IN (@col1, @col2, @col3)") + .bind("col1") + .to(Value.pgNumeric("1.23")) + .bind("col2") + .to(Value.pgNumeric("NaN")) + .bind("col3") + .to(Value.pgNumeric(null)) + .build(); + final com.google.spanner.v1.ResultSet result = + com.google.spanner.v1.ResultSet.newBuilder() + .setMetadata(RESULT_SET_METADATA) + .addRows(ListValue.newBuilder().build()) + .build(); + mockSpanner.putStatementResult(StatementResult.query(statement, result)); + + try (ResultSet resultSet = databaseClient.singleUse().executeQuery(statement)) { + resultSet.next(); + + final List requests = + mockSpanner.getRequestsOfType(ExecuteSqlRequest.class); + final ExecuteSqlRequest request = requests.get(0); + + assertEquals(1, requests.size()); + assertEquals( + ImmutableMap.of( + "col1", Type.pgNumeric().toProto(), + "col2", Type.pgNumeric().toProto(), + "col3", Type.pgNumeric().toProto()), + request.getParamTypesMap()); + } + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java index fc82954ad40..80a542c5305 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java @@ -81,6 +81,7 @@ public void defaultBuilder() { } assertThat(options.getPrefetchChunks()).isEqualTo(4); assertThat(options.getSessionLabels()).isNull(); + assertThat(options.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); } @Test @@ -95,11 +96,13 @@ public void builder() { .setProjectId(projectId) .setPrefetchChunks(2) .setSessionLabels(labels) + .setDialect(Dialect.POSTGRESQL) .build(); assertThat(options.getHost()).isEqualTo(host); assertThat(options.getProjectId()).isEqualTo(projectId); assertThat(options.getPrefetchChunks()).isEqualTo(2); assertThat(options.getSessionLabels()).containsExactlyEntriesIn(labels); + assertThat(options.getDialect()).isEqualTo(Dialect.POSTGRESQL); } @Test diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java index 75e49cc642f..d357a14f9d0 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StructTest.java @@ -22,6 +22,7 @@ import com.google.common.testing.EqualsTester; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; @@ -206,6 +207,32 @@ public void equalsAndHashCode() { tester.addEqualityGroup(emptyFieldStruct1, emptyFieldStruct2); tester.testEquals(); + + // PgNumeric + tester.addEqualityGroup( + Struct.newBuilder().set("x").to(Value.pgNumeric("1.23")).build(), + Struct.newBuilder().set("x").to(Value.pgNumeric("1.23")).build()); + tester.addEqualityGroup( + Struct.newBuilder().set("x").to(Value.pgNumeric("NaN")).build(), + Struct.newBuilder().set("x").to(Value.pgNumeric("NaN")).build()); + tester.addEqualityGroup( + Struct.newBuilder().set("x").to(Value.pgNumeric(null)).build(), + Struct.newBuilder().set("x").to(Value.pgNumeric(null)).build()); + tester.addEqualityGroup( + Struct.newBuilder() + .set("x") + .to(Value.pgNumericArray(Arrays.asList(null, "1.23", "NaN"))) + .build(), + Struct.newBuilder() + .set("x") + .to(Value.pgNumericArray(Arrays.asList(null, "1.23", "NaN"))) + .build()); + tester.addEqualityGroup( + Struct.newBuilder().set("x").to(Value.pgNumericArray(Collections.emptyList())).build(), + Struct.newBuilder().set("x").to(Value.pgNumericArray(Collections.emptyList())).build()); + tester.addEqualityGroup( + Struct.newBuilder().set("x").to(Value.pgNumericArray(null)).build(), + Struct.newBuilder().set("x").to(Value.pgNumericArray(null)).build()); } @Test diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TypeTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TypeTest.java index afbf273bf89..7dfe9f3a985 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TypeTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TypeTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertThrows; import com.google.cloud.spanner.Type.Code; +import com.google.spanner.v1.TypeAnnotationCode; import com.google.spanner.v1.TypeCode; import org.hamcrest.MatcherAssert; import org.junit.Test; @@ -34,12 +35,21 @@ public class TypeTest { private abstract static class ScalarTypeTester { - final Type.Code expectedCode; - final TypeCode expectedProtoCode; + private final Type.Code expectedCode; + private final TypeCode expectedTypeCode; + private final TypeAnnotationCode expectedTypeAnnotationCode; - ScalarTypeTester(Type.Code expectedCode, TypeCode expectedProtoCode) { + ScalarTypeTester(Type.Code expectedCode, TypeCode expectedTypeCode) { + this(expectedCode, expectedTypeCode, TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED); + } + + ScalarTypeTester( + Type.Code expectedCode, + TypeCode expectedTypeCode, + TypeAnnotationCode expectedTypeAnnotationCode) { this.expectedCode = expectedCode; - this.expectedProtoCode = expectedProtoCode; + this.expectedTypeCode = expectedTypeCode; + this.expectedTypeAnnotationCode = expectedTypeAnnotationCode; } abstract Type newType(); @@ -49,10 +59,17 @@ void test() { assertThat(t.getCode()).isEqualTo(expectedCode); assertThat(newType()).isSameInstanceAs(t); // Interned. // String form is deliberately the same as the corresponding type enum in the public API. - assertThat(t.toString()).isEqualTo(expectedProtoCode.toString()); + if (expectedTypeAnnotationCode != TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED) { + assertThat(t.toString()) + .isEqualTo( + expectedTypeCode.toString() + "<" + expectedTypeAnnotationCode.toString() + ">"); + } else { + assertThat(t.toString()).isEqualTo(expectedTypeCode.toString()); + } com.google.spanner.v1.Type proto = t.toProto(); - assertThat(proto.getCode()).isEqualTo(expectedProtoCode); + assertThat(proto.getCode()).isEqualTo(expectedTypeCode); + assertThat(proto.getTypeAnnotation()).isEqualTo(expectedTypeAnnotationCode); assertThat(proto.hasArrayElementType()).isFalse(); assertThat(proto.hasStructType()).isFalse(); @@ -105,6 +122,16 @@ Type newType() { }.test(); } + @Test + public void pgNumeric() { + new ScalarTypeTester(Type.Code.PG_NUMERIC, TypeCode.NUMERIC, TypeAnnotationCode.PG_NUMERIC) { + @Override + Type newType() { + return Type.pgNumeric(); + } + }.test(); + } + @Test public void string() { new ScalarTypeTester(Type.Code.STRING, TypeCode.STRING) { @@ -156,14 +183,28 @@ Type newType() { } abstract static class ArrayTypeTester { - final Type.Code expectedElementCode; - final TypeCode expectedElementProtoCode; - final boolean expectInterned; + private final Type.Code expectedElementCode; + private final TypeCode expectedElementTypeCode; + private final TypeAnnotationCode expectedTypeAnnotationCode; + private final boolean expectInterned; + + ArrayTypeTester( + Type.Code expectedElementCode, TypeCode expectedElementTypeCode, boolean expectInterned) { + this( + expectedElementCode, + expectedElementTypeCode, + TypeAnnotationCode.TYPE_ANNOTATION_CODE_UNSPECIFIED, + expectInterned); + } - protected ArrayTypeTester( - Type.Code expectedElementCode, TypeCode expectedElementProtoCode, boolean expectInterned) { + ArrayTypeTester( + Type.Code expectedElementCode, + TypeCode expectedElementTypeCode, + TypeAnnotationCode expectedTypeAnnotationCode, + boolean expectInterned) { this.expectedElementCode = expectedElementCode; - this.expectedElementProtoCode = expectedElementProtoCode; + this.expectedElementTypeCode = expectedElementTypeCode; + this.expectedTypeAnnotationCode = expectedTypeAnnotationCode; this.expectInterned = expectInterned; } @@ -234,6 +275,17 @@ Type newElementType() { }.test(); } + @Test + public void pgNumericArray() { + new ArrayTypeTester( + Type.Code.PG_NUMERIC, TypeCode.NUMERIC, TypeAnnotationCode.PG_NUMERIC, true) { + @Override + Type newElementType() { + return Type.pgNumeric(); + } + }.test(); + } + @Test public void stringArray() { new ArrayTypeTester(Type.Code.STRING, TypeCode.STRING, true) { @@ -296,25 +348,36 @@ Type newElementType() { @Test public void struct() { - Type t = Type.struct(StructField.of("f1", Type.int64()), StructField.of("f2", Type.string())); + Type t = + Type.struct( + StructField.of("f1", Type.int64()), + StructField.of("f2", Type.string()), + StructField.of("f3", Type.pgNumeric())); assertThat(t.getCode()).isEqualTo(Type.Code.STRUCT); // Exercise StructField equality. assertThat(t.getStructFields()) - .containsExactly(StructField.of("f1", Type.int64()), StructField.of("f2", Type.string())) + .containsExactly( + StructField.of("f1", Type.int64()), + StructField.of("f2", Type.string()), + StructField.of("f3", Type.pgNumeric())) .inOrder(); // Exercise StructField getters. assertThat(t.getStructFields().get(0).getName()).isEqualTo("f1"); assertThat(t.getStructFields().get(0).getType()).isEqualTo(Type.int64()); assertThat(t.getStructFields().get(1).getName()).isEqualTo("f2"); assertThat(t.getStructFields().get(1).getType()).isEqualTo(Type.string()); - assertThat(t.toString()).isEqualTo("STRUCT"); + assertThat(t.getStructFields().get(2).getName()).isEqualTo("f3"); + assertThat(t.getStructFields().get(2).getType()).isEqualTo(Type.pgNumeric()); + assertThat(t.toString()).isEqualTo("STRUCT>"); assertThat(t.getFieldIndex("f1")).isEqualTo(0); assertThat(t.getFieldIndex("f2")).isEqualTo(1); + assertThat(t.getFieldIndex("f3")).isEqualTo(2); assertProtoEquals( t.toProto(), "code: STRUCT struct_type { fields { name: 'f1' type { code: INT64 } }" - + " fields { name: 'f2' type { code: STRING } } }"); + + " fields { name: 'f2' type { code: STRING } } " + + " fields { name: 'f3' type { code: NUMERIC, type_annotation: PG_NUMERIC } } }"); } @Test diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java index bc1674e5a0f..122f5582736 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueBinderTest.java @@ -37,6 +37,8 @@ @RunWith(JUnit4.class) public class ValueBinderTest { private static final String JSON_METHOD_NAME = "json"; + private static final String PG_NUMERIC_METHOD_NAME = "pgNumeric"; + public static final String DEFAULT_PG_NUMERIC = "1.23"; private Value lastValue; private int lastReturnValue; @@ -120,6 +122,10 @@ public void reflection() // ValueBinder.to(Value) binderMethod = ValueBinder.class.getMethod("to", Value.class); assertThat(binderMethod.invoke(binder, Value.json(null))).isEqualTo(lastReturnValue); + } else if (method.getName().equalsIgnoreCase(PG_NUMERIC_METHOD_NAME)) { + binderMethod = ValueBinder.class.getMethod("to", Value.class); + assertThat(binderMethod.invoke(binder, Value.pgNumeric(null))) + .isEqualTo(lastReturnValue); } else { assertThat(binderMethod.invoke(binder, (Object) null)).isEqualTo(lastReturnValue); } @@ -136,6 +142,11 @@ public void reflection() binderMethod = ValueBinder.class.getMethod("to", Value.class); assertThat(binderMethod.invoke(binder, Value.json(defaultJson()))) .isEqualTo(lastReturnValue); + } else if (method.getName().equalsIgnoreCase(PG_NUMERIC_METHOD_NAME)) { + defaultObject = DEFAULT_PG_NUMERIC; + binderMethod = ValueBinder.class.getMethod("to", Value.class); + assertThat(binderMethod.invoke(binder, Value.pgNumeric(DEFAULT_PG_NUMERIC))) + .isEqualTo(lastReturnValue); } else { defaultObject = DefaultValues.getDefault(method.getGenericParameterTypes()[0]); assertThat(binderMethod.invoke(binder, defaultObject)).isEqualTo(lastReturnValue); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java index 7c2d7d0a95f..a350fe68469 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/ValueTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -174,6 +175,28 @@ public void numeric() { assertThat(v.toString()).isEqualTo("1.23"); } + @Test + public void pgNumeric() { + final Value value = Value.pgNumeric("1234.5678"); + assertEquals(Type.pgNumeric(), value.getType()); + assertFalse("pgNumeric value should not be null", value.isNull()); + assertEquals("1234.5678", value.getString()); + assertEquals(BigDecimal.valueOf(12345678, 4), value.getNumeric()); + assertEquals(1234.5678D, value.getFloat64(), 0.00001); + assertEquals("1234.5678", value.toString()); + } + + @Test + public void pgNumericNaN() { + final Value value = Value.pgNumeric("NaN"); + assertEquals(Type.pgNumeric(), value.getType()); + assertFalse("pgNumeric value should not be null", value.isNull()); + assertEquals("NaN", value.getString()); + assertThrows(NumberFormatException.class, value::getNumeric); + assertEquals(Double.NaN, value.getFloat64(), 0.00001); + assertEquals("NaN", value.toString()); + } + @Test public void testNumericFormats() { // The following is copied from the Numeric proto documentation. @@ -331,6 +354,33 @@ public void numericNull() { assertThat(e.getMessage()).contains("null value"); } + @Test + public void pgNumericNull() { + final Value value = Value.pgNumeric(null); + assertEquals(Type.pgNumeric(), value.getType()); + assertTrue("pgNumeric value should be null", value.isNull()); + assertEquals(NULL_STRING, value.toString()); + + final IllegalStateException e1 = assertThrows(IllegalStateException.class, value::getString); + assertTrue("exception should mention value is null", e1.getMessage().contains("null value")); + final IllegalStateException e2 = assertThrows(IllegalStateException.class, value::getNumeric); + assertTrue("exception should mention value is null", e2.getMessage().contains("null value")); + final IllegalStateException e3 = assertThrows(IllegalStateException.class, value::getFloat64); + assertTrue("exception should mention value is null", e3.getMessage().contains("null value")); + } + + @Test + public void pgNumericInvalid() { + final Value value = Value.pgNumeric("INVALID"); + assertEquals(Type.pgNumeric(), value.getType()); + assertFalse("pgNumeric value should not be null", value.isNull()); + assertEquals("INVALID", value.toString()); + + assertEquals("INVALID", value.getString()); + assertThrows(NumberFormatException.class, value::getNumeric); + assertThrows(NumberFormatException.class, value::getFloat64); + } + @Test public void string() { Value v = Value.string("abc"); @@ -682,6 +732,32 @@ public void numericArray() { assertThat(v.toString()).isEqualTo("[0.1,NULL,0.3]"); } + @Test + public void pgNumericArray() { + final Value value = Value.pgNumericArray(Arrays.asList("1.23", null, "1.24")); + assertFalse("pgNumericArray value should not be null", value.isNull()); + assertEquals(Arrays.asList("1.23", null, "1.24"), value.getStringArray()); + assertEquals( + Arrays.asList(new BigDecimal("1.23"), null, new BigDecimal("1.24")), + value.getNumericArray()); + final List float64Array = value.getFloat64Array(); + assertEquals(1.23D, float64Array.get(0), 0.001); + assertNull(float64Array.get(1)); + assertEquals(1.24D, float64Array.get(2), 0.001); + } + + @Test + public void pgNumericArrayWithNaNs() { + final Value value = Value.pgNumericArray(Arrays.asList("1.23", null, Value.NAN)); + assertFalse("pgNumericArray value should not be null", value.isNull()); + assertEquals(Arrays.asList("1.23", null, "NaN"), value.getStringArray()); + assertThrows(NumberFormatException.class, value::getNumericArray); + final List float64Array = value.getFloat64Array(); + assertEquals(1.23D, float64Array.get(0), 0.001); + assertNull(float64Array.get(1)); + assertEquals(Double.NaN, float64Array.get(2), 0.001); + } + @Test public void numericArrayNull() { Value v = Value.numericArray(null); @@ -692,6 +768,23 @@ public void numericArrayNull() { assertThat(e.getMessage()).contains("null value"); } + @Test + public void pgNumericArrayNull() { + final Value value = Value.pgNumericArray(null); + assertTrue("pgNumericArray value should be null", value.isNull()); + assertEquals(NULL_STRING, value.toString()); + + final IllegalStateException e1 = + assertThrows(IllegalStateException.class, value::getStringArray); + assertTrue("exception should mention value is null", e1.getMessage().contains("null value")); + final IllegalStateException e2 = + assertThrows(IllegalStateException.class, value::getNumericArray); + assertTrue("exception should mention value is null", e2.getMessage().contains("null value")); + final IllegalStateException e3 = + assertThrows(IllegalStateException.class, value::getFloat64Array); + assertTrue("exception should mention value is null", e3.getMessage().contains("null value")); + } + @Test public void numericArrayTryGetInt64Array() { Value value = Value.numericArray(Collections.singletonList(BigDecimal.valueOf(1, 1))); @@ -700,6 +793,16 @@ public void numericArrayTryGetInt64Array() { assertThat(e.getMessage()).contains("Expected: ARRAY actual: ARRAY"); } + @Test + public void pgNumericArrayTryGetInt64Array() { + final Value value = Value.pgNumericArray(Collections.singletonList("1.23")); + + final IllegalStateException e = assertThrows(IllegalStateException.class, value::getInt64Array); + assertTrue( + "exception should mention type expectation", + e.getMessage().contains("Expected: ARRAY actual: ARRAY>")); + } + @Test public void stringArray() { Value v = Value.stringArray(Arrays.asList("a", null, "c")); @@ -1046,6 +1149,13 @@ public void testValueToProto() { com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(), Value.numeric(null).toProto()); + assertEquals( + com.google.protobuf.Value.newBuilder().setStringValue("1234.5678").build(), + Value.pgNumeric("1234.5678").toProto()); + assertEquals( + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(), + Value.pgNumeric(null).toProto()); + assertEquals( com.google.protobuf.Value.newBuilder().setStringValue("2010-02-28").build(), Value.date(Date.fromYearMonthDay(2010, 2, 28)).toProto()); @@ -1150,6 +1260,19 @@ public void testValueToProto() { .build()))) .build(), Value.numericArray(Arrays.asList(new BigDecimal("3.14"), null)).toProto()); + assertEquals( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addAllValues( + Arrays.asList( + com.google.protobuf.Value.newBuilder().setStringValue("1.23").build(), + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build(), + com.google.protobuf.Value.newBuilder().setStringValue("NaN").build()))) + .build(), + Value.pgNumericArray(Arrays.asList("1.23", null, Value.NAN)).toProto()); assertEquals( com.google.protobuf.Value.newBuilder() .setListValue( @@ -1380,6 +1503,45 @@ public void testValueToProto() { Timestamp.parseTimestamp("2012-04-10T15:16:17.123456789Z"), null))) .build()) .toProto()); + // Struct with pgNumeric + assertEquals( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder().setStringValue("1.23").build()) + .build()) + .build(), + Value.struct(Struct.newBuilder().set("x").to(Value.pgNumeric("1.23")).build()).toProto()); + // Struct with pgNumeric Array + assertEquals( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setListValue( + ListValue.newBuilder() + .addAllValues( + Arrays.asList( + com.google.protobuf.Value.newBuilder() + .setNullValue(NullValue.NULL_VALUE) + .build(), + com.google.protobuf.Value.newBuilder() + .setStringValue("1.23") + .build(), + com.google.protobuf.Value.newBuilder() + .setStringValue("NaN") + .build())) + .build()) + .build()) + .build()) + .build(), + Value.struct( + Struct.newBuilder() + .add(Value.pgNumericArray(Arrays.asList(null, "1.23", "NaN"))) + .build()) + .toProto()); } @Test @@ -1405,6 +1567,11 @@ public void testEqualsHashCode() { tester.addEqualityGroup(Value.numeric(BigDecimal.valueOf(456, 2))); tester.addEqualityGroup(Value.numeric(null)); + tester.addEqualityGroup(Value.pgNumeric("1234.5678"), Value.pgNumeric("1234.5678")); + tester.addEqualityGroup(Value.pgNumeric("NaN"), Value.pgNumeric(Value.NAN)); + tester.addEqualityGroup(Value.pgNumeric("8765.4321")); + tester.addEqualityGroup(Value.pgNumeric(null)); + tester.addEqualityGroup(Value.string("abc"), Value.string("abc")); tester.addEqualityGroup(Value.string("def")); tester.addEqualityGroup(Value.string(null)); @@ -1471,6 +1638,12 @@ public void testEqualsHashCode() { Value.numericArray(Collections.singletonList(BigDecimal.valueOf(3, 1)))); tester.addEqualityGroup(Value.numericArray(null)); + tester.addEqualityGroup( + Value.pgNumericArray(Arrays.asList("1.23", null, Value.NAN)), + Value.pgNumericArray(Arrays.asList("1.23", null, "NaN"))); + tester.addEqualityGroup(Value.pgNumericArray(Collections.singletonList("1.25"))); + tester.addEqualityGroup(Value.pgNumericArray(null), Value.pgNumericArray(null)); + tester.addEqualityGroup( Value.stringArray(Arrays.asList("a", "b")), Value.stringArray(Arrays.asList("a", "b"))); tester.addEqualityGroup(Value.stringArray(Collections.singletonList("c"))); @@ -1529,6 +1702,10 @@ public void serialization() { reserializeAndAssert(Value.numeric(BigDecimal.valueOf(123, 2))); reserializeAndAssert(Value.numeric(null)); + reserializeAndAssert(Value.pgNumeric("1.23")); + reserializeAndAssert(Value.pgNumeric(Value.NAN)); + reserializeAndAssert(Value.pgNumeric(null)); + reserializeAndAssert(Value.string("abc")); reserializeAndAssert(Value.string(null)); @@ -1569,6 +1746,11 @@ public void serialization() { BigDecimal.valueOf(1, 1), BigDecimal.valueOf(2, 1), BigDecimal.valueOf(3, 1)))); reserializeAndAssert(Value.numericArray(null)); + reserializeAndAssert(Value.pgNumericArray(Arrays.asList("1.23", null, Value.NAN))); + reserializeAndAssert( + Value.pgNumericArray(BrokenSerializationList.of("1.23", "1.24", Value.NAN))); + reserializeAndAssert(Value.pgNumericArray(null)); + reserializeAndAssert(Value.timestamp(null)); reserializeAndAssert(Value.timestamp(Value.COMMIT_TIMESTAMP)); reserializeAndAssert(Value.timestamp(Timestamp.now())); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractConnectionImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractConnectionImplTest.java index 9fda9c68bbb..06b2c0cf891 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractConnectionImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractConnectionImplTest.java @@ -33,7 +33,7 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptTest.java new file mode 100644 index 00000000000..11e27802214 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2022 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 com.google.cloud.NoCredentials; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; +import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; +import com.google.common.base.Preconditions; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public abstract class AbstractSqlScriptTest { + + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + static class TestConnectionProvider implements GenericConnectionProvider { + final Dialect dialect; + + TestConnectionProvider(Dialect dialect) { + this.dialect = Preconditions.checkNotNull(dialect); + } + + @Override + public GenericConnection getConnection() { + return SpannerGenericConnection.of( + ConnectionImplTest.createConnection( + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri(ConnectionImplTest.URI + ";dialect=" + dialect.name()) + .build())); + } + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptVerifier.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptVerifier.java index ccf36449be3..ec40c8c0d0b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptVerifier.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractSqlScriptVerifier.java @@ -26,6 +26,7 @@ import static org.junit.Assert.fail; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; @@ -136,6 +137,8 @@ public abstract static class GenericConnection implements AutoCloseable { @Override public abstract void close() throws Exception; + + public abstract Dialect getDialect(); } /** @@ -309,7 +312,7 @@ public void verifyStatementsInFile( + " ---- verifying statement:"); System.out.println(sql); } - verifyStatement(variables, connection, sql); + verifyStatement(variables, connection, sql, connection.getDialect()); } connection.close(); } catch (Exception e) { @@ -339,10 +342,14 @@ private List> toBatches(List statements) { } private void verifyStatement( - Map variables, GenericConnection connection, String statement) + Map variables, + GenericConnection connection, + String statement, + Dialect dialect) throws Exception { statement = replaceVariables(variables, statement); - String statementWithoutComments = StatementParser.removeCommentsAndTrim(statement); + String statementWithoutComments = + AbstractStatementParser.getInstance(dialect).removeCommentsAndTrim(statement); Matcher verifyMatcher = VERIFY_PATTERN.matcher(statementWithoutComments); Matcher putMatcher = PUT_PATTERN.matcher(statementWithoutComments); if (verifyMatcher.matches()) { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ClientSideStatementsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ClientSideStatementsTest.java index eab14248149..629d8bbc6c7 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ClientSideStatementsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ClientSideStatementsTest.java @@ -16,11 +16,7 @@ package com.google.cloud.spanner.connection; -import com.google.cloud.NoCredentials; import com.google.cloud.spanner.ErrorCode; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; @@ -31,8 +27,6 @@ import java.util.regex.Pattern; import org.junit.AfterClass; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; /** * Test that runs a pre-generated sql script for {@link ClientSideStatement}s. The sql script can be @@ -43,12 +37,11 @@ *

This class does not need to be implemented for the client libraries of other programming * languages. All test cases are covered by the sql file ClientSideStatementsTest.sql. */ -@RunWith(JUnit4.class) -public class ClientSideStatementsTest { +public class ClientSideStatementsTest extends AbstractSqlScriptTest { @Test public void testExecuteClientSideStatementsScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile("ClientSideStatementsTest.sql", getClass(), true); } @@ -110,18 +103,6 @@ public static void closeLog() { } } - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } - /** Generates test statements for all {@link ClientSideStatement}s */ private static void generateTestStatements(ClientSideStatementImpl statement) { for (String sql : statement.getExampleStatements()) { @@ -145,7 +126,7 @@ private static void generateTestStatements(ClientSideStatementImpl statement) { log( statement.getExamplePrerequisiteStatements(), withInvalidSuffix(sql), - ErrorCode.INVALID_ARGUMENT); + statement.isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); final String[] replacements = { "%", "_", "&", "$", "@", "!", "*", "(", ")", "-", "+", "-#", "/", "\\", "?", "-/", "/#", @@ -159,11 +140,11 @@ private static void generateTestStatements(ClientSideStatementImpl statement) { log( statement.getExamplePrerequisiteStatements(), withSuffix(replacement, sql), - ErrorCode.INVALID_ARGUMENT); + statement.isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); log( statement.getExamplePrerequisiteStatements(), replaceLastSpaceWith(replacement, sql), - ErrorCode.INVALID_ARGUMENT); + statement.isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); } } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadOnlyTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadOnlyTest.java index dd4692a72dd..246dc03bb12 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadOnlyTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadOnlyTest.java @@ -20,7 +20,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import java.util.concurrent.TimeUnit; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadWriteTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadWriteTest.java index 78c21a3233b..48eeb5a96d0 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadWriteTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplAutocommitReadWriteTest.java @@ -20,7 +20,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.java index bfa023c1ddc..61ba525efdb 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.java @@ -16,10 +16,6 @@ package com.google.cloud.spanner.connection; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.ClassPath; import com.google.common.reflect.ClassPath.ClassInfo; @@ -30,8 +26,6 @@ import org.junit.Test; import org.junit.runner.JUnitCore; import org.junit.runner.Result; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; /** * This test executes a SQL script that has been generated from the log of all the subclasses of @@ -45,24 +39,11 @@ * not allowed in AUTOCOMMIT mode, but this has changed to be a no-op). A new test script must also * be generated if additional test cases have been added to {@link AbstractConnectionImplTest}. */ -@RunWith(JUnit4.class) -public class ConnectionImplGeneratedSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } +public class ConnectionImplGeneratedSqlScriptTest extends AbstractSqlScriptTest { @Test public void testGeneratedScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile("ConnectionImplGeneratedSqlScriptTest.sql", getClass(), true); } 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 f68581ee845..f6afee6da2d 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 @@ -45,6 +45,7 @@ import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.CommitStats; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ForwardingResultSet; import com.google.cloud.spanner.Options; @@ -62,10 +63,10 @@ import com.google.cloud.spanner.TransactionManager; import com.google.cloud.spanner.TransactionRunner; import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.ConnectionImpl.UnitOfWorkType; import com.google.cloud.spanner.connection.ConnectionStatementExecutorImpl.StatementTimeoutGetter; import com.google.cloud.spanner.connection.ReadOnlyStalenessUtil.GetExactStaleness; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.cloud.spanner.connection.StatementResult.ResultType; import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; @@ -233,6 +234,11 @@ public static ConnectionImpl createConnection(final ConnectionOptions options) { final SimpleResultSet select1ResultSet = new SimpleResultSet(createSelect1MockResultSet()); final SimpleResultSet select1ResultSetWithStats = new SimpleResultSet(mockResultSetWithStats); + when(singleUseReadOnlyTx.executeQuery( + Mockito.argThat(statement -> statement.getSql().toUpperCase().startsWith("SHOW")))) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.UNIMPLEMENTED, "SHOW queries are not supported")); when(singleUseReadOnlyTx.executeQuery(Statement.of(SELECT))) .thenAnswer( invocation -> { @@ -271,6 +277,12 @@ public static ConnectionImpl createConnection(final ConnectionOptions options) { } return select1ResultSet; }); + when(txContext.executeQuery( + Mockito.argThat( + statement -> statement.getSql().toUpperCase().startsWith("SHOW")))) + .thenThrow( + SpannerExceptionFactory.newSpannerException( + ErrorCode.UNIMPLEMENTED, "SHOW queries are not supported")); when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PLAN)) .thenReturn(select1ResultSetWithStats); when(txContext.analyzeQuery(Statement.of(SELECT), QueryAnalyzeMode.PROFILE)) @@ -1350,6 +1362,7 @@ public void testAddRemoveTransactionRetryListener() { @Test public void testMergeQueryOptions() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); + when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); @@ -1370,14 +1383,15 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); verify(unitOfWork) .executeQueryAsync( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions( - QueryOptions.newBuilder() - .setOptimizerVersion("1") - .setOptimizerStatisticsPackage("custom-package-1") - .build()) - .build()), + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions( + QueryOptions.newBuilder() + .setOptimizerVersion("1") + .setOptimizerStatisticsPackage("custom-package-1") + .build()) + .build()), AnalyzeMode.NONE); // Execute query with an optimizer version and statistics package set on the connection. @@ -1386,14 +1400,15 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { impl.executeQuery(Statement.of("SELECT FOO FROM BAR")); verify(unitOfWork) .executeQueryAsync( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions( - QueryOptions.newBuilder() - .setOptimizerVersion("2") - .setOptimizerStatisticsPackage("custom-package-2") - .build()) - .build()), + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions( + QueryOptions.newBuilder() + .setOptimizerVersion("2") + .setOptimizerStatisticsPackage("custom-package-2") + .build()) + .build()), AnalyzeMode.NONE); // Execute query with an optimizer version and statistics package set on the connection and @@ -1405,14 +1420,15 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { impl.executeQuery(Statement.of("SELECT FOO FROM BAR"), prefetchOption); verify(unitOfWork) .executeQueryAsync( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions( - QueryOptions.newBuilder() - .setOptimizerVersion("3") - .setOptimizerStatisticsPackage("custom-package-3") - .build()) - .build()), + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions( + QueryOptions.newBuilder() + .setOptimizerVersion("3") + .setOptimizerStatisticsPackage("custom-package-3") + .build()) + .build()), AnalyzeMode.NONE, prefetchOption); @@ -1432,14 +1448,15 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { prefetchOption); verify(unitOfWork) .executeQueryAsync( - StatementParser.INSTANCE.parse( - Statement.newBuilder("SELECT FOO FROM BAR") - .withQueryOptions( - QueryOptions.newBuilder() - .setOptimizerVersion("5") - .setOptimizerStatisticsPackage("custom-package-5") - .build()) - .build()), + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse( + Statement.newBuilder("SELECT FOO FROM BAR") + .withQueryOptions( + QueryOptions.newBuilder() + .setOptimizerVersion("5") + .setOptimizerStatisticsPackage("custom-package-5") + .build()) + .build()), AnalyzeMode.NONE, prefetchOption); } @@ -1449,6 +1466,7 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { public void testStatementTagAlwaysAllowed() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(true); + when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); @@ -1491,6 +1509,7 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { public void testTransactionTagAllowedInTransaction() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(false); + when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); @@ -1531,6 +1550,7 @@ public void testTransactionTagAllowedInTransaction() { public void testTransactionTagNotAllowedWithoutTransaction() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(true); + when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); @@ -1551,6 +1571,7 @@ public void testTransactionTagNotAllowedWithoutTransaction() { public void testTransactionTagNotAllowedAfterTransactionStarted() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(false); + when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadOnlyTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadOnlyTest.java index c94b73926d1..d98861d0d1b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadOnlyTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadOnlyTest.java @@ -20,7 +20,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import java.util.concurrent.TimeUnit; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadWriteTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadWriteTest.java index 3aa3e9fdd48..1fa01abaf16 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadWriteTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTransactionalReadWriteTest.java @@ -20,7 +20,7 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TimestampBound.Mode; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import java.util.concurrent.TimeUnit; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java index 1f9bad7b6c2..e8758c36d03 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java @@ -22,9 +22,12 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.api.gax.rpc.TransportChannelProvider; import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerOptions; @@ -573,4 +576,77 @@ public void testSetCredentialsAndEncodedCredentials() throws Exception { .contains( "Cannot specify both a credentials URL and encoded credentials. Only set one of the properties."); } + + @Test + public void testSetDialect() { + ConnectionOptions options = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") + .build(); + assertThat(options.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); + + ConnectionOptions optionsSpanner = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=GOOGLE_STANDARD_SQL") + .build(); + assertThat(optionsSpanner.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); + + ConnectionOptions optionsPostgreSQL = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=POSTGRESQL") + .build(); + assertThat(optionsPostgreSQL.getDialect()).isEqualTo(Dialect.POSTGRESQL); + + ConnectionOptions optionsSpannerLC = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=google_standard_sql") + .build(); + assertThat(optionsSpannerLC.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); + + ConnectionOptions optionsPostgreSQLLC = + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=postgresql") + .build(); + assertThat(optionsPostgreSQLLC.getDialect()).isEqualTo(Dialect.POSTGRESQL); + + try { + ConnectionOptions.newBuilder() + .setCredentials(NoCredentials.getInstance()) + .setUri( + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=POSTGRES") + .build(); + fail("missing expected exception"); + } catch (SpannerException e) { + assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); + assertThat(e.getMessage()) + .contains("Dialect must be one of [GOOGLE_STANDARD_SQL, POSTGRESQL]"); + } + } + + @Test + public void testExternalChannelProvider() { + String baseUri = + "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database"; + + ConnectionOptions options = + ConnectionOptions.newBuilder() + .setUri( + baseUri + + "?channelProvider=com.google.cloud.spanner.connection.TestChannelProvider") + .setCredentials(NoCredentials.getInstance()) + .build(); + + TransportChannelProvider provider = options.getChannelProvider(); + assertTrue(provider instanceof InstantiatingGrpcChannelProvider); + } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithNoParametersTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithNoParametersTest.java index 84c6b8c8ced..2f2b538d073 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithNoParametersTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithNoParametersTest.java @@ -22,14 +22,33 @@ import static org.mockito.Mockito.when; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import java.util.concurrent.TimeUnit; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +@RunWith(Parameterized.class) public class ConnectionStatementWithNoParametersTest { - private final StatementParser parser = StatementParser.INSTANCE; + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + private AbstractStatementParser parser; + + @Before + public void setup() { + parser = AbstractStatementParser.getInstance(dialect); + } @Test public void testExecuteGetAutocommit() { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithOneParameterTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithOneParameterTest.java index fee70f05eaa..645d2f3b566 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithOneParameterTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionStatementWithOneParameterTest.java @@ -23,15 +23,34 @@ import static org.mockito.Mockito.when; import com.google.cloud.Timestamp; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.protobuf.Duration; import java.util.concurrent.TimeUnit; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +@RunWith(Parameterized.class) public class ConnectionStatementWithOneParameterTest { - private final StatementParser parser = StatementParser.INSTANCE; + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + private AbstractStatementParser parser; + + @Before + public void setup() { + parser = AbstractStatementParser.getInstance(dialect); + } @Test public void testExecuteSetAutocommit() { 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 0d310df6905..23792572d79 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 @@ -36,6 +36,7 @@ import com.google.api.core.ApiFutures; import com.google.api.gax.longrunning.OperationFuture; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ReadContext; @@ -44,9 +45,9 @@ import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.Connection.InternalMetadataQuery; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState; import com.google.protobuf.Timestamp; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; @@ -393,8 +394,12 @@ public void testUpdateCount() throws InterruptedException, ExecutionException { .setDdlClient(client) .setDatabaseClient(mock(DatabaseClient.class)) .build(); - batch.executeDdlAsync(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); - batch.executeDdlAsync(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE BAR"))); + batch.executeDdlAsync( + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE FOO"))); + batch.executeDdlAsync( + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE BAR"))); long[] updateCounts = get(batch.runBatchAsync()); assertThat(updateCounts.length, is(equalTo(2))); assertThat(updateCounts[0], is(equalTo(1L))); @@ -425,9 +430,12 @@ public void testFailedUpdateCount() throws InterruptedException, ExecutionExcept .setDdlClient(client) .setDatabaseClient(mock(DatabaseClient.class)) .build(); - batch.executeDdlAsync(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); batch.executeDdlAsync( - StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE INVALID_TABLE"))); + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE FOO"))); + batch.executeDdlAsync( + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE INVALID_TABLE"))); try { get(batch.runBatchAsync()); fail("missing expected exception"); @@ -462,9 +470,12 @@ public void testFailedAfterFirstStatement() throws InterruptedException, Executi .setDdlClient(client) .setDatabaseClient(mock(DatabaseClient.class)) .build(); - batch.executeDdlAsync(StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE FOO"))); batch.executeDdlAsync( - StatementParser.INSTANCE.parse(Statement.of("CREATE TABLE INVALID_TABLE"))); + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE FOO"))); + batch.executeDdlAsync( + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("CREATE TABLE INVALID_TABLE"))); try { get(batch.runBatchAsync()); fail("missing expected exception"); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DmlBatchTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DmlBatchTest.java index 10a8d5d46c4..f92b5bf1a92 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DmlBatchTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DmlBatchTest.java @@ -27,12 +27,13 @@ import static org.mockito.Mockito.when; import com.google.api.core.ApiFutures; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState; import java.util.Arrays; import java.util.Collections; @@ -44,9 +45,11 @@ public class DmlBatchTest { private final ParsedStatement statement1 = - StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2")); + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("UPDATE FOO SET BAR=1 WHERE BAZ=2")); private final ParsedStatement statement2 = - StatementParser.INSTANCE.parse(Statement.of("UPDATE FOO SET BAR=2 WHERE BAZ=3")); + AbstractStatementParser.getInstance(Dialect.GOOGLE_STANDARD_SQL) + .parse(Statement.of("UPDATE FOO SET BAR=2 WHERE BAZ=3")); private DmlBatch createSubject() { UnitOfWork transaction = mock(UnitOfWork.class); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java index 0a16b102097..a36b12b2fe9 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java @@ -29,8 +29,8 @@ import com.google.cloud.spanner.TransactionManager.TransactionState; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import com.google.common.base.Strings; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyTransactionTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyTransactionTest.java index 28d8b986029..027d85bc8d2 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyTransactionTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyTransactionTest.java @@ -44,8 +44,8 @@ import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.UnitOfWork.UnitOfWorkState; import com.google.spanner.v1.ResultSetStats; import java.util.Arrays; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadWriteTransactionTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadWriteTransactionTest.java index a4e2397db83..aae85bcec62 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadWriteTransactionTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadWriteTransactionTest.java @@ -50,8 +50,8 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.rpc.RetryInfo; import com.google.spanner.v1.ResultSetStats; import io.grpc.Metadata; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetReadOnlyStalenessSqlScriptTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetReadOnlyStalenessSqlScriptTest.java index 25aad948fee..ce3f5b99d48 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetReadOnlyStalenessSqlScriptTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetReadOnlyStalenessSqlScriptTest.java @@ -16,32 +16,13 @@ package com.google.cloud.spanner.connection; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -@RunWith(JUnit4.class) -public class SetReadOnlyStalenessSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri(ConnectionImplTest.URI) - .build())); - } - } +public class SetReadOnlyStalenessSqlScriptTest extends AbstractSqlScriptTest { @Test public void testSetReadOnlyStalenessScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile("SetReadOnlyStalenessTest.sql", getClass(), true); } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetStatementTimeoutSqlScriptTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetStatementTimeoutSqlScriptTest.java index c47fde41c17..5ec209dac3f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetStatementTimeoutSqlScriptTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetStatementTimeoutSqlScriptTest.java @@ -16,32 +16,13 @@ package com.google.cloud.spanner.connection; -import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnection; -import com.google.cloud.spanner.connection.AbstractSqlScriptVerifier.GenericConnectionProvider; -import com.google.cloud.spanner.connection.SqlScriptVerifier.SpannerGenericConnection; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -@RunWith(JUnit4.class) -public class SetStatementTimeoutSqlScriptTest { - - static class TestConnectionProvider implements GenericConnectionProvider { - @Override - public GenericConnection getConnection() { - return SpannerGenericConnection.of( - ConnectionImplTest.createConnection( - ConnectionOptions.newBuilder() - .setUri(ConnectionImplTest.URI) - .setCredentials(NoCredentials.getInstance()) - .build())); - } - } +public class SetStatementTimeoutSqlScriptTest extends AbstractSqlScriptTest { @Test public void testSetStatementTimeoutScript() throws Exception { - SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider()); + SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider(dialect)); verifier.verifyStatementsInFile("SetStatementTimeoutTest.sql", getClass(), true); } } 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 c927718d229..26a3952be28 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 @@ -50,9 +50,9 @@ import com.google.cloud.spanner.TransactionContext; import com.google.cloud.spanner.TransactionManager; import com.google.cloud.spanner.TransactionRunner; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.StatementExecutor.StatementTimeout; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; -import com.google.cloud.spanner.connection.StatementParser.StatementType; import com.google.common.base.Preconditions; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import com.google.spanner.v1.ResultSetStats; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SqlScriptVerifier.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SqlScriptVerifier.java index 2c3eae6623d..d9de876ceda 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SqlScriptVerifier.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SqlScriptVerifier.java @@ -21,6 +21,7 @@ import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; @@ -156,6 +157,11 @@ public void close() { this.connection.close(); } } + + @Override + public Dialect getDialect() { + return connection.getDialect(); + } } public SqlScriptVerifier() { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserTest.java index 47f79979135..d2176b53a2e 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserTest.java @@ -16,17 +16,24 @@ package com.google.cloud.spanner.connection; +import static com.google.common.truth.Truth.assertThat; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.ErrorCode; +import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType; import com.google.cloud.spanner.connection.ClientSideStatementImpl.CompileException; -import com.google.cloud.spanner.connection.StatementParser.ParsedStatement; +import com.google.common.collect.ImmutableMap; +import com.google.common.truth.Truth; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; @@ -35,8 +42,15 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.junit.Assume; +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +@RunWith(Parameterized.class) public class StatementParserTest { public static final String COPYRIGHT_PATTERN = "\\/\\*\n" @@ -54,12 +68,32 @@ public class StatementParserTest { + " \\* See the License for the specific language governing permissions and\n" + " \\* limitations under the License.\n" + " \\*\\/\n"; - private final StatementParser parser = StatementParser.INSTANCE; private static final Pattern EXPECT_PATTERN = Pattern.compile("(?is)\\s*(?:@EXPECT)\\s+'(.*)'"); + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + private AbstractStatementParser parser; + + @Before + public void setupParser() { + parser = AbstractStatementParser.getInstance(dialect); + } + + private static final ImmutableMap COMMENTS_SCRIPTS = + ImmutableMap.of( + Dialect.GOOGLE_STANDARD_SQL, + "CommentsTest.sql", + Dialect.POSTGRESQL, + "PostgreSQLCommentsTest.sql"); + @Test - public void testRemoveComments() { - List statements = readStatementsFromFile("CommentsTest.sql"); + public void testRemoveCommentsInScript() { + List statements = readStatementsFromFile(COMMENTS_SCRIPTS.get(dialect)); String currentlyExpected = ""; for (String statement : statements) { String sql = statement.trim(); @@ -71,30 +105,78 @@ public void testRemoveComments() { throw new IllegalArgumentException("Unknown @EXPECT statement: " + sql); } } else { - assertThat( - StatementParser.removeCommentsAndTrim(statement), is(equalTo(currentlyExpected))); + assertThat(parser.removeCommentsAndTrim(statement)).isEqualTo(currentlyExpected); } } + } + + @Test + public void testRemoveComments() { + assertThat(parser.removeCommentsAndTrim("")).isEqualTo(""); + assertThat(parser.removeCommentsAndTrim("SELECT * FROM FOO")).isEqualTo("SELECT * FROM FOO"); + assertThat(parser.removeCommentsAndTrim("-- This is a one line comment\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim( + "/* This is a simple multi line comment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim("/* This is a \nmulti line comment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim( + "/* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + } + + @Test + public void testGoogleStandardSQLRemoveCommentsGsql() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); - assertThat(StatementParser.removeCommentsAndTrim(""), is(equalTo(""))); + assertThat(parser.removeCommentsAndTrim("/*GSQL*/")).isEqualTo(""); + assertThat(parser.removeCommentsAndTrim("/*GSQL*/SELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim( + "/*GSQL*/-- This is a one line comment\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); assertThat( - StatementParser.removeCommentsAndTrim("SELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); + parser.removeCommentsAndTrim( + "/*GSQL*//* This is a simple multi line comment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); assertThat( - StatementParser.removeCommentsAndTrim("-- This is a one line comment\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); + parser.removeCommentsAndTrim( + "/*GSQL*//* This is a \nmulti line comment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); assertThat( - StatementParser.removeCommentsAndTrim( - "/* This is a simple multi line comment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); + parser.removeCommentsAndTrim( + "/*GSQL*//* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO")) + .isEqualTo("SELECT * FROM FOO"); + } + + @Test + public void testPostgreSQLDialectRemoveCommentsGsql() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + assertThat(parser.removeCommentsAndTrim("/*GSQL*/")).isEqualTo("/*GSQL*/"); + assertThat(parser.removeCommentsAndTrim("/*GSQL*/SELECT * FROM FOO")) + .isEqualTo("/*GSQL*/SELECT * FROM FOO"); assertThat( - StatementParser.removeCommentsAndTrim( - "/* This is a \nmulti line comment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); + parser.removeCommentsAndTrim( + "/*GSQL*/-- This is a one line comment\nSELECT * FROM FOO")) + .isEqualTo("/*GSQL*/SELECT * FROM FOO"); assertThat( - StatementParser.removeCommentsAndTrim( - "/* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO"), - is(equalTo("SELECT * FROM FOO"))); + parser.removeCommentsAndTrim( + "/*GSQL*//* This is a simple multi line comment */\nSELECT * FROM FOO")) + .isEqualTo("/*GSQL*/SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim( + "/*GSQL*//* This is a \nmulti line comment */\nSELECT * FROM FOO")) + .isEqualTo("/*GSQL*/SELECT * FROM FOO"); + assertThat( + parser.removeCommentsAndTrim( + "/*GSQL*//* This\nis\na\nmulti\nline\ncomment */\nSELECT * FROM FOO")) + .isEqualTo("/*GSQL*/SELECT * FROM FOO"); } @Test @@ -126,7 +208,7 @@ public void testStatementWithCommentContainingSlash() { + " UPDATE SET FirstName = v.column2,\n" + " LastName = v.column3"; ParsedStatement statement = parser.parse(Statement.of(sql)); - assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); + assertThat(statement.getSqlWithoutComments()).isEqualTo(sqlWithoutComments); } @Test @@ -159,92 +241,215 @@ public void testStatementWithCommentContainingSlashAndNoAsteriskOnNewLine() { + " UPDATE SET FirstName = v.column2,\n" + " LastName = v.column3"; ParsedStatement statement = parser.parse(Statement.of(sql)); - assertThat(statement.getSqlWithoutComments(), is(equalTo(sqlWithoutComments))); + assertThat(statement.getSqlWithoutComments()).isEqualTo(sqlWithoutComments); } @Test - public void testStatementWithHashTagSingleLineComment() { + public void testPostgresSQLDialectDollarQuoted() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + assertThat(parser.removeCommentsAndTrim("$$foo$$")).isEqualTo("$$foo$$"); + assertThat(parser.removeCommentsAndTrim("$$--foo$$")).isEqualTo("$$--foo$$"); + assertThat(parser.removeCommentsAndTrim("$$\nline 1\n--line2$$")) + .isEqualTo("$$\nline 1\n--line2$$"); + assertThat(parser.removeCommentsAndTrim("$bar$--foo$bar$")).isEqualTo("$bar$--foo$bar$"); assertThat( - parser - .parse(Statement.of("# this is a comment\nselect * from foo")) - .getSqlWithoutComments(), - is(equalTo("select * from foo"))); + parser.removeCommentsAndTrim( + "$bar$\nThis is a valid string\n -- That could contain special characters$bar$")) + .isEqualTo("$bar$\nThis is a valid string\n -- That could contain special characters$bar$"); + + assertThat(parser.removeCommentsAndTrim("SELECT FOO$BAR FROM SOME_TABLE")) + .isEqualTo("SELECT FOO$BAR FROM SOME_TABLE"); + assertThat(parser.removeCommentsAndTrim("SELECT FOO$BAR -- This is a comment\nFROM SOME_TABLE")) + .isEqualTo("SELECT FOO$BAR \nFROM SOME_TABLE"); assertThat( - parser.parse(Statement.of("select * from foo\n#this is a comment")).getSqlWithoutComments(), - is(equalTo("select * from foo"))); + parser.removeCommentsAndTrim("SELECT FOO, $BAR -- This is a comment\nFROM SOME_TABLE")) + .isEqualTo("SELECT FOO, $BAR \nFROM SOME_TABLE"); + } + + @Test + public void testPostgreSQLDialectSupportsEmbeddedComments() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + final String sql = + "/* This is a comment /* This is an embedded comment */ This is after the embedded comment */ SELECT 1"; + assertEquals("SELECT 1", parser.removeCommentsAndTrim(sql)); + } + + @Test + public void testGoogleStandardSQLDialectDoesNotSupportEmbeddedComments() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + final String sql = + "/* This is a comment /* This is an embedded comment */ This is after the embedded comment */ SELECT 1"; + assertEquals( + "This is after the embedded comment */ SELECT 1", parser.removeCommentsAndTrim(sql)); + } + + @Test + public void testPostgreSQLDialectUnterminatedComment() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + final String sql = + "/* This is a comment /* This is still a comment */ this is unterminated SELECT 1"; + try { + // Cloud Spanner would see this as a valid comment, while PostgreSQL + // requires 'embedded' comments to be properly terminated. + parser.removeCommentsAndTrim(sql); + fail("missing expected exception"); + } catch (SpannerException e) { + assertEquals(ErrorCode.INVALID_ARGUMENT, e.getErrorCode()); + assertTrue( + "Message should contain 'unterminated block comment'", + e.getMessage().contains("unterminated block comment")); + } + } + + @Test + public void testGoogleStandardSqlDialectDialectUnterminatedComment() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + final String sql = + "/* This is a comment /* This is still a comment */ this is unterminated SELECT 1"; + assertEquals("this is unterminated SELECT 1", parser.removeCommentsAndTrim(sql)); + } + + @Test + public void testShowStatements() { + AbstractStatementParser parser = AbstractStatementParser.getInstance(dialect); + + assertThat(parser.parse(Statement.of("show variable autocommit bar")).getType()) + .isEqualTo(StatementType.QUERY); + assertThat(parser.parse(Statement.of("show variable autocommit")).getType()) + .isEqualTo(StatementType.CLIENT_SIDE); + assertThat(parser.parse(Statement.of("show autocommit")).getType()) + .isEqualTo(StatementType.QUERY); + + assertThat(parser.parse(Statement.of("show variable retry_aborts_internally")).getType()) + .isEqualTo(StatementType.CLIENT_SIDE); + assertThat(parser.parse(Statement.of("show variable retry_aborts_internally bar")).getType()) + .isEqualTo(StatementType.QUERY); + } + + @Test + public void testGoogleStandardSQLDialectStatementWithHashTagSingleLineComment() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + // Supports # based comments assertThat( - parser - .parse(Statement.of("select *\nfrom foo # this is a comment\nwhere bar=1")) - .getSqlWithoutComments(), - is(equalTo("select *\nfrom foo \nwhere bar=1"))); + parser + .parse(Statement.of("# this is a comment\nselect * from foo")) + .getSqlWithoutComments()) + .isEqualTo("select * from foo"); + assertThat( + parser + .parse(Statement.of("select * from foo\n#this is a comment")) + .getSqlWithoutComments()) + .isEqualTo("select * from foo"); + assertThat( + parser + .parse(Statement.of("select *\nfrom foo # this is a comment\nwhere bar=1")) + .getSqlWithoutComments()) + .isEqualTo("select *\nfrom foo \nwhere bar=1"); + } + + @Test + public void testPostgreSQLDialectStatementWithHashTagSingleLineComment() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + // Does not support # based comments + assertThat( + parser + .parse(Statement.of("# this is a comment\nselect * from foo")) + .getSqlWithoutComments()) + .isEqualTo("# this is a comment\nselect * from foo"); + assertThat( + parser + .parse(Statement.of("select * from foo\n#this is a comment")) + .getSqlWithoutComments()) + .isEqualTo("select * from foo\n#this is a comment"); + assertThat( + parser + .parse(Statement.of("select *\nfrom foo # this is a comment\nwhere bar=1")) + .getSqlWithoutComments()) + .isEqualTo("select *\nfrom foo # this is a comment\nwhere bar=1"); } @Test public void testIsDdlStatement() { - assertFalse(parser.isDdlStatement("")); - assertFalse(parser.isDdlStatement("random text")); - assertFalse(parser.isDdlStatement("CREATETABLE")); - assertFalse(parser.isDdlStatement("CCREATE TABLE")); - assertFalse(parser.isDdlStatement("SELECT 1")); - assertFalse(parser.isDdlStatement("SELECT FOO FROM BAR")); - assertFalse(parser.isDdlStatement("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); - assertFalse(parser.isDdlStatement("UPDATE FOO SET NAME='NAME' WHERE ID=1")); - assertFalse(parser.isDdlStatement("DELETE FROM FOO")); + assertThat(parser.isDdlStatement("")).isFalse(); + assertThat(parser.isDdlStatement("random text")).isFalse(); + assertThat(parser.isDdlStatement("CREATETABLE")).isFalse(); + assertThat(parser.isDdlStatement("CCREATE TABLE")).isFalse(); + assertThat(parser.isDdlStatement("SELECT 1")).isFalse(); + assertThat(parser.isDdlStatement("SELECT FOO FROM BAR")).isFalse(); + assertThat(parser.isDdlStatement("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")).isFalse(); + assertThat(parser.isDdlStatement("UPDATE FOO SET NAME='NAME' WHERE ID=1")).isFalse(); + assertThat(parser.isDdlStatement("DELETE FROM FOO")).isFalse(); - assertTrue( - parser.isDdlStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertTrue(parser.isDdlStatement("alter table foo add Description string(100)")); - assertTrue(parser.isDdlStatement("drop table foo")); - assertTrue(parser.isDdlStatement("Create index BAR on foo (name)")); + assertThat( + parser.isDdlStatement("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isTrue(); + assertThat(parser.isDdlStatement("alter table foo add Description string(100)")).isTrue(); + assertThat(parser.isDdlStatement("drop table foo")).isTrue(); + assertThat(parser.isDdlStatement("Create index BAR on foo (name)")).isTrue(); - assertTrue( - parser - .parse( - Statement.of( - "\t\tCREATE\n\t TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "\n\n\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "-- this is a comment\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "-- SELECT in a single line comment \nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/* SELECT in a multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); - assertTrue( - parser - .parse( - Statement.of( - "/** SELECT in a java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) - .isDdl()); + assertThat( + parser + .parse( + Statement.of( + "\t\tCREATE\n\t TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "\n\n\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "-- this is a comment\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "-- SELECT in a single line comment \nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/* SELECT in a multi line comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/** SELECT in a java doc comment\n* with more information on the next line\n*/\nCREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isDdl()) + .isTrue(); assertTrue( parser @@ -298,75 +503,94 @@ public void testIsDdlStatement() { @Test public void testIsQuery() { - assertFalse(parser.isQuery("")); - assertFalse(parser.isQuery("random text")); - assertFalse(parser.isQuery("SELECT1")); - assertFalse(parser.isQuery("SSELECT 1")); - assertTrue(parser.isQuery("SELECT 1")); - assertTrue(parser.isQuery("select 1")); - assertTrue(parser.isQuery("SELECT foo FROM bar WHERE id=@id")); - assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")); - assertFalse(parser.isQuery("UPDATE FOO SET NAME='NAME' WHERE ID=1")); - assertFalse(parser.isQuery("DELETE FROM FOO")); - assertFalse(parser.isQuery("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")); - assertFalse(parser.isQuery("alter table foo add Description string(100)")); - assertFalse(parser.isQuery("drop table foo")); - assertFalse(parser.isQuery("Create index BAR on foo (name)")); - assertTrue(parser.isQuery("select * from foo")); - assertFalse(parser.isQuery("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")); + assertThat(parser.isQuery("")).isFalse(); + assertThat(parser.isQuery("random text")).isFalse(); + assertThat(parser.isQuery("SELECT1")).isFalse(); + assertThat(parser.isQuery("SSELECT 1")).isFalse(); - assertTrue( - parser.isQuery( - "WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" - + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" - + "SELECT * FROM subQ1\n" - + "UNION ALL\n" - + "SELECT * FROM subQ2")); - assertTrue( - parser.isQuery( - "with subQ1 AS (SELECT SchoolID FROM Roster),\n" - + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" - + "select * FROM subQ1\n" - + "UNION ALL\n" - + "SELECT * FROM subQ2")); - assertTrue( - parser - .parse( - Statement.of( - "-- this is a comment\nwith foo as (select * from bar)\nselect * from foo")) - .isQuery()); + assertThat(parser.isQuery("SELECT 1")).isTrue(); + assertThat(parser.isQuery("select 1")).isTrue(); + assertThat(parser.isQuery("SELECT foo FROM bar WHERE id=@id")).isTrue(); - assertTrue(parser.parse(Statement.of("-- this is a comment\nselect * from foo")).isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/* multi line comment\n* with more information on the next line\n*/\nSELECT ID, NAME\nFROM\tTEST\n\tWHERE ID=1")) - .isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/** java doc comment\n* with more information on the next line\n*/\nselect max(id) from test")) - .isQuery()); - assertTrue( - parser.parse(Statement.of("-- INSERT in a single line comment \n select 1")).isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/* UPDATE in a multi line comment\n* with more information on the next line\n*/\nSELECT 1")) - .isQuery()); - assertTrue( - parser - .parse( - Statement.of( - "/** DELETE in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- UPDATE test\nSELECT 1")) - .isQuery()); + assertThat(parser.isQuery("INSERT INTO FOO (ID, NAME) VALUES (1, 'NAME')")).isFalse(); + assertThat(parser.isQuery("UPDATE FOO SET NAME='NAME' WHERE ID=1")).isFalse(); + assertThat(parser.isQuery("DELETE FROM FOO")).isFalse(); + assertThat(parser.isQuery("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)")) + .isFalse(); + assertThat(parser.isQuery("alter table foo add Description string(100)")).isFalse(); + assertThat(parser.isQuery("drop table foo")).isFalse(); + assertThat(parser.isQuery("Create index BAR on foo (name)")).isFalse(); + + assertThat(parser.isQuery("select * from foo")).isTrue(); + + assertThat(parser.isQuery("INSERT INTO FOO (ID, NAME) SELECT ID+1, NAME FROM FOO")).isFalse(); + + assertThat( + parser.isQuery( + "WITH subQ1 AS (SELECT SchoolID FROM Roster),\n" + + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + + "SELECT * FROM subQ1\n" + + "UNION ALL\n" + + "SELECT * FROM subQ2")) + .isTrue(); + assertThat( + parser.isQuery( + "with subQ1 AS (SELECT SchoolID FROM Roster),\n" + + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + + "select * FROM subQ1\n" + + "UNION ALL\n" + + "SELECT * FROM subQ2")) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "-- this is a comment\nwith foo as (select * from bar)\nselect * from foo")) + .isQuery()) + .isTrue(); + + assertThat(parser.parse(Statement.of("-- this is a comment\nselect * from foo")).isQuery()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/* multi line comment\n* with more information on the next line\n*/\nSELECT ID, NAME\nFROM\tTEST\n\tWHERE ID=1")) + .isQuery()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/** java doc comment\n* with more information on the next line\n*/\nselect max(id) from test")) + .isQuery()) + .isTrue(); + assertThat( + parser + .parse(Statement.of("-- INSERT in a single line comment \n select 1")) + .isQuery()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/* UPDATE in a multi line comment\n* with more information on the next line\n*/\nSELECT 1")) + .isQuery()) + .isTrue(); + assertThat( + parser + .parse( + Statement.of( + "/** DELETE in a java doc comment\n* with more information on the next line\n*/\n\n\n\n -- UPDATE test\nSELECT 1")) + .isQuery()) + .isTrue(); } @Test - public void testIsQuery_QueryHints() { + public void testGoogleStandardSQLDialectIsQuery_QueryHints() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + // Supports query hints, PostgreSQL dialect does NOT // Valid query hints. assertTrue(parser.isQuery("@{JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); assertTrue(parser.isQuery("@ {JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); @@ -390,13 +614,11 @@ public void testIsQuery_QueryHints() { // Multiple query hints. assertTrue( - StatementParser.INSTANCE.isQuery( - "@{FORCE_INDEX=index_name} @{JOIN_METHOD=HASH_JOIN} SELECT * FROM tbl")); + parser.isQuery("@{FORCE_INDEX=index_name} @{JOIN_METHOD=HASH_JOIN} SELECT * FROM tbl")); assertTrue( - StatementParser.INSTANCE.isQuery( - "@{FORCE_INDEX=index_name} @{JOIN_METHOD=HASH_JOIN} Select * FROM tbl")); + parser.isQuery("@{FORCE_INDEX=index_name} @{JOIN_METHOD=HASH_JOIN} Select * FROM tbl")); assertTrue( - StatementParser.INSTANCE.isQuery( + parser.isQuery( "@{FORCE_INDEX=index_name}\n@{JOIN_METHOD=HASH_JOIN}\nWITH subQ1 AS (SELECT SchoolID FROM Roster),\n" + " subQ2 AS (SELECT OpponentID FROM PlayerStats)\n" + "SELECT * FROM subQ1\n" @@ -407,10 +629,16 @@ public void testIsQuery_QueryHints() { assertFalse(parser.isQuery("@{JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN} SELECT * FROM PersonsTable")); assertFalse(parser.isQuery("@JOIN_METHOD=HASH_JOIN SELECT * FROM PersonsTable")); + assertFalse( + parser.isQuery( + "@{FORCE_INDEX=index_name} @{JOIN_METHOD=HASH_JOIN} UPDATE tbl set FOO=1 WHERE ID=2")); } @Test public void testIsUpdate_QueryHints() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + // Supports query hints, PostgreSQL dialect does NOT // Valid query hints. assertTrue( parser.isUpdateStatement( @@ -439,7 +667,7 @@ public void testIsUpdate_QueryHints() { // Multiple query hints. assertTrue( - StatementParser.INSTANCE.isUpdateStatement( + parser.isUpdateStatement( "@{LOCK_SCANNED_RANGES=exclusive} @{USE_ADDITIONAL_PARALLELISM=TRUE} UPDATE FOO SET NAME='foo' WHERE ID=1")); // Invalid query hints. @@ -652,15 +880,14 @@ private Set getAllStatements() throws CompileException private void assertParsing( String value, Class statementClass) { - assertThat(this.parse(value), is(equalTo(statementClass))); + assertThat(this.parse(value)).isEqualTo(statementClass); } private void testParseStatement( String statement, Class statementClass) { - assertThat( - "\"" + statement + "\" should be " + statementClass.getName(), - this.parse(statement), - is(equalTo(statementClass))); + Truth.assertWithMessage("\"" + statement + "\" should be " + statementClass.getName()) + .that(this.parse(statement)) + .isEqualTo(statementClass); assertParsing(upper(statement), statementClass); assertParsing(lower(statement), statementClass); assertParsing(withSpaces(statement), statementClass); @@ -673,39 +900,37 @@ private void testParseStatement( assertParsing(withTrailingTabs(statement), statementClass); assertParsing(withTrailingLinefeeds(statement), statementClass); - assertThat(parse(withInvalidPrefix(statement)), is(nullValue())); - assertThat(parse(withInvalidSuffix(statement)), is(nullValue())); - - assertNull(parse(withPrefix("%", statement))); - assertNull(parse(withPrefix("_", statement))); - assertNull(parse(withPrefix("&", statement))); - assertNull(parse(withPrefix("$", statement))); - assertNull(parse(withPrefix("@", statement))); - assertNull(parse(withPrefix("!", statement))); - assertNull(parse(withPrefix("*", statement))); - assertNull(parse(withPrefix("(", statement))); - assertNull(parse(withPrefix(")", statement))); - - assertThat( - withSuffix("%", statement) + " is not a valid statement", - parse(withSuffix("%", statement)), - is(nullValue())); - assertNull(parse(withSuffix("_", statement))); - assertNull(parse(withSuffix("&", statement))); - assertNull(parse(withSuffix("$", statement))); - assertNull(parse(withSuffix("@", statement))); - assertNull(parse(withSuffix("!", statement))); - assertNull(parse(withSuffix("*", statement))); - assertNull(parse(withSuffix("(", statement))); - assertNull(parse(withSuffix(")", statement))); + assertThat(parse(withInvalidPrefix(statement))).isNull(); + assertThat(parse(withInvalidSuffix(statement))).isNull(); + + assertThat(parse(withPrefix("%", statement))).isNull(); + assertThat(parse(withPrefix("_", statement))).isNull(); + assertThat(parse(withPrefix("&", statement))).isNull(); + assertThat(parse(withPrefix("$", statement))).isNull(); + assertThat(parse(withPrefix("@", statement))).isNull(); + assertThat(parse(withPrefix("!", statement))).isNull(); + assertThat(parse(withPrefix("*", statement))).isNull(); + assertThat(parse(withPrefix("(", statement))).isNull(); + assertThat(parse(withPrefix(")", statement))).isNull(); + + Truth.assertWithMessage(withSuffix("%", statement) + " is not a valid statement") + .that(parse(withSuffix("%", statement))) + .isNull(); + assertThat(parse(withSuffix("_", statement))).isNull(); + assertThat(parse(withSuffix("&", statement))).isNull(); + assertThat(parse(withSuffix("$", statement))).isNull(); + assertThat(parse(withSuffix("@", statement))).isNull(); + assertThat(parse(withSuffix("!", statement))).isNull(); + assertThat(parse(withSuffix("*", statement))).isNull(); + assertThat(parse(withSuffix("(", statement))).isNull(); + assertThat(parse(withSuffix(")", statement))).isNull(); } private void testParseStatementWithOneParameterAtTheEnd( String statement, Class statementClass) { - assertThat( - "\"" + statement + "\" should be " + statementClass.getName(), - this.parse(statement), - is(equalTo(statementClass))); + Truth.assertWithMessage("\"" + statement + "\" should be " + statementClass.getName()) + .that(this.parse(statement)) + .isEqualTo(statementClass); assertParsing(upper(statement), statementClass); assertParsing(lower(statement), statementClass); assertParsing(withSpaces(statement), statementClass); @@ -718,18 +943,18 @@ private void testParseStatementWithOneParame assertParsing(withTrailingTabs(statement), statementClass); assertParsing(withTrailingLinefeeds(statement), statementClass); - assertNull(parse(withInvalidPrefix(statement))); + assertThat(parse(withInvalidPrefix(statement))).isNull(); assertParsing(withInvalidSuffix(statement), statementClass); - assertNull(parse(withPrefix("%", statement))); - assertNull(parse(withPrefix("_", statement))); - assertNull(parse(withPrefix("&", statement))); - assertNull(parse(withPrefix("$", statement))); - assertNull(parse(withPrefix("@", statement))); - assertNull(parse(withPrefix("!", statement))); - assertNull(parse(withPrefix("*", statement))); - assertNull(parse(withPrefix("(", statement))); - assertNull(parse(withPrefix(")", statement))); + assertThat(parse(withPrefix("%", statement))).isNull(); + assertThat(parse(withPrefix("_", statement))).isNull(); + assertThat(parse(withPrefix("&", statement))).isNull(); + assertThat(parse(withPrefix("$", statement))).isNull(); + assertThat(parse(withPrefix("@", statement))).isNull(); + assertThat(parse(withPrefix("!", statement))).isNull(); + assertThat(parse(withPrefix("*", statement))).isNull(); + assertThat(parse(withPrefix("(", statement))).isNull(); + assertThat(parse(withPrefix(")", statement))).isNull(); assertParsing(withSuffix("%", statement), statementClass); assertParsing(withSuffix("_", statement), statementClass); @@ -742,6 +967,337 @@ private void testParseStatementWithOneParame assertParsing(withSuffix(")", statement), statementClass); } + @Test + public void testConvertPositionalParametersToNamedParametersWithGsqlException() { + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "/*GSQL*/select * from foo where name=?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/select * from foo where name=@p1"); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "/*GSQL*/?'?test?\"?test?\"?'?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1'?test?\"?test?\"?'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "/*GSQL*/?'?it\\'?s'?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1'?it\\'?s'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "/*GSQL*/?'?it\\\"?s'?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1'?it\\\"?s'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "/*GSQL*/?\"?it\\\"?s\"?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1\"?it\\\"?s\"@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "/*GSQL*/?'''?it\\'?s'''?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1'''?it\\'?s'''@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "/*GSQL*/?\"\"\"?it\\\"?s\"\"\"?") + .sqlWithNamedParameters) + .isEqualTo("/*GSQL*/@p1\"\"\"?it\\\"?s\"\"\"@p2"); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "/*GSQL*/select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") + .sqlWithNamedParameters, + is( + equalTo( + "/*GSQL*/select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'"))); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "/*GSQL*/select * " + + "from foo " + + "where name=? " + + "and col2 like ? " + + "and col3 > ?") + .sqlWithNamedParameters, + is( + equalTo( + "/*GSQL*/select * " + + "from foo " + + "where name=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "/*GSQL*/select * " + "from foo " + "where id between ? and ?") + .sqlWithNamedParameters, + is(equalTo("/*GSQL*/select * " + "from foo " + "where id between @p1 and @p2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "/*GSQL*/select * " + "from foo " + "limit ? offset ?") + .sqlWithNamedParameters, + is(equalTo("/*GSQL*/select * " + "from foo " + "limit @p1 offset @p2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "/*GSQL*/select * " + + "from foo " + + "where col1=? " + + "and col2 like ? " + + "and col3 > ? " + + "and col4 < ? " + + "and col5 != ? " + + "and col6 not in (?, ?, ?) " + + "and col7 in (?, ?, ?) " + + "and col8 between ? and ?") + .sqlWithNamedParameters, + is( + equalTo( + "/*GSQL*/select * " + + "from foo " + + "where col1=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3 " + + "and col4 < @p4 " + + "and col5 != @p5 " + + "and col6 not in (@p6, @p7, @p8) " + + "and col7 in (@p9, @p10, @p11) " + + "and col8 between @p12 and @p13"))); + } + + @Test + public void testGoogleStandardSQLDialectConvertPositionalParametersToNamedParameters() { + Assume.assumeTrue(dialect == Dialect.GOOGLE_STANDARD_SQL); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * from foo where name=?") + .sqlWithNamedParameters) + .isEqualTo("select * from foo where name=@p1"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?test?\"?test?\"?'?") + .sqlWithNamedParameters) + .isEqualTo("@p1'?test?\"?test?\"?'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s'?") + .sqlWithNamedParameters) + .isEqualTo("@p1'?it\\'?s'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\\"?s'?") + .sqlWithNamedParameters) + .isEqualTo("@p1'?it\\\"?s'@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?\"?it\\\"?s\"?") + .sqlWithNamedParameters) + .isEqualTo("@p1\"?it\\\"?s\"@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s'''?") + .sqlWithNamedParameters) + .isEqualTo("@p1'''?it\\'?s'''@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") + .sqlWithNamedParameters) + .isEqualTo("@p1\"\"\"?it\\\"?s\"\"\"@p2"); + + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?`?it\\`?s`?") + .sqlWithNamedParameters) + .isEqualTo("@p1`?it\\`?s`@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?```?it\\`?s```?") + .sqlWithNamedParameters) + .isEqualTo("@p1```?it\\`?s```@p2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s \n ?it\\'?s'''?") + .sqlWithNamedParameters) + .isEqualTo("@p1'''?it\\'?s \n ?it\\'?s'''@p2"); + + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); + assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") + .sqlWithNamedParameters, + is( + equalTo( + "select 1, @p1, 'test?test', \"test?test\", foo.* from `foo` where col1=@p2 and col2='test' and col3=@p3 and col4='?' and col5=\"?\" and col6='?''?''?'"))); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where name=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where id between ? and ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "where id between @p1 and @p2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "limit ? offset ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "limit @p1 offset @p2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + + "from foo " + + "where col1=? " + + "and col2 like ? " + + "and col3 > ? " + + "and col4 < ? " + + "and col5 != ? " + + "and col6 not in (?, ?, ?) " + + "and col7 in (?, ?, ?) " + + "and col8 between ? and ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where col1=@p1 " + + "and col2 like @p2 " + + "and col3 > @p3 " + + "and col4 < @p4 " + + "and col5 != @p5 " + + "and col6 not in (@p6, @p7, @p8) " + + "and col7 in (@p9, @p10, @p11) " + + "and col8 between @p12 and @p13"))); + } + + @Test + public void testPostgreSQLDialectDialectConvertPositionalParametersToNamedParameters() { + Assume.assumeTrue(dialect == Dialect.POSTGRESQL); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * from foo where name=?") + .sqlWithNamedParameters) + .isEqualTo("select * from foo where name=$1"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?test?\"?test?\"?'?") + .sqlWithNamedParameters) + .isEqualTo("$1'?test?\"?test?\"?'$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\'?s'?") + .sqlWithNamedParameters) + .isEqualTo("$1'?it\\'?s'$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'?it\\\"?s'?") + .sqlWithNamedParameters) + .isEqualTo("$1'?it\\\"?s'$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?\"?it\\\"?s\"?") + .sqlWithNamedParameters) + .isEqualTo("$1\"?it\\\"?s\"$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?'''?it\\'?s'''?") + .sqlWithNamedParameters) + .isEqualTo("$1'''?it\\'?s'''$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?\"\"\"?it\\\"?s\"\"\"?") + .sqlWithNamedParameters) + .isEqualTo("$1\"\"\"?it\\\"?s\"\"\"$2"); + + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?$$?it$?s$$?") + .sqlWithNamedParameters) + .isEqualTo("$1$$?it$?s$$$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?$tag$?it$$?s$tag$?") + .sqlWithNamedParameters) + .isEqualTo("$1$tag$?it$$?s$tag$$2"); + assertThat( + parser.convertPositionalParametersToNamedParameters('?', "?$$?it\\'?s \n ?it\\'?s$$?") + .sqlWithNamedParameters) + .isEqualTo("$1$$?it\\'?s \n ?it\\'?s$$$2"); + + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s'?"); + assertUnclosedLiteral("?'?it\\'?s \n ?it\\'?s?"); + assertUnclosedLiteral("?'''?it\\'?s \n ?it\\'?s'?"); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select 1, ?, 'test?test', \"test?test\", foo.* from `foo` where col1=? and col2='test' and col3=? and col4='?' and col5=\"?\" and col6='?''?''?'") + .sqlWithNamedParameters, + is( + equalTo( + "select 1, $1, 'test?test', \"test?test\", foo.* from `foo` where col1=$2 and col2='test' and col3=$3 and col4='?' and col5=\"?\" and col6='?''?''?'"))); + + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + "from foo " + "where name=? " + "and col2 like ? " + "and col3 > ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where name=$1 " + + "and col2 like $2 " + + "and col3 > $3"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "where id between ? and ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "where id between $1 and $2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', "select * " + "from foo " + "limit ? offset ?") + .sqlWithNamedParameters, + is(equalTo("select * " + "from foo " + "limit $1 offset $2"))); + assertThat( + parser.convertPositionalParametersToNamedParameters( + '?', + "select * " + + "from foo " + + "where col1=? " + + "and col2 like ? " + + "and col3 > ? " + + "and col4 < ? " + + "and col5 != ? " + + "and col6 not in (?, ?, ?) " + + "and col7 in (?, ?, ?) " + + "and col8 between ? and ?") + .sqlWithNamedParameters, + is( + equalTo( + "select * " + + "from foo " + + "where col1=$1 " + + "and col2 like $2 " + + "and col3 > $3 " + + "and col4 < $4 " + + "and col5 != $5 " + + "and col6 not in ($6, $7, $8) " + + "and col7 in ($9, $10, $11) " + + "and col8 between $12 and $13"))); + } + + private void assertUnclosedLiteral(String sql) { + try { + parser.convertPositionalParametersToNamedParameters('?', sql); + fail("missing expected exception"); + } catch (SpannerException e) { + assertThat(e.getErrorCode()).isSameInstanceAs(ErrorCode.INVALID_ARGUMENT); + assertThat(e.getMessage()) + .startsWith( + ErrorCode.INVALID_ARGUMENT.name() + + ": SQL statement contains an unclosed literal: " + + sql); + } + } + @SuppressWarnings("unchecked") private Class parse(String statement) { ClientSideStatementImpl optional = parser.parseClientSideStatement(statement); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TestChannelProvider.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TestChannelProvider.java new file mode 100644 index 00000000000..7331c8d03c7 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TestChannelProvider.java @@ -0,0 +1,26 @@ +/* + * Copyright 2022 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 com.google.api.gax.rpc.TransportChannelProvider; +import com.google.cloud.spanner.v1.SpannerSettings; + +public final class TestChannelProvider implements ConnectionOptions.ExternalChannelProvider { + public TransportChannelProvider getChannelProvider(String host, int port) { + return SpannerSettings.defaultTransportChannelProvider(); + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/DialectTestParameter.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/DialectTestParameter.java new file mode 100644 index 00000000000..bb17bed5512 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/DialectTestParameter.java @@ -0,0 +1,50 @@ +/* + * Copyright 2021 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.it; + +import com.google.cloud.spanner.Dialect; +import java.util.Map; + +public class DialectTestParameter { + + final Dialect dialect; + final String createTableFile; + final Map executeQueriesFiles; + final String[] queries; + + DialectTestParameter( + Dialect dialect, + String createTableFile, + Map executeQueriesFiles, + String[] queries) { + this.dialect = dialect; + this.createTableFile = createTableFile; + this.executeQueriesFiles = executeQueriesFiles; + this.queries = queries; + } + + DialectTestParameter(Dialect dialect) { + this.dialect = dialect; + this.createTableFile = ""; + this.executeQueriesFiles = null; + this.queries = null; + } + + public String toString() { + return this.dialect.name(); + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java index 94c3723439a..ed9484c5632 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java @@ -16,7 +16,9 @@ package com.google.cloud.spanner.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeFalse; import com.google.cloud.ByteArray; import com.google.cloud.Timestamp; @@ -25,6 +27,7 @@ import com.google.cloud.spanner.BatchTransactionId; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; @@ -34,6 +37,7 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; +import com.google.common.collect.ImmutableList; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; import java.util.ArrayList; @@ -50,32 +54,46 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; /** * Integration test reading large amounts of data using the Batch APIs. The size of data ensures * that multiple partitions are returned by the server. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITBatchReadTest { private static int numRows; private static final int WRITE_BATCH_SIZE = 1 << 20; private static final String TABLE_NAME = "BatchTestTable"; private static final String INDEX_NAME = "TestIndexByValue"; - private static final long STALENESS_MILLISEC = 1 * 1000; + private static final long STALENESS_MILLISEC = 1000; @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static Database db; private static HashFunction hasher; - private static DatabaseClient dbClient; - private static BatchClient client; + private static BatchClient googleStandardSQLBatchClient; + private static BatchClient postgreSQLBatchClient; private static final Random RANDOM = new Random(); private BatchReadOnlyTransaction batchTxn; + @Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + // PG dialect tests are not supported by the emulator + if (!isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameter public DialectTestParameter dialect; + // Generate a large number of rows to allow multiple read/query partitions. private static List manyRows() { List rows = new ArrayList<>(); @@ -88,7 +106,7 @@ private static List manyRows() { @BeforeClass public static void setUpDatabase() throws Exception { - db = + Database googleStandardDatabase = env.getTestHelper() .createTestDatabase( "CREATE TABLE " @@ -101,46 +119,86 @@ public static void setUpDatabase() throws Exception { + ") PRIMARY KEY (Key)", "CREATE INDEX " + INDEX_NAME + " ON " + TABLE_NAME + "(Fingerprint)"); hasher = Hashing.goodFastHash(64); - dbClient = env.getTestHelper().getDatabaseClient(db); - client = env.getTestHelper().getBatchClient(db); - - List mutations = new ArrayList<>(); - int totalSize = 0; - int i = 0; - for (int row : manyRows()) { - numRows++; - byte[] data = new byte[row]; - RANDOM.nextBytes(data); - mutations.add( - Mutation.newInsertOrUpdateBuilder(TABLE_NAME) - .set("Key") - .to(i) - .set("Data") - .to(ByteArray.copyFrom(data)) - .set("Fingerprint") - .to(hasher.hashBytes(data).asLong()) - .set("Size") - .to(row) - .build()); - totalSize += row; - i++; - if (totalSize >= WRITE_BATCH_SIZE) { - dbClient.write(mutations); - mutations.clear(); - totalSize = 0; + googleStandardSQLBatchClient = env.getTestHelper().getBatchClient(googleStandardDatabase); + + List databaseClients = new ArrayList<>(); + databaseClients.add(env.getTestHelper().getDatabaseClient(googleStandardDatabase)); + + if (!isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper().createTestDatabase(Dialect.POSTGRESQL, Collections.emptyList()); + env.getTestHelper() + .getClient() + .getDatabaseAdminClient() + .updateDatabaseDdl( + env.getTestHelper().getInstanceId().getInstance(), + postgreSQLDatabase.getId().getDatabase(), + ImmutableList.of( + "CREATE TABLE " + + TABLE_NAME + + " (" + + " Key bigint not null primary key," + + " Data bytea," + + " Fingerprint bigint," + + " Size bigint" + + ")", + "CREATE INDEX " + INDEX_NAME + " ON " + TABLE_NAME + "(Fingerprint)"), + null) + .get(); + postgreSQLBatchClient = env.getTestHelper().getBatchClient(postgreSQLDatabase); + databaseClients.add(env.getTestHelper().getDatabaseClient(postgreSQLDatabase)); + } + + List rows = manyRows(); + numRows = rows.size(); + for (DatabaseClient dbClient : databaseClients) { + List mutations = new ArrayList<>(); + int totalSize = 0; + int i = 0; + for (int row : rows) { + byte[] data = new byte[row]; + RANDOM.nextBytes(data); + mutations.add( + Mutation.newInsertOrUpdateBuilder(TABLE_NAME) + .set("Key") + .to(i) + .set("Data") + .to(ByteArray.copyFrom(data)) + .set("Fingerprint") + .to(hasher.hashBytes(data).asLong()) + .set("Size") + .to(row) + .build()); + totalSize += row; + i++; + if (totalSize >= WRITE_BATCH_SIZE) { + dbClient.write(mutations); + mutations.clear(); + totalSize = 0; + } } + dbClient.write(mutations); } - dbClient.write(mutations); // Our read/queries are executed with some staleness. Thread.sleep(2 * STALENESS_MILLISEC); } + private BatchClient getBatchClient() { + if (dialect.dialect == Dialect.POSTGRESQL) { + return postgreSQLBatchClient; + } + return googleStandardSQLBatchClient; + } + @Test public void read() { + assumeFalse( + "PostgreSQL does not support the PartitionRead RPC", dialect.dialect == Dialect.POSTGRESQL); + BitSet seenRows = new BitSet(numRows); TimestampBound bound = getRandomBound(); PartitionOptions partitionParams = getRandomPartitionOptions(); - batchTxn = client.batchReadOnlyTransaction(bound); + batchTxn = getBatchClient().batchReadOnlyTransaction(bound); List partitions = batchTxn.partitionRead( partitionParams, @@ -153,9 +211,12 @@ public void read() { @Test public void readUsingIndex() { + assumeFalse( + "PostgreSQL does not support the PartitionRead RPC", dialect.dialect == Dialect.POSTGRESQL); + TimestampBound bound = getRandomBound(); PartitionOptions partitionParams = getRandomPartitionOptions(); - batchTxn = client.batchReadOnlyTransaction(bound); + batchTxn = getBatchClient().batchReadOnlyTransaction(bound); List partitions = batchTxn.partitionReadUsingIndex( partitionParams, @@ -166,7 +227,8 @@ public void readUsingIndex() { BatchTransactionId txnID = batchTxn.getBatchTransactionId(); int numRowsRead = 0; for (Partition p : partitions) { - BatchReadOnlyTransaction batchTxnOnEachWorker = client.batchReadOnlyTransaction(txnID); + BatchReadOnlyTransaction batchTxnOnEachWorker = + getBatchClient().batchReadOnlyTransaction(txnID); try (ResultSet result = batchTxnOnEachWorker.execute(p)) { while (result.next()) { numRowsRead++; @@ -188,7 +250,7 @@ public void query() { BitSet seenRows = new BitSet(numRows); TimestampBound bound = getRandomBound(); PartitionOptions partitionParams = getRandomPartitionOptions(); - batchTxn = client.batchReadOnlyTransaction(bound); + batchTxn = getBatchClient().batchReadOnlyTransaction(bound); List partitions = batchTxn.partitionQuery( partitionParams, @@ -227,7 +289,8 @@ private TimestampBound getRandomBound() { private void fetchAndValidateRows( List partitions, BatchTransactionId txnID, BitSet seenRows) { for (Partition p : partitions) { - BatchReadOnlyTransaction batchTxnOnEachWorker = client.batchReadOnlyTransaction(txnID); + BatchReadOnlyTransaction batchTxnOnEachWorker = + getBatchClient().batchReadOnlyTransaction(txnID); try (ResultSet result = batchTxnOnEachWorker.execute(p)) { // validate no duplicate rows; verify all columns read. validate(result, seenRows); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java index 2a94ed82abb..2c7a8da27c3 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java @@ -16,12 +16,14 @@ package com.google.cloud.spanner.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Key; @@ -36,22 +38,27 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TransactionRunner; import com.google.cloud.spanner.TransactionRunner.TransactionCallable; +import com.google.cloud.spanner.connection.ConnectionOptions; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; +import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; /** Integration tests for DML. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public final class ITDMLTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static Database db; - private static DatabaseClient client; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; /** Sequence for assigning unique keys to test cases. */ private static int seq; @@ -60,30 +67,65 @@ public final class ITDMLTest { private static final String INSERT_DML = "INSERT INTO T (k, v) VALUES ('%d-boo1', 1), ('%d-boo2', 2), ('%d-boo3', 3), ('%d-boo4', 4);"; - private static final String UPDATE_DML = "UPDATE T SET T.V = 100 WHERE T.K LIKE '%d-boo%%';"; - private static final String DELETE_DML = "DELETE FROM T WHERE T.K like '%d-boo%%';"; + private static final String UPDATE_DML = "UPDATE T SET V = 100 WHERE K LIKE '%d-boo%%';"; + private static final String DELETE_DML = "DELETE FROM T WHERE K like '%d-boo%%';"; + private static final long DML_COUNT = 4; private static boolean throwAbortOnce = false; @BeforeClass public static void setUpDatabase() { - db = + Database googleStandardSQLDatabase = env.getTestHelper() .createTestDatabase( "CREATE TABLE T (" + " K STRING(MAX) NOT NULL," + " V INT64," + ") PRIMARY KEY (K)"); - client = env.getTestHelper().getDatabaseClient(db); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + if (!isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, + Arrays.asList( + "CREATE TABLE T (" + " K VARCHAR PRIMARY KEY," + " V BIGINT" + ")")); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); } @Before public void increaseTestIdAndDeleteTestData() { - client.writeAtLeastOnce(Collections.singletonList(Mutation.delete("T", KeySet.all()))); + if (dialect.dialect == Dialect.GOOGLE_STANDARD_SQL) { + googleStandardSQLClient.writeAtLeastOnce( + Collections.singletonList(Mutation.delete("T", KeySet.all()))); + } else { + postgreSQLClient.writeAtLeastOnce( + Collections.singletonList(Mutation.delete("T", KeySet.all()))); + } id++; } + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + // "PG dialect tests are not supported by the emulator" + if (!isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter(0) + public DialectTestParameter dialect; + private static String uniqueKey() { return "k" + seq++; } @@ -114,11 +156,18 @@ private void executeUpdate(long expectedCount, final String... stmts) { } return rowCount; }; - TransactionRunner runner = client.readWriteTransaction(); + TransactionRunner runner = getClient(dialect.dialect).readWriteTransaction(); Long rowCount = runner.run(callable); assertThat(rowCount).isEqualTo(expectedCount); } + private DatabaseClient getClient(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return postgreSQLClient; + } + return googleStandardSQLClient; + } + @Test public void abortOnceShouldSucceedAfterRetry() { try { @@ -134,27 +183,27 @@ public void abortOnceShouldSucceedAfterRetry() { public void partitionedDML() { executeUpdate(DML_COUNT, insertDml()); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V")) .getLong(0)) .isEqualTo(1); - long rowCount = client.executePartitionedUpdate(Statement.of(updateDml())); + long rowCount = getClient(dialect.dialect).executePartitionedUpdate(Statement.of(updateDml())); // Note: With PDML there is a possibility of network replay or partial update to occur, causing // this assert to fail. We should remove this assert if it is a recurring failure in IT tests. assertThat(rowCount).isEqualTo(DML_COUNT); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V")) .getLong(0)) .isEqualTo(100); - rowCount = client.executePartitionedUpdate(Statement.of(deleteDml())); + rowCount = getClient(dialect.dialect).executePartitionedUpdate(Statement.of(deleteDml())); assertThat(rowCount).isEqualTo(DML_COUNT); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V"))) .isNull(); @@ -164,21 +213,21 @@ public void partitionedDML() { public void standardDML() { executeUpdate(DML_COUNT, insertDml()); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V")) .getLong(0)) .isEqualTo(1); executeUpdate(DML_COUNT, updateDml()); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V")) .getLong(0)) .isEqualTo(100); executeUpdate(DML_COUNT, deleteDml()); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V"))) .isNull(); @@ -208,7 +257,7 @@ public void standardDMLWithDuplicates() { String.format("UPDATE T SET v = 400 WHERE k = '%d-boo1';", id), String.format("UPDATE T SET v = 500 WHERE k = '%d-boo1';", id)); assertThat( - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow("T", Key.of(String.format("%d-boo1", id)), Collections.singletonList("V")) .getLong(0)) @@ -235,7 +284,7 @@ public void standardDMLReadYourWrites() { .isEqualTo(2 * 2); return null; }; - TransactionRunner runner = client.readWriteTransaction(); + TransactionRunner runner = getClient(dialect.dialect).readWriteTransaction(); runner.run(callable); executeUpdate(DML_COUNT, deleteDml()); @@ -256,7 +305,7 @@ class UserException extends Exception { }; try { - TransactionRunner runner = client.readWriteTransaction(); + TransactionRunner runner = getClient(dialect.dialect).readWriteTransaction(); runner.run(callable); fail("Expected user exception"); } catch (SpannerException e) { @@ -266,7 +315,7 @@ class UserException extends Exception { } ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read( "T", @@ -292,13 +341,13 @@ public void standardDMLAndMutations() { Mutation.newInsertOrUpdateBuilder("T").set("K").to(key2).set("V").to(2).build()); return null; }; - TransactionRunner runner = client.readWriteTransaction(); + TransactionRunner runner = getClient(dialect.dialect).readWriteTransaction(); runner.run(callable); KeySet.Builder keys = KeySet.newBuilder(); keys.addKey(Key.of(key1)).addKey(Key.of(key2)); ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read("T", keys.build(), Collections.singletonList("K")); int rowCount = 0; @@ -320,7 +369,7 @@ private void executeQuery(long expectedCount, final String... stmts) { } return rowCount; }; - TransactionRunner runner = client.readWriteTransaction(); + TransactionRunner runner = getClient(dialect.dialect).readWriteTransaction(); Long rowCount = runner.run(callable); assertThat(rowCount).isEqualTo(expectedCount); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminDialectAwareTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminDialectAwareTest.java new file mode 100644 index 00000000000..584dc1fc247 --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminDialectAwareTest.java @@ -0,0 +1,120 @@ +/* + * Copyright 2022 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.it; + +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; + +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.IntegrationTestEnv; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.testing.RemoteSpannerHelper; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; +import java.util.stream.StreamSupport; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +/** Dialect aware integration tests for {@link com.google.cloud.spanner.DatabaseAdminClient}. */ +@Category(ParallelIntegrationTest.class) +@RunWith(Parameterized.class) +public class ITDatabaseAdminDialectAwareTest { + + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(20); + private DatabaseAdminClient client; + private RemoteSpannerHelper testHelper; + private List databases; + + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + @Before + public void setUp() { + testHelper = env.getTestHelper(); + client = testHelper.getClient().getDatabaseAdminClient(); + databases = new ArrayList<>(); + } + + @After + public void tearDown() { + if (databases != null) { + for (DatabaseId id : databases) { + try { + client.dropDatabase(id.getInstanceId().getInstance(), id.getDatabase()); + } catch (Exception e) { + System.err.println("Could not drop database " + id + ", skipping...: " + e.getMessage()); + } + } + } + } + + @Test + public void testCreateDatabaseWithDialect() throws Exception { + assumeFalse("emulator does not support different dialects", isUsingEmulator()); + + final String projectId = testHelper.getInstanceId().getProject(); + final String instanceId = testHelper.getInstanceId().getInstance(); + final String databaseId = testHelper.getUniqueDatabaseId(); + + final Database databaseToCreate = + client + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(dialect) + .build(); + databases.add(databaseToCreate.getId()); + + // Creates the database with the dialect set + final Database createdDatabase = + client + .createDatabase(databaseToCreate, Collections.emptyList()) + .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + assertEquals(dialect, createdDatabase.getDialect()); + + // Test dialect in database retrieval + final Database retrievedDatabase = client.getDatabase(instanceId, databaseId); + assertEquals(dialect, retrievedDatabase.getDialect()); + + // Test dialect database listing + final Optional maybeListedDatabase = + StreamSupport.stream(client.listDatabases(instanceId).iterateAll().spliterator(), false) + .filter(database -> database.getId().getDatabase().equals(databaseId)) + .findFirst(); + assertTrue("Expected to find database in list", maybeListedDatabase.isPresent()); + assertEquals(dialect, maybeListedDatabase.get().getDialect()); + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminTest.java index 5559177d537..bc9a075e0ca 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDatabaseAdminTest.java @@ -17,12 +17,15 @@ package com.google.cloud.spanner.it; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.paging.Page; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Options; @@ -31,11 +34,11 @@ import com.google.cloud.spanner.testing.RemoteSpannerHelper; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; import com.google.spanner.admin.database.v1.CreateDatabaseMetadata; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Before; @@ -70,44 +73,52 @@ public void tearDown() { } @Test - public void databaseOperations() throws Exception { - String dbId = testHelper.getUniqueDatabaseId(); - String instanceId = testHelper.getInstanceId().getInstance(); - String statement1 = "CREATE TABLE T (\n" + " K STRING(MAX),\n" + ") PRIMARY KEY(K)"; - OperationFuture op = - dbAdminClient.createDatabase(instanceId, dbId, ImmutableList.of(statement1)); - Database db = op.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); - dbs.add(db); - assertThat(db.getId().getDatabase()).isEqualTo(dbId); - - db = dbAdminClient.getDatabase(instanceId, dbId); - assertThat(db.getId().getDatabase()).isEqualTo(dbId); - - boolean foundDb = false; - for (Database dbInList : - Iterators.toArray( - dbAdminClient.listDatabases(instanceId).iterateAll().iterator(), Database.class)) { - if (dbInList.getId().getDatabase().equals(dbId)) { - foundDb = true; + public void testDatabaseOperations() throws Exception { + final String databaseId = testHelper.getUniqueDatabaseId(); + final String instanceId = testHelper.getInstanceId().getInstance(); + final String createTableT = "CREATE TABLE T (\n" + " K STRING(MAX),\n" + ") PRIMARY KEY(K)"; + + final Database createdDatabase = + dbAdminClient + .createDatabase(instanceId, databaseId, ImmutableList.of(createTableT)) + .get(5, TimeUnit.MINUTES); + dbs.add(createdDatabase); + + assertEquals(databaseId, createdDatabase.getId().getDatabase()); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, createdDatabase.getDialect()); + + final Database retrievedDatabase = dbAdminClient.getDatabase(instanceId, databaseId); + assertEquals(databaseId, retrievedDatabase.getId().getDatabase()); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, retrievedDatabase.getDialect()); + + Optional maybeDatabaseInList = Optional.empty(); + for (Database listedDatabase : dbAdminClient.listDatabases(instanceId).iterateAll()) { + if (listedDatabase.getId().getDatabase().equals(databaseId)) { + maybeDatabaseInList = Optional.of(listedDatabase); break; } } - assertThat(foundDb).isTrue(); + assertTrue("Expected to find database in list", maybeDatabaseInList.isPresent()); + assertEquals(databaseId, maybeDatabaseInList.get().getId().getDatabase()); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, maybeDatabaseInList.get().getDialect()); - String statement2 = "CREATE TABLE T2 (\n" + " K2 STRING(MAX),\n" + ") PRIMARY KEY(K2)"; - OperationFuture op2 = - dbAdminClient.updateDatabaseDdl(instanceId, dbId, ImmutableList.of(statement2), null); - op2.get(TIMEOUT_MINUTES, TimeUnit.MINUTES); - List statementsInDb = dbAdminClient.getDatabaseDdl(instanceId, dbId); - assertThat(statementsInDb).containsExactly(statement1, statement2); + final String createTableT2 = + "CREATE TABLE T2 (\n" + " K2 STRING(MAX),\n" + ") PRIMARY KEY(K2)"; + dbAdminClient + .updateDatabaseDdl(instanceId, databaseId, ImmutableList.of(createTableT2), null) + .get(5, TimeUnit.MINUTES); - dbAdminClient.dropDatabase(instanceId, dbId); + final List databaseDdl = dbAdminClient.getDatabaseDdl(instanceId, databaseId); + assertEquals(databaseDdl, ImmutableList.of(createTableT, createTableT2)); + + dbAdminClient.dropDatabase(instanceId, databaseId); dbs.clear(); + try { - dbAdminClient.getDatabase(testHelper.getInstanceId().getInstance(), dbId); + dbAdminClient.getDatabase(instanceId, databaseId); fail("Expected exception"); - } catch (SpannerException ex) { - assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND); + } catch (SpannerException e) { + assertEquals(ErrorCode.NOT_FOUND, e.getErrorCode()); } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITLargeReadTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITLargeReadTest.java index 3fa99c225f3..b60505c873a 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITLargeReadTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITLargeReadTest.java @@ -16,11 +16,13 @@ package com.google.cloud.spanner.it; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static com.google.common.truth.Truth.assertThat; import com.google.cloud.ByteArray; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.KeySet; import com.google.cloud.spanner.Mutation; @@ -28,6 +30,7 @@ import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; import java.util.ArrayList; @@ -35,19 +38,20 @@ import java.util.Collections; import java.util.List; import java.util.Random; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; /** * Integration test reading large amounts of data. The size of data ensures that multiple chunks are * returned by the server. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITLargeReadTest { private static int numRows; @@ -56,9 +60,9 @@ public class ITLargeReadTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static Database db; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; private static HashFunction hasher; - private static DatabaseClient client; // Generate a combination of small and large row sizes to allow multiple read/query restarts and // to exercise chunking. @@ -74,7 +78,7 @@ private static List rowSizes() { @BeforeClass public static void setUpDatabase() { - db = + Database googleStandardSQLDatabase = env.getTestHelper() .createTestDatabase( "CREATE TABLE TestTable (" @@ -83,8 +87,22 @@ public static void setUpDatabase() { + " Fingerprint INT64," + " Size INT64," + ") PRIMARY KEY (Key)"); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + if (!isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, + Arrays.asList( + "CREATE TABLE TestTable (" + + " Key BIGINT PRIMARY KEY," + + " Data BYTEA," + + " Fingerprint BIGINT," + + " Size BIGINT" + + ")")); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } hasher = Hashing.goodFastHash(64); - client = env.getTestHelper().getDatabaseClient(db); List mutations = new ArrayList<>(); Random rnd = new Random(); @@ -108,18 +126,50 @@ public static void setUpDatabase() { totalSize += rowSize; i++; if (totalSize >= WRITE_BATCH_SIZE) { - client.write(mutations); + googleStandardSQLClient.write(mutations); + if (!isUsingEmulator()) { + postgreSQLClient.write(mutations); + } mutations.clear(); totalSize = 0; } } - client.write(mutations); + googleStandardSQLClient.write(mutations); + if (!isUsingEmulator()) { + postgreSQLClient.write(mutations); + } + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); + } + + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + // "PG dialect tests are not supported by the emulator" + if (!isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter(0) + public DialectTestParameter dialect; + + private DatabaseClient getClient(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return postgreSQLClient; + } + return googleStandardSQLClient; } @Test public void read() { try (ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse() .read(TABLE_NAME, KeySet.all(), Arrays.asList("Key", "Data", "Fingerprint", "Size"))) { validate(resultSet); @@ -129,7 +179,7 @@ public void read() { @Test public void readWithSmallPrefetchChunks() { try (ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse() .read( TABLE_NAME, @@ -143,7 +193,7 @@ public void readWithSmallPrefetchChunks() { @Test public void query() { try (ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse() .executeQuery( Statement.of( @@ -155,7 +205,7 @@ public void query() { @Test public void queryWithSmallPrefetchChunks() { try (ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse() .executeQuery( Statement.of( diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITPgNumericTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITPgNumericTest.java new file mode 100644 index 00000000000..b5fc084a54c --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITPgNumericTest.java @@ -0,0 +1,472 @@ +/* + * Copyright 2022 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.it; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; +import com.google.cloud.spanner.IntegrationTestEnv; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ParallelIntegrationTest; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; +import com.google.cloud.spanner.testing.RemoteSpannerHelper; +import com.google.common.collect.ImmutableList; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; + +@Category(ParallelIntegrationTest.class) +@RunWith(JUnit4.class) +public class ITPgNumericTest { + + private static final Duration OPERATION_TIMEOUT = Duration.ofMinutes(5); + + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + private static RemoteSpannerHelper testHelper; + private static DatabaseAdminClient databaseAdminClient; + private static List databasesToDrop; + private static String projectId; + private static String instanceId; + private static String databaseId; + private DatabaseClient databaseClient; + private String tableName; + + @BeforeClass + public static void beforeClass() throws Exception { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + testHelper = env.getTestHelper(); + databaseAdminClient = testHelper.getClient().getDatabaseAdminClient(); + databasesToDrop = new ArrayList<>(); + projectId = testHelper.getInstanceId().getProject(); + instanceId = testHelper.getInstanceId().getInstance(); + databaseId = testHelper.getUniqueDatabaseId(); + final Database database = + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .setDialect(Dialect.POSTGRESQL) + .build(); + databaseAdminClient + .createDatabase(database, Collections.emptyList()) + .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + databasesToDrop.add(database.getId()); + } + + @AfterClass + public static void afterClass() throws Exception { + if (databasesToDrop != null) { + for (DatabaseId id : databasesToDrop) { + try { + databaseAdminClient.dropDatabase(id.getInstanceId().getInstance(), id.getDatabase()); + } catch (Exception e) { + System.err.println("Failed to drop database " + id + ", skipping...: " + e.getMessage()); + } + } + } + } + + @Before + public void setUp() throws Exception { + databaseClient = + testHelper.getClient().getDatabaseClient(DatabaseId.of(projectId, instanceId, databaseId)); + tableName = testHelper.getUniqueDatabaseId(); + databaseAdminClient + .updateDatabaseDdl( + instanceId, + databaseId, + Collections.singletonList( + "CREATE TABLE \"" + tableName + "\" (id BIGINT PRIMARY KEY, col1 NUMERIC)"), + null) + .get(OPERATION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS); + } + + @Test + public void testLiteralPgNumeric() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.executeUpdate( + Statement.of( + "INSERT INTO " + + tableName + + " (id, col1) VALUES" + + " (1, 1.23)" + + ", (2, 'NaN')" + + ", (3, null)")); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertEquals("NaN", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } + + @Test + public void testParameterizedWithPgNumericAsValue() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.executeUpdate( + Statement.newBuilder( + "INSERT INTO " + + tableName + + " (id, col1) VALUES" + + " (1, $1)" + + ", (2, $2)" + + ", (3, $3)") + .bind("p1") + .to(Value.pgNumeric("1.23")) + .bind("p2") + .to(Value.pgNumeric("NaN")) + .bind("p3") + .to(Value.pgNumeric(null)) + .build()); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertEquals("NaN", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } + + @Test + public void testParameterizedWithPgNumericAsDouble() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.executeUpdate( + Statement.newBuilder( + "INSERT INTO " + + tableName + + " (id, col1) VALUES" + + " (1, $1)" + + ", (2, $2)" + + ", (3, $3)") + .bind("p1") + .to(1.23D) + .bind("p2") + .to(Double.NaN) + .bind("p3") + .to((Double) null) + .build()); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertEquals("NaN", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } + + @Test + public void testParameterizedWithPgNumericAsInt() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.executeUpdate( + Statement.newBuilder("INSERT INTO " + tableName + " (id, col1) VALUES (1, $1)") + .bind("p1") + .to(1) + .build()); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1"), resultSet.getValue("col1")); + } + } + + @Test + public void testParameterizedWithPgNumericAsLong() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.executeUpdate( + Statement.newBuilder("INSERT INTO " + tableName + " (id, col1) VALUES (1, $1)") + .bind("p1") + .to(1L) + .build()); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1"), resultSet.getValue("col1")); + } + } + + @Test + public void testMutationsWithPgNumericAsString() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer( + ImmutableList.of( + Mutation.newInsertBuilder(tableName) + .set("id") + .to(1) + .set("col1") + .to("1.23") + .build(), + Mutation.newInsertBuilder(tableName) + .set("id") + .to(2) + .set("col1") + .to("NaN") + .build(), + Mutation.newInsertBuilder(tableName) + .set("id") + .to(3) + .set("col1") + .to((String) null) + .build())); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertEquals("NaN", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } + + @Test + public void testMutationsWithPgNumericAsInt() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer( + ImmutableList.of( + Mutation.newInsertBuilder(tableName) + .set("id") + .to(1) + .set("col1") + .to(1) + .build())); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1"), resultSet.getValue("col1")); + } + } + + @Test + public void testMutationsWithPgNumericAsLong() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer( + ImmutableList.of( + Mutation.newInsertBuilder(tableName) + .set("id") + .to(1) + .set("col1") + .to(1L) + .build())); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1"), resultSet.getValue("col1")); + } + } + + @Test + public void testMutationsWithPgNumericAsBigDecimal() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer( + ImmutableList.of( + Mutation.newInsertBuilder(tableName) + .set("id") + .to(1) + .set("col1") + .to(new BigDecimal("1.23")) + .build(), + Mutation.newInsertBuilder(tableName) + .set("id") + .to(3) + .set("col1") + .to((BigDecimal) null) + .build())); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } + + @Test + public void testMutationsWithPgNumericAsValue() { + assumeFalse( + "PgNumeric is not supported in the emulator", EmulatorSpannerHelper.isUsingEmulator()); + databaseClient + .readWriteTransaction() + .run( + transaction -> { + transaction.buffer( + ImmutableList.of( + Mutation.newInsertBuilder(tableName) + .set("id") + .to(1) + .set("col1") + .to(Value.pgNumeric("1.23")) + .build(), + Mutation.newInsertBuilder(tableName) + .set("id") + .to(2) + .set("col1") + .to(Value.pgNumeric("NaN")) + .build(), + Mutation.newInsertBuilder(tableName) + .set("id") + .to(3) + .set("col1") + .to(Value.pgNumeric(null)) + .build())); + return null; + }); + + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT * FROM " + tableName))) { + + resultSet.next(); + assertEquals("1.23", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("1.23"), resultSet.getValue("col1")); + + resultSet.next(); + assertEquals("NaN", resultSet.getString("col1")); + assertEquals(Value.pgNumeric("NaN"), resultSet.getValue("col1")); + + resultSet.next(); + assertTrue(resultSet.isNull("col1")); + } + } +} diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java index e0e887624bf..f07bffc2d8f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITQueryTest.java @@ -30,6 +30,7 @@ import com.google.cloud.Timestamp; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Mutation; @@ -43,6 +44,7 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; @@ -52,27 +54,69 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; /** Integration tests for query execution. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITQueryTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static Database db; - private static DatabaseClient client; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; + private String selectValueQuery; @BeforeClass public static void setUpDatabase() { // Empty database. - db = env.getTestHelper().createTestDatabase(); - client = env.getTestHelper().getDatabaseClient(db); + Database googleStandardSQLDatabase = env.getTestHelper().createTestDatabase(); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + if (!isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper().createTestDatabase(Dialect.POSTGRESQL, Collections.emptyList()); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); + } + + @Before + public void initSelectValueQuery() { + selectValueQuery = "SELECT @p1"; + if (dialect.dialect == Dialect.POSTGRESQL) { + selectValueQuery = "SELECT $1"; + } + } + + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + // "PG dialect tests are not supported by the emulator" + if (!isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter(0) + public DialectTestParameter dialect; + + private DatabaseClient getClient(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return postgreSQLClient; + } + return googleStandardSQLClient; } @Test @@ -88,12 +132,17 @@ public void badQuery() { fail("Expected exception"); } catch (SpannerException ex) { assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); - assertThat(ex.getMessage()).contains("Unrecognized name: Apples"); + if (dialect.dialect == Dialect.POSTGRESQL) { + assertThat(ex.getMessage()).contains("column \"apples\" does not exist"); + } else { + assertThat(ex.getMessage()).contains("Unrecognized name: Apples"); + } } } @Test public void arrayOfStruct() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Type structType = Type.struct(StructField.of("C1", Type.string()), StructField.of("C2", Type.int64())); Struct row = @@ -131,6 +180,7 @@ public void arrayOfStruct() { @Test public void arrayOfStructEmpty() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Type structType = Type.struct(StructField.of("", Type.string()), StructField.of("", Type.int64())); Struct row = @@ -176,7 +226,8 @@ public void arrayOfStructNullElement() { @Test public void bindBool() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(true).build(), Type.bool()); + Struct row = + execute(Statement.newBuilder(selectValueQuery).bind("p1").to(true).build(), Type.bool()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBoolean(0)).isEqualTo(true); } @@ -184,26 +235,27 @@ public void bindBool() { @Test public void bindBoolNull() { Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((Boolean) null), Type.bool()); + execute(Statement.newBuilder(selectValueQuery).bind("p1").to((Boolean) null), Type.bool()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindInt64() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(1234), Type.int64()); + Struct row = execute(Statement.newBuilder(selectValueQuery).bind("p1").to(1234), Type.int64()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getLong(0)).isEqualTo(1234); } @Test public void bindInt64Null() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to((Long) null), Type.int64()); + Struct row = + execute(Statement.newBuilder(selectValueQuery).bind("p1").to((Long) null), Type.int64()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindFloat64() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(2.0), Type.float64()); + Struct row = execute(Statement.newBuilder(selectValueQuery).bind("p1").to(2.0), Type.float64()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getDouble(0)).isWithin(0.0).of(2.0); } @@ -211,13 +263,15 @@ public void bindFloat64() { @Test public void bindFloat64Null() { Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((Double) null), Type.float64()); + execute( + Statement.newBuilder(selectValueQuery).bind("p1").to((Double) null), Type.float64()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindString() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to("abc"), Type.string()); + Struct row = + execute(Statement.newBuilder(selectValueQuery).bind("p1").to("abc"), Type.string()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getString(0)).isEqualTo("abc"); } @@ -225,17 +279,18 @@ public void bindString() { @Test public void bindStringNull() { Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((String) null), Type.string()); + execute(Statement.newBuilder(selectValueQuery).bind("p1").to((String) null), Type.string()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindJson() { + assumeFalse("JSON are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v") - .bind("v") + Statement.newBuilder(selectValueQuery) + .bind("p1") .to(Value.json("{\"rating\":9,\"open\":true}")), Type.json()); assertThat(row.isNull(0)).isFalse(); @@ -244,18 +299,22 @@ public void bindJson() { @Test public void bindJsonEmpty() { + assumeFalse("JSON are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to(Value.json("{}")), Type.json()); + execute( + Statement.newBuilder(selectValueQuery).bind("p1").to(Value.json("{}")), Type.json()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getJson(0)).isEqualTo("{}"); } @Test public void bindJsonNull() { + assumeFalse("JSON is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to(Value.json(null)), Type.json()); + execute( + Statement.newBuilder(selectValueQuery).bind("p1").to(Value.json(null)), Type.json()); assertThat(row.isNull(0)).isTrue(); } @@ -263,7 +322,7 @@ public void bindJsonNull() { public void bindBytes() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").to(ByteArray.copyFrom("xyz")), + Statement.newBuilder(selectValueQuery).bind("p1").to(ByteArray.copyFrom("xyz")), Type.bytes()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBytes(0)).isEqualTo(ByteArray.copyFrom("xyz")); @@ -272,14 +331,15 @@ public void bindBytes() { @Test public void bindBytesNull() { Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((ByteArray) null), Type.bytes()); + execute( + Statement.newBuilder(selectValueQuery).bind("p1").to((ByteArray) null), Type.bytes()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindTimestamp() { Timestamp t = Timestamp.parseTimestamp("2016-09-18T00:00:00Z"); - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(t), Type.timestamp()); + Struct row = execute(Statement.newBuilder(selectValueQuery).bind("p1").to(t), Type.timestamp()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getTimestamp(0)).isEqualTo(t); } @@ -287,21 +347,26 @@ public void bindTimestamp() { @Test public void bindTimestampNull() { Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((Timestamp) null), Type.timestamp()); + execute( + Statement.newBuilder(selectValueQuery).bind("p1").to((Timestamp) null), + Type.timestamp()); assertThat(row.isNull(0)).isTrue(); } @Test public void bindDate() { + assumeFalse("date type is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Date d = Date.parseDate("2016-09-18"); - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(d), Type.date()); + Struct row = execute(Statement.newBuilder(selectValueQuery).bind("p1").to(d), Type.date()); assertThat(row.isNull(0)).isFalse(); assertThat(row.getDate(0)).isEqualTo(d); } @Test public void bindDateNull() { - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to((Date) null), Type.date()); + assumeFalse("date type is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); + Struct row = + execute(Statement.newBuilder(selectValueQuery).bind("p1").to((Date) null), Type.date()); assertThat(row.isNull(0)).isTrue(); } @@ -309,16 +374,39 @@ public void bindDateNull() { public void bindNumeric() { assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); BigDecimal b = new BigDecimal("1.1"); - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(b), Type.numeric()); + Statement.Builder statement = Statement.newBuilder(selectValueQuery); + Type expectedType = Type.numeric(); + Object expectedValue = b; + if (dialect.dialect == Dialect.POSTGRESQL) { + expectedType = Type.pgNumeric(); + expectedValue = Value.pgNumeric(b.toString()); + statement.bind("p1").to(Value.pgNumeric(b.toString())); + } else { + statement.bind("p1").to(b); + } + Struct row = execute(statement, expectedType); assertThat(row.isNull(0)).isFalse(); - assertThat(row.getBigDecimal(0)).isEqualTo(b); + Object got; + if (dialect.dialect == Dialect.POSTGRESQL) { + got = row.getValue(0); + } else { + got = row.getBigDecimal(0); + } + assertThat(got).isEqualTo(expectedValue); } @Test public void bindNumericNull() { assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); - Struct row = - execute(Statement.newBuilder("SELECT @v").bind("v").to((BigDecimal) null), Type.numeric()); + Statement.Builder statement = Statement.newBuilder(selectValueQuery); + Type expectedType = Type.numeric(); + if (dialect.dialect == Dialect.POSTGRESQL) { + expectedType = Type.pgNumeric(); + statement.bind("p1").to(Value.pgNumeric(null)); + } else { + statement.bind("p1").to((BigDecimal) null); + } + Struct row = execute(statement, expectedType); assertThat(row.isNull(0)).isTrue(); } @@ -326,18 +414,37 @@ public void bindNumericNull() { public void bindNumeric_doesNotPreservePrecision() { assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); BigDecimal b = new BigDecimal("1.10"); - Struct row = execute(Statement.newBuilder("SELECT @v").bind("v").to(b), Type.numeric()); - assertThat(row.isNull(0)).isFalse(); + Statement.Builder statement = Statement.newBuilder(selectValueQuery); + Type expectedType = Type.numeric(); // Cloud Spanner does not store precision, and will therefore return 1.10 as 1.1. - assertThat(row.getBigDecimal(0)).isNotEqualTo(b); - assertThat(row.getBigDecimal(0)).isEqualTo(b.stripTrailingZeros()); + Object expectedValue = b.stripTrailingZeros(); + if (dialect.dialect == Dialect.POSTGRESQL) { + expectedType = Type.pgNumeric(); + // Cloud Spanner with PG dialect store precision, and will therefore return 1.10. + expectedValue = Value.pgNumeric(b.toString()); + statement.bind("p1").to(Value.pgNumeric(b.toString())); + } else { + statement.bind("p1").to(b); + } + Struct row = execute(statement, expectedType); + assertThat(row.isNull(0)).isFalse(); + Object got; + if (dialect.dialect == Dialect.POSTGRESQL) { + got = row.getValue(0); + } else { + got = row.getBigDecimal(0); + } + assertThat(got).isNotEqualTo(b); + assertThat(got).isEqualTo(expectedValue); } @Test public void bindBoolArray() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBoolArray(asList(true, null, false)), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toBoolArray(asList(true, null, false)), Type.array(Type.bool())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBooleanList(0)).containsExactly(true, null, false).inOrder(); @@ -347,7 +454,7 @@ public void bindBoolArray() { public void bindBoolArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBoolArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery).bind("p1").toBoolArray(Collections.emptyList()), Type.array(Type.bool())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBooleanList(0)).containsExactly(); @@ -357,7 +464,7 @@ public void bindBoolArrayEmpty() { public void bindBoolArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBoolArray((boolean[]) null), + Statement.newBuilder(selectValueQuery).bind("p1").toBoolArray((boolean[]) null), Type.array(Type.bool())); assertThat(row.isNull(0)).isTrue(); } @@ -366,7 +473,7 @@ public void bindBoolArrayNull() { public void bindInt64Array() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toInt64Array(asList(null, 1L, 2L)), + Statement.newBuilder(selectValueQuery).bind("p1").toInt64Array(asList(null, 1L, 2L)), Type.array(Type.int64())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getLongList(0)).containsExactly(null, 1L, 2L).inOrder(); @@ -376,7 +483,7 @@ public void bindInt64Array() { public void bindInt64ArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toInt64Array(Collections.emptyList()), + Statement.newBuilder(selectValueQuery).bind("p1").toInt64Array(Collections.emptyList()), Type.array(Type.int64())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getLongList(0)).containsExactly(); @@ -386,7 +493,7 @@ public void bindInt64ArrayEmpty() { public void bindInt64ArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toInt64Array((long[]) null), + Statement.newBuilder(selectValueQuery).bind("p1").toInt64Array((long[]) null), Type.array(Type.int64())); assertThat(row.isNull(0)).isTrue(); } @@ -395,8 +502,8 @@ public void bindInt64ArrayNull() { public void bindFloat64Array() { Struct row = execute( - Statement.newBuilder("SELECT @v") - .bind("v") + Statement.newBuilder(selectValueQuery) + .bind("p1") .toFloat64Array( asList( null, @@ -417,7 +524,9 @@ public void bindFloat64Array() { public void bindFloat64ArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toFloat64Array(Collections.emptyList()), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toFloat64Array(Collections.emptyList()), Type.array(Type.float64())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getDoubleList(0)).containsExactly(); @@ -427,7 +536,7 @@ public void bindFloat64ArrayEmpty() { public void bindFloat64ArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toFloat64Array((double[]) null), + Statement.newBuilder(selectValueQuery).bind("p1").toFloat64Array((double[]) null), Type.array(Type.float64())); assertThat(row.isNull(0)).isTrue(); } @@ -436,7 +545,7 @@ public void bindFloat64ArrayNull() { public void bindStringArray() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toStringArray(asList("a", "b", null)), + Statement.newBuilder(selectValueQuery).bind("p1").toStringArray(asList("a", "b", null)), Type.array(Type.string())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getStringList(0)).containsExactly("a", "b", null).inOrder(); @@ -446,7 +555,9 @@ public void bindStringArray() { public void bindStringArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toStringArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toStringArray(Collections.emptyList()), Type.array(Type.string())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getStringList(0)).containsExactly(); @@ -456,18 +567,20 @@ public void bindStringArrayEmpty() { public void bindStringArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toStringArray(null), + Statement.newBuilder(selectValueQuery).bind("p1").toStringArray(null), Type.array(Type.string())); assertThat(row.isNull(0)).isTrue(); } @Test public void bindJsonArray() { + assumeFalse( + "array JSON binding is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v") - .bind("v") + Statement.newBuilder(selectValueQuery) + .bind("p1") .toJsonArray(asList("{}", "[]", "{\"rating\":9,\"open\":true}", null)), Type.array(Type.json())); assertThat(row.isNull(0)).isFalse(); @@ -478,10 +591,11 @@ public void bindJsonArray() { @Test public void bindJsonArrayEmpty() { + assumeFalse("JSON is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toJsonArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery).bind("p1").toJsonArray(Collections.emptyList()), Type.array(Type.json())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getJsonList(0)).isEqualTo(Collections.emptyList()); @@ -489,10 +603,12 @@ public void bindJsonArrayEmpty() { @Test public void bindJsonArrayNull() { + assumeFalse("JSON is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toJsonArray(null), Type.array(Type.json())); + Statement.newBuilder(selectValueQuery).bind("p1").toJsonArray(null), + Type.array(Type.json())); assertThat(row.isNull(0)).isTrue(); } @@ -503,7 +619,7 @@ public void bindBytesArray() { ByteArray e3 = null; Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBytesArray(asList(e1, e2, e3)), + Statement.newBuilder(selectValueQuery).bind("p1").toBytesArray(asList(e1, e2, e3)), Type.array(Type.bytes())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBytesList(0)).containsExactly(e1, e2, e3).inOrder(); @@ -513,7 +629,7 @@ public void bindBytesArray() { public void bindBytesArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBytesArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery).bind("p1").toBytesArray(Collections.emptyList()), Type.array(Type.bytes())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBytesList(0)).isEmpty(); @@ -523,7 +639,7 @@ public void bindBytesArrayEmpty() { public void bindBytesArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toBytesArray(null), + Statement.newBuilder(selectValueQuery).bind("p1").toBytesArray(null), Type.array(Type.bytes())); assertThat(row.isNull(0)).isTrue(); } @@ -535,7 +651,9 @@ public void bindTimestampArray() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toTimestampArray(asList(t1, t2, null)), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toTimestampArray(asList(t1, t2, null)), Type.array(Type.timestamp())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getTimestampList(0)).containsExactly(t1, t2, null).inOrder(); @@ -545,7 +663,9 @@ public void bindTimestampArray() { public void bindTimestampArrayEmpty() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toTimestampArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toTimestampArray(Collections.emptyList()), Type.array(Type.timestamp())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getTimestampList(0)).containsExactly(); @@ -555,13 +675,14 @@ public void bindTimestampArrayEmpty() { public void bindTimestampArrayNull() { Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toTimestampArray(null), + Statement.newBuilder(selectValueQuery).bind("p1").toTimestampArray(null), Type.array(Type.timestamp())); assertThat(row.isNull(0)).isTrue(); } @Test public void bindDateArray() { + assumeFalse("date type is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Date d1 = Date.parseDate("2016-09-18"); Date d2 = Date.parseDate("2016-09-19"); @@ -575,6 +696,7 @@ public void bindDateArray() { @Test public void bindDateArrayEmpty() { + assumeFalse("date type is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute( Statement.newBuilder("SELECT @v").bind("v").toDateArray(Collections.emptyList()), @@ -585,6 +707,7 @@ public void bindDateArrayEmpty() { @Test public void bindDateArrayNull() { + assumeFalse("date type is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute( Statement.newBuilder("SELECT @v").bind("v").toDateArray(null), Type.array(Type.date())); @@ -593,13 +716,16 @@ public void bindDateArrayNull() { @Test public void bindNumericArray() { + assumeFalse( + "array numeric binding is not supported on POSTGRESQL", + dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); BigDecimal b1 = new BigDecimal("3.14"); BigDecimal b2 = new BigDecimal("6.626"); Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toNumericArray(asList(b1, b2, null)), + Statement.newBuilder(selectValueQuery).bind("p1").toNumericArray(asList(b1, b2, null)), Type.array(Type.numeric())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBigDecimalList(0)).containsExactly(b1, b2, null).inOrder(); @@ -607,10 +733,15 @@ public void bindNumericArray() { @Test public void bindNumericArrayEmpty() { + assumeFalse( + "array numeric binding is not supported on POSTGRESQL", + dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toNumericArray(Collections.emptyList()), + Statement.newBuilder(selectValueQuery) + .bind("p1") + .toNumericArray(Collections.emptyList()), Type.array(Type.numeric())); assertThat(row.isNull(0)).isFalse(); assertThat(row.getBigDecimalList(0)).containsExactly(); @@ -618,16 +749,22 @@ public void bindNumericArrayEmpty() { @Test public void bindNumericArrayNull() { + assumeFalse( + "array numeric binding is not supported on POSTGRESQL", + dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); Struct row = execute( - Statement.newBuilder("SELECT @v").bind("v").toNumericArray(null), + Statement.newBuilder(selectValueQuery).bind("p1").toNumericArray(null), Type.array(Type.numeric())); assertThat(row.isNull(0)).isTrue(); } @Test public void bindNumericArray_doesNotPreservePrecision() { + assumeFalse( + "array numeric binding is not supported on POSTGRESQL", + dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); BigDecimal b1 = new BigDecimal("3.14"); BigDecimal b2 = new BigDecimal("6.626070"); @@ -644,10 +781,11 @@ public void bindNumericArray_doesNotPreservePrecision() { @Test public void unsupportedSelectStructValue() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("The emulator accepts this query", isUsingEmulator()); Struct p = structValue(); try { - execute(Statement.newBuilder("SELECT @p").bind("p").to(p).build(), p.getType()); + execute(Statement.newBuilder(selectValueQuery).bind("p1").to(p).build(), p.getType()); fail("Expected exception"); } catch (SpannerException ex) { assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.UNIMPLEMENTED); @@ -659,6 +797,7 @@ public void unsupportedSelectStructValue() { @Test public void unsupportedSelectArrayStructValue() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); assumeFalse( "Emulator evaluates this expression differently than Cloud Spanner", isUsingEmulator()); @@ -683,6 +822,7 @@ public void unsupportedSelectArrayStructValue() { @Test public void invalidAmbiguousFieldAccess() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder().set("f1").to(20).set("f1").to("abc").build(); try { execute(Statement.newBuilder("SELECT @p.f1").bind("p").to(p).build(), Type.int64()); @@ -714,6 +854,7 @@ private Struct structValue() { @Test public void bindStruct() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = structValue(); String query = "SELECT " @@ -732,6 +873,7 @@ public void bindStruct() { @Test public void bindArrayOfStruct() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct arrayElement = structValue(); List p = asList(arrayElement, null); @@ -756,6 +898,7 @@ public void bindArrayOfStruct() { @Test public void bindStructNull() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute( Statement.newBuilder("SELECT @p IS NULL") @@ -773,6 +916,7 @@ public void bindStructNull() { @Test public void bindArrayOfStructNull() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Type elementType = Type.struct( asList( @@ -791,6 +935,7 @@ public void bindArrayOfStructNull() { @Test public void bindEmptyStruct() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder().build(); Struct row = execute(Statement.newBuilder("SELECT @p IS NULL").bind("p").to(p).build(), Type.bool()); @@ -799,6 +944,7 @@ public void bindEmptyStruct() { @Test public void bindStructWithUnnamedFields() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder().add(Value.int64(1337)).add(Value.int64(7331)).build(); Struct row = executeWithRowResultType( @@ -810,6 +956,7 @@ public void bindStructWithUnnamedFields() { @Test public void bindStructWithDuplicateFieldNames() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder() .set("f1") @@ -827,6 +974,7 @@ public void bindStructWithDuplicateFieldNames() { @Test public void bindEmptyArrayOfStruct() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Type elementType = Type.struct(Collections.singletonList(StructField.of("f1", Type.date()))); List p = Collections.emptyList(); assertThat(p).isEmpty(); @@ -843,6 +991,7 @@ public void bindEmptyArrayOfStruct() { @Test public void bindStructWithNullStructField() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Type emptyStructType = Type.struct(new ArrayList<>()); Struct p = Struct.newBuilder().set("f1").to(emptyStructType, null).build(); @@ -853,6 +1002,7 @@ public void bindStructWithNullStructField() { @Test public void bindStructWithBoolArrayFieldThatContainsNulls() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder() .set("boolArray") @@ -872,6 +1022,7 @@ public void bindStructWithBoolArrayFieldThatContainsNulls() { @Test public void bindStructWithInt64ArrayFieldThatContainsNulls() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder() .set("int64Array") @@ -891,6 +1042,7 @@ public void bindStructWithInt64ArrayFieldThatContainsNulls() { @Test public void bindStructWithFloat64ArrayFieldThatContainsNulls() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct p = Struct.newBuilder() .set("float64Array") @@ -910,6 +1062,7 @@ public void bindStructWithFloat64ArrayFieldThatContainsNulls() { @Test public void bindStructWithStructField() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct nestedStruct = Struct.newBuilder().set("ff1").to("abc").build(); Struct p = Struct.newBuilder().set("f1").to(nestedStruct).build(); @@ -922,6 +1075,7 @@ public void bindStructWithStructField() { @Test public void bindStructWithArrayOfStructField() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct arrayElement1 = Struct.newBuilder().set("ff1").to("abc").build(); Struct arrayElement2 = Struct.newBuilder().set("ff1").to("def").build(); Struct p = @@ -940,8 +1094,13 @@ public void bindStructWithArrayOfStructField() { @Test public void unboundParameter() { + String query = "SELECT @v"; + if (dialect.dialect == Dialect.POSTGRESQL) { + query = "SELECT $1"; + } ResultSet resultSet = - Statement.of("SELECT @v").executeQuery(client.singleUse(TimestampBound.strong())); + Statement.of(query) + .executeQuery(getClient(dialect.dialect).singleUse(TimestampBound.strong())); try { resultSet.next(); fail("Expected exception"); @@ -952,24 +1111,32 @@ public void unboundParameter() { @Test public void positiveInfinity() { + assumeFalse( + "function ieee_divide not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute(Statement.newBuilder("SELECT IEEE_DIVIDE(1, 0)"), Type.float64()); assertThat(row.getDouble(0)).isPositiveInfinity(); } @Test public void negativeInfinity() { + assumeFalse( + "function ieee_divide not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute(Statement.newBuilder("SELECT IEEE_DIVIDE(-1, 0)"), Type.float64()); assertThat(row.getDouble(0)).isNegativeInfinity(); } @Test public void notANumber() { + assumeFalse( + "function ieee_divide not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute(Statement.newBuilder("SELECT IEEE_DIVIDE(0, 0)"), Type.float64()); assertThat(row.getDouble(0)).isNaN(); } @Test public void nonNumberArray() { + assumeFalse( + "function ieee_divide not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); Struct row = execute( Statement.newBuilder( @@ -983,6 +1150,8 @@ public void nonNumberArray() { @Test public void largeErrorText() { + assumeFalse( + "regexp_contains is not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); String veryLongString = Joiner.on("").join(Iterables.limit(Iterables.cycle("x"), 8000)); Statement statement = Statement.newBuilder("SELECT REGEXP_CONTAINS(@value, @regexp)") @@ -991,7 +1160,8 @@ public void largeErrorText() { .bind("regexp") .to("(" + veryLongString) .build(); - ResultSet resultSet = statement.executeQuery(client.singleUse(TimestampBound.strong())); + ResultSet resultSet = + statement.executeQuery(getClient(dialect.dialect).singleUse(TimestampBound.strong())); try { resultSet.next(); fail("Expected exception"); @@ -1003,10 +1173,19 @@ public void largeErrorText() { @Test public void queryRealTable() { - Database populatedDb = - env.getTestHelper() - .createTestDatabase( - "CREATE TABLE T ( K STRING(MAX) NOT NULL, V STRING(MAX) ) PRIMARY KEY (K)"); + Database populatedDb; + if (dialect.dialect == Dialect.POSTGRESQL) { + populatedDb = + env.getTestHelper() + .createTestDatabase( + dialect.dialect, + Arrays.asList("CREATE TABLE T ( K VARCHAR PRIMARY KEY, V VARCHAR )")); + } else { + populatedDb = + env.getTestHelper() + .createTestDatabase( + "CREATE TABLE T ( K STRING(MAX) NOT NULL, V STRING(MAX) ) PRIMARY KEY (K)"); + } DatabaseClient client = env.getTestHelper().getDatabaseClient(populatedDb); client.writeAtLeastOnce( asList( @@ -1015,23 +1194,22 @@ public void queryRealTable() { Mutation.newInsertBuilder("T").set("K").to("k3").set("V").to("v3").build(), Mutation.newInsertBuilder("T").set("K").to("k4").set("V").to("v4").build())); + String query = "SELECT k, v FROM T WHERE k >= @p1 AND k < @p2 ORDER BY K ASC"; + if (dialect.dialect == Dialect.POSTGRESQL) { + query = "SELECT k, v FROM T WHERE k >= $1 AND k < $2 ORDER BY K ASC"; + } Statement statement = - Statement.newBuilder("SELECT K, V FROM T WHERE K >= @min AND K < @max ORDER BY K ASC") - .bind("min") - .to("k13") - .bind("max") - .to("k32") - .build(); + Statement.newBuilder(query).bind("p1").to("k13").bind("p2").to("k32").build(); ResultSet resultSet = statement.executeQuery(client.singleUse(TimestampBound.strong())); assertThat(resultSet.next()).isTrue(); assertThat(resultSet.getType()) .isEqualTo( - Type.struct(StructField.of("K", Type.string()), StructField.of("V", Type.string()))); + Type.struct(StructField.of("k", Type.string()), StructField.of("v", Type.string()))); assertThat(resultSet.getString(0)).isEqualTo("k2"); assertThat(resultSet.getString(1)).isEqualTo("v2"); assertThat(resultSet.next()).isTrue(); - assertThat(resultSet.getString("K")).isEqualTo("k3"); - assertThat(resultSet.getString("V")).isEqualTo("v3"); + assertThat(resultSet.getString("k")).isEqualTo("k3"); + assertThat(resultSet.getString("v")).isEqualTo("v3"); assertThat(resultSet.next()).isFalse(); } @@ -1039,11 +1217,12 @@ public void queryRealTable() { public void analyzePlan() { assumeFalse("Emulator does not support Analyze Plan", isUsingEmulator()); - Statement statement = Statement.of("SELECT 1 AS column UNION ALL SELECT 2"); + Statement statement = Statement.of("SELECT 1 AS data UNION ALL SELECT 2"); ResultSet resultSet = - statement.analyzeQuery(client.singleUse(TimestampBound.strong()), QueryAnalyzeMode.PLAN); + statement.analyzeQuery( + getClient(dialect.dialect).singleUse(TimestampBound.strong()), QueryAnalyzeMode.PLAN); assertThat(resultSet.next()).isFalse(); - assertThat(resultSet.getType()).isEqualTo(Type.struct(StructField.of("column", Type.int64()))); + assertThat(resultSet.getType()).isEqualTo(Type.struct(StructField.of("data", Type.int64()))); ResultSetStats receivedStats = resultSet.getStats(); assertThat(receivedStats).isNotNull(); assertThat(receivedStats.hasQueryPlan()).isTrue(); @@ -1054,12 +1233,18 @@ public void analyzePlan() { public void analyzeProfile() { assumeFalse("Emulator does not support Analyze Profile", isUsingEmulator()); - Statement statement = - Statement.of("SELECT 1 AS column UNION ALL SELECT 2 AS column ORDER BY column"); + String query = "SELECT 1 AS data UNION ALL SELECT 2 AS data ORDER BY data"; + if (dialect.dialect == Dialect.POSTGRESQL) { + // "Statements with set operations and ORDER BY are not supported" + query = "SELECT 1 AS data UNION ALL SELECT 2 AS data"; + } + Statement statement = Statement.of(query); ResultSet resultSet = - statement.analyzeQuery(client.singleUse(TimestampBound.strong()), QueryAnalyzeMode.PROFILE); + statement.analyzeQuery( + getClient(dialect.dialect).singleUse(TimestampBound.strong()), + QueryAnalyzeMode.PROFILE); assertThat(resultSet.next()).isTrue(); - assertThat(resultSet.getType()).isEqualTo(Type.struct(StructField.of("column", Type.int64()))); + assertThat(resultSet.getType()).isEqualTo(Type.struct(StructField.of("data", Type.int64()))); assertThat(resultSet.getLong(0)).isEqualTo(1); assertThat(resultSet.next()).isTrue(); assertThat(resultSet.getLong(0)).isEqualTo(2); @@ -1072,8 +1257,9 @@ public void analyzeProfile() { @Test public void testSelectArrayOfStructs() { + assumeFalse("structs are not supported on POSTGRESQL", dialect.dialect == Dialect.POSTGRESQL); try (ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse() .executeQuery( Statement.of( @@ -1102,7 +1288,8 @@ public void testSelectArrayOfStructs() { private List resultRows(Statement statement, Type expectedRowType) { ArrayList results = new ArrayList<>(); - ResultSet resultSet = statement.executeQuery(client.singleUse(TimestampBound.strong())); + ResultSet resultSet = + statement.executeQuery(getClient(dialect.dialect).singleUse(TimestampBound.strong())); while (resultSet.next()) { Struct row = resultSet.getCurrentRowAsStruct(); results.add(row); @@ -1113,7 +1300,8 @@ private List resultRows(Statement statement, Type expectedRowType) { } private Struct executeWithRowResultType(Statement statement, Type expectedRowType) { - ResultSet resultSet = statement.executeQuery(client.singleUse(TimestampBound.strong())); + ResultSet resultSet = + statement.executeQuery(getClient(dialect.dialect).singleUse(TimestampBound.strong())); assertThat(resultSet.next()).isTrue(); assertThat(resultSet.getType()).isEqualTo(expectedRowType); Struct row = resultSet.getCurrentRowAsStruct(); @@ -1123,6 +1311,9 @@ private Struct executeWithRowResultType(Statement statement, Type expectedRowTyp private Struct execute(Statement statement, Type expectedColumnType) { Type rowType = Type.struct(StructField.of("", expectedColumnType)); + if (dialect.dialect == Dialect.POSTGRESQL) { + rowType = Type.struct(StructField.of("?column?", expectedColumnType)); + } return executeWithRowResultType(statement, rowType); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITReadTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITReadTest.java index 5fd4b27fa4e..c28b48c529a 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITReadTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITReadTest.java @@ -18,6 +18,7 @@ import static com.google.cloud.spanner.SpannerMatchers.isSpannerException; import static com.google.cloud.spanner.Type.StructField; +import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; @@ -25,6 +26,7 @@ import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Key; @@ -38,6 +40,7 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Type; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.testing.RemoteSpannerHelper; import io.grpc.Context; import java.util.ArrayList; @@ -49,12 +52,13 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.hamcrest.MatcherAssert; +import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; /** * Integration tests for read and query. @@ -63,7 +67,7 @@ * Spanner types. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITReadTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); private static final String TABLE_NAME = "TestTable"; @@ -72,42 +76,85 @@ public class ITReadTest { private static final List ALL_COLUMNS = Arrays.asList("Key", "StringValue"); private static final Type TABLE_TYPE = Type.struct( - StructField.of("Key", Type.string()), StructField.of("StringValue", Type.string())); + StructField.of("key", Type.string()), StructField.of("stringvalue", Type.string())); - private static Database db; - private static DatabaseClient client; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; @BeforeClass public static void setUpDatabase() { - db = + Database googleStandardSQLDatabase = env.getTestHelper() .createTestDatabase( "CREATE TABLE TestTable (" - + " Key STRING(MAX) NOT NULL," - + " StringValue STRING(MAX)," - + ") PRIMARY KEY (Key)", - "CREATE INDEX TestTableByValue ON TestTable(StringValue)", - "CREATE INDEX TestTableByValueDesc ON TestTable(StringValue DESC)"); - client = env.getTestHelper().getDatabaseClient(db); + + " key STRING(MAX) NOT NULL," + + " stringvalue STRING(MAX)," + + ") PRIMARY KEY (key)", + "CREATE INDEX TestTableByValue ON TestTable(stringvalue)", + "CREATE INDEX TestTableByValueDesc ON TestTable(stringvalue DESC)"); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + if (!isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, + Arrays.asList( + "CREATE TABLE TestTable (" + + " Key VARCHAR PRIMARY KEY," + + " StringValue VARCHAR" + + ")", + "CREATE INDEX TestTableByValue ON TestTable(StringValue)", + "CREATE INDEX TestTableByValueDesc ON TestTable(StringValue DESC)")); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } // Includes k0..k14. Note that strings k{10,14} sort between k1 and k2. List mutations = new ArrayList<>(); for (int i = 0; i < 15; ++i) { mutations.add( Mutation.newInsertOrUpdateBuilder(TABLE_NAME) - .set("Key") + .set("key") .to("k" + i) - .set("StringValue") + .set("stringvalue") .to("v" + i) .build()); } - client.write(mutations); + googleStandardSQLClient.write(mutations); + if (!isUsingEmulator()) { + postgreSQLClient.write(mutations); + } + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); + } + + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + // "PG dialect tests are not supported by the emulator" + if (!isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter(0) + public DialectTestParameter dialect; + + private DatabaseClient getClient(Dialect dialect) { + if (dialect == Dialect.POSTGRESQL) { + return postgreSQLClient; + } + return googleStandardSQLClient; } @Test public void emptyRead() { ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read( TABLE_NAME, @@ -120,7 +167,7 @@ public void emptyRead() { @Test public void indexEmptyRead() { ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readUsingIndex( TABLE_NAME, @@ -134,19 +181,21 @@ public void indexEmptyRead() { @Test public void pointRead() { Struct row = - client.singleUse(TimestampBound.strong()).readRow(TABLE_NAME, Key.of("k1"), ALL_COLUMNS); + getClient(dialect.dialect) + .singleUse(TimestampBound.strong()) + .readRow(TABLE_NAME, Key.of("k1"), ALL_COLUMNS); assertThat(row).isNotNull(); assertThat(row.getString(0)).isEqualTo("k1"); assertThat(row.getString(1)).isEqualTo("v1"); // Ensure that the Struct implementation supports equality properly. assertThat(row) - .isEqualTo(Struct.newBuilder().set("Key").to("k1").set("StringValue").to("v1").build()); + .isEqualTo(Struct.newBuilder().set("key").to("k1").set("stringvalue").to("v1").build()); } @Test public void indexPointRead() { Struct row = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRowUsingIndex(TABLE_NAME, INDEX_NAME, Key.of("v1"), ALL_COLUMNS); assertThat(row).isNotNull(); @@ -157,14 +206,16 @@ public void indexPointRead() { @Test public void pointReadNotFound() { Struct row = - client.singleUse(TimestampBound.strong()).readRow(TABLE_NAME, Key.of("k999"), ALL_COLUMNS); + getClient(dialect.dialect) + .singleUse(TimestampBound.strong()) + .readRow(TABLE_NAME, Key.of("k999"), ALL_COLUMNS); assertThat(row).isNull(); } @Test public void indexPointReadNotFound() { Struct row = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRowUsingIndex(TABLE_NAME, INDEX_NAME, Key.of("v999"), ALL_COLUMNS); assertThat(row).isNull(); @@ -262,7 +313,7 @@ public void indexMultiPointRead() { public void rowsAreSnapshots() { List rows = new ArrayList<>(); ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read( TABLE_NAME, @@ -303,7 +354,9 @@ public void invalidDatabase() { @Test public void tableNotFound() { try { - client.singleUse(TimestampBound.strong()).readRow("BadTableName", Key.of("k1"), ALL_COLUMNS); + getClient(dialect.dialect) + .singleUse(TimestampBound.strong()) + .readRow("BadTableName", Key.of("k1"), ALL_COLUMNS); fail("Expected exception"); } catch (SpannerException ex) { assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND); @@ -314,7 +367,7 @@ public void tableNotFound() { @Test public void columnNotFound() { try { - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow(TABLE_NAME, Key.of("k1"), Arrays.asList("Key", "BadColumnName")); fail("Expected exception"); @@ -329,7 +382,7 @@ public void cursorErrorDeferred() { // Error should be deferred until next(). This gives consistent behavior with respect to // non-blocking implementations (e.g., gRPC). ResultSet resultSet = - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read("BadTableName", KeySet.singleKey(Key.of("k1")), ALL_COLUMNS); try { @@ -347,7 +400,7 @@ public void cancellation() { Runnable work = context.wrap( () -> { - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow(TABLE_NAME, Key.of("k1"), ALL_COLUMNS); }); @@ -369,7 +422,7 @@ public void deadline() { Runnable work = context.wrap( () -> { - client + getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readRow(TABLE_NAME, Key.of("k1"), ALL_COLUMNS); }); @@ -401,32 +454,34 @@ private void checkReadRange(Source source, KeySet keySet, long limit, int[] expe case INDEX: resultSet = limit != 0 - ? client + ? getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readUsingIndex( TABLE_NAME, INDEX_NAME, keySet, ALL_COLUMNS, Options.limit(limit)) - : client + : getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readUsingIndex(TABLE_NAME, INDEX_NAME, keySet, ALL_COLUMNS); break; case DESC_INDEX: resultSet = limit != 0 - ? client + ? getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readUsingIndex( TABLE_NAME, DESC_INDEX_NAME, keySet, ALL_COLUMNS, Options.limit(limit)) - : client + : getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .readUsingIndex(TABLE_NAME, DESC_INDEX_NAME, keySet, ALL_COLUMNS); break; case BASE_TABLE: resultSet = limit != 0 - ? client + ? getClient(dialect.dialect) .singleUse(TimestampBound.strong()) .read(TABLE_NAME, keySet, ALL_COLUMNS, Options.limit(limit)) - : client.singleUse(TimestampBound.strong()).read(TABLE_NAME, keySet, ALL_COLUMNS); + : getClient(dialect.dialect) + .singleUse(TimestampBound.strong()) + .read(TABLE_NAME, keySet, ALL_COLUMNS); break; default: throw new IllegalArgumentException("Invalid source"); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITResultSetGetValue.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITResultSetGetValue.java index 0b2f19e99da..64220421bf1 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITResultSetGetValue.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITResultSetGetValue.java @@ -21,12 +21,14 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeFalse; import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Mutation; import com.google.cloud.spanner.ParallelIntegrationTest; @@ -36,61 +38,114 @@ import com.google.cloud.spanner.Type; import com.google.cloud.spanner.Type.StructField; import com.google.cloud.spanner.Value; -import com.google.cloud.spanner.testing.RemoteSpannerHelper; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.primitives.Doubles; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITResultSetGetValue { + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter() public DialectTestParameter dialect; + @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); // For floats / doubles comparison private static final double DELTA = 1e-15; private static final String TABLE_NAME = "TestTable"; - private static DatabaseClient databaseClient; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; + private DatabaseClient databaseClient; @BeforeClass - public static void beforeClass() { - final RemoteSpannerHelper testHelper = env.getTestHelper(); - final Database database = - testHelper.createTestDatabase( - "CREATE TABLE " - + TABLE_NAME - + "(" - + "Id INT64 NOT NULL," - + "bool BOOL," - + "int64 INT64," - + "float64 FLOAT64," - + "numeric NUMERIC," - + "string STRING(MAX)," - + "bytes BYTES(MAX)," - + "timestamp TIMESTAMP," - + "date DATE," - + "boolArray ARRAY," - + "int64Array ARRAY," - + "float64Array ARRAY," - + "numericArray ARRAY," - + "stringArray ARRAY," - + "bytesArray ARRAY," - + "timestampArray ARRAY," - + "dateArray ARRAY" - + ") PRIMARY KEY (Id)"); + public static void beforeClass() + throws ExecutionException, InterruptedException, TimeoutException { + Database googleStandardSqlDatabase = + env.getTestHelper() + .createTestDatabase( + "CREATE TABLE " + + TABLE_NAME + + "(" + + "Id INT64 NOT NULL," + + "bool BOOL," + + "int64 INT64," + + "float64 FLOAT64," + + "numeric NUMERIC," + + "string STRING(MAX)," + + "bytes BYTES(MAX)," + + "timestamp TIMESTAMP," + + "date DATE," + + "boolArray ARRAY," + + "int64Array ARRAY," + + "float64Array ARRAY," + + "numericArray ARRAY," + + "stringArray ARRAY," + + "bytesArray ARRAY," + + "timestampArray ARRAY," + + "dateArray ARRAY" + + ") PRIMARY KEY (Id)"); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSqlDatabase); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, + Collections.singletonList( + "CREATE TABLE " + + TABLE_NAME + + "(" + + "id BIGINT PRIMARY KEY," + + "bool BOOL," + + "int64 BIGINT," + + "float64 DOUBLE PRECISION," + + "numeric NUMERIC," + + "string VARCHAR," + + "bytes BYTEA" + + ")")); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } + } - databaseClient = testHelper.getDatabaseClient(database); + @Before + public void before() { + databaseClient = + dialect.dialect == Dialect.GOOGLE_STANDARD_SQL ? googleStandardSQLClient : postgreSQLClient; + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); } @Test - public void testReadNonNullValues() { + public void testReadNonNullValuesGoogleStandardSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.GOOGLE_STANDARD_SQL); databaseClient.write( Collections.singletonList( Mutation.newInsertBuilder(TABLE_NAME) @@ -135,7 +190,6 @@ public void testReadNonNullValues() { Arrays.asList( Date.fromYearMonthDay(2021, 2, 3), Date.fromYearMonthDay(2021, 3, 4))) .build())); - try (ResultSet resultSet = databaseClient .singleUse() @@ -181,7 +235,45 @@ public void testReadNonNullValues() { } @Test - public void testReadNullValues() { + public void testReadNonNullValuesPostgreSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.POSTGRESQL); + databaseClient.write( + Collections.singletonList( + Mutation.newInsertBuilder(TABLE_NAME) + .set("id") + .to(1L) + .set("bool") + .to(true) + .set("int64") + .to(10L) + .set("float64") + .to(20D) + .set("numeric") + .to(new BigDecimal("30")) + .set("string") + .to("stringValue") + .set("bytes") + .to(ByteArray.copyFrom("bytesValue")) + .build())); + + try (ResultSet resultSet = + databaseClient + .singleUse() + .executeQuery(Statement.of("SELECT * FROM " + TABLE_NAME + " WHERE id = 1"))) { + resultSet.next(); + assertEquals(Value.int64(1L), resultSet.getValue("id")); + assertEquals(Value.bool(true), resultSet.getValue("bool")); + assertEquals(Value.int64(10L), resultSet.getValue("int64")); + assertEquals(20D, resultSet.getValue("float64").getFloat64(), 1e-15); + assertEquals(Value.pgNumeric("30"), resultSet.getValue("numeric")); + assertEquals(Value.string("stringValue"), resultSet.getValue("string")); + assertEquals(Value.bytes(ByteArray.copyFrom("bytesValue")), resultSet.getValue("bytes")); + } + } + + @Test + public void testReadNullValuesGoogleStandardSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.GOOGLE_STANDARD_SQL); databaseClient.write( Collections.singletonList(Mutation.newInsertBuilder(TABLE_NAME).set("Id").to(2L).build())); try (ResultSet resultSet = @@ -236,8 +328,36 @@ public void testReadNullValues() { } } + @Test + public void testReadNullValuesPostgreSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.POSTGRESQL); + databaseClient.write( + Collections.singletonList(Mutation.newInsertBuilder(TABLE_NAME).set("id").to(2L).build())); + try (ResultSet resultSet = + databaseClient + .singleUse() + .executeQuery(Statement.of("SELECT * FROM " + TABLE_NAME + " WHERE id = 2"))) { + resultSet.next(); + + assertEquals(Value.int64(2L), resultSet.getValue("id")); + assertTrue(resultSet.getValue("bool").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("bool").getBool()); + assertTrue(resultSet.getValue("int64").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("int64").getInt64()); + assertTrue(resultSet.getValue("float64").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("float64").getFloat64()); + assertTrue(resultSet.getValue("numeric").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("numeric").getNumeric()); + assertTrue(resultSet.getValue("string").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("string").getString()); + assertTrue(resultSet.getValue("bytes").isNull()); + assertThrows(IllegalStateException.class, () -> resultSet.getValue("bytes").getBytes()); + } + } + @Test public void testReadNullValuesInArrays() { + assumeFalse("PostgreSQL does not yet support Arrays", dialect.dialect == Dialect.POSTGRESQL); databaseClient.write( Collections.singletonList( Mutation.newInsertBuilder(TABLE_NAME) @@ -290,7 +410,8 @@ public void testReadNullValuesInArrays() { } @Test - public void testReadNonFloat64Literals() { + public void testReadNonFloat64LiteralsGoogleStandardSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.GOOGLE_STANDARD_SQL); try (ResultSet resultSet = databaseClient .singleUse() @@ -417,7 +538,32 @@ public void testReadNonFloat64Literals() { } @Test - public void testReadFloat64Literals() { + public void testReadNonFloat64LiteralsPostgreSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.POSTGRESQL); + try (ResultSet resultSet = + databaseClient + .singleUse() + .executeQuery( + Statement.of( + "SELECT " + + "TRUE AS bool," + + "1 AS int64," + + "CAST('100' AS numeric) AS numeric," + + "'stringValue' AS string," + + "CAST('bytesValue' AS BYTEA) AS bytes"))) { + resultSet.next(); + + assertEquals(Value.bool(true), resultSet.getValue("bool")); + assertEquals(Value.int64(1L), resultSet.getValue("int64")); + assertEquals(Value.pgNumeric("100"), resultSet.getValue("numeric")); + assertEquals(Value.string("stringValue"), resultSet.getValue("string")); + assertEquals(Value.bytes(ByteArray.copyFrom("bytesValue")), resultSet.getValue("bytes")); + } + } + + @Test + public void testReadFloat64LiteralsGoogleStandardSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.GOOGLE_STANDARD_SQL); try (ResultSet resultSet = databaseClient .singleUse() @@ -444,4 +590,14 @@ public void testReadFloat64Literals() { new double[] {50D, 60D}, struct.getDoubleArray("structFloat64Array"), DELTA); } } + + @Test + public void testReadFloat64LiteralsPostgreSQL() { + Assume.assumeTrue(dialect.dialect == Dialect.POSTGRESQL); + try (ResultSet resultSet = + databaseClient.singleUse().executeQuery(Statement.of("SELECT 10.0 AS float64"))) { + resultSet.next(); + assertEquals(10D, resultSet.getValue("float64").getFloat64(), DELTA); + } + } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerTest.java index bb70864d3c3..736f00ebd69 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerTest.java @@ -26,6 +26,7 @@ import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Key; import com.google.cloud.spanner.KeySet; @@ -37,43 +38,84 @@ import com.google.cloud.spanner.TransactionContext; import com.google.cloud.spanner.TransactionManager; import com.google.cloud.spanner.TransactionManager.TransactionState; +import com.google.cloud.spanner.connection.ConnectionOptions; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableList; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITTransactionManagerTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); - private static Database db; private static DatabaseClient client; + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; + + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter() public DialectTestParameter dialect; @BeforeClass - public static void setUpDatabase() { - // Empty database. - db = + public static void setUpDatabase() + throws ExecutionException, InterruptedException, TimeoutException { + + Database googleStandardSQLDatabase = env.getTestHelper() .createTestDatabase( "CREATE TABLE T (" + " K STRING(MAX) NOT NULL," + " BoolValue BOOL," + ") PRIMARY KEY (K)"); - client = env.getTestHelper().getDatabaseClient(db); + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, + Collections.singletonList( + "CREATE TABLE T (" + + " K VARCHAR PRIMARY KEY," + + " BoolValue BOOL" + + ")")); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); + } } @Before - public void deleteTestData() { + public void before() { + client = + dialect.dialect == Dialect.GOOGLE_STANDARD_SQL ? googleStandardSQLClient : postgreSQLClient; + // Delete all test data client.write(ImmutableList.of(Mutation.delete("T", KeySet.all()))); } + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); + } + @SuppressWarnings("resource") @Test public void simpleInsert() throws InterruptedException { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java index a76c40ea61b..d274cdb91f5 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java @@ -32,6 +32,7 @@ import com.google.cloud.spanner.CommitResponse; import com.google.cloud.spanner.Database; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.Key; @@ -44,36 +45,57 @@ import com.google.cloud.spanner.Struct; import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.Value; +import com.google.cloud.spanner.connection.ConnectionOptions; import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.collect.ImmutableList; import io.grpc.Context; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.hamcrest.MatcherAssert; +import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Ignore; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; /** Integration test for writing data to Cloud Spanner. */ @Category(ParallelIntegrationTest.class) -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class ITWriteTest { @ClassRule public static IntegrationTestEnv env = new IntegrationTestEnv(); + @Parameterized.Parameters(name = "Dialect = {0}") + public static List data() { + List params = new ArrayList<>(); + params.add(new DialectTestParameter(Dialect.GOOGLE_STANDARD_SQL)); + if (!EmulatorSpannerHelper.isUsingEmulator()) { + params.add(new DialectTestParameter(Dialect.POSTGRESQL)); + } + return params; + } + + @Parameterized.Parameter() public DialectTestParameter dialect; + + private static DatabaseClient googleStandardSQLClient; + private static DatabaseClient postgreSQLClient; + // TODO: Remove when the emulator supports NUMERIC and JSON - private static final String SCHEMA_WITH_NUMERIC_AND_JSON = + private static final String GOOGLE_STANDARD_SQL_SCHEMA_WITH_NUMERIC_AND_JSON = "CREATE TABLE T (" + " K STRING(MAX) NOT NULL," + " BoolValue BOOL," @@ -95,7 +117,19 @@ public class ITWriteTest { + " DateArrayValue ARRAY," + " NumericArrayValue ARRAY," + ") PRIMARY KEY (K)"; - private static final String SCHEMA_WITHOUT_NUMERIC_AND_JSON = + + private static final String POSTGRESQL_SCHEMA_WITH_NUMERIC = + "CREATE TABLE T (" + + " K VARCHAR PRIMARY KEY," + + " BoolValue BOOL," + + " Int64Value BIGINT," + + " Float64Value DOUBLE PRECISION," + + " StringValue VARCHAR," + + " BytesValue BYTEA," + + " NumericValue NUMERIC" + + ")"; + + private static final String GOOGLE_STANDARD_SQL_SCHEMA_WITHOUT_NUMERIC_AND_JSON = "CREATE TABLE T (" + " K STRING(MAX) NOT NULL," + " BoolValue BOOL," @@ -114,21 +148,42 @@ public class ITWriteTest { + " DateArrayValue ARRAY," + ") PRIMARY KEY (K)"; - private static Database db; /** Sequence used to generate unique keys. */ private static int seq; private static DatabaseClient client; @BeforeClass - public static void setUpDatabase() { + public static void setUpDatabase() + throws ExecutionException, InterruptedException, TimeoutException { if (EmulatorSpannerHelper.isUsingEmulator()) { - // The emulator does not yet support NUMERIC or JSON. - db = env.getTestHelper().createTestDatabase(SCHEMA_WITHOUT_NUMERIC_AND_JSON); + Database googleStandardSQLDatabase = + env.getTestHelper() + .createTestDatabase(GOOGLE_STANDARD_SQL_SCHEMA_WITHOUT_NUMERIC_AND_JSON); + + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); } else { - db = env.getTestHelper().createTestDatabase(SCHEMA_WITH_NUMERIC_AND_JSON); + Database googleStandardSQLDatabase = + env.getTestHelper().createTestDatabase(GOOGLE_STANDARD_SQL_SCHEMA_WITH_NUMERIC_AND_JSON); + + googleStandardSQLClient = env.getTestHelper().getDatabaseClient(googleStandardSQLDatabase); + Database postgreSQLDatabase = + env.getTestHelper() + .createTestDatabase( + Dialect.POSTGRESQL, Collections.singletonList(POSTGRESQL_SCHEMA_WITH_NUMERIC)); + postgreSQLClient = env.getTestHelper().getDatabaseClient(postgreSQLDatabase); } - client = env.getTestHelper().getDatabaseClient(db); + } + + @Before + public void before() { + client = + dialect.dialect == Dialect.GOOGLE_STANDARD_SQL ? googleStandardSQLClient : postgreSQLClient; + } + + @AfterClass + public static void teardown() { + ConnectionOptions.closeSpanner(); } private static String uniqueString() { @@ -328,6 +383,7 @@ public void writeStringNull() { @Test public void writeJson() { assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("PostgreSQL does not yet support JSON", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("JsonValue").to(Value.json("{\"rating\":9,\"open\":true}")).build()); Struct row = readLastRow("JsonValue"); assertThat(row.isNull(0)).isFalse(); @@ -338,6 +394,7 @@ public void writeJson() { @Test public void writeJsonEmpty() { assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("PostgreSQL does not yet support JSON", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("JsonValue").to(Value.json("{}")).build()); Struct row = readLastRow("JsonValue"); assertThat(row.isNull(0)).isFalse(); @@ -348,6 +405,7 @@ public void writeJsonEmpty() { @Test public void writeJsonNull() { assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); + assumeFalse("PostgreSQL does not yet support JSON", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("JsonValue").to(Value.json(null)).build()); Struct row = readLastRow("JsonValue"); assertThat(row.isNull(0)).isTrue(); @@ -423,6 +481,8 @@ public void writeBytesNull() { @Test public void writeTimestamp() { + assumeFalse( + "PostgresSQL does not yet support Timestamp", dialect.dialect == Dialect.POSTGRESQL); Timestamp timestamp = Timestamp.parseTimestamp("2016-09-15T00:00:00.111111Z"); write(baseInsert().set("TimestampValue").to(timestamp).build()); Struct row = readLastRow("TimestampValue"); @@ -432,6 +492,7 @@ public void writeTimestamp() { @Test public void writeTimestampNull() { + assumeFalse("PostgreSQL does not yet support Timestamp", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("TimestampValue").to((Timestamp) null).build()); Struct row = readLastRow("TimestampValue"); assertThat(row.isNull(0)).isTrue(); @@ -439,6 +500,7 @@ public void writeTimestampNull() { @Test public void writeCommitTimestamp() { + assumeFalse("PostgreSQL does not yet support Timestamp", dialect.dialect == Dialect.POSTGRESQL); Timestamp commitTimestamp = write(baseInsert().set("TimestampValue").to(Value.COMMIT_TIMESTAMP).build()); Struct row = readLastRow("TimestampValue"); @@ -447,6 +509,7 @@ public void writeCommitTimestamp() { @Test public void writeDate() { + assumeFalse("PostgreSQL does not yet support Date", dialect.dialect == Dialect.POSTGRESQL); Date date = Date.parseDate("2016-09-15"); write(baseInsert().set("DateValue").to(date).build()); Struct row = readLastRow("DateValue"); @@ -456,6 +519,7 @@ public void writeDate() { @Test public void writeDateNull() { + assumeFalse("PostgreSQL does not yet support Date", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("DateValue").to((Date) null).build()); Struct row = readLastRow("DateValue"); assertThat(row.isNull(0)).isTrue(); @@ -464,22 +528,27 @@ public void writeDateNull() { @Test public void writeNumeric() { assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); - write(baseInsert().set("NumericValue").to(new BigDecimal("3.141592")).build()); + write(baseInsert().set("NumericValue").to("3.141592").build()); Struct row = readLastRow("NumericValue"); assertThat(row.isNull(0)).isFalse(); - assertThat(row.getBigDecimal(0)).isEqualTo(BigDecimal.valueOf(3141592, 6)); + if (dialect.dialect == Dialect.GOOGLE_STANDARD_SQL) { + assertThat(row.getBigDecimal(0)).isEqualTo(BigDecimal.valueOf(3141592, 6)); + } else { + assertThat(row.getString(0)).isEqualTo("3.141592"); + } } @Test public void writeNumericNull() { assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); - write(baseInsert().set("NumericValue").to((Long) null).build()); + write(baseInsert().set("NumericValue").to((String) null).build()); Struct row = readLastRow("NumericValue"); assertThat(row.isNull(0)).isTrue(); } @Test public void writeBoolArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BoolArrayValue").toBoolArray((boolean[]) null).build()); Struct row = readLastRow("BoolArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -487,6 +556,7 @@ public void writeBoolArrayNull() { @Test public void writeBoolArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BoolArrayValue").toBoolArray(new boolean[] {}).build()); Struct row = readLastRow("BoolArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -495,6 +565,7 @@ public void writeBoolArrayEmpty() { @Test public void writeBoolArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BoolArrayValue").toBoolArray(Arrays.asList(true, null, false)).build()); Struct row = readLastRow("BoolArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -509,6 +580,7 @@ public void writeBoolArray() { @Test public void writeBoolArrayNoNulls() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BoolArrayValue").toBoolArray(Arrays.asList(true, false)).build()); Struct row = readLastRow("BoolArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -517,6 +589,7 @@ public void writeBoolArrayNoNulls() { @Test public void writeInt64ArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Int64ArrayValue").toInt64Array((long[]) null).build()); Struct row = readLastRow("Int64ArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -524,6 +597,7 @@ public void writeInt64ArrayNull() { @Test public void writeInt64ArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Int64ArrayValue").toInt64Array(new long[] {}).build()); Struct row = readLastRow("Int64ArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -532,6 +606,7 @@ public void writeInt64ArrayEmpty() { @Test public void writeInt64Array() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Int64ArrayValue").toInt64Array(Arrays.asList(1L, 2L, null)).build()); Struct row = readLastRow("Int64ArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -546,6 +621,7 @@ public void writeInt64Array() { @Test public void writeInt64ArrayNoNulls() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Int64ArrayValue").toInt64Array(Arrays.asList(1L, 2L)).build()); Struct row = readLastRow("Int64ArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -554,6 +630,7 @@ public void writeInt64ArrayNoNulls() { @Test public void writeFloat64ArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Float64ArrayValue").toFloat64Array((double[]) null).build()); Struct row = readLastRow("Float64ArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -561,6 +638,7 @@ public void writeFloat64ArrayNull() { @Test public void writeFloat64ArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Float64ArrayValue").toFloat64Array(new double[] {}).build()); Struct row = readLastRow("Float64ArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -569,6 +647,7 @@ public void writeFloat64ArrayEmpty() { @Test public void writeFloat64Array() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write( baseInsert() .set("Float64ArrayValue") @@ -587,6 +666,7 @@ public void writeFloat64Array() { @Test public void writeFloat64ArrayNoNulls() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("Float64ArrayValue").toFloat64Array(Arrays.asList(1.0, 2.0)).build()); Struct row = readLastRow("Float64ArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -597,6 +677,7 @@ public void writeFloat64ArrayNoNulls() { @Test public void writeStringArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("StringArrayValue").toStringArray(null).build()); Struct row = readLastRow("StringArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -604,6 +685,7 @@ public void writeStringArrayNull() { @Test public void writeStringArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("StringArrayValue").toStringArray(Collections.emptyList()).build()); Struct row = readLastRow("StringArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -612,6 +694,7 @@ public void writeStringArrayEmpty() { @Test public void writeStringArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write( baseInsert().set("StringArrayValue").toStringArray(Arrays.asList("a", null, "b")).build()); Struct row = readLastRow("StringArrayValue"); @@ -621,6 +704,7 @@ public void writeStringArray() { @Test public void writeJsonArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); write(baseInsert().set("JsonArrayValue").toJsonArray(null).build()); Struct row = readLastRow("JsonArrayValue"); @@ -630,6 +714,7 @@ public void writeJsonArrayNull() { @Test public void writeJsonArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); write(baseInsert().set("JsonArrayValue").toJsonArray(Collections.emptyList()).build()); Struct row = readLastRow("JsonArrayValue"); @@ -640,6 +725,7 @@ public void writeJsonArrayEmpty() { @Test public void writeJsonArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); write(baseInsert().set("JsonArrayValue").toJsonArray(Arrays.asList("[]", null, "{}")).build()); Struct row = readLastRow("JsonArrayValue"); @@ -650,6 +736,7 @@ public void writeJsonArray() { @Test public void writeJsonArrayNoNulls() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support JSON", EmulatorSpannerHelper.isUsingEmulator()); write( baseInsert() @@ -666,6 +753,7 @@ public void writeJsonArrayNoNulls() { @Test public void writeBytesArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BytesArrayValue").toBytesArray(null).build()); Struct row = readLastRow("BytesArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -673,6 +761,7 @@ public void writeBytesArrayNull() { @Test public void writeBytesArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("BytesArrayValue").toBytesArray(Collections.emptyList()).build()); Struct row = readLastRow("BytesArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -681,6 +770,7 @@ public void writeBytesArrayEmpty() { @Test public void writeBytesArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); List data = Arrays.asList(ByteArray.copyFrom("a"), ByteArray.copyFrom("b"), null); write(baseInsert().set("BytesArrayValue").toBytesArray(data).build()); Struct row = readLastRow("BytesArrayValue"); @@ -690,6 +780,7 @@ public void writeBytesArray() { @Test public void writeTimestampArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("TimestampArrayValue").toTimestampArray(null).build()); Struct row = readLastRow("TimestampArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -697,6 +788,7 @@ public void writeTimestampArrayNull() { @Test public void writeTimestampArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write( baseInsert().set("TimestampArrayValue").toTimestampArray(Collections.emptyList()).build()); Struct row = readLastRow("TimestampArrayValue"); @@ -706,6 +798,7 @@ public void writeTimestampArrayEmpty() { @Test public void writeTimestampArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); Timestamp t1 = Timestamp.parseTimestamp("2016-09-18T00:00:00Z"); Timestamp t2 = Timestamp.parseTimestamp("2016-09-19T00:00:00Z"); write( @@ -720,6 +813,7 @@ public void writeTimestampArray() { @Test public void writeDateArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("DateArrayValue").toDateArray(null).build()); Struct row = readLastRow("DateArrayValue"); assertThat(row.isNull(0)).isTrue(); @@ -727,6 +821,7 @@ public void writeDateArrayNull() { @Test public void writeDateArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); write(baseInsert().set("DateArrayValue").toDateArray(Collections.emptyList()).build()); Struct row = readLastRow("DateArrayValue"); assertThat(row.isNull(0)).isFalse(); @@ -735,6 +830,7 @@ public void writeDateArrayEmpty() { @Test public void writeDateArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); Date d1 = Date.parseDate("2016-09-18"); Date d2 = Date.parseDate("2016-09-19"); write(baseInsert().set("DateArrayValue").toDateArray(Arrays.asList(d1, null, d2)).build()); @@ -745,6 +841,7 @@ public void writeDateArray() { @Test public void writeNumericArrayNull() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); write(baseInsert().set("NumericArrayValue").toNumericArray(null).build()); Struct row = readLastRow("NumericArrayValue"); @@ -753,6 +850,7 @@ public void writeNumericArrayNull() { @Test public void writeNumericArrayEmpty() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); write(baseInsert().set("NumericArrayValue").toNumericArray(ImmutableList.of()).build()); Struct row = readLastRow("NumericArrayValue"); @@ -762,6 +860,7 @@ public void writeNumericArrayEmpty() { @Test public void writeNumericArray() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); write( baseInsert() @@ -778,6 +877,7 @@ public void writeNumericArray() { @Test public void writeNumericArrayNoNulls() { + assumeFalse("PostgreSQL does not yet support Array", dialect.dialect == Dialect.POSTGRESQL); assumeFalse("Emulator does not yet support NUMERIC", EmulatorSpannerHelper.isUsingEmulator()); write( baseInsert() diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/slow/ITBackupTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/slow/ITBackupTest.java index a40a416b4c9..e27909abe89 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/slow/ITBackupTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/slow/ITBackupTest.java @@ -40,6 +40,7 @@ import com.google.cloud.spanner.DatabaseAdminClient; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Instance; import com.google.cloud.spanner.InstanceAdminClient; @@ -264,6 +265,8 @@ public void test01_Backups() throws InterruptedException, ExecutionException, Ti // Verifies that the database encryption has been properly set testDatabaseEncryption(database, keyName); + // Verifies that the database dialect has been properly set + testDatabaseDialect(database, Dialect.GOOGLE_STANDARD_SQL); // Create a backup of the database. String backupId = testHelper.getUniqueBackupId() + "_bck1"; @@ -598,6 +601,13 @@ private void testDatabaseEncryption(Database database, String expectedKey) { logger.info("Done verifying database encryption for " + database.getId()); } + private void testDatabaseDialect(Database database, Dialect expectedDialect) { + logger.info("Verifying dialect for " + database.getId()); + assertNotNull(database.getDialect()); + assertEquals(expectedDialect, database.getDialect()); + logger.info("Done verifying database dialect for " + database.getId()); + } + private void testBackupEncryption(Backup backup, String expectedKey) { logger.info("Verifying backup encryption for " + backup.getId()); assertNotNull(backup.getEncryptionInfo()); @@ -813,6 +823,7 @@ private void testRestore(Backup backup, Timestamp versionTime, String expectedKe Timestamp.fromProto( reloadedDatabase.getProto().getRestoreInfo().getBackupInfo().getVersionTime())); testDatabaseEncryption(reloadedDatabase, expectedKey); + testDatabaseDialect(reloadedDatabase, Dialect.GOOGLE_STANDARD_SQL); // Restoring the backup to an existing database should fail. logger.info( diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java index 7c6d6df346c..4ed6c32c7bf 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java @@ -29,6 +29,7 @@ import com.google.auth.oauth2.OAuth2Credentials; import com.google.cloud.spanner.DatabaseClient; import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; @@ -70,14 +71,15 @@ import java.util.Map; import java.util.concurrent.TimeUnit; import org.junit.After; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; import org.threeten.bp.Duration; -@RunWith(JUnit4.class) +@RunWith(Parameterized.class) public class GapicSpannerRpcTest { private static final Statement SELECT1AND2 = @@ -134,8 +136,15 @@ public class GapicSpannerRpcTest { private static String defaultUserAgent; private static Spanner spanner; - @BeforeClass - public static void startServer() throws IOException { + @Parameter public Dialect dialect; + + @Parameters(name = "dialect = {0}") + public static Object[] data() { + return Dialect.values(); + } + + @Before + public void startServer() throws IOException { assumeTrue( "Skip tests when emulator is enabled as this test interferes with the check whether the emulator is running", System.getenv("SPANNER_EMULATOR_HOST") == null); @@ -172,20 +181,20 @@ public ServerCall.Listener interceptCall( spanner = createSpannerOptions().getService(); } - @AfterClass - public static void stopServer() throws InterruptedException { + @After + public void reset() throws InterruptedException { + if (mockSpanner != null) { + mockSpanner.reset(); + } if (spanner != null) { spanner.close(); + } + if (server != null) { server.shutdown(); server.awaitTermination(); } } - @After - public void reset() { - mockSpanner.reset(); - } - @Test public void testCallCredentialsProviderPreferenceAboveCredentials() { SpannerOptions options = @@ -387,10 +396,11 @@ public void testCustomUserAgent() { } } - private static SpannerOptions createSpannerOptions() { + private SpannerOptions createSpannerOptions() { String endpoint = address.getHostString() + ":" + server.getPort(); return SpannerOptions.newBuilder() .setProjectId("[PROJECT]") + .setDialect(dialect) // Set a custom channel configurator to allow http instead of https. .setChannelConfigurator( input -> { 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 0e87a357c45..4fe25d53b05 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 @@ -33,169 +33,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable autocommit; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-autocommit; NEW_CONNECTION; show variable readonly; @@ -232,169 +232,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable readonly; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable readonly/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-readonly; NEW_CONNECTION; set readonly=false; @@ -459,7 +459,7 @@ foo show variable retry_aborts_internally; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally bar; NEW_CONNECTION; set readonly=false; @@ -469,12 +469,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally%; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -484,12 +484,12 @@ _show variable retry_aborts_internally; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally_; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -499,12 +499,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally&; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -514,12 +514,12 @@ $show variable retry_aborts_internally; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally$; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -529,12 +529,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally@; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -544,12 +544,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally!; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -559,12 +559,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally*; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -574,12 +574,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally(; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -589,12 +589,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally); NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -604,12 +604,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally-; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -619,12 +619,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally+; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -634,12 +634,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally-#; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -649,12 +649,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally/; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -664,12 +664,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally\; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -679,12 +679,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally?; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -694,12 +694,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally-/; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -709,12 +709,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally/#; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#retry_aborts_internally; NEW_CONNECTION; set readonly=false; @@ -724,12 +724,12 @@ set autocommit=false; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable retry_aborts_internally/-; NEW_CONNECTION; set readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-retry_aborts_internally; NEW_CONNECTION; show variable autocommit_dml_mode; @@ -766,169 +766,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable autocommit_dml_mode; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable autocommit_dml_mode/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-autocommit_dml_mode; NEW_CONNECTION; show variable statement_timeout; @@ -965,169 +965,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable statement_timeout; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_timeout/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-statement_timeout; NEW_CONNECTION; set readonly = true; @@ -1192,7 +1192,7 @@ foo show variable read_timestamp; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp bar; NEW_CONNECTION; set readonly = true; @@ -1202,12 +1202,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp%; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1217,12 +1217,12 @@ _show variable read_timestamp; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp_; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1232,12 +1232,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp&; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1247,12 +1247,12 @@ $show variable read_timestamp; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp$; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1262,12 +1262,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp@; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1277,12 +1277,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp!; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1292,12 +1292,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp*; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1307,12 +1307,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp(; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1322,12 +1322,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp); NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1337,12 +1337,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp-; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1352,12 +1352,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp+; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1367,12 +1367,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp-#; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1382,12 +1382,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp/; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1397,12 +1397,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp\; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1412,12 +1412,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp?; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1427,12 +1427,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp-/; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1442,12 +1442,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp/#; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#read_timestamp; NEW_CONNECTION; set readonly = true; @@ -1457,12 +1457,12 @@ SELECT 1 AS TEST; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_timestamp/-; NEW_CONNECTION; set readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-read_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1513,7 +1513,7 @@ update foo set bar=1; foo show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp bar; NEW_CONNECTION; update foo set bar=1; @@ -1521,11 +1521,11 @@ update foo set bar=1; %show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp%; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1533,11 +1533,11 @@ update foo set bar=1; _show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp_; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1545,11 +1545,11 @@ update foo set bar=1; &show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp&; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1557,11 +1557,11 @@ update foo set bar=1; $show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp$; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1569,11 +1569,11 @@ update foo set bar=1; @show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp@; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1581,11 +1581,11 @@ update foo set bar=1; !show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp!; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1593,11 +1593,11 @@ update foo set bar=1; *show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp*; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1605,11 +1605,11 @@ update foo set bar=1; (show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp(; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1617,11 +1617,11 @@ update foo set bar=1; )show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp); NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1629,11 +1629,11 @@ update foo set bar=1; -show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1641,11 +1641,11 @@ update foo set bar=1; +show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp+; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1653,11 +1653,11 @@ update foo set bar=1; -#show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp-#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1665,11 +1665,11 @@ update foo set bar=1; /show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1677,11 +1677,11 @@ update foo set bar=1; \show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp\; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1689,11 +1689,11 @@ update foo set bar=1; ?show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp?; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1701,11 +1701,11 @@ update foo set bar=1; -/show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp-/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1713,11 +1713,11 @@ update foo set bar=1; /#show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp/#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -1725,11 +1725,11 @@ update foo set bar=1; /-show variable commit_timestamp; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_timestamp/-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-commit_timestamp; NEW_CONNECTION; show variable read_only_staleness; @@ -1766,169 +1766,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable read_only_staleness; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable read_only_staleness/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-read_only_staleness; NEW_CONNECTION; show variable optimizer_version; @@ -1965,169 +1965,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable optimizer_version; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_version/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-optimizer_version; NEW_CONNECTION; show variable optimizer_statistics_package; @@ -2164,169 +2164,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable optimizer_statistics_package; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable optimizer_statistics_package/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-optimizer_statistics_package; NEW_CONNECTION; show variable return_commit_stats; @@ -2363,169 +2363,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable return_commit_stats; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable return_commit_stats/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-return_commit_stats; NEW_CONNECTION; update foo set bar=1; @@ -2576,7 +2576,7 @@ update foo set bar=1; foo show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response bar; NEW_CONNECTION; update foo set bar=1; @@ -2584,11 +2584,11 @@ update foo set bar=1; %show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response%; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2596,11 +2596,11 @@ update foo set bar=1; _show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response_; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2608,11 +2608,11 @@ update foo set bar=1; &show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response&; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2620,11 +2620,11 @@ update foo set bar=1; $show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response$; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2632,11 +2632,11 @@ update foo set bar=1; @show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response@; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2644,11 +2644,11 @@ update foo set bar=1; !show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response!; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2656,11 +2656,11 @@ update foo set bar=1; *show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response*; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2668,11 +2668,11 @@ update foo set bar=1; (show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response(; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2680,11 +2680,11 @@ update foo set bar=1; )show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response); NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2692,11 +2692,11 @@ update foo set bar=1; -show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2704,11 +2704,11 @@ update foo set bar=1; +show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response+; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2716,11 +2716,11 @@ update foo set bar=1; -#show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response-#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2728,11 +2728,11 @@ update foo set bar=1; /show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2740,11 +2740,11 @@ update foo set bar=1; \show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response\; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2752,11 +2752,11 @@ update foo set bar=1; ?show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response?; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2764,11 +2764,11 @@ update foo set bar=1; -/show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response-/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2776,11 +2776,11 @@ update foo set bar=1; /#show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response/#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#commit_response; NEW_CONNECTION; update foo set bar=1; @@ -2788,11 +2788,11 @@ update foo set bar=1; /-show variable commit_response; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable commit_response/-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-commit_response; NEW_CONNECTION; show variable statement_tag; @@ -2829,169 +2829,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable statement_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable statement_tag/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-statement_tag; NEW_CONNECTION; show variable transaction_tag; @@ -3028,169 +3028,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable transaction_tag; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable transaction_tag/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-transaction_tag; NEW_CONNECTION; show variable rpc_priority; @@ -3227,169 +3227,169 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT foo show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority bar; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT %show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable%rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT _show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable_rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT &show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable&rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT $show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable$rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable@rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT !show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable!rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT *show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable*rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT (show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable(rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT )show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable)rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT +show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable+rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -#show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-#rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT \show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable\rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT ?show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable?rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT -/show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable-/rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /#show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/#rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT /-show variable rpc_priority; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable rpc_priority/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show variable/-rpc_priority; NEW_CONNECTION; begin; 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 4091717231d..d1eabfeaec3 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 @@ -1,23 +1,23 @@ NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -26,123 +26,125 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -151,58 +153,60 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:24.004000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:24.004000000Z' +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:09.176000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:09.176000000Z' 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 2021-11-12T19:08:24.004000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:09.176000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:09.176000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -217,34 +221,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -253,8 +257,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -297,45 +301,46 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -346,28 +351,36 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -376,123 +389,173 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -501,58 +564,78 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:24.184000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:24.184000000Z' +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:09.407000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:09.407000000Z' 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 2021-11-12T19:08:24.184000000Z'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:09.407000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:09.407000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' 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 AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -567,34 +650,48 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -603,8 +700,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -647,45 +746,62 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -NEW_CONNECTION; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -696,324 +812,207 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; -SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -ROLLBACK; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:24.391000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:24.391000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:09.583000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:09.583000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:24.391000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:09.583000000Z'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1028,55 +1027,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1085,11 +1063,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1132,116 +1107,71 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -1250,195 +1180,125 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -1447,85 +1307,60 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:24.603000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:24.603000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:09.731000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:09.731000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:24.603000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:09.731000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:09.731000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1540,55 +1375,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1597,11 +1411,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -1644,69 +1455,46 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -1717,208 +1505,217 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:24.746000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:24.746000000Z' +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:09.897000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:09.897000000Z' 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 2021-11-12T19:08:24.746000000Z'; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:09.897000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:09.897000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -1933,34 +1730,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -1969,8 +1766,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2013,282 +1810,230 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=TRUE; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; 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='READ_TIMESTAMP 2021-11-12T19:08:24.942000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.078000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:10.078000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; 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 2021-11-12T19:08:24.942000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.078000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:10.078000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2303,41 +2048,27 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2346,9 +2077,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2391,254 +2120,243 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -NEW_CONNECTION; -SET READONLY=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'TEST',1 +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=TRUE; +SET READONLY=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:25.174000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.239000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:25.174000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.239000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2652,35 +2370,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2688,9 +2406,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -2732,220 +2450,285 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; -NEW_CONNECTION; -SET READONLY=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:25.357000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:25.357000000Z' +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.386000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:10.386000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:25.357000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.386000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -2959,28 +2742,42 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -2988,8 +2785,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3031,68 +2830,88 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -COMMIT; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; +COMMIT; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -3102,103 +2921,150 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -3210,7 +3076,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -3222,12 +3090,17 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -3237,57 +3110,77 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:25.549000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:25.549000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.614000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:10.614000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:25.549000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.614000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:10.614000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -3303,33 +3196,47 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -3339,7 +3246,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -3383,43 +3292,61 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -3430,198 +3357,138 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +UPDATE foo SET bar=1; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -3632,95 +3499,69 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; -SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -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 2021-11-12T19:08:25.723000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:25.723000000Z' +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.809000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:10.809000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:25.723000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.809000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -3735,48 +3576,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -3785,10 +3612,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -3831,303 +3656,272 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -RUN BATCH; +SET AUTOCOMMIT=TRUE; +BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:25.858000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:10.941000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:10.941000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:25.858000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:10.941000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:10.941000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -4143,40 +3937,33 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -4186,8 +3973,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -4231,254 +4017,280 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.003000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.120000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.120000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:26.003000000Z'; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.120000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:11.120000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4493,34 +4305,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -4529,8 +4341,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -4573,83 +4385,81 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -START BATCH DDL; +SET AUTOCOMMIT=TRUE; +UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -4658,167 +4468,130 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -4829,11 +4602,9 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -4844,19 +4615,16 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -4865,85 +4633,69 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.155000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.155000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.271000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.271000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:26.155000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.271000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:11.271000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -4958,55 +4710,41 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5015,11 +4753,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5062,68 +4798,54 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -5133,207 +4855,232 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.311000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.311000000Z' +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.432000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.432000000Z' 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 2021-11-12T19:08:26.311000000Z'; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.432000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:11.432000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5348,34 +5095,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5384,8 +5131,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5428,71 +5175,73 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET TRANSACTION READ ONLY; +SET AUTOCOMMIT=TRUE; +SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -5501,104 +5250,88 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' +SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -5609,8 +5342,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -5621,13 +5353,12 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -5636,58 +5367,51 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.437000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.437000000Z' +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.577000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.577000000Z' 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 2021-11-12T19:08:26.437000000Z'; +SET AUTOCOMMIT=TRUE; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.577000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2022-02-08T09:47:11.577000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' 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 AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -5702,34 +5426,27 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -5738,8 +5455,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -5782,44 +5498,38 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -5829,40 +5539,27 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -5870,206 +5567,124 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -@EXPECT UPDATE_COUNT 1 +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -6077,86 +5692,59 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.614000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.614000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.702000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.702000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:26.614000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.702000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -6170,56 +5758,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -6227,12 +5794,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6274,115 +5838,78 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -ROLLBACK; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -6390,206 +5917,124 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT UPDATE_COUNT 1 +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -6597,86 +6042,59 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.803000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.803000000Z' +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.804000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.804000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:26.803000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.804000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -6690,56 +6108,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -6747,12 +6144,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -6794,284 +6188,374 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; -@EXPECT RESULT_SET 'TEST',1 -SELECT 1 AS TEST; -COMMIT; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -COMMIT; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT UPDATE_COUNT 1 +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +ROLLBACK; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:26.930000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:26.930000000Z' +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:11.962000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:11.962000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:26.930000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:11.962000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7085,35 +6569,56 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7121,9 +6626,12 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7165,287 +6673,401 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +COMMIT; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; +SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.097000000Z'; +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.213000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:12.213000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:27.097000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.213000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7459,42 +7081,56 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7502,10 +7138,12 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7547,260 +7185,282 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +BEGIN TRANSACTION; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +BEGIN TRANSACTION; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.270000000Z'; +BEGIN TRANSACTION; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.372000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:12.372000000Z' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:27.270000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.372000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' +SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -7814,35 +7474,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -7850,9 +7510,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -7894,230 +7554,283 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SELECT 1 AS TEST; +BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT UPDATE_COUNT 1 +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.406000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:27.406000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.493000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +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 2021-11-12T19:08:27.406000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.493000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8131,28 +7844,42 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -8160,8 +7887,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8203,241 +7932,255 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT RESULT_SET 'READ_TIMESTAMP',null +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; ROLLBACK; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +SET READONLY=TRUE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.519000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.629000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:27.519000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.629000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8451,35 +8194,35 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -8487,9 +8230,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8531,285 +8274,220 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -START BATCH DDL; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -@EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.620000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:27.620000000Z' +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.745000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:12.745000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:27.620000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.745000000Z'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -8823,42 +8501,28 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -8866,10 +8530,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -8911,88 +8573,68 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION READ ONLY; +SET READONLY=TRUE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE @@ -9002,150 +8644,103 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -9157,9 +8752,7 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION @@ -9171,17 +8764,12 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE @@ -9191,77 +8779,57 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.738000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:27.738000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:12.848000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:12.848000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:27.738000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:27.738000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.848000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -9277,47 +8845,33 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -9327,9 +8881,7 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -9373,61 +8925,43 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; @@ -9438,138 +8972,198 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE +SHOW VARIABLE AUTOCOMMIT; +SET AUTOCOMMIT=TRUE; +@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE +SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -NEW_CONNECTION; -SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -9580,69 +9174,95 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET READONLY=FALSE; +@EXPECT RESULT_SET 'READONLY',FALSE +SHOW VARIABLE READONLY; +SET READONLY=TRUE; +@EXPECT RESULT_SET 'READONLY',TRUE +SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +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='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:27.876000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:27.876000000Z' +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 2022-02-08T09:47:12.981000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:12.981000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +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 2021-11-12T19:08:27.876000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:12.981000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +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='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +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='MAX_STALENESS 100ms'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +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='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -9657,34 +9277,48 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -9693,8 +9327,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -9737,272 +9373,303 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; -SET TRANSACTION_TAG = 'some-tag'; -NEW_CONNECTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; +SET TRANSACTION_TAG = 'some-tag'; +NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; BEGIN TRANSACTION; +SELECT 1 AS TEST; +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -BEGIN TRANSACTION; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +START BATCH DDL; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT UPDATE_COUNT 1 +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT RESULT_SET 'TEST',1 +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +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='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.014000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.014000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.109000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.014000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.014000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.109000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +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='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +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='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +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='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -10018,33 +9685,40 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -10054,7 +9728,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -10098,280 +9773,254 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -ABORT BATCH; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT UPDATE_COUNT 1 +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'TEST',1 +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.150000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.150000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.229000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.150000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.150000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.229000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10386,34 +10035,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -10422,8 +10071,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10466,81 +10115,83 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS' +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +START BATCH DDL; RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -10549,130 +10200,167 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_TIMESTAMP' SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10683,9 +10371,11 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -10696,16 +10386,19 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -10714,69 +10407,85 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.249000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.249000000Z' +COMMIT; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.350000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:13.350000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.249000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.249000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.350000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -10791,41 +10500,55 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -10834,9 +10557,11 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -10879,54 +10604,68 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +COMMIT; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -10936,232 +10675,207 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT UPDATE_COUNT 1 +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DDL; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -START BATCH DML; -@EXPECT EXCEPTION FAILED_PRECONDITION -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -UPDATE foo SET bar=1; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.377000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.377000000Z' +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.472000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:13.472000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.377000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.377000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.472000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11176,34 +10890,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -11212,8 +10926,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11256,73 +10970,71 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET AUTOCOMMIT=FALSE; +SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -NEW_CONNECTION; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11331,88 +11043,104 @@ SET AUTOCOMMIT=TRUE; SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; -@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC' -SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ ONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION READ WRITE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11423,7 +11151,8 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); START BATCH DDL; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; START BATCH DML; @EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @@ -11434,12 +11163,13 @@ UPDATE foo SET bar=1; START BATCH DML; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; ROLLBACK; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -11448,51 +11178,58 @@ SET READONLY=TRUE; SHOW VARIABLE READONLY; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.469000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.469000000Z' +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.568000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:13.568000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.469000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.469000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.568000000Z'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11507,27 +11244,34 @@ SET OPTIMIZER_VERSION=''; SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -11536,7 +11280,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11579,38 +11324,44 @@ SET STATEMENT_TIMEOUT='0ns'; SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; COMMIT; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; BEGIN TRANSACTION; SELECT 1 AS TEST; UPDATE foo SET bar=1; @@ -11620,27 +11371,40 @@ CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); BEGIN TRANSACTION; NEW_CONNECTION; SET READONLY=FALSE; -SET AUTOCOMMIT=TRUE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -11648,126 +11412,206 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -11775,61 +11619,86 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.552000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.552000000Z' +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.700000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:13.700000000Z' 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 2021-11-12T19:08:28.552000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.552000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.700000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -11843,35 +11712,56 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -11879,9 +11769,12 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -11923,85 +11816,113 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET AUTOCOMMIT=FALSE; @@ -12011,172 +11932,204 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READONLY=FALSE; @@ -12186,77 +12139,84 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.668000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.668000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:13.931000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:13.931000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.668000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.668000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:13.931000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_VERSION='1'; @@ -12272,47 +12232,54 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null +@EXPECT RESULT_SET 'COMMIT_TIMESTAMP' SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @@ -12322,9 +12289,10 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; SET STATEMENT_TIMEOUT='1s'; @@ -12368,273 +12336,283 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET AUTOCOMMIT=FALSE; -NEW_CONNECTION; -SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READONLY=FALSE; -NEW_CONNECTION; SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +NEW_CONNECTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.767000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.767000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:14.114000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:14.114000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.767000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:14.114000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -12649,34 +12627,34 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -12685,8 +12663,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -12729,260 +12707,286 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -@EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.862000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.862000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:14.244000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.862000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.862000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:14.244000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -12997,34 +13001,41 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13033,8 +13044,9 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13077,267 +13089,259 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -BEGIN TRANSACTION; -SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 +SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; +SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -@EXPECT RESULT_SET 'AUTOCOMMIT',FALSE -SHOW VARIABLE AUTOCOMMIT; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT=TRUE; -@EXPECT RESULT_SET 'AUTOCOMMIT',TRUE -SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -@EXPECT RESULT_SET 'READ_TIMESTAMP' +@EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; +@EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; SET READONLY=FALSE; -@EXPECT RESULT_SET 'READONLY',FALSE -SHOW VARIABLE READONLY; +SET AUTOCOMMIT=FALSE; +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READONLY=TRUE; -@EXPECT RESULT_SET 'READONLY',TRUE -SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='STRONG'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:28.959000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:28.959000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:14.384000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:28.959000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:28.959000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:14.384000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' @@ -13352,34 +13356,34 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' @@ -13388,8 +13392,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' @@ -13432,75 +13436,68 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SELECT 1 AS TEST; -BEGIN TRANSACTION; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -UPDATE foo SET bar=1; -@EXPECT EXCEPTION FAILED_PRECONDITION -CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -@EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_VERSION' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION ABORT BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT',FALSE SHOW VARIABLE AUTOCOMMIT; @@ -13508,102 +13505,110 @@ SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'AUTOCOMMIT',TRUE SHOW VARIABLE AUTOCOMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT UPDATE_COUNT 1 UPDATE foo SET bar=1; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE' SHOW VARIABLE AUTOCOMMIT_DML_MODE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET TRANSACTION READ WRITE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_TIMESTAMP',null SHOW VARIABLE READ_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DDL; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +UPDATE foo SET bar=1; +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DDL; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +START BATCH DML; +@EXPECT EXCEPTION FAILED_PRECONDITION +SELECT 1 AS TEST; +@EXPECT EXCEPTION FAILED_PRECONDITION +CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); +UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION START BATCH DML; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; ROLLBACK; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET READONLY=FALSE; @EXPECT RESULT_SET 'READONLY',FALSE SHOW VARIABLE READONLY; @@ -13611,52 +13616,50 @@ SET READONLY=TRUE; @EXPECT RESULT_SET 'READONLY',TRUE SHOW VARIABLE READONLY; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='STRONG'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','STRONG' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2021-11-12T19:08:29.047000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2021-11-12T19:08:29.047000000Z' +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2022-02-08T09:47:14.507000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2022-02-08T09:47:14.507000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2021-11-12T19:08:29.047000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2021-11-12T19:08:29.047000000Z' -SHOW VARIABLE READ_ONLY_STALENESS; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2022-02-08T09:47:14.507000000Z'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 1s'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 1s' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; +@EXPECT EXCEPTION FAILED_PRECONDITION SET READ_ONLY_STALENESS='MAX_STALENESS 100ms'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MAX_STALENESS 100ms' -SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 100us'; @EXPECT RESULT_SET 'READ_ONLY_STALENESS','EXACT_STALENESS 100us' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_RESPONSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_VERSION='1'; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','1' SHOW VARIABLE OPTIMIZER_VERSION; @@ -13670,28 +13673,28 @@ SET OPTIMIZER_VERSION=''; @EXPECT RESULT_SET 'OPTIMIZER_VERSION','' SHOW VARIABLE OPTIMIZER_VERSION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'COMMIT_TIMESTAMP',null SHOW VARIABLE COMMIT_TIMESTAMP; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET OPTIMIZER_STATISTICS_PACKAGE='custom-package'; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','custom-package' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; @@ -13699,8 +13702,8 @@ SET OPTIMIZER_STATISTICS_PACKAGE=''; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE','' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET STATEMENT_TIMEOUT='1s'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT','1s' SHOW VARIABLE STATEMENT_TIMEOUT; @@ -13742,47 +13745,44 @@ SET STATEMENT_TIMEOUT='0ns'; @EXPECT RESULT_SET 'STATEMENT_TIMEOUT',null SHOW VARIABLE STATEMENT_TIMEOUT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'READ_ONLY_STALENESS' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; COMMIT; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'OPTIMIZER_STATISTICS_PACKAGE' SHOW VARIABLE OPTIMIZER_STATISTICS_PACKAGE; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION RUN BATCH; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; -@EXPECT EXCEPTION FAILED_PRECONDITION +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; SET TRANSACTION_TAG = 'some-tag'; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; SELECT 1 AS TEST; -@EXPECT EXCEPTION FAILED_PRECONDITION UPDATE foo SET bar=1; @EXPECT EXCEPTION FAILED_PRECONDITION CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION BEGIN TRANSACTION; NEW_CONNECTION; -SET READONLY=TRUE; -SET AUTOCOMMIT=TRUE; +SET READONLY=FALSE; +SET AUTOCOMMIT=FALSE; diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/PostgreSQLCommentsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/PostgreSQLCommentsTest.sql new file mode 100644 index 00000000000..51ae1e7203c --- /dev/null +++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/PostgreSQLCommentsTest.sql @@ -0,0 +1,187 @@ +/* + * Copyright 2022 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. + */ + +@EXPECT 'SELECT 1'; +SELECT 1; +-- This is a single line comment +SELECT 1; +/* This is a multi line comment on one line */ +SELECT 1; +/* This + is + a + multiline + comment +*/ +SELECT 1; +/* This + * is + * a + * multiline + * comment + */ +SELECT 1; +/** This is a javadoc style comment on one line*/ +SELECT 1; +/** This + is + a + javadoc + style + comment + on + multiple + lines +*/ +SELECT 1; +/** This + * is + * a + * javadoc + * style + * comment + * on + * multiple + * lines + */ +SELECT 1; + +@EXPECT 'SELECT + 1'; +-- First comment +SELECT-- second comment + 1; +-- First comment +SELECT-- second comment + 1--third comment +; +@EXPECT 'SELECT + 1'; +/* First comment */ +SELECT/* second comment */ + 1; +/* First comment */ +SELECT/* second comment */ + 1/* Third comment */ +; + + +@EXPECT 'SELECT + 1'; +-- First comment +SELECT -- second comment + 1 ; +-- First comment +SELECT -- second comment + 1 --third comment +; +@EXPECT 'SELECT + 1'; +/* First comment */ +SELECT /* second comment */ + 1 ; +/* First comment */ +SELECT /* second comment */ + 1 /* Third comment */ +; + +@EXPECT 'SELECT "TEST -- This is not a comment"'; +SELECT "TEST -- This is not a comment"; +-- This is a comment +SELECT "TEST -- This is not a comment"; +-- This is a comment +SELECT "TEST -- This is not a comment" -- This is a comment; + + @EXPECT 'SELECT "TEST /* This is not a comment */"'; +SELECT "TEST /* This is not a comment */"; +/* This is a comment */ +SELECT "TEST /* This is not a comment */"; +/* This is a comment */ +SELECT "TEST /* This is not a comment */" /* This is a comment */; + +@EXPECT 'SELECT 'TEST -- This is not a comment''; +SELECT 'TEST -- This is not a comment'; +-- This is a comment +SELECT 'TEST -- This is not a comment'; +-- This is a comment +SELECT 'TEST -- This is not a comment' -- This is a comment; + + @EXPECT 'SELECT 'TEST /* This is not a comment */''; +SELECT 'TEST /* This is not a comment */'; +/* This is a comment */ +SELECT 'TEST /* This is not a comment */'; +/* This is a comment */ +SELECT 'TEST /* This is not a comment */' /* This is a comment */; + +@EXPECT 'SELECT $$TEST +-- This is not a comment +$$'; +SELECT $$TEST +-- This is not a comment +$$; +-- This is a comment +SELECT $$TEST +-- This is not a comment +$$; +-- This is a comment +SELECT $$TEST +-- This is not a comment +$$ -- This is a comment; + + @EXPECT 'SELECT $$TEST +/* This is not a comment */ +$$'; +SELECT $$TEST +/* This is not a comment */ +$$; +/* This is a comment */ +SELECT $$TEST +/* This is not a comment */ +$$; +/* This is a comment */ +SELECT $$TEST +/* This is not a comment */ +$$ /* This is a comment */; + +@EXPECT 'SELECT 1'; +/* This is a comment /* This is an embedded comment */ This is still a comment */ +SELECT 1; +/** This is a javadoc style comment /* This is an embedded comment */ This is still a comment */ +SELECT 1; +/** This is a javadoc style comment /** This is an embedded comment */ This is still a comment */ +SELECT 1; +/** This is a javadoc style comment /** This is an embedded comment **/ This is still a comment **/ +SELECT 1; +/* multiline comment + * with nesting: /* nested block comment */ + */ +SELECT 1; + +@EXPECT 'SELECT U&"d\0061t\+000061" FROM FOO'; +SELECT U&"d\0061t\+000061" FROM FOO; +/* This is a comment /* U&"d\0061t\+000061" */ This is still a comment */ +SELECT U&"d\0061t\+000061" FROM FOO; +SELECT U&"d\0061t\+000061" /* This is a comment /* U&"d\0061t\+000061" */ This is still a comment */FROM FOO; + +@EXPECT 'SELECT U&"d\0061t\+000061" +FROM FOO'; +SELECT U&"d\0061t\+000061" -- U&"d\0061t\+000061" == data */ This is still a comment */ +FROM FOO; + +@EXPECT 'SELECT 'foo' +'bar' +SELECT 'foo' -- This is allowed in PostgreSQL +'bar'; From 0d54e412f994e3feba98846e6925d300a0c88955 Mon Sep 17 00:00:00 2001 From: Thiago Nunes Date: Mon, 14 Feb 2022 10:41:34 +1100 Subject: [PATCH 11/19] test: fix it json read write test (#1686) The max accepted nesting level is 90. In this commit we change the test case from 100 levels of nesting to 90. --- .../spanner/it/valid/{y_100_nested.json => y_90_nested.json} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/{y_100_nested.json => y_90_nested.json} (78%) diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_100_nested.json b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_90_nested.json similarity index 78% rename from google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_100_nested.json rename to google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_90_nested.json index 552b0bff0fb..5d1bd8e16cc 100644 --- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_100_nested.json +++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/it/valid/y_90_nested.json @@ -1 +1 @@ -{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} \ No newline at end of file +{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{"nest":{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} From b8da7251a08c2231476caef7d34b49e2dd53bfbd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Feb 2022 00:48:51 +0100 Subject: [PATCH 12/19] build(deps): update dependency org.sonatype.plugins:nexus-staging-maven-plugin to v1.6.10 (#1682) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.sonatype.plugins:nexus-staging-maven-plugin](http://www.sonatype.com/) ([source](https://togithub.com/sonatype/nexus-maven-plugins)) | `1.6.8` -> `1.6.10` | [![age](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/compatibility-slim/1.6.8)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.sonatype.plugins:nexus-staging-maven-plugin/1.6.10/confidence-slim/1.6.8)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes

sonatype/nexus-maven-plugins ### [`v1.6.10`](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.9...release-1.6.10) [Compare Source](https://togithub.com/sonatype/nexus-maven-plugins/compare/release-1.6.9...release-1.6.10)
--- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- samples/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/pom.xml b/samples/pom.xml index 3a78a08d95e..493c88bcaf5 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -46,7 +46,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.10 true From 5dc3e191bee603a7feec29b7d4412646d53d73e4 Mon Sep 17 00:00:00 2001 From: Rajat Bhatta <93644539+rajatbhatta@users.noreply.github.com> Date: Tue, 15 Feb 2022 07:33:14 +0000 Subject: [PATCH 13/19] fix: do not delete session in close method for BatchReadOnlyTransactionImpl (#1688) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: do not delete session in close method for BatchReadOnlyTransactionImpl - remove session.close() from close() method implementation in BatchReadOnlyTransactionImpl class. - add a cleanup() method to BatchReadOnlyTransaction interface and give user the control to delete session when the session is no longer in use. - add tests for txn.cleanup() method. * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * Incorporate review comments Co-authored-by: Knut Olav Løite * Incorporate review comments. Co-authored-by: Knut Olav Løite * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * 🦉 Updates from OwlBot See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md Co-authored-by: Owl Bot Co-authored-by: Knut Olav Løite --- .../clirr-ignored-differences.xml | 5 +++++ .../google/cloud/spanner/BatchClientImpl.java | 9 ++++++-- .../spanner/BatchReadOnlyTransaction.java | 8 +++++++ .../cloud/spanner/DatabaseClientImplTest.java | 21 ++++++++++++------- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml index c750b2a7f40..f65bfd94332 100644 --- a/google-cloud-spanner/clirr-ignored-differences.xml +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -6,6 +6,11 @@ com/google/cloud/spanner/connection/Connection com.google.cloud.spanner.Dialect getDialect() + + 7012 + com/google/cloud/spanner/BatchReadOnlyTransaction + void cleanup() + 8001 com/google/cloud/spanner/connection/StatementParser diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java index c84bef77cf8..fe31a3b0101 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java @@ -214,9 +214,14 @@ public ResultSet execute(Partition partition) throws SpannerException { partition.getPartitionToken()); } + /** + * Closes the session as part of the cleanup. It is the responsibility of the caller to make a + * call to this method once the transaction completes execution across all the channels (which + * is understandably hard to identify). It is okay if the caller does not call the method + * because the backend will anyways clean up the unused session. + */ @Override - public void close() { - super.close(); + public void cleanup() { session.close(); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchReadOnlyTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchReadOnlyTransaction.java index 9a9613f3247..03b08a11730 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchReadOnlyTransaction.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchReadOnlyTransaction.java @@ -197,4 +197,12 @@ List partitionQuery( * BatchTransactionId guarantees the subsequent read/query to be executed at the same timestamp. */ BatchTransactionId getBatchTransactionId(); + + /** + * Closes the session as part of the cleanup. It is the responsibility of the caller to make a + * call to this method once the transaction completes execution across all the channels (which is + * understandably hard to identify). It is okay if the caller does not call the method because the + * backend will anyways clean up the unused session. + */ + default void cleanup() {} } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java index 20e8c6b8ea6..21c9d3eaa77 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java @@ -54,6 +54,7 @@ import com.google.common.util.concurrent.SettableFuture; import com.google.protobuf.AbstractMessage; import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.DeleteSessionRequest; import com.google.spanner.v1.ExecuteBatchDmlRequest; import com.google.spanner.v1.ExecuteSqlRequest; import com.google.spanner.v1.ExecuteSqlRequest.QueryMode; @@ -1630,16 +1631,20 @@ public void testBackendPartitionQueryOptions() { try (ResultSet rs = transaction.execute(partitions.get(0))) { // Just iterate over the results to execute the query. while (rs.next()) {} + } finally { + transaction.cleanup(); } - // Check that the last query was executed using a custom optimizer version and statistics - // package. + // Check if the last query executed is a DeleteSessionRequest and the second last query + // executed is a ExecuteSqlRequest and was executed using a custom optimizer version and + // statistics package. List requests = mockSpanner.getRequests(); - assertThat(requests).isNotEmpty(); - assertThat(requests.get(requests.size() - 1)).isInstanceOf(ExecuteSqlRequest.class); - ExecuteSqlRequest request = (ExecuteSqlRequest) requests.get(requests.size() - 1); - assertThat(request.getQueryOptions()).isNotNull(); - assertThat(request.getQueryOptions().getOptimizerVersion()).isEqualTo("1"); - assertThat(request.getQueryOptions().getOptimizerStatisticsPackage()) + assert requests.size() >= 2 : "required to have at least 2 requests"; + assertThat(requests.get(requests.size() - 1)).isInstanceOf(DeleteSessionRequest.class); + assertThat(requests.get(requests.size() - 2)).isInstanceOf(ExecuteSqlRequest.class); + ExecuteSqlRequest executeSqlRequest = (ExecuteSqlRequest) requests.get(requests.size() - 2); + assertThat(executeSqlRequest.getQueryOptions()).isNotNull(); + assertThat(executeSqlRequest.getQueryOptions().getOptimizerVersion()).isEqualTo("1"); + assertThat(executeSqlRequest.getQueryOptions().getOptimizerStatisticsPackage()) .isEqualTo("custom-package"); } } From 7095f940638d786745ed6715cf7a221d3e4a41a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 15 Feb 2022 10:15:12 +0100 Subject: [PATCH 14/19] fix: untyped null parameters would cause NPE (#1680) Adding an untyped null value as a parameter to a statement was not possible, as: 1. The parameter collection would allow a null value to be added, but when the statement was built, it would throw a NullPointerException because it used an ImmutableMap internally, which does not support null values. 2. The translation from a hand-written Statement instance to a proto Statement instance would fail, as it did not take into account that the parameter could be null. Fixes #1679 --- .../cloud/spanner/AbstractReadContext.java | 16 ++++--- .../google/cloud/spanner/BatchClientImpl.java | 6 ++- .../spanner/PartitionedDmlTransaction.java | 6 ++- .../com/google/cloud/spanner/Statement.java | 19 +++++--- .../java/com/google/cloud/spanner/Value.java | 10 +++-- .../google/cloud/spanner/StatementTest.java | 5 +++ .../google/cloud/spanner/it/ITDMLTest.java | 43 +++++++++++++++++++ 7 files changed, 86 insertions(+), 19 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractReadContext.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractReadContext.java index 8412fac67e3..ea658a36eab 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractReadContext.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbstractReadContext.java @@ -583,8 +583,10 @@ ExecuteSqlRequest.Builder getExecuteSqlRequestBuilder( if (!stmtParameters.isEmpty()) { com.google.protobuf.Struct.Builder paramsBuilder = builder.getParamsBuilder(); for (Map.Entry param : stmtParameters.entrySet()) { - paramsBuilder.putFields(param.getKey(), param.getValue().toProto()); - builder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + paramsBuilder.putFields(param.getKey(), Value.toProto(param.getValue())); + if (param.getValue() != null) { + builder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + } } } if (withTransactionSelector) { @@ -612,10 +614,12 @@ ExecuteBatchDmlRequest.Builder getExecuteBatchDmlRequestBuilder( com.google.protobuf.Struct.Builder paramsBuilder = builder.getStatementsBuilder(idx).getParamsBuilder(); for (Map.Entry param : stmtParameters.entrySet()) { - paramsBuilder.putFields(param.getKey(), param.getValue().toProto()); - builder - .getStatementsBuilder(idx) - .putParamTypes(param.getKey(), param.getValue().getType().toProto()); + paramsBuilder.putFields(param.getKey(), Value.toProto(param.getValue())); + if (param.getValue() != null) { + builder + .getStatementsBuilder(idx) + .putParamTypes(param.getKey(), param.getValue().getType().toProto()); + } } } idx++; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java index fe31a3b0101..222d754dac9 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BatchClientImpl.java @@ -169,8 +169,10 @@ public List partitionQuery( if (!stmtParameters.isEmpty()) { Struct.Builder paramsBuilder = builder.getParamsBuilder(); for (Map.Entry param : stmtParameters.entrySet()) { - paramsBuilder.putFields(param.getKey(), param.getValue().toProto()); - builder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + paramsBuilder.putFields(param.getKey(), Value.toProto(param.getValue())); + if (param.getValue() != null) { + builder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + } } } TransactionSelector selector = getTransactionSelector(); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/PartitionedDmlTransaction.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/PartitionedDmlTransaction.java index 2aeceb276da..78c092f1792 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/PartitionedDmlTransaction.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/PartitionedDmlTransaction.java @@ -217,8 +217,10 @@ private void setParameters( if (!statementParameters.isEmpty()) { com.google.protobuf.Struct.Builder paramsBuilder = requestBuilder.getParamsBuilder(); for (Map.Entry param : statementParameters.entrySet()) { - paramsBuilder.putFields(param.getKey(), param.getValue().toProto()); - requestBuilder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + paramsBuilder.putFields(param.getKey(), Value.toProto(param.getValue())); + if (param.getValue() != null) { + requestBuilder.putParamTypes(param.getKey(), param.getValue().getType().toProto()); + } } } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Statement.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Statement.java index 401aef92998..3693e2cb587 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Statement.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Statement.java @@ -21,9 +21,9 @@ import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; import java.io.Serializable; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -56,11 +56,11 @@ public final class Statement implements Serializable { private static final long serialVersionUID = -1967958247625065259L; - private final ImmutableMap parameters; + private final Map parameters; private final String sql; private final QueryOptions queryOptions; - private Statement(String sql, ImmutableMap parameters, QueryOptions queryOptions) { + private Statement(String sql, Map parameters, QueryOptions queryOptions) { this.sql = sql; this.parameters = parameters; this.queryOptions = queryOptions; @@ -112,14 +112,17 @@ public ValueBinder bind(String parameter) { public Statement build() { checkState( currentBinding == null, "Binding for parameter '%s' is incomplete.", currentBinding); - return new Statement(sqlBuffer.toString(), ImmutableMap.copyOf(parameters), queryOptions); + return new Statement( + sqlBuffer.toString(), + Collections.unmodifiableMap(new HashMap<>(parameters)), + queryOptions); } private class Binder extends ValueBinder { @Override Builder handle(Value value) { Preconditions.checkArgument( - !value.isCommitTimestamp(), + value == null || !value.isCommitTimestamp(), "Mutation.COMMIT_TIMESTAMP cannot be bound as a query parameter"); checkState(currentBinding != null, "No binding in progress"); parameters.put(currentBinding, value); @@ -218,7 +221,11 @@ StringBuilder toString(StringBuilder b) { b.append(", "); } b.append(parameter.getKey()).append(": "); - parameter.getValue().toString(b); + if (parameter.getValue() == null) { + b.append("NULL"); + } else { + parameter.getValue().toString(b); + } } b.append("}"); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java index 38b4361d755..db9cee56e92 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Value.java @@ -73,6 +73,9 @@ public abstract class Value implements Serializable { */ public static final Timestamp COMMIT_TIMESTAMP = Timestamp.ofTimeMicroseconds(0L); + static final com.google.protobuf.Value NULL_PROTO = + com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); + /** Constant to specify a PG Numeric NaN value. */ public static final String NAN = "NaN"; @@ -622,6 +625,10 @@ public String toString() { // END OF PUBLIC API. + static com.google.protobuf.Value toProto(Value value) { + return value == null ? NULL_PROTO : value.toProto(); + } + abstract void toString(StringBuilder b); abstract com.google.protobuf.Value toProto(); @@ -737,9 +744,6 @@ Value newValue(boolean isNull, BitSet nulls, boolean[] values) { /** Template class for {@code Value} implementations. */ private abstract static class AbstractValue extends Value { - static final com.google.protobuf.Value NULL_PROTO = - com.google.protobuf.Value.newBuilder().setNullValue(NullValue.NULL_VALUE).build(); - private final boolean isNull; private final Type type; diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StatementTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StatementTest.java index b2c8244f64d..d5b5a3ec619 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StatementTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/StatementTest.java @@ -61,6 +61,8 @@ public void serialization() { .append("bytes_field = @bytes_field ") .bind("bytes_field") .to(ByteArray.fromBase64("abcd")) + .bind("untyped_null_field") + .to((Value) null) .build(); reserializeAndAssert(stmt); } @@ -165,6 +167,9 @@ public void equalsAndHashCode() { tester.addEqualityGroup(Statement.newBuilder("SELECT @x, @y").bind("y").to(2).build()); tester.addEqualityGroup( Statement.newBuilder("SELECT @x, @y").bind("x").to(1).bind("y").to(2).build()); + tester.addEqualityGroup( + Statement.newBuilder("SELECT @x, @y").bind("x").to((Value) null).build(), + Statement.newBuilder("SELECT @x, @y").bind("x").to((Value) null).build()); tester.testEquals(); } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java index 2c7a8da27c3..5ea30912103 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITDMLTest.java @@ -18,7 +18,12 @@ import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator; import static com.google.common.truth.Truth.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.junit.Assume.assumeFalse; import com.google.cloud.spanner.AbortedException; import com.google.cloud.spanner.Database; @@ -38,6 +43,7 @@ import com.google.cloud.spanner.TimestampBound; import com.google.cloud.spanner.TransactionRunner; import com.google.cloud.spanner.TransactionRunner.TransactionCallable; +import com.google.cloud.spanner.Value; import com.google.cloud.spanner.connection.ConnectionOptions; import java.util.ArrayList; import java.util.Arrays; @@ -380,4 +386,41 @@ public void standardDMLWithExecuteSQL() { // checks for multi-stmts within a txn, therefore also verifying seqNo. executeQuery(DML_COUNT * 2, updateDml(), deleteDml()); } + + @Test + public void testUntypedNullValues() { + assumeFalse( + "Spanner PostgreSQL does not yet support untyped null values", + dialect.dialect == Dialect.POSTGRESQL); + + DatabaseClient client = getClient(dialect.dialect); + String sql; + if (dialect.dialect == Dialect.POSTGRESQL) { + sql = "INSERT INTO T (K, V) VALUES ($1, $2)"; + } else { + sql = "INSERT INTO T (K, V) VALUES (@p1, @p2)"; + } + Long updateCount = + client + .readWriteTransaction() + .run( + transaction -> + transaction.executeUpdate( + Statement.newBuilder(sql) + .bind("p1") + .to("k1") + .bind("p2") + .to((Value) null) + .build())); + + assertNotNull(updateCount); + assertEquals(1L, updateCount.longValue()); + + // Read the row back and verify that the value is null. + try (ResultSet resultSet = client.singleUse().executeQuery(Statement.of("SELECT V FROM T"))) { + assertTrue(resultSet.next()); + assertTrue(resultSet.isNull(0)); + assertFalse(resultSet.next()); + } + } } From 9eccfc441237272b01140c1f3d7da51b2b985554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 15 Feb 2022 11:08:59 +0100 Subject: [PATCH 15/19] feat: automatically detect database dialect (#1677) The dialect of the database that a `DatabaseClient` is connected to can be automatically detected: 1. `DatabaseClient#getDialect()` has been added. This method always returns the dialect of the underlying database. It will do so by executing a query that detects the dialect. This query can also be executed and cached automatically in the background during startup (see below). 2. `SessionPoolOptions#setAutoDetectDialect(true)` will cause the dialect detection query to be executed in the background automatically when a new client is created. This is disabled by default, except for when a Connection API connection (or anything that depends on that, such as JDBC) is opened. The reason for this default behavior is that a normal Spanner instance does normally not need to know what the dialect of the underlying database is, while the Connection API does. This reduces the number of times the detection query will be executed during production use. --- .../clirr-ignored-differences.xml | 20 ++++ .../google/cloud/spanner/DatabaseClient.java | 9 ++ .../cloud/spanner/DatabaseClientImpl.java | 5 + .../com/google/cloud/spanner/SessionPool.java | 99 ++++++++++++++++++- .../cloud/spanner/SessionPoolOptions.java | 32 +++++- .../google/cloud/spanner/SpannerOptions.java | 19 ---- .../spanner/connection/ConnectionImpl.java | 29 +++--- .../spanner/connection/ConnectionOptions.java | 27 +---- .../cloud/spanner/connection/SpannerPool.java | 12 +-- .../cloud/spanner/DatabaseClientImplTest.java | 56 +++++++++++ .../cloud/spanner/MockSpannerServiceImpl.java | 51 +++++++++- .../com/google/cloud/spanner/SpanTest.java | 22 ++--- .../cloud/spanner/SpannerOptionsTest.java | 3 - .../connection/AutocommitDmlModeTest.java | 2 + .../ConnectionAsyncApiAbortedTest.java | 8 ++ .../connection/ConnectionAsyncApiTest.java | 8 ++ .../connection/ConnectionImplTest.java | 11 ++- .../connection/ConnectionOptionsTest.java | 57 ----------- .../connection/ReadOnlyStalenessTest.java | 2 + .../spanner/connection/SpannerPoolTest.java | 14 ++- .../connection/StatementTimeoutTest.java | 12 +++ .../spanner/spi/v1/GapicSpannerRpcTest.java | 1 - 22 files changed, 350 insertions(+), 149 deletions(-) diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml index f65bfd94332..464f6e9e9f8 100644 --- a/google-cloud-spanner/clirr-ignored-differences.xml +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -6,6 +6,11 @@ com/google/cloud/spanner/connection/Connection com.google.cloud.spanner.Dialect getDialect() + + 7012 + com/google/cloud/spanner/DatabaseClient + com.google.cloud.spanner.Dialect getDialect() + 7012 com/google/cloud/spanner/BatchReadOnlyTransaction @@ -15,4 +20,19 @@ 8001 com/google/cloud/spanner/connection/StatementParser + + 7002 + com/google/cloud/spanner/SpannerOptions + com.google.cloud.spanner.Dialect getDialect() + + + 7002 + com/google/cloud/spanner/SpannerOptions$Builder + com.google.cloud.spanner.SpannerOptions$Builder setDialect(com.google.cloud.spanner.Dialect) + + + 7002 + com/google/cloud/spanner/connection/ConnectionOptions + com.google.cloud.spanner.Dialect getDialect() + diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java index 60e8b6910cf..a09c06bcbe2 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClient.java @@ -27,6 +27,15 @@ */ public interface DatabaseClient { + /** + * Returns the SQL dialect that is used by the database. + * + * @return the SQL dialect that is used by the database. + */ + default Dialect getDialect() { + throw new UnsupportedOperationException("method should be overwritten"); + } + /** * Writes the given mutations atomically to the database. * diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java index e2121910ad8..d0ee29ada17 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java @@ -53,6 +53,11 @@ PooledSessionFuture getSession() { return pool.getSession(); } + @Override + public Dialect getDialect() { + return pool.getDialect(); + } + @Override public Timestamp write(final Iterable mutations) throws SpannerException { return writeWithOptions(mutations).getCommitTimestamp(); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPool.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPool.java index 95cc167fe10..5c13a410984 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPool.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPool.java @@ -1484,6 +1484,34 @@ private void keepAlive() { } } + private void determineDialectAsync(final SettableFuture dialect) { + Preconditions.checkNotNull(dialect); + executor.submit( + () -> { + try { + dialect.set(determineDialect()); + } catch (Throwable t) { + // Catch-all as we want to propagate all exceptions to anyone who might be interested + // in the database dialect, and there's nothing sensible that we can do with it here. + dialect.setException(t); + } finally { + releaseSession(this, Position.FIRST); + } + }); + } + + private Dialect determineDialect() { + try (ResultSet dialectResultSet = + delegate.singleUse().executeQuery(DETERMINE_DIALECT_STATEMENT)) { + if (dialectResultSet.next()) { + return Dialect.fromName(dialectResultSet.getString(0)); + } else { + throw SpannerExceptionFactory.newSpannerException( + ErrorCode.NOT_FOUND, "No dialect found for database"); + } + } + } + private void markBusy(Span span) { this.delegate.setCurrentSpan(span); this.state = SessionState.BUSY; @@ -1724,7 +1752,27 @@ private enum Position { RANDOM } + /** + * This statement is (currently) used to determine the dialect of the database that is used by the + * session pool. This statement is subject to change when the INFORMATION_SCHEMA contains a table + * where the dialect of the database can be read directly, and any tests that want to detect the + * specific 'determine dialect statement' should rely on this constant instead of the actual + * value. + */ + @VisibleForTesting + static final Statement DETERMINE_DIALECT_STATEMENT = + Statement.newBuilder( + "SELECT 'POSTGRESQL' AS DIALECT\n" + + "FROM INFORMATION_SCHEMA.SCHEMATA\n" + + "WHERE SCHEMA_NAME='pg_catalog'\n" + + "UNION ALL\n" + + "SELECT 'GOOGLE_STANDARD_SQL' AS DIALECT\n" + + "FROM INFORMATION_SCHEMA.SCHEMATA\n" + + "WHERE SCHEMA_NAME='INFORMATION_SCHEMA' AND CATALOG_NAME=''") + .build(); + private final SessionPoolOptions options; + private final SettableFuture dialect = SettableFuture.create(); private final SessionClient sessionClient; private final ScheduledExecutorService executor; private final ExecutorFactory executorFactory; @@ -1734,6 +1782,9 @@ private enum Position { private final Object lock = new Object(); private final Random random = new Random(); + @GuardedBy("lock") + private boolean detectDialectStarted; + @GuardedBy("lock") private int pendingClosure; @@ -1861,6 +1912,39 @@ private SessionPool( this.initMetricsCollection(metricRegistry, labelValues); } + /** + * @return the {@link Dialect} of the underlying database. This method will block until the + * dialect is available. It will potentially execute one or two RPCs to get the dialect if + * necessary: One to create a session if there are no sessions in the pool (yet), and one to + * query the database for the dialect that is used. It is recommended that clients that always + * need to know the dialect set {@link + * SessionPoolOptions.Builder#setAutoDetectDialect(boolean)} to true. This will ensure that + * the dialect is fetched automatically in a background task when a session pool is created. + */ + Dialect getDialect() { + boolean mustDetectDialect = false; + synchronized (lock) { + if (!detectDialectStarted) { + mustDetectDialect = true; + detectDialectStarted = true; + } + } + if (mustDetectDialect) { + try (PooledSessionFuture session = getSession()) { + dialect.set(session.get().determineDialect()); + } + } + try { + return dialect.get(60L, TimeUnit.SECONDS); + } catch (ExecutionException executionException) { + throw SpannerExceptionFactory.asSpannerException(executionException); + } catch (InterruptedException interruptedException) { + throw SpannerExceptionFactory.propagateInterrupt(interruptedException); + } catch (TimeoutException timeoutException) { + throw SpannerExceptionFactory.propagateTimeout(timeoutException); + } + } + @VisibleForTesting int getNumberOfSessionsInUse() { synchronized (lock) { @@ -2290,10 +2374,17 @@ public void onSessionReady(SessionImpl session) { } else { Preconditions.checkState(totalSessions() <= options.getMaxSessions() - 1); allSessions.add(pooledSession); - // Release the session to a random position in the pool to prevent the case that a batch - // of sessions that are affiliated with the same channel are all placed sequentially in - // the pool. - releaseSession(pooledSession, Position.RANDOM); + if (options.isAutoDetectDialect() && !detectDialectStarted) { + // Get the dialect of the underlying database if that has not yet been done. Note that + // this method will release the session into the pool once it is done. + detectDialectStarted = true; + pooledSession.determineDialectAsync(SessionPool.this.dialect); + } else { + // Release the session to a random position in the pool to prevent the case that a batch + // of sessions that are affiliated with the same channel are all placed sequentially in + // the pool. + releaseSession(pooledSession, Position.RANDOM); + } } } if (closeSession) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java index 208c025e6da..408b3d73965 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java @@ -50,6 +50,7 @@ public class SessionPoolOptions { private final ActionOnSessionNotFound actionOnSessionNotFound; private final ActionOnSessionLeak actionOnSessionLeak; private final long initialWaitForSessionTimeoutMillis; + private final boolean autoDetectDialect; private SessionPoolOptions(Builder builder) { // minSessions > maxSessions is only possible if the user has only set a value for maxSessions. @@ -67,6 +68,7 @@ private SessionPoolOptions(Builder builder) { this.loopFrequency = builder.loopFrequency; this.keepAliveIntervalMinutes = builder.keepAliveIntervalMinutes; this.removeInactiveSessionAfter = builder.removeInactiveSessionAfter; + this.autoDetectDialect = builder.autoDetectDialect; } @Override @@ -87,7 +89,8 @@ public boolean equals(Object o) { this.initialWaitForSessionTimeoutMillis, other.initialWaitForSessionTimeoutMillis) && Objects.equals(this.loopFrequency, other.loopFrequency) && Objects.equals(this.keepAliveIntervalMinutes, other.keepAliveIntervalMinutes) - && Objects.equals(this.removeInactiveSessionAfter, other.removeInactiveSessionAfter); + && Objects.equals(this.removeInactiveSessionAfter, other.removeInactiveSessionAfter) + && Objects.equals(this.autoDetectDialect, other.autoDetectDialect); } @Override @@ -104,7 +107,8 @@ public int hashCode() { this.initialWaitForSessionTimeoutMillis, this.loopFrequency, this.keepAliveIntervalMinutes, - this.removeInactiveSessionAfter); + this.removeInactiveSessionAfter, + this.autoDetectDialect); } public Builder toBuilder() { @@ -163,6 +167,10 @@ public boolean isBlockIfPoolExhausted() { return actionOnExhaustion == ActionOnExhaustion.BLOCK; } + public boolean isAutoDetectDialect() { + return autoDetectDialect; + } + @VisibleForTesting long getInitialWaitForSessionTimeoutMillis() { return initialWaitForSessionTimeoutMillis; @@ -220,6 +228,7 @@ public static class Builder { private long loopFrequency = 10 * 1000L; private int keepAliveIntervalMinutes = 30; private Duration removeInactiveSessionAfter = Duration.ofMinutes(55L); + private boolean autoDetectDialect = false; public Builder() {} @@ -237,6 +246,7 @@ private Builder(SessionPoolOptions options) { this.loopFrequency = options.loopFrequency; this.keepAliveIntervalMinutes = options.keepAliveIntervalMinutes; this.removeInactiveSessionAfter = options.removeInactiveSessionAfter; + this.autoDetectDialect = options.autoDetectDialect; } /** @@ -327,6 +337,24 @@ public Builder setBlockIfPoolExhausted() { return this; } + /** + * Sets whether the client should automatically execute a background query to detect the dialect + * that is used by the database or not. Set this option to true if you do not know what the + * dialect of the database will be. + * + *

Note that you can always call {@link DatabaseClient#getDialect()} to get the dialect of a + * database regardless of this setting, but by setting this to true, the value will be + * pre-populated and cached in the client. + * + * @param autoDetectDialect Whether the client should automatically execute a background query + * to detect the dialect of the underlying database + * @return this builder for chaining + */ + public Builder setAutoDetectDialect(boolean autoDetectDialect) { + this.autoDetectDialect = autoDetectDialect; + return this; + } + /** * The initial number of milliseconds to wait for a session to become available when one is * requested. The session pool will keep retrying to get a session, and the timeout will be diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java index 14f07314e8f..65de63b720f 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java @@ -125,7 +125,6 @@ public class SpannerOptions extends ServiceOptions { private final CallCredentialsProvider callCredentialsProvider; private final CloseableExecutorProvider asyncExecutorProvider; private final String compressorName; - private final Dialect dialect; /** * Interface that can be used to provide {@link CallCredentials} instead of {@link Credentials} to @@ -593,7 +592,6 @@ private SpannerOptions(Builder builder) { callCredentialsProvider = builder.callCredentialsProvider; asyncExecutorProvider = builder.asyncExecutorProvider; compressorName = builder.compressorName; - dialect = builder.dialect; } /** @@ -693,7 +691,6 @@ public static class Builder private CloseableExecutorProvider asyncExecutorProvider; private String compressorName; private String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST"); - private Dialect dialect = Dialect.GOOGLE_STANDARD_SQL; private Builder() { // Manually set retry and polling settings that work. @@ -748,7 +745,6 @@ private Builder() { this.channelProvider = options.channelProvider; this.channelConfigurator = options.channelConfigurator; this.interceptorProvider = options.interceptorProvider; - this.dialect = options.dialect; } @Override @@ -779,7 +775,6 @@ protected Set getAllowedClientLibTokens() { *

  • {@link #setHost(String)} *
  • {@link #setNumChannels(int)} *
  • {@link #setInterceptorProvider(GrpcInterceptorProvider)} - *
  • {@link #setDialect(Dialect)} *
  • {@link #setHeaderProvider(com.google.api.gax.rpc.HeaderProvider)} * */ @@ -1139,16 +1134,6 @@ public Builder setEmulatorHost(String emulatorHost) { return this; } - /** - * Sets the {@link Dialect} to use with Cloud Spanner. The default is {@link - * Dialect#GOOGLE_STANDARD_SQL}. - */ - public Builder setDialect(Dialect dialect) { - Preconditions.checkNotNull(dialect); - this.dialect = dialect; - return this; - } - @SuppressWarnings("rawtypes") @Override public SpannerOptions build() { @@ -1276,10 +1261,6 @@ public String getCompressorName() { return compressorName; } - public Dialect getDialect() { - return dialect; - } - /** Returns the default query options to use for the specific database. */ public QueryOptions getDefaultQueryOptions(DatabaseId databaseId) { // Use the specific query options for the database if any have been specified. These have 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 9cea3810a98..3f3bd218ef2 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 @@ -83,7 +83,7 @@ private LeakedConnectionException() { private volatile LeakedConnectionException leakedException = new LeakedConnectionException(); private final SpannerPool spannerPool; - private final AbstractStatementParser parser; + private AbstractStatementParser statementParser; /** * The {@link ConnectionStatementExecutor} is responsible for translating parsed {@link * ClientSideStatement}s into actual method calls on this {@link ConnectionImpl}. I.e. the {@link @@ -221,7 +221,6 @@ static UnitOfWorkType of(TransactionMode transactionMode) { this.statementExecutor = new StatementExecutor(options.getStatementExecutionInterceptors()); this.spannerPool = SpannerPool.INSTANCE; this.options = options; - this.parser = AbstractStatementParser.getInstance(options.getDialect()); this.spanner = spannerPool.getSpanner(options, this); if (options.isAutoConfigEmulator()) { EmulatorUtil.maybeCreateInstanceAndDatabase(spanner, options.getDatabaseId()); @@ -251,7 +250,6 @@ static UnitOfWorkType of(TransactionMode transactionMode) { this.statementExecutor = new StatementExecutor(Collections.emptyList()); this.spannerPool = spannerPool; this.options = options; - this.parser = AbstractStatementParser.getInstance(options.getDialect()); this.spanner = spannerPool.getSpanner(options, this); this.ddlClient = ddlClient; this.dbClient = dbClient; @@ -269,6 +267,13 @@ private DdlClient createDdlClient() { .build(); } + private AbstractStatementParser getStatementParser() { + if (this.statementParser == null) { + this.statementParser = AbstractStatementParser.getInstance(dbClient.getDialect()); + } + return this.statementParser; + } + @Override public void close() { try { @@ -324,7 +329,7 @@ LeakedConnectionException getLeakedException() { @Override public Dialect getDialect() { - return options.getDialect(); + return dbClient.getDialect(); } @Override @@ -812,7 +817,7 @@ private ApiFuture endCurrentTransactionAsync(EndTransactionMethod endTrans public StatementResult execute(Statement statement) { Preconditions.checkNotNull(statement); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(statement, this.queryOptions); + ParsedStatement parsedStatement = getStatementParser().parse(statement, this.queryOptions); switch (parsedStatement.getType()) { case CLIENT_SIDE: return parsedStatement @@ -837,7 +842,7 @@ public StatementResult execute(Statement statement) { public AsyncStatementResult executeAsync(Statement statement) { Preconditions.checkNotNull(statement); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(statement, this.queryOptions); + ParsedStatement parsedStatement = getStatementParser().parse(statement, this.queryOptions); switch (parsedStatement.getType()) { case CLIENT_SIDE: return AsyncStatementResultImpl.of( @@ -885,7 +890,7 @@ private ResultSet parseAndExecuteQuery( Preconditions.checkNotNull(query); Preconditions.checkNotNull(analyzeMode); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(query, this.queryOptions); + ParsedStatement parsedStatement = getStatementParser().parse(query, this.queryOptions); if (parsedStatement.isQuery()) { switch (parsedStatement.getType()) { case CLIENT_SIDE: @@ -910,7 +915,7 @@ private AsyncResultSet parseAndExecuteQueryAsync( Statement query, AnalyzeMode analyzeMode, QueryOption... options) { Preconditions.checkNotNull(query); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(query, this.queryOptions); + ParsedStatement parsedStatement = getStatementParser().parse(query, this.queryOptions); if (parsedStatement.isQuery()) { switch (parsedStatement.getType()) { case CLIENT_SIDE: @@ -938,7 +943,7 @@ private AsyncResultSet parseAndExecuteQueryAsync( public long executeUpdate(Statement update) { Preconditions.checkNotNull(update); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(update); + ParsedStatement parsedStatement = getStatementParser().parse(update); if (parsedStatement.isUpdate()) { switch (parsedStatement.getType()) { case UPDATE: @@ -958,7 +963,7 @@ public long executeUpdate(Statement update) { public ApiFuture executeUpdateAsync(Statement update) { Preconditions.checkNotNull(update); ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); - ParsedStatement parsedStatement = parser.parse(update); + ParsedStatement parsedStatement = getStatementParser().parse(update); if (parsedStatement.isUpdate()) { switch (parsedStatement.getType()) { case UPDATE: @@ -982,7 +987,7 @@ public long[] executeBatchUpdate(Iterable updates) { // Check that there are only DML statements in the input. List parsedStatements = new LinkedList<>(); for (Statement update : updates) { - ParsedStatement parsedStatement = parser.parse(update); + ParsedStatement parsedStatement = getStatementParser().parse(update); switch (parsedStatement.getType()) { case UPDATE: parsedStatements.add(parsedStatement); @@ -1008,7 +1013,7 @@ public ApiFuture executeBatchUpdateAsync(Iterable updates) { // Check that there are only DML statements in the input. List parsedStatements = new LinkedList<>(); for (Statement update : updates) { - ParsedStatement parsedStatement = parser.parse(update); + ParsedStatement parsedStatement = getStatementParser().parse(update); switch (parsedStatement.getType()) { case UPDATE: parsedStatements.add(parsedStatement); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java index eb6a430f6d0..e4f3cfdbee2 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java @@ -25,7 +25,6 @@ import com.google.cloud.NoCredentials; import com.google.cloud.ServiceOptions; import com.google.cloud.spanner.DatabaseId; -import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.Options.RpcPriority; import com.google.cloud.spanner.SessionPoolOptions; @@ -166,7 +165,6 @@ public String[] getValidValues() { private static final RpcPriority DEFAULT_RPC_PRIORITY = null; private static final boolean DEFAULT_RETURN_COMMIT_STATS = false; private static final boolean DEFAULT_LENIENT = false; - private static final String DEFAULT_DIALECT = Dialect.GOOGLE_STANDARD_SQL.name(); private static final String PLAIN_TEXT_PROTOCOL = "http:"; private static final String HOST_PROTOCOL = "https:"; @@ -519,7 +517,6 @@ public static Builder newBuilder() { private final Integer maxSessions; private final String userAgent; private final QueryOptions queryOptions; - private final Dialect dialect; private final boolean returnCommitStats; private final boolean autoConfigEmulator; private final RpcPriority rpcPriority; @@ -563,14 +560,6 @@ private ConnectionOptions(Builder builder) { queryOptionsBuilder.setOptimizerStatisticsPackage(parseOptimizerStatisticsPackage(this.uri)); this.queryOptions = queryOptionsBuilder.build(); this.returnCommitStats = parseReturnCommitStats(this.uri); - - try { - this.dialect = Dialect.fromName(parseDialect(uri)); - } catch (IllegalArgumentException e) { - throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, e.getMessage(), e); - } - this.autoConfigEmulator = parseAutoConfigEmulator(this.uri); this.usePlainText = this.autoConfigEmulator || parseUsePlainText(this.uri); this.host = determineHost(matcher, autoConfigEmulator, usePlainText); @@ -622,6 +611,7 @@ private ConnectionOptions(Builder builder) { builder.sessionPoolOptions == null ? SessionPoolOptions.newBuilder() : builder.sessionPoolOptions.toBuilder(); + sessionPoolOptionsBuilder.setAutoDetectDialect(true); if (this.minSessions != null) { sessionPoolOptionsBuilder.setMinSessions(this.minSessions); } @@ -629,8 +619,10 @@ private ConnectionOptions(Builder builder) { sessionPoolOptionsBuilder.setMaxSessions(this.maxSessions); } this.sessionPoolOptions = sessionPoolOptionsBuilder.build(); - } else { + } else if (builder.sessionPoolOptions != null) { this.sessionPoolOptions = builder.sessionPoolOptions; + } else { + this.sessionPoolOptions = SessionPoolOptions.newBuilder().setAutoDetectDialect(true).build(); } } @@ -780,12 +772,6 @@ static RpcPriority parseRPCPriority(String uri) { return value != null ? RpcPriority.valueOf(value) : DEFAULT_RPC_PRIORITY; } - @VisibleForTesting - static String parseDialect(String uri) { - String value = parseUriProperty(uri, DIALECT_PROPERTY_NAME); - return value != null ? value.toUpperCase() : DEFAULT_DIALECT; - } - @VisibleForTesting static String parseUriProperty(String uri, String property) { Pattern pattern = Pattern.compile(String.format("(?is)(?:;|\\?)%s=(.*?)(?:;|$)", property)); @@ -970,11 +956,6 @@ public String getWarnings() { return warnings; } - /** The dialect to use for connections created by this {@link ConnectionOptions}. */ - public Dialect getDialect() { - return dialect; - } - /** Use http instead of https. Only valid for (local) test servers. */ boolean isUsePlainText() { return usePlainText; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java index 479b10df2e5..2712143da7a 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java @@ -17,7 +17,6 @@ package com.google.cloud.spanner.connection; import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SessionPoolOptions; import com.google.cloud.spanner.Spanner; @@ -153,7 +152,6 @@ static class SpannerPoolKey { private final Integer numChannels; private final boolean usePlainText; private final String userAgent; - private final Dialect dialect; @VisibleForTesting static SpannerPoolKey of(ConnectionOptions options) { @@ -171,7 +169,6 @@ private SpannerPoolKey(ConnectionOptions options) { this.numChannels = options.getNumChannels(); this.usePlainText = options.isUsePlainText(); this.userAgent = options.getUserAgent(); - this.dialect = options.getDialect(); } @Override @@ -186,8 +183,7 @@ public boolean equals(Object o) { && Objects.equals(this.sessionPoolOptions, other.sessionPoolOptions) && Objects.equals(this.numChannels, other.numChannels) && Objects.equals(this.usePlainText, other.usePlainText) - && Objects.equals(this.userAgent, other.userAgent) - && Objects.equals(this.dialect, other.dialect); + && Objects.equals(this.userAgent, other.userAgent); } @Override @@ -199,8 +195,7 @@ public int hashCode() { this.sessionPoolOptions, this.numChannels, this.usePlainText, - this.userAgent, - this.dialect); + this.userAgent); } } @@ -326,8 +321,7 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) { .setClientLibToken(MoreObjects.firstNonNull(key.userAgent, CONNECTION_API_CLIENT_LIB_TOKEN)) .setHost(key.host) .setProjectId(key.projectId) - .setCredentials(options.getCredentials()) - .setDialect(options.getDialect()); + .setCredentials(options.getCredentials()); builder.setSessionPoolOption(key.sessionPoolOptions); if (key.numChannels != null) { builder.setNumChannels(key.numChannels); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java index 21c9d3eaa77..c0e1e606402 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseClientImplTest.java @@ -2204,4 +2204,60 @@ public Long apply(TransactionContext transactionContext) { () -> client.readWriteTransaction().run(tx -> function.apply(tx))); assertTrue(exception.getMessage().contains("Context has been closed")); } + + @Test + public void testGetDialectDefault() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, client.getDialect()); + } + + @Test + public void testGetDialectDefaultPreloaded() { + try (Spanner spanner = + this.spanner + .getOptions() + .toBuilder() + .setSessionPoolOption( + SessionPoolOptions.newBuilder().setAutoDetectDialect(true).build()) + .build() + .getService()) { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + assertEquals(Dialect.GOOGLE_STANDARD_SQL, client.getDialect()); + } + } + + @Test + public void testGetDialectPostgreSQL() { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + try { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + assertEquals(Dialect.POSTGRESQL, client.getDialect()); + } finally { + mockSpanner.putStatementResult( + StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); + } + } + + @Test + public void testGetDialectPostgreSQLPreloaded() { + mockSpanner.putStatementResult(StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + try (Spanner spanner = + this.spanner + .getOptions() + .toBuilder() + .setSessionPoolOption( + SessionPoolOptions.newBuilder().setAutoDetectDialect(true).build()) + .build() + .getService()) { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + assertEquals(Dialect.POSTGRESQL, client.getDialect()); + } finally { + mockSpanner.putStatementResult( + StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); + } + } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java index a307e23db22..feb4e680a50 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java @@ -33,6 +33,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.Duration; import com.google.protobuf.Empty; +import com.google.protobuf.ListValue; import com.google.protobuf.Timestamp; import com.google.protobuf.Value.KindCase; import com.google.rpc.Code; @@ -271,6 +272,32 @@ public static StatementResult exception(Statement statement, StatusRuntimeExcept return new StatementResult(statement, exception); } + /** Creates a result for the query that detects the dialect that is used for the database. */ + public static StatementResult detectDialectResult(Dialect resultDialect) { + return StatementResult.query( + SessionPool.DETERMINE_DIALECT_STATEMENT, + ResultSet.newBuilder() + .setMetadata( + ResultSetMetadata.newBuilder() + .setRowType( + StructType.newBuilder() + .addFields( + Field.newBuilder() + .setName("DIALECT") + .setType(Type.newBuilder().setCode(TypeCode.STRING).build()) + .build()) + .build()) + .build()) + .addRows( + ListValue.newBuilder() + .addValues( + com.google.protobuf.Value.newBuilder() + .setStringValue(resultDialect.toString()) + .build()) + .build()) + .build()); + } + private static class KeepLastElementDeque extends LinkedList { private static KeepLastElementDeque singleton(E item) { return new KeepLastElementDeque<>(Collections.singleton(item)); @@ -525,6 +552,12 @@ private static void checkStreamException( private final Random random = new Random(); private double abortProbability = 0.0010D; + /** + * Flip this switch to true if you want the {@link SessionPool#DETERMINE_DIALECT_STATEMENT} + * statement to be included in the recorded requests on the mock server. It is ignored by default + * to prevent tests that do not expect this request to suddenly start failing. + */ + private boolean includeDetermineDialectStatementInRequests = false; private final Object lock = new Object(); private Deque requests = new ConcurrentLinkedDeque<>(); @@ -568,6 +601,10 @@ private static void checkStreamException( private SimulatedExecutionTime rollbackExecutionTime = NO_EXECUTION_TIME; private SimulatedExecutionTime streamingReadExecutionTime = NO_EXECUTION_TIME; + public MockSpannerServiceImpl() { + putStatementResult(StatementResult.detectDialectResult(Dialect.GOOGLE_STANDARD_SQL)); + } + private String generateSessionName(String database) { return String.format("%s/sessions/%s", database, UUID.randomUUID().toString()); } @@ -663,6 +700,15 @@ public void setAbortProbability(double probability) { this.abortProbability = probability; } + /** + * Set this to true if you want the {@link SessionPool#DETERMINE_DIALECT_STATEMENT} statement to + * be included in the recorded requests on the mock server. It is ignored by default to prevent + * tests that do not expect this request to suddenly start failing. + */ + public void setIncludeDetermineDialectStatementInRequests(boolean include) { + this.includeDetermineDialectStatementInRequests = include; + } + /** * Instruct the mock server to abort the specified transaction. Use this method to test handling * of {@link AbortedException} in your code. @@ -1097,7 +1143,10 @@ public void executeBatchDml( @Override public void executeStreamingSql( ExecuteSqlRequest request, StreamObserver responseObserver) { - requests.add(request); + if (includeDetermineDialectStatementInRequests + || !request.getSql().equals(SessionPool.DETERMINE_DIALECT_STATEMENT.getSql())) { + requests.add(request); + } Preconditions.checkNotNull(request.getSession()); Session session = sessions.get(request.getSession()); if (session == null) { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpanTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpanTest.java index dec7e59c4b1..84074787655 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpanTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpanTest.java @@ -106,6 +106,17 @@ public static void startStaticServer() throws Exception { "This test is only supported on JDK11 and lower", JavaVersionUtil.getJavaMajorVersion() < 12); + // Use a little reflection to set the test tracer. + // This is not possible in Java 12 and later. + java.lang.reflect.Field field = Tracing.class.getDeclaredField("traceComponent"); + field.setAccessible(true); + java.lang.reflect.Field modifiersField = + java.lang.reflect.Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + // Remove the final modifier from the 'traceComponent' field. + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(null, failOnOverkillTraceComponent); + mockSpanner = new MockSpannerServiceImpl(); mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions. mockSpanner.putStatementResult(StatementResult.update(UPDATE_STATEMENT, UPDATE_COUNT)); @@ -124,17 +135,6 @@ public static void startStaticServer() throws Exception { .build() .start(); channelProvider = LocalChannelProvider.create(uniqueName); - - // Use a little reflection to set the test tracer. - // This is not possible in Java 12 and later. - java.lang.reflect.Field field = Tracing.class.getDeclaredField("traceComponent"); - field.setAccessible(true); - java.lang.reflect.Field modifiersField = - java.lang.reflect.Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - // Remove the final modifier from the 'traceComponent' field. - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(null, failOnOverkillTraceComponent); } @AfterClass diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java index 80a542c5305..fc82954ad40 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerOptionsTest.java @@ -81,7 +81,6 @@ public void defaultBuilder() { } assertThat(options.getPrefetchChunks()).isEqualTo(4); assertThat(options.getSessionLabels()).isNull(); - assertThat(options.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); } @Test @@ -96,13 +95,11 @@ public void builder() { .setProjectId(projectId) .setPrefetchChunks(2) .setSessionLabels(labels) - .setDialect(Dialect.POSTGRESQL) .build(); assertThat(options.getHost()).isEqualTo(host); assertThat(options.getProjectId()).isEqualTo(projectId); assertThat(options.getPrefetchChunks()).isEqualTo(2); assertThat(options.getSessionLabels()).containsExactlyEntriesIn(labels); - assertThat(options.getDialect()).isEqualTo(Dialect.POSTGRESQL); } @Test diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java index 78834f69c89..2acdf6f3d15 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java @@ -26,6 +26,7 @@ import com.google.cloud.NoCredentials; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TransactionContext; @@ -48,6 +49,7 @@ public class AutocommitDmlModeTest { @SuppressWarnings("unchecked") private ConnectionImpl createConnection(ConnectionOptions options) { dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); txContext = mock(TransactionContext.class); Spanner spanner = mock(Spanner.class); SpannerPool spannerPool = mock(SpannerPool.class); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiAbortedTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiAbortedTest.java index 8aac69acdf8..97d745edd7f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiAbortedTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiAbortedTest.java @@ -50,6 +50,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -107,6 +108,13 @@ public static void stopExecutor() { multiThreadedExecutor.shutdown(); } + @Before + public void setup() { + try (Connection connection = createConnection()) { + connection.getDialect(); + } + } + @After public void reset() { mockSpanner.removeAllExecutionTimes(); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiTest.java index ff409e88c63..21fe086d4f8 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionAsyncApiTest.java @@ -54,6 +54,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.After; import org.junit.AfterClass; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -78,6 +79,13 @@ public static void stopExecutor() { executor.shutdown(); } + @Before + public void setup() { + try (Connection connection = createConnection()) { + connection.getDialect(); + } + } + @After public void reset() { mockSpanner.removeAllExecutionTimes(); 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 f6afee6da2d..6d04caa8c26 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 @@ -227,6 +227,7 @@ public static ConnectionImpl createConnection(final ConnectionOptions options) { .thenReturn(spanner); DdlClient ddlClient = createDefaultMockDdlClient(); DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); ReadOnlyTransaction singleUseReadOnlyTx = mock(ReadOnlyTransaction.class); ResultSet mockResultSetWithStats = createSelect1MockResultSet(); @@ -1362,10 +1363,10 @@ public void testAddRemoveTransactionRetryListener() { @Test public void testMergeQueryOptions() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); - when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); 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); when(unitOfWork.executeQueryAsync( any(ParsedStatement.class), any(AnalyzeMode.class), Mockito.any())) @@ -1466,10 +1467,10 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { public void testStatementTagAlwaysAllowed() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(true); - when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); 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); when(unitOfWork.executeQueryAsync( any(ParsedStatement.class), any(AnalyzeMode.class), Mockito.any())) @@ -1509,10 +1510,10 @@ UnitOfWork getCurrentUnitOfWorkOrStartNewUnitOfWork() { public void testTransactionTagAllowedInTransaction() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(false); - when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); try (ConnectionImpl connection = new ConnectionImpl(connectionOptions, spannerPool, ddlClient, dbClient)) { assertFalse(connection.isAutocommit()); @@ -1550,10 +1551,10 @@ public void testTransactionTagAllowedInTransaction() { public void testTransactionTagNotAllowedWithoutTransaction() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(true); - when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); SpannerPool spannerPool = mock(SpannerPool.class); DdlClient ddlClient = mock(DdlClient.class); DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); try (ConnectionImpl connection = new ConnectionImpl(connectionOptions, spannerPool, ddlClient, dbClient)) { assertTrue(connection.isAutocommit()); @@ -1571,10 +1572,10 @@ public void testTransactionTagNotAllowedWithoutTransaction() { public void testTransactionTagNotAllowedAfterTransactionStarted() { ConnectionOptions connectionOptions = mock(ConnectionOptions.class); when(connectionOptions.isAutocommit()).thenReturn(false); - when(connectionOptions.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); 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); // Indicate that a transaction has been started. when(unitOfWork.getState()).thenReturn(UnitOfWorkState.STARTED); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java index e8758c36d03..837783ee18b 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java @@ -27,7 +27,6 @@ import com.google.auth.oauth2.GoogleCredentials; import com.google.auth.oauth2.ServiceAccountCredentials; import com.google.cloud.NoCredentials; -import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.SpannerOptions; @@ -577,62 +576,6 @@ public void testSetCredentialsAndEncodedCredentials() throws Exception { "Cannot specify both a credentials URL and encoded credentials. Only set one of the properties."); } - @Test - public void testSetDialect() { - ConnectionOptions options = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database") - .build(); - assertThat(options.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); - - ConnectionOptions optionsSpanner = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=GOOGLE_STANDARD_SQL") - .build(); - assertThat(optionsSpanner.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); - - ConnectionOptions optionsPostgreSQL = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=POSTGRESQL") - .build(); - assertThat(optionsPostgreSQL.getDialect()).isEqualTo(Dialect.POSTGRESQL); - - ConnectionOptions optionsSpannerLC = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=google_standard_sql") - .build(); - assertThat(optionsSpannerLC.getDialect()).isEqualTo(Dialect.GOOGLE_STANDARD_SQL); - - ConnectionOptions optionsPostgreSQLLC = - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=postgresql") - .build(); - assertThat(optionsPostgreSQLLC.getDialect()).isEqualTo(Dialect.POSTGRESQL); - - try { - ConnectionOptions.newBuilder() - .setCredentials(NoCredentials.getInstance()) - .setUri( - "cloudspanner:/projects/test-project-123/instances/test-instance/databases/test-database?dialect=POSTGRES") - .build(); - fail("missing expected exception"); - } catch (SpannerException e) { - assertThat(e.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT); - assertThat(e.getMessage()) - .contains("Dialect must be one of [GOOGLE_STANDARD_SQL, POSTGRESQL]"); - } - } - @Test public void testExternalChannelProvider() { String baseUri = diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyStalenessTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyStalenessTest.java index 51722b00d40..fa155ea33bc 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyStalenessTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ReadOnlyStalenessTest.java @@ -27,6 +27,7 @@ import com.google.cloud.NoCredentials; import com.google.cloud.Timestamp; import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ReadOnlyTransaction; import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.Spanner; @@ -46,6 +47,7 @@ public class ReadOnlyStalenessTest { private final DatabaseClient dbClient = mock(DatabaseClient.class); private ConnectionImpl createConnection(ConnectionOptions options) { + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); Spanner spanner = mock(Spanner.class); SpannerPool spannerPool = mock(SpannerPool.class); when(spannerPool.getSpanner(any(ConnectionOptions.class), any(ConnectionImpl.class))) diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SpannerPoolTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SpannerPoolTest.java index ab5a345909f..59c9065e41e 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SpannerPoolTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SpannerPoolTest.java @@ -27,6 +27,8 @@ import com.google.auth.Credentials; import com.google.cloud.NoCredentials; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SessionPoolOptions; import com.google.cloud.spanner.Spanner; @@ -271,14 +273,22 @@ public void testCloseSpanner() { @Test public void testLeakedConnection() { + attachLogCapturer(); ConnectionOptions options = ConnectionOptions.newBuilder() .setCredentials(NoCredentials.getInstance()) - .setSessionPoolOptions(SessionPoolOptions.newBuilder().setMinSessions(0).build()) + .setSessionPoolOptions( + SessionPoolOptions.newBuilder() + .setMinSessions(0) + .setAutoDetectDialect(false) + .build()) .setUri(URI) .build(); + DdlClient ddlClient = mock(DdlClient.class); + DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); // create an actual connection object but not in a try-with-resources block - Connection connection = options.getConnection(); + Connection connection = new ConnectionImpl(options, SpannerPool.INSTANCE, ddlClient, dbClient); // try to close the application which should fail try { ConnectionOptions.closeSpanner(); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementTimeoutTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementTimeoutTest.java index 08f47c0c5d4..af6190a8fd6 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementTimeoutTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementTimeoutTest.java @@ -54,6 +54,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -105,6 +106,17 @@ ITConnection createConnection() { return createITConnection(options); } + @Before + public void setup() { + // Set up a connection and get the dialect to ensure that the auto-detect-dialect query has + // already been executed when any of the test cases start. This is necessary to ensure that any + // errors or slow execution times that are used by the different test cases are not applied to + // the query that is used for automatic dialect detection. + try (Connection connection = createConnection()) { + connection.getDialect(); + } + } + @After public void clearExecutionTimes() { mockSpanner.removeAllExecutionTimes(); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java index 4ed6c32c7bf..ab11e141cb1 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpcTest.java @@ -400,7 +400,6 @@ private SpannerOptions createSpannerOptions() { String endpoint = address.getHostString() + ":" + server.getPort(); return SpannerOptions.newBuilder() .setProjectId("[PROJECT]") - .setDialect(dialect) // Set a custom channel configurator to allow http instead of https. .setChannelConfigurator( input -> { From 96cbac9cd819735c4f826b6d7763566453dbf5d0 Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 15 Feb 2022 20:28:59 +0100 Subject: [PATCH 16/19] build(deps): update dependency org.apache.maven.plugins:maven-javadoc-plugin to v3.3.2 (#1678) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![WhiteSource Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.apache.maven.plugins:maven-javadoc-plugin](https://maven.apache.org/plugins/) ([source](https://togithub.com/apache/maven-javadoc-plugin)) | `3.3.1` -> `3.3.2` | [![age](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/compatibility-slim/3.3.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/maven/org.apache.maven.plugins:maven-javadoc-plugin/3.3.2/confidence-slim/3.3.1)](https://docs.renovatebot.com/merge-confidence/) | --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. â™» **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [WhiteSource Renovate](https://renovate.whitesourcesoftware.com). View repository job log [here](https://app.renovatebot.com/dashboard#github/googleapis/java-spanner). --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f634da99bd4..d034dfe3c33 100644 --- a/pom.xml +++ b/pom.xml @@ -186,7 +186,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.3.1 + 3.3.2 html From 4cfe74ef780f57747ea1dfef1a7098f809bcb300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 16 Feb 2022 07:58:57 +0100 Subject: [PATCH 17/19] fix: allow getting metadata without calling next() (#1691) * fix: allow getting metadata without calling next() DirectExecuteResultSet, which is used in the Connection API, directly executes any query that it is given without the need to call ResultSet.next() first. This also makes it possible to get the ResultSet metadata from the result without the need to calling ResultSet.next() first. * fix: add methods to exclude list for test --- .../connection/DirectExecuteResultSet.java | 5 ---- .../DirectExecuteResultSetTest.java | 12 ++++++++- .../connection/it/ITReadOnlySpannerTest.java | 25 +++++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DirectExecuteResultSet.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DirectExecuteResultSet.java index cf577cbc361..21c3dae7ec9 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DirectExecuteResultSet.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DirectExecuteResultSet.java @@ -96,31 +96,26 @@ public ResultSetStats getStats() { @Override public Type getType() { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); return delegate.getType(); } @Override public int getColumnCount() { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); return delegate.getColumnCount(); } @Override public int getColumnIndex(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); return delegate.getColumnIndex(columnName); } @Override public Type getColumnType(int columnIndex) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); return delegate.getColumnType(columnIndex); } @Override public Type getColumnType(String columnName) { - Preconditions.checkState(nextCalledByClient, MISSING_NEXT_CALL); return delegate.getColumnType(columnName); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DirectExecuteResultSetTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DirectExecuteResultSetTest.java index 7145ccdf743..896055ee9a8 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DirectExecuteResultSetTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DirectExecuteResultSetTest.java @@ -53,7 +53,17 @@ private DirectExecuteResultSet createSubject() { public void testMethodCallBeforeNext() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { List excludedMethods = - Arrays.asList("getStats", "next", "close", "ofResultSet", "equals", "hashCode"); + Arrays.asList( + "getStats", + "next", + "close", + "ofResultSet", + "equals", + "hashCode", + "getType", + "getColumnCount", + "getColumnIndex", + "getColumnType"); DirectExecuteResultSet subject = createSubject(); callMethods(subject, excludedMethods, IllegalStateException.class); } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITReadOnlySpannerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITReadOnlySpannerTest.java index fd5df07954e..5e626d50ebf 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITReadOnlySpannerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITReadOnlySpannerTest.java @@ -33,6 +33,7 @@ import com.google.cloud.spanner.ResultSet; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Type; import com.google.cloud.spanner.connection.ITAbstractSpannerTest; import com.google.cloud.spanner.connection.SqlScriptVerifier; import java.math.BigInteger; @@ -213,4 +214,28 @@ public void testMultipleOpenResultSets() throws InterruptedException { rs2.close(); } } + + @Test + public void testGetMetadataFromAnalyzeQuery() { + assumeFalse("analyze query is not supported on the emulator", isUsingEmulator()); + try (ITConnection connection = createConnection()) { + // Request a query plan without executing the query and verify that we can get the column + // metadata of the query without calling resultSet.next() first. + try (ResultSet resultSet = + connection.analyzeQuery( + Statement.of("SELECT number, name FROM NUMBERS"), QueryAnalyzeMode.PLAN)) { + assertEquals(2, resultSet.getColumnCount()); + + assertEquals(0, resultSet.getColumnIndex("number")); + assertEquals("number", resultSet.getType().getStructFields().get(0).getName()); + assertEquals(Type.int64(), resultSet.getColumnType(0)); + assertEquals(Type.int64(), resultSet.getColumnType("number")); + + assertEquals(1, resultSet.getColumnIndex("name")); + assertEquals("name", resultSet.getType().getStructFields().get(1).getName()); + assertEquals(Type.string(), resultSet.getColumnType(1)); + assertEquals(Type.string(), resultSet.getColumnType("name")); + } + } + } } From a0f05ad422dd47235c48bbd52bf2c8a208c201e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Wed, 16 Feb 2022 07:59:20 +0100 Subject: [PATCH 18/19] chore: make statement parsing public (marked as InternalApi) (#1690) Statement parsing is currently done internally in the Connection API do determine what RPC to execute on the backend. The parsing is however also very useful to some other applications, specifically PgAdapter, which can use this to determine what response to send to a PG client. This makes the parse method and related class and methods public, but marks them as InternalApi, so they can be used in PgAdapter. This follows the same pattern that was used to expose certain methods in the Connection API for the JDBC driver. --- .../connection/AbstractStatementParser.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java index 62cee4e26e1..82fb12acac3 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AbstractStatementParser.java @@ -130,7 +130,8 @@ public static AbstractStatementParser getInstance(Dialect dialect) { .parse(Statement.of("RUN BATCH")); /** The type of statement that has been recognized by the parser. */ - enum StatementType { + @InternalApi + public enum StatementType { CLIENT_SIDE, DDL, QUERY, @@ -139,7 +140,8 @@ enum StatementType { } /** A statement that has been parsed */ - static class ParsedStatement { + @InternalApi + public static class ParsedStatement { private final StatementType type; private final ClientSideStatementImpl clientSideStatement; private final Statement statement; @@ -217,11 +219,18 @@ public boolean equals(Object other) { && Objects.equals(this.sqlWithoutComments, o.sqlWithoutComments); } - StatementType getType() { + /** Returns the type of statement that was recognized by the parser. */ + @InternalApi + public StatementType getType() { return type; } - boolean isQuery() { + /** + * Returns true if the statement is a query that will return a {@link + * com.google.cloud.spanner.ResultSet}. + */ + @InternalApi + public boolean isQuery() { switch (type) { case CLIENT_SIDE: return getClientSideStatement().isQuery(); @@ -235,7 +244,12 @@ boolean isQuery() { return false; } - boolean isUpdate() { + /** + * Returns true if the statement is a DML statement or a client side statement that will return + * an update count. + */ + @InternalApi + public boolean isUpdate() { switch (type) { case CLIENT_SIDE: return getClientSideStatement().isUpdate(); @@ -249,7 +263,9 @@ boolean isUpdate() { return false; } - boolean isDdl() { + /** Returns true if the statement is a DDL statement. */ + @InternalApi + public boolean isDdl() { switch (type) { case DDL: return true; @@ -286,7 +302,9 @@ Statement mergeQueryOptions(Statement statement, QueryOptions defaultQueryOption .build(); } - String getSqlWithoutComments() { + /** Returns the SQL statement with all comments removed from the SQL string. */ + @InternalApi + public String getSqlWithoutComments() { return sqlWithoutComments; } @@ -321,7 +339,8 @@ ClientSideStatement getClientSideStatement() { * @param statement The statement to parse. * @return the parsed and categorized statement. */ - ParsedStatement parse(Statement statement) { + @InternalApi + public ParsedStatement parse(Statement statement) { return parse(statement, null); } From 8e6aebf1bf992b19e5885869e9bb6e59e88524fc Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Thu, 17 Feb 2022 10:41:12 +0530 Subject: [PATCH 19/19] chore(main): release 6.19.0 (#1675) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 21 +++++++++++++++++++ google-cloud-spanner-bom/pom.xml | 18 ++++++++-------- google-cloud-spanner/pom.xml | 4 ++-- .../pom.xml | 4 ++-- .../pom.xml | 4 ++-- grpc-google-cloud-spanner-v1/pom.xml | 4 ++-- pom.xml | 16 +++++++------- .../pom.xml | 4 ++-- .../pom.xml | 4 ++-- proto-google-cloud-spanner-v1/pom.xml | 4 ++-- samples/snapshot/pom.xml | 2 +- versions.txt | 14 ++++++------- 12 files changed, 60 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79dc4815b89..63018f365cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ # Changelog +## [6.19.0](https://github.com/googleapis/java-spanner/compare/v6.18.0...v6.19.0) (2022-02-16) + + +### Features + +* automatically detect database dialect ([#1677](https://github.com/googleapis/java-spanner/issues/1677)) ([9eccfc4](https://github.com/googleapis/java-spanner/commit/9eccfc441237272b01140c1f3d7da51b2b985554)) +* PostgreSQL dialect databases ([#1673](https://github.com/googleapis/java-spanner/issues/1673)) ([5f156f2](https://github.com/googleapis/java-spanner/commit/5f156f2efdb4726679766b385d500a030c24e477)) + + +### Bug Fixes + +* allow getting metadata without calling next() ([#1691](https://github.com/googleapis/java-spanner/issues/1691)) ([4cfe74e](https://github.com/googleapis/java-spanner/commit/4cfe74ef780f57747ea1dfef1a7098f809bcb300)) +* do not delete session in close method for BatchReadOnlyTransactionImpl ([#1688](https://github.com/googleapis/java-spanner/issues/1688)) ([5dc3e19](https://github.com/googleapis/java-spanner/commit/5dc3e191bee603a7feec29b7d4412646d53d73e4)) +* untyped null parameters would cause NPE ([#1680](https://github.com/googleapis/java-spanner/issues/1680)) ([7095f94](https://github.com/googleapis/java-spanner/commit/7095f940638d786745ed6715cf7a221d3e4a41a9)), closes [#1679](https://github.com/googleapis/java-spanner/issues/1679) + + +### Dependencies + +* update dependency com.google.cloud:google-cloud-monitoring to v3.2.2 ([#1666](https://github.com/googleapis/java-spanner/issues/1666)) ([8ea2220](https://github.com/googleapis/java-spanner/commit/8ea22205ea1361012b8f237af9150f320b41cc23)) +* update dependency com.google.cloud:google-cloud-trace to v2.1.2 ([#1664](https://github.com/googleapis/java-spanner/issues/1664)) ([4f46635](https://github.com/googleapis/java-spanner/commit/4f46635577f0e754ce271e4aba338b84d34f57dd)) + ## [6.18.0](https://github.com/googleapis/java-spanner/compare/v6.17.4...v6.18.0) (2022-02-03) diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml index 4a35fe5707a..d6c9766f438 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.18.1-SNAPSHOT + 6.19.0 pom com.google.cloud @@ -53,43 +53,43 @@ com.google.cloud google-cloud-spanner - 6.18.1-SNAPSHOT + 6.19.0 com.google.cloud google-cloud-spanner test-jar - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.18.1-SNAPSHOT + 6.19.0 diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 62276e23e79..9df3f668c4f 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.18.1-SNAPSHOT + 6.19.0 jar Google Cloud Spanner https://github.com/googleapis/java-spanner @@ -11,7 +11,7 @@ com.google.cloud google-cloud-spanner-parent - 6.18.1-SNAPSHOT + 6.19.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 81396931682..36dc6867259 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.18.1-SNAPSHOT + 6.19.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.18.1-SNAPSHOT + 6.19.0 diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml index 54e2993a612..bdc54971759 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.18.1-SNAPSHOT + 6.19.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.18.1-SNAPSHOT + 6.19.0 diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml index 13407ad03ba..8e40e6f248c 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.18.1-SNAPSHOT + 6.19.0 grpc-google-cloud-spanner-v1 GRPC library for grpc-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.18.1-SNAPSHOT + 6.19.0 diff --git a/pom.xml b/pom.xml index d034dfe3c33..32830150ed9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-spanner-parent pom - 6.18.1-SNAPSHOT + 6.19.0 Google Cloud Spanner Parent https://github.com/googleapis/java-spanner @@ -62,37 +62,37 @@ com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.18.1-SNAPSHOT + 6.19.0 com.google.cloud google-cloud-spanner - 6.18.1-SNAPSHOT + 6.19.0 diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml index ffbaef0f38c..eba53f77c0b 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.18.1-SNAPSHOT + 6.19.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.18.1-SNAPSHOT + 6.19.0 diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml index 2bee0aa10e2..4cc9a5a51b4 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.18.1-SNAPSHOT + 6.19.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.18.1-SNAPSHOT + 6.19.0 diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml index 0b061fb01dd..b19ae35ac5b 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.18.1-SNAPSHOT + 6.19.0 proto-google-cloud-spanner-v1 PROTO library for proto-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.18.1-SNAPSHOT + 6.19.0 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index aa087e6ca9c..faea75f4426 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -31,7 +31,7 @@ com.google.cloud google-cloud-spanner - 6.18.1-SNAPSHOT + 6.19.0 diff --git a/versions.txt b/versions.txt index cb5830abe5e..c2422d5b4ab 100644 --- a/versions.txt +++ b/versions.txt @@ -1,10 +1,10 @@ # Format: # module:released-version:current-version -proto-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.1-SNAPSHOT -proto-google-cloud-spanner-v1:6.18.0:6.18.1-SNAPSHOT -proto-google-cloud-spanner-admin-database-v1:6.18.0:6.18.1-SNAPSHOT -grpc-google-cloud-spanner-v1:6.18.0:6.18.1-SNAPSHOT -grpc-google-cloud-spanner-admin-instance-v1:6.18.0:6.18.1-SNAPSHOT -grpc-google-cloud-spanner-admin-database-v1:6.18.0:6.18.1-SNAPSHOT -google-cloud-spanner:6.18.0:6.18.1-SNAPSHOT +proto-google-cloud-spanner-admin-instance-v1:6.19.0:6.19.0 +proto-google-cloud-spanner-v1:6.19.0:6.19.0 +proto-google-cloud-spanner-admin-database-v1:6.19.0:6.19.0 +grpc-google-cloud-spanner-v1:6.19.0:6.19.0 +grpc-google-cloud-spanner-admin-instance-v1:6.19.0:6.19.0 +grpc-google-cloud-spanner-admin-database-v1:6.19.0:6.19.0 +google-cloud-spanner:6.19.0:6.19.0