diff --git a/.kokoro/build.sh b/.kokoro/build.sh index 8875b41d373..9782a77e507 100755 --- a/.kokoro/build.sh +++ b/.kokoro/build.sh @@ -98,8 +98,9 @@ integration) -Dclirr.skip=true \ -Denforcer.skip=true \ -Dmaven.main.skip=true \ - -Dspanner.gce.config.project_id=gcloud-devel \ - -Dspanner.testenv.instance=projects/gcloud-devel/instances/java-client-integration-tests \ + -Dspanner.gce.config.server_url=https://staging-wrenchworks.sandbox.googleapis.com \ + -Dspanner.gce.config.project_id=span-cloud-testing \ + -Dspanner.testenv.instance=projects/span-cloud-testing/instances/java-client-integration-tests \ -fae \ verify RETURN_CODE=$? @@ -113,6 +114,7 @@ integration-directpath-enabled) -Dclirr.skip=true \ -Denforcer.skip=true \ -Dmaven.main.skip=true \ + -Dspanner.gce.config.server_url=https://staging-wrenchworks.sandbox.googleapis.com \ -Dspanner.testenv.instance=projects/span-cloud-testing/instances/spanner-java-client-directpath \ -Dspanner.gce.config.project_id=span-cloud-testing \ -fae \ @@ -128,8 +130,9 @@ integration-multiplexed-sessions-enabled) -Dclirr.skip=true \ -Denforcer.skip=true \ -Dmaven.main.skip=true \ - -Dspanner.gce.config.project_id=gcloud-devel \ - -Dspanner.testenv.instance=projects/gcloud-devel/instances/java-client-integration-tests-multiplexed-sessions \ + -Dspanner.gce.config.server_url=https://staging-wrenchworks.sandbox.googleapis.com \ + -Dspanner.gce.config.project_id=span-cloud-testing \ + -Dspanner.testenv.instance=projects/span-cloud-testing/instances/java-client-integration-tests-multiplexed-sessions \ -fae \ verify RETURN_CODE=$? diff --git a/.kokoro/presubmit/integration-directpath-enabled.cfg b/.kokoro/presubmit/integration-directpath-enabled.cfg index ceb3bddfa70..c7b3d45e771 100644 --- a/.kokoro/presubmit/integration-directpath-enabled.cfg +++ b/.kokoro/presubmit/integration-directpath-enabled.cfg @@ -11,17 +11,6 @@ env_vars: { value: "integration-directpath-enabled" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "gcloud-devel" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" value: "secret_manager/java-client-testing" diff --git a/.kokoro/presubmit/integration-multiplexed-sessions-enabled.cfg b/.kokoro/presubmit/integration-multiplexed-sessions-enabled.cfg index 800e2a21558..28b95345f71 100644 --- a/.kokoro/presubmit/integration-multiplexed-sessions-enabled.cfg +++ b/.kokoro/presubmit/integration-multiplexed-sessions-enabled.cfg @@ -11,25 +11,14 @@ env_vars: { value: "integration-multiplexed-sessions-enabled" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "gcloud-devel" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "secret_manager/java-it-service-account" + value: "secret_manager/java-client-testing" } env_vars: { key: "SECRET_MANAGER_KEYS" - value: "java-it-service-account" + value: "java-client-testing" } env_vars: { diff --git a/.kokoro/presubmit/integration.cfg b/.kokoro/presubmit/integration.cfg index 5864c603e5a..cc4e22eaf9a 100644 --- a/.kokoro/presubmit/integration.cfg +++ b/.kokoro/presubmit/integration.cfg @@ -11,24 +11,12 @@ env_vars: { value: "integration" } -# TODO: remove this after we've migrated all tests and scripts -env_vars: { - key: "GCLOUD_PROJECT" - value: "gcloud-devel" -} - -env_vars: { - key: "GOOGLE_CLOUD_PROJECT" - value: "gcloud-devel" -} - env_vars: { key: "GOOGLE_APPLICATION_CREDENTIALS" - value: "secret_manager/java-it-service-account" + value: "secret_manager/java-client-testing" } env_vars: { key: "SECRET_MANAGER_KEYS" - value: "java-it-service-account" + value: "java-client-testing" } - diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ce8985adf1..7f2f2a2ab41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## [6.91.0](https://github.com/googleapis/java-spanner/compare/v6.90.0...v6.91.0) (2025-04-17) + + +### Features + +* [Internal] open telemetry built in metrics for GRPC ([#3709](https://github.com/googleapis/java-spanner/issues/3709)) ([cd76c73](https://github.com/googleapis/java-spanner/commit/cd76c73d838a9ccde2c8c11fc63144a62d76886c)) +* Add java sample for the pre-splitting feature ([#3713](https://github.com/googleapis/java-spanner/issues/3713)) ([e97b92e](https://github.com/googleapis/java-spanner/commit/e97b92ea4728bc8f013ff73478de4af9eaa1793b)) +* Add TransactionMutationLimitExceededException as cause to SpannerBatchUpdateException ([#3723](https://github.com/googleapis/java-spanner/issues/3723)) ([4cf5261](https://github.com/googleapis/java-spanner/commit/4cf52613c6c8280fdb864f5b8d04f8fb6ea55e16)) +* Built in metrics for afe latency and connectivity error ([#3724](https://github.com/googleapis/java-spanner/issues/3724)) ([e13a2f9](https://github.com/googleapis/java-spanner/commit/e13a2f9c5cadd15ab5a565c7dd1c1eec64c09488)) +* Support unnamed parameters ([#3820](https://github.com/googleapis/java-spanner/issues/3820)) ([1afd815](https://github.com/googleapis/java-spanner/commit/1afd815869785588dfd03ffc12e381e32c4aa0fe)) + + +### Bug Fixes + +* Add default implementations for Interval methods in AbstractStructReader ([#3722](https://github.com/googleapis/java-spanner/issues/3722)) ([97f4544](https://github.com/googleapis/java-spanner/commit/97f45448ecb51bd20699d1f163f78b2a7736b21f)) +* Set transaction isolation level had no effect ([#3718](https://github.com/googleapis/java-spanner/issues/3718)) ([b382999](https://github.com/googleapis/java-spanner/commit/b382999f42d1b643472cf3f605f8c6dc839dec19)) + + +### Performance Improvements + +* Cache the key used for OTEL traces and metrics ([#3814](https://github.com/googleapis/java-spanner/issues/3814)) ([c5a2045](https://github.com/googleapis/java-spanner/commit/c5a20452ad2ed5a8f1ac12cca4072a86f4457b93)) +* Optimize parsing in Connection API ([#3800](https://github.com/googleapis/java-spanner/issues/3800)) ([a2780ed](https://github.com/googleapis/java-spanner/commit/a2780edb3d9d4972c78befd097692f626a6a4bea)) +* Qualify statements without removing comments ([#3810](https://github.com/googleapis/java-spanner/issues/3810)) ([d358cb9](https://github.com/googleapis/java-spanner/commit/d358cb96e33bdf6de6528d03c884aa702b40b802)) +* Remove all calls to getSqlWithoutComments ([#3822](https://github.com/googleapis/java-spanner/issues/3822)) ([0e1e14c](https://github.com/googleapis/java-spanner/commit/0e1e14c0e8c1f3726c4d3cfd836c580b3b4122d0)) + ## [6.90.0](https://github.com/googleapis/java-spanner/compare/v6.89.0...v6.90.0) (2025-03-31) diff --git a/README.md b/README.md index 2e6b5bd87e9..4517cb7908f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you are using Maven with [BOM][libraries-bom], add this to your pom.xml file: com.google.cloud libraries-bom - 26.54.0 + 26.57.0 pom import @@ -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.90.0' +implementation 'com.google.cloud:google-cloud-spanner:6.91.0' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.90.0" +libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.91.0" ``` ## Authentication @@ -525,6 +525,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/ | Create Sequence Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CreateSequenceSample.java) | | Create Table With Foreign Key Delete Cascade Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CreateTableWithForeignKeyDeleteCascadeSample.java) | | Custom Timeout And Retry Settings Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/CustomTimeoutAndRetrySettingsExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/CustomTimeoutAndRetrySettingsExample.java) | +| Database Add Split Points Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java) | | Delete Backup Schedule Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DeleteBackupScheduleSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DeleteBackupScheduleSample.java) | | Delete Instance Config Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DeleteInstanceConfigSample.java) | | Delete Using Dml Returning Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/DeleteUsingDmlReturningSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/DeleteUsingDmlReturningSample.java) | @@ -727,7 +728,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner.svg -[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.90.0 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.91.0 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles diff --git a/benchmarks/pom.xml b/benchmarks/pom.xml index 273b7172a23..81178731770 100644 --- a/benchmarks/pom.xml +++ b/benchmarks/pom.xml @@ -24,7 +24,7 @@ com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/google-cloud-spanner-bom/pom.xml b/google-cloud-spanner-bom/pom.xml index f83a7fe873a..8bf2e1c11ca 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.90.0 + 6.91.0 pom com.google.cloud @@ -53,43 +53,43 @@ com.google.cloud google-cloud-spanner - 6.90.0 + 6.91.0 com.google.cloud google-cloud-spanner test-jar - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.90.0 + 6.91.0 diff --git a/google-cloud-spanner-executor/pom.xml b/google-cloud-spanner-executor/pom.xml index c335174188a..285ea1f507c 100644 --- a/google-cloud-spanner-executor/pom.xml +++ b/google-cloud-spanner-executor/pom.xml @@ -5,14 +5,14 @@ 4.0.0 com.google.cloud google-cloud-spanner-executor - 6.90.0 + 6.91.0 jar Google Cloud Spanner Executor com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml index 735b28dae2a..d6d36b0e147 100644 --- a/google-cloud-spanner/clirr-ignored-differences.xml +++ b/google-cloud-spanner/clirr-ignored-differences.xml @@ -597,16 +597,6 @@ com/google/cloud/spanner/StructReader java.util.List getIntervalList(java.lang.String) - - 7013 - com/google/cloud/spanner/AbstractStructReader - com.google.cloud.spanner.Interval getIntervalInternal(int) - - - 7013 - com/google/cloud/spanner/AbstractStructReader - java.util.List getIntervalListInternal(int) - 7013 com/google/cloud/spanner/Value @@ -761,6 +751,13 @@ boolean isEnableBuiltInMetrics() + + + 7012 + com/google/cloud/spanner/SpannerOptions$SpannerEnvironment + boolean isEnableGRPCBuiltInMetrics() + + 7012 @@ -817,7 +814,7 @@ com/google/cloud/spanner/connection/Connection boolean isKeepTransactionAlive() - + 7012 @@ -849,7 +846,7 @@ com/google/cloud/spanner/connection/Connection boolean isAutoBatchDmlUpdateCountVerification() - + 7012 @@ -873,7 +870,7 @@ com/google/cloud/spanner/connection/Connection java.lang.Object runTransaction(com.google.cloud.spanner.connection.Connection$TransactionCallable) - + 7012 @@ -937,5 +934,27 @@ com/google/cloud/spanner/connection/ConnectionOptions VALID_PROPERTIES - + + + + 7002 + com/google/cloud/spanner/connection/AbstractStatementParser + boolean supportsExplain() + + + 7002 + com/google/cloud/spanner/connection/PostgreSQLStatementParser + boolean supportsExplain() + + + 7002 + com/google/cloud/spanner/connection/SpannerStatementParser + boolean supportsExplain() + + + + 7012 + com/google/cloud/spanner/DatabaseClient + com.google.cloud.spanner.Statement$StatementFactory getStatementFactory() + diff --git a/google-cloud-spanner/pom.xml b/google-cloud-spanner/pom.xml index 5f883ce9b04..04495b8c6f6 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.90.0 + 6.91.0 jar Google Cloud Spanner https://github.com/googleapis/java-spanner @@ -11,7 +11,7 @@ com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 google-cloud-spanner @@ -191,6 +191,10 @@ io.grpc grpc-stub + + io.grpc + grpc-opentelemetry + com.google.api api-common @@ -517,6 +521,19 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + + + + diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbortedException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbortedException.java index 03dff9f7609..3e5227888d9 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbortedException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AbortedException.java @@ -35,7 +35,7 @@ public class AbortedException extends SpannerException { /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ AbortedException( DoNotConstructDirectly token, @Nullable String message, @Nullable Throwable cause) { - this(token, message, cause, null); + this(token, message, cause, null, null); } /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ @@ -43,8 +43,9 @@ public class AbortedException extends SpannerException { DoNotConstructDirectly token, @Nullable String message, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, ErrorCode.ABORTED, IS_RETRYABLE, message, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, ErrorCode.ABORTED, IS_RETRYABLE, message, cause, apiException, reqId); } /** 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 10287544e96..e5b9fa00123 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 @@ -67,7 +67,9 @@ protected String getPgJsonbInternal(int columnIndex) { protected abstract Date getDateInternal(int columnIndex); - protected abstract Interval getIntervalInternal(int columnIndex); + protected Interval getIntervalInternal(int columnIndex) { + throw new UnsupportedOperationException("Not implemented"); + } protected T getProtoMessageInternal(int columnIndex, T message) { throw new UnsupportedOperationException("Not implemented"); @@ -130,7 +132,9 @@ protected List getPgJsonbListInternal(int columnIndex) { protected abstract List getDateListInternal(int columnIndex); - protected abstract List getIntervalListInternal(int columnIndex); + protected List getIntervalListInternal(int columnIndex) { + throw new UnsupportedOperationException("Not implemented"); + } protected abstract List getStructListInternal(int columnIndex); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AdminRequestsPerMinuteExceededException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AdminRequestsPerMinuteExceededException.java index 72d8b0ab15d..b7d76ab9e82 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AdminRequestsPerMinuteExceededException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/AdminRequestsPerMinuteExceededException.java @@ -32,7 +32,7 @@ public class AdminRequestsPerMinuteExceededException extends SpannerException { /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ AdminRequestsPerMinuteExceededException( DoNotConstructDirectly token, @Nullable String message, @Nullable Throwable cause) { - this(token, message, cause, null); + this(token, message, cause, null, null); } /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ @@ -40,7 +40,8 @@ public class AdminRequestsPerMinuteExceededException extends SpannerException { DoNotConstructDirectly token, @Nullable String message, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, ErrorCode.RESOURCE_EXHAUSTED, true, message, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, ErrorCode.RESOURCE_EXHAUSTED, true, message, cause, apiException, reqId); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java index 4adf53d7e40..050484ae66e 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsConstant.java @@ -26,6 +26,7 @@ import io.opentelemetry.sdk.metrics.InstrumentSelector; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.View; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -36,6 +37,7 @@ public class BuiltInMetricsConstant { public static final String METER_NAME = "spanner.googleapis.com/internal/client"; public static final String GAX_METER_NAME = OpenTelemetryMetricsRecorder.GAX_METER_NAME; static final String SPANNER_METER_NAME = "spanner-java"; + static final String GRPC_METER_NAME = "grpc-java"; static final String GFE_LATENCIES_NAME = "gfe_latencies"; static final String OPERATION_LATENCIES_NAME = "operation_latencies"; static final String ATTEMPT_LATENCIES_NAME = "attempt_latencies"; @@ -55,6 +57,14 @@ public class BuiltInMetricsConstant { .map(m -> METER_NAME + '/' + m) .collect(Collectors.toSet()); + static final Collection GRPC_METRICS_TO_ENABLE = + ImmutableList.of( + "grpc.lb.rls.default_target_picks", + "grpc.lb.rls.target_picks", + "grpc.xds_client.server_failure", + "grpc.xds_client.resource_updates_invalid", + "grpc.xds_client.resource_updates_valid"); + public static final String SPANNER_RESOURCE_TYPE = "spanner_instance_client"; public static final AttributeKey PROJECT_ID_KEY = AttributeKey.stringKey("project_id"); @@ -66,12 +76,7 @@ public class BuiltInMetricsConstant { // These metric labels will be promoted to the spanner monitored resource fields public static final Set> SPANNER_PROMOTED_RESOURCE_LABELS = - ImmutableSet.of( - PROJECT_ID_KEY, - INSTANCE_ID_KEY, - INSTANCE_CONFIG_ID_KEY, - LOCATION_ID_KEY, - CLIENT_HASH_KEY); + ImmutableSet.of(INSTANCE_ID_KEY); public static final AttributeKey DATABASE_KEY = AttributeKey.stringKey("database"); public static final AttributeKey CLIENT_UID_KEY = AttributeKey.stringKey("client_uid"); @@ -102,6 +107,9 @@ public class BuiltInMetricsConstant { DIRECT_PATH_ENABLED_KEY, DIRECT_PATH_USED_KEY); + static final Set GRPC_LB_RLS_ATTRIBUTES = + ImmutableSet.of("grpc.lb.rls.data_plane_target", "grpc.lb.pick_result"); + static Aggregation AGGREGATION_WITH_MILLIS_HISTOGRAM = Aggregation.explicitBucketHistogram( ImmutableList.of( @@ -111,6 +119,14 @@ public class BuiltInMetricsConstant { 10000.0, 20000.0, 50000.0, 100000.0, 200000.0, 400000.0, 800000.0, 1600000.0, 3200000.0)); + static final Collection GRPC_METRICS_ENABLED_BY_DEFAULT = + ImmutableList.of( + "grpc.client.attempt.sent_total_compressed_message_size", + "grpc.client.attempt.rcvd_total_compressed_message_size", + "grpc.client.attempt.started", + "grpc.client.attempt.duration", + "grpc.client.call.duration"); + static Map getAllViews() { ImmutableMap.Builder views = ImmutableMap.builder(); defineView( @@ -153,6 +169,7 @@ static Map getAllViews() { Aggregation.sum(), InstrumentType.COUNTER, "1"); + defineGRPCView(views); return views.build(); } @@ -183,4 +200,26 @@ private static void defineView( .build(); viewMap.put(selector, view); } + + private static void defineGRPCView(ImmutableMap.Builder viewMap) { + for (String metric : BuiltInMetricsConstant.GRPC_METRICS_TO_ENABLE) { + InstrumentSelector selector = + InstrumentSelector.builder() + .setName(metric) + .setMeterName(BuiltInMetricsConstant.GRPC_METER_NAME) + .build(); + Set attributesFilter = + BuiltInMetricsConstant.COMMON_ATTRIBUTES.stream() + .map(AttributeKey::getKey) + .collect(Collectors.toSet()); + attributesFilter.addAll(BuiltInMetricsConstant.GRPC_LB_RLS_ATTRIBUTES); + + View view = + View.builder() + .setName(BuiltInMetricsConstant.METER_NAME + '/' + metric.replace(".", "/")) + .setAttributeFilter(attributesFilter) + .build(); + viewMap.put(selector, view); + } + } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java index f624f310f77..888eff90b58 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsProvider.java @@ -21,19 +21,28 @@ import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_NAME_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_UID_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.INSTANCE_CONFIG_ID_KEY; +import static com.google.cloud.spanner.BuiltInMetricsConstant.INSTANCE_ID_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.LOCATION_ID_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.PROJECT_ID_KEY; +import com.google.api.core.ApiFunction; +import com.google.api.gax.core.GaxProperties; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.auth.Credentials; import com.google.cloud.opentelemetry.detection.AttributeKeys; import com.google.cloud.opentelemetry.detection.DetectedPlatform; import com.google.cloud.opentelemetry.detection.GCPPlatformDetector; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; +import io.grpc.ManagedChannelBuilder; +import io.grpc.opentelemetry.GrpcOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.SdkMeterProviderBuilder; +import io.opentelemetry.sdk.resources.Resource; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Method; @@ -66,6 +75,7 @@ OpenTelemetry getOrCreateOpenTelemetry( BuiltInMetricsView.registerBuiltinMetrics( SpannerCloudMonitoringExporter.create(projectId, credentials, monitoringHost), sdkMeterProviderBuilder); + sdkMeterProviderBuilder.setResource(Resource.create(createResourceAttributes(projectId))); SdkMeterProvider sdkMeterProvider = sdkMeterProviderBuilder.build(); this.openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(sdkMeterProvider).build(); Runtime.getRuntime().addShutdownHook(new Thread(sdkMeterProvider::close)); @@ -80,15 +90,47 @@ OpenTelemetry getOrCreateOpenTelemetry( } } - Map createClientAttributes(String projectId, String client_name) { + void enableGrpcMetrics( + InstantiatingGrpcChannelProvider.Builder channelProviderBuilder, + String projectId, + @Nullable Credentials credentials, + @Nullable String monitoringHost) { + GrpcOpenTelemetry grpcOpenTelemetry = + GrpcOpenTelemetry.newBuilder() + .sdk(this.getOrCreateOpenTelemetry(projectId, credentials, monitoringHost)) + .enableMetrics(BuiltInMetricsConstant.GRPC_METRICS_TO_ENABLE) + // Disable gRPCs default metrics as they are not needed for Spanner. + .disableMetrics(BuiltInMetricsConstant.GRPC_METRICS_ENABLED_BY_DEFAULT) + .build(); + ApiFunction channelConfigurator = + channelProviderBuilder.getChannelConfigurator(); + channelProviderBuilder.setChannelConfigurator( + b -> { + grpcOpenTelemetry.configureChannelBuilder(b); + if (channelConfigurator != null) { + return channelConfigurator.apply(b); + } + return b; + }); + } + + Attributes createResourceAttributes(String projectId) { + AttributesBuilder attributesBuilder = + Attributes.builder() + .put(PROJECT_ID_KEY.getKey(), projectId) + .put(INSTANCE_CONFIG_ID_KEY.getKey(), "unknown") + .put(CLIENT_HASH_KEY.getKey(), generateClientHash(getDefaultTaskValue())) + .put(INSTANCE_ID_KEY.getKey(), "unknown") + .put(LOCATION_ID_KEY.getKey(), detectClientLocation()); + + return attributesBuilder.build(); + } + + Map createClientAttributes() { Map clientAttributes = new HashMap<>(); - clientAttributes.put(LOCATION_ID_KEY.getKey(), detectClientLocation()); - clientAttributes.put(PROJECT_ID_KEY.getKey(), projectId); - clientAttributes.put(INSTANCE_CONFIG_ID_KEY.getKey(), "unknown"); - clientAttributes.put(CLIENT_NAME_KEY.getKey(), client_name); - String clientUid = getDefaultTaskValue(); - clientAttributes.put(CLIENT_UID_KEY.getKey(), clientUid); - clientAttributes.put(CLIENT_HASH_KEY.getKey(), generateClientHash(clientUid)); + clientAttributes.put( + CLIENT_NAME_KEY.getKey(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass())); + clientAttributes.put(CLIENT_UID_KEY.getKey(), getDefaultTaskValue()); return clientAttributes; } 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 a33f39d47fd..e30c648c367 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 @@ -21,6 +21,7 @@ import com.google.cloud.spanner.Options.RpcPriority; import com.google.cloud.spanner.Options.TransactionOption; import com.google.cloud.spanner.Options.UpdateOption; +import com.google.cloud.spanner.Statement.StatementFactory; import com.google.spanner.v1.BatchWriteResponse; import com.google.spanner.v1.TransactionOptions.IsolationLevel; @@ -606,4 +607,24 @@ ServerStream batchWriteAtLeastOnce( * idempotent, such as deleting old rows from a very large table. */ long executePartitionedUpdate(Statement stmt, UpdateOption... options); + + /** + * Returns a {@link StatementFactory} for the given dialect. + * + *

A {@link StatementFactory} can be used to create statements with unnamed parameters. This is + * primarily intended for framework developers who want to integrate the Spanner client with + * frameworks that use unnamed parameters. Developers who just want to use the Spanner client in + * their application, should use named parameters. + * + *

Examples using {@link StatementFactory} + * + *

{@code
+   * Statement statement = databaseClient
+   *     .getStatementFactory()
+   *     .withUnnamedParameters("SELECT NAME FROM TABLE WHERE ID = ?", 10);
+   * }
+ */ + default StatementFactory getStatementFactory() { + throw new UnsupportedOperationException("method should be overwritten"); + } } 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 775e38f05b9..8e0e07c457b 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 @@ -22,11 +22,16 @@ import com.google.cloud.spanner.Options.UpdateOption; import com.google.cloud.spanner.SessionPool.PooledSessionFuture; import com.google.cloud.spanner.SpannerImpl.ClosedException; +import com.google.cloud.spanner.Statement.StatementFactory; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.util.concurrent.ListenableFuture; import com.google.spanner.v1.BatchWriteResponse; import io.opentelemetry.api.common.Attributes; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import javax.annotation.Nullable; class DatabaseClientImpl implements DatabaseClient { @@ -139,6 +144,30 @@ public Dialect getDialect() { return pool.getDialect(); } + private final AbstractLazyInitializer statementFactorySupplier = + new AbstractLazyInitializer() { + @Override + protected StatementFactory initialize() { + try { + Dialect dialect = getDialectAsync().get(30, TimeUnit.SECONDS); + return new StatementFactory(dialect); + } catch (ExecutionException | TimeoutException e) { + throw SpannerExceptionFactory.asSpannerException(e); + } catch (InterruptedException e) { + throw SpannerExceptionFactory.propagateInterrupt(e); + } + } + }; + + @Override + public StatementFactory getStatementFactory() { + try { + return statementFactorySupplier.get(); + } catch (Exception exception) { + throw SpannerExceptionFactory.asSpannerException(exception); + } + } + @Override @Nullable public String getDatabaseRole() { @@ -346,6 +375,14 @@ public long executePartitionedUpdate(final Statement stmt, final UpdateOption... return executePartitionedUpdateWithPooledSession(stmt, options); } + private Future getDialectAsync() { + MultiplexedSessionDatabaseClient client = getMultiplexedSessionDatabaseClient(); + if (client != null) { + return client.getDialectAsync(); + } + return pool.getDialectAsync(); + } + private long executePartitionedUpdateWithPooledSession( final Statement stmt, final UpdateOption... options) { ISpan span = tracer.spanBuilder(PARTITION_DML_TRANSACTION, commonAttributes); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseNotFoundException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseNotFoundException.java index cc4a2e32f0b..474acb04890 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseNotFoundException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseNotFoundException.java @@ -35,7 +35,7 @@ public class DatabaseNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause) { - this(token, message, resourceInfo, cause, null); + this(token, message, resourceInfo, cause, null, null); } /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ @@ -44,7 +44,8 @@ public class DatabaseNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, message, resourceInfo, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, message, resourceInfo, cause, apiException, reqId); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/InstanceNotFoundException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/InstanceNotFoundException.java index 82c451f9475..18961569bbf 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/InstanceNotFoundException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/InstanceNotFoundException.java @@ -35,7 +35,7 @@ public class InstanceNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause) { - this(token, message, resourceInfo, cause, null); + this(token, message, resourceInfo, cause, null, null); } /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ InstanceNotFoundException( @@ -43,7 +43,8 @@ public class InstanceNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, message, resourceInfo, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, message, resourceInfo, cause, apiException, reqId); } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MissingDefaultSequenceKindException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MissingDefaultSequenceKindException.java index 7b61dbbd881..5ed594e10cd 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MissingDefaultSequenceKindException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MissingDefaultSequenceKindException.java @@ -37,8 +37,9 @@ public class MissingDefaultSequenceKindException extends SpannerException { ErrorCode errorCode, String message, Throwable cause, - @Nullable ApiException apiException) { - super(token, errorCode, /*retryable = */ false, message, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, errorCode, /*retryable = */ false, message, cause, apiException, reqId); } static boolean isMissingDefaultSequenceKindException(Throwable cause) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java index 798b976c721..aa2dc857122 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java @@ -44,6 +44,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -652,6 +653,14 @@ public Dialect getDialect() { } } + Future getDialectAsync() { + try { + return MAINTAINER_SERVICE.submit(dialectSupplier::get); + } catch (Exception exception) { + throw SpannerExceptionFactory.asSpannerException(exception); + } + } + @Override public Timestamp write(Iterable mutations) throws SpannerException { return createMultiplexedSessionTransaction(/* singleUse = */ false).write(mutations); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Operation.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Operation.java index 66b1165f4a9..8cfbcedc175 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Operation.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Operation.java @@ -89,7 +89,7 @@ private static Operation failed( SpannerRpc rpc, String name, Status status, M metadata, Parser parser, ApiClock clock) { SpannerException e = SpannerExceptionFactory.newSpannerException( - ErrorCode.fromRpcStatus(status), status.getMessage(), null); + ErrorCode.fromRpcStatus(status), status.getMessage(), (Throwable) (null)); return new Operation<>(rpc, name, metadata, null, e, true, parser, clock); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ResumableStreamIterator.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ResumableStreamIterator.java index 793f3bcbe32..25cc30a2814 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ResumableStreamIterator.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/ResumableStreamIterator.java @@ -180,10 +180,10 @@ private void backoffSleep(Context context, long backoffMillis) throws SpannerExc } if (latch.await(backoffMillis, TimeUnit.MILLISECONDS)) { // Woken by context cancellation. - throw newSpannerExceptionForCancellation(context, null); + throw newSpannerExceptionForCancellation(context, null, null /*TODO: requestId*/); } } catch (InterruptedException interruptExcept) { - throw newSpannerExceptionForCancellation(context, interruptExcept); + throw newSpannerExceptionForCancellation(context, interruptExcept, null /*TODO: requestId*/); } finally { context.removeListener(listener); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionNotFoundException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionNotFoundException.java index f4a62b1954a..c17384db3ec 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionNotFoundException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionNotFoundException.java @@ -35,7 +35,7 @@ public class SessionNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause) { - this(token, message, resourceInfo, cause, null); + this(token, message, resourceInfo, cause, null, null); } /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ @@ -44,7 +44,8 @@ public class SessionNotFoundException extends ResourceNotFoundException { @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, message, resourceInfo, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, message, resourceInfo, cause, apiException, reqId); } } 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 c0a7fd9fa0e..37fa2c5d202 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 @@ -104,6 +104,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -2548,6 +2549,10 @@ Dialect getDialect() { } } + Future getDialectAsync() { + return executor.submit(this::getDialect); + } + PooledSessionReplacementHandler getPooledSessionReplacementHandler() { return pooledSessionReplacementHandler; } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerApiFutures.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerApiFutures.java index 39afc1b81a4..fb55378aa56 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerApiFutures.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerApiFutures.java @@ -35,9 +35,10 @@ public static T getOrNull(ApiFuture future) throws SpannerException { } throw SpannerExceptionFactory.newSpannerException(e.getCause()); } catch (InterruptedException e) { - throw SpannerExceptionFactory.propagateInterrupt(e); + throw SpannerExceptionFactory.propagateInterrupt(e, null /*TODO: requestId*/); } catch (CancellationException e) { - throw SpannerExceptionFactory.newSpannerExceptionForCancellation(null, e); + throw SpannerExceptionFactory.newSpannerExceptionForCancellation( + null, e, null /*TODO: requestId*/); } } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerBatchUpdateException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerBatchUpdateException.java index 0e51c5f91f3..0d841d24463 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerBatchUpdateException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerBatchUpdateException.java @@ -17,11 +17,17 @@ package com.google.cloud.spanner; public class SpannerBatchUpdateException extends SpannerException { - private long[] updateCounts; + private final long[] updateCounts; + /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ SpannerBatchUpdateException( - DoNotConstructDirectly token, ErrorCode code, String message, long[] counts) { - super(token, code, false, message, null); + DoNotConstructDirectly token, + ErrorCode code, + String message, + long[] counts, + Throwable cause, + XGoogSpannerRequestId reqId) { + super(token, code, false, message, cause, null, reqId); updateCounts = counts; } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporter.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporter.java index f9c91b91833..35503fff337 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporter.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporter.java @@ -16,8 +16,6 @@ package com.google.cloud.spanner; -import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_METRICS; - import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutureCallback; import com.google.api.core.ApiFutures; @@ -39,8 +37,8 @@ import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; import io.opentelemetry.sdk.metrics.data.MetricData; -import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.export.MetricExporter; +import io.opentelemetry.sdk.resources.Resource; import java.io.IOException; import java.time.Duration; import java.util.ArrayList; @@ -114,27 +112,19 @@ public CompletableResultCode export(@Nonnull Collection collection) /** Export client built in metrics */ private CompletableResultCode exportSpannerClientMetrics(Collection collection) { - // Filter spanner metrics. Only include metrics that contain a project and instance ID. - List spannerMetricData = - collection.stream() - .filter(md -> SPANNER_METRICS.contains(md.getName())) - .collect(Collectors.toList()); + // Filter spanner metrics. Only include metrics that contain a valid project. + List spannerMetricData = collection.stream().collect(Collectors.toList()); // Log warnings for metrics that will be skipped. boolean mustFilter = false; if (spannerMetricData.stream() - .flatMap(metricData -> metricData.getData().getPoints().stream()) + .map(metricData -> metricData.getResource()) .anyMatch(this::shouldSkipPointDataDueToProjectId)) { logger.log( Level.WARNING, "Some metric data contain a different projectId. These will be skipped."); mustFilter = true; } - if (spannerMetricData.stream() - .flatMap(metricData -> metricData.getData().getPoints().stream()) - .anyMatch(this::shouldSkipPointDataDueToMissingInstanceId)) { - logger.log(Level.WARNING, "Some metric data miss instanceId. These will be skipped."); - mustFilter = true; - } + if (mustFilter) { spannerMetricData = spannerMetricData.stream() @@ -198,19 +188,11 @@ public void onSuccess(List empty) { } private boolean shouldSkipMetricData(MetricData metricData) { - return metricData.getData().getPoints().stream() - .anyMatch( - pd -> - shouldSkipPointDataDueToProjectId(pd) - || shouldSkipPointDataDueToMissingInstanceId(pd)); - } - - private boolean shouldSkipPointDataDueToProjectId(PointData pointData) { - return !spannerProjectId.equals(SpannerCloudMonitoringExporterUtils.getProjectId(pointData)); + return shouldSkipPointDataDueToProjectId(metricData.getResource()); } - private boolean shouldSkipPointDataDueToMissingInstanceId(PointData pointData) { - return SpannerCloudMonitoringExporterUtils.getInstanceId(pointData) == null; + private boolean shouldSkipPointDataDueToProjectId(Resource resource) { + return !spannerProjectId.equals(SpannerCloudMonitoringExporterUtils.getProjectId(resource)); } boolean lastExportSkippedData() { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java index 620430b87df..f67621db963 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java @@ -23,7 +23,7 @@ import static com.google.api.MetricDescriptor.ValueType.DOUBLE; import static com.google.api.MetricDescriptor.ValueType.INT64; import static com.google.cloud.spanner.BuiltInMetricsConstant.GAX_METER_NAME; -import static com.google.cloud.spanner.BuiltInMetricsConstant.INSTANCE_ID_KEY; +import static com.google.cloud.spanner.BuiltInMetricsConstant.GRPC_METER_NAME; import static com.google.cloud.spanner.BuiltInMetricsConstant.PROJECT_ID_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_METER_NAME; import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_PROMOTED_RESOURCE_LABELS; @@ -52,6 +52,7 @@ import io.opentelemetry.sdk.metrics.data.MetricDataType; import io.opentelemetry.sdk.metrics.data.PointData; import io.opentelemetry.sdk.metrics.data.SumData; +import io.opentelemetry.sdk.resources.Resource; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -64,34 +65,45 @@ class SpannerCloudMonitoringExporterUtils { private SpannerCloudMonitoringExporterUtils() {} - static String getProjectId(PointData pointData) { - return pointData.getAttributes().get(PROJECT_ID_KEY); - } - - static String getInstanceId(PointData pointData) { - return pointData.getAttributes().get(INSTANCE_ID_KEY); + static String getProjectId(Resource resource) { + return resource.getAttributes().get(PROJECT_ID_KEY); } static List convertToSpannerTimeSeries(List collection) { List allTimeSeries = new ArrayList<>(); for (MetricData metricData : collection) { - // Get metrics data from GAX library and Spanner library + // Get metrics data from GAX library, GRPC library and Spanner library if (!(metricData.getInstrumentationScopeInfo().getName().equals(GAX_METER_NAME) - || metricData.getInstrumentationScopeInfo().getName().equals(SPANNER_METER_NAME))) { + || metricData.getInstrumentationScopeInfo().getName().equals(SPANNER_METER_NAME) + || metricData.getInstrumentationScopeInfo().getName().equals(GRPC_METER_NAME))) { // Filter out metric data for instruments that are not part of the spanner metrics list continue; } + + // Create MonitoredResource Builder + MonitoredResource.Builder monitoredResourceBuilder = + MonitoredResource.newBuilder().setType(SPANNER_RESOURCE_TYPE); + + Attributes resourceAttributes = metricData.getResource().getAttributes(); + for (AttributeKey key : resourceAttributes.asMap().keySet()) { + monitoredResourceBuilder.putLabels( + key.getKey(), String.valueOf(resourceAttributes.get(key))); + } + metricData.getData().getPoints().stream() - .map(pointData -> convertPointToSpannerTimeSeries(metricData, pointData)) + .map( + pointData -> + convertPointToSpannerTimeSeries(metricData, pointData, monitoredResourceBuilder)) .forEach(allTimeSeries::add); } - return allTimeSeries; } private static TimeSeries convertPointToSpannerTimeSeries( - MetricData metricData, PointData pointData) { + MetricData metricData, + PointData pointData, + MonitoredResource.Builder monitoredResourceBuilder) { TimeSeries.Builder builder = TimeSeries.newBuilder() .setMetricKind(convertMetricKind(metricData)) @@ -99,17 +111,21 @@ private static TimeSeries convertPointToSpannerTimeSeries( Metric.Builder metricBuilder = Metric.newBuilder().setType(metricData.getName()); Attributes attributes = pointData.getAttributes(); - MonitoredResource.Builder monitoredResourceBuilder = - MonitoredResource.newBuilder().setType(SPANNER_RESOURCE_TYPE); for (AttributeKey key : attributes.asMap().keySet()) { if (SPANNER_PROMOTED_RESOURCE_LABELS.contains(key)) { monitoredResourceBuilder.putLabels(key.getKey(), String.valueOf(attributes.get(key))); } else { - metricBuilder.putLabels(key.getKey(), String.valueOf(attributes.get(key))); + // Replace metric label names by converting "." to "_" since Cloud Monitoring does not + // support labels containing "." + metricBuilder.putLabels( + key.getKey().replace(".", "_"), String.valueOf(attributes.get(key))); } } + // Add common labels like "client_name" and "client_uid" for all the exported metrics. + metricBuilder.putAllLabels(BuiltInMetricsProvider.INSTANCE.createClientAttributes()); + builder.setResource(monitoredResourceBuilder.build()); builder.setMetric(metricBuilder.build()); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerException.java index 58076570c20..22a5270cef7 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerException.java @@ -40,8 +40,9 @@ public abstract static class ResourceNotFoundException extends SpannerException @Nullable String message, ResourceInfo resourceInfo, @Nullable Throwable cause, - @Nullable ApiException apiException) { - super(token, ErrorCode.NOT_FOUND, /* retryable */ false, message, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, ErrorCode.NOT_FOUND, /* retryable */ false, message, cause, apiException, reqId); this.resourceInfo = resourceInfo; } @@ -56,6 +57,7 @@ public String getResourceName() { private final ErrorCode code; private final ApiException apiException; + private final XGoogSpannerRequestId requestId; /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ SpannerException( @@ -75,12 +77,25 @@ public String getResourceName() { @Nullable String message, @Nullable Throwable cause, @Nullable ApiException apiException) { + this(token, code, retryable, message, cause, apiException, null); + } + + /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ + SpannerException( + DoNotConstructDirectly token, + ErrorCode code, + boolean retryable, + @Nullable String message, + @Nullable Throwable cause, + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId requestId) { super(message, cause, code.getCode(), retryable); if (token != DoNotConstructDirectly.ALLOWED) { throw new AssertionError("Do not construct directly: use SpannerExceptionFactory"); } this.code = Preconditions.checkNotNull(code); this.apiException = apiException; + this.requestId = requestId; } /** Returns the error code associated with this exception. */ @@ -88,6 +103,13 @@ public ErrorCode getErrorCode() { return code; } + public String getRequestId() { + if (requestId == null) { + return ""; + } + return requestId.toString(); + } + enum DoNotConstructDirectly { ALLOWED } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java index 6476b94b144..941f3b405b6 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java @@ -58,17 +58,37 @@ public final class SpannerExceptionFactory { ProtoUtils.keyForProto(ErrorInfo.getDefaultInstance()); public static SpannerException newSpannerException(ErrorCode code, @Nullable String message) { - return newSpannerException(code, message, null); + return newSpannerException(code, message, (XGoogSpannerRequestId) (null)); + } + + public static SpannerException newSpannerException( + ErrorCode code, + @Nullable String message, + @Nullable Throwable cause, + @Nullable XGoogSpannerRequestId reqId) { + return newSpannerExceptionPreformatted( + code, formatMessage(code, message), cause, (ApiException) (null), reqId); + } + + public static SpannerException newSpannerException( + ErrorCode code, @Nullable String message, @Nullable XGoogSpannerRequestId reqId) { + return newSpannerException(code, message, (Throwable) (null), reqId); } public static SpannerException newSpannerException( ErrorCode code, @Nullable String message, @Nullable Throwable cause) { - return newSpannerExceptionPreformatted(code, formatMessage(code, message), cause); + return newSpannerException(code, message, cause, null); } public static SpannerException propagateInterrupt(InterruptedException e) { + return propagateInterrupt(e, null); + } + + public static SpannerException propagateInterrupt( + InterruptedException e, XGoogSpannerRequestId reqId) { Thread.currentThread().interrupt(); - return SpannerExceptionFactory.newSpannerException(ErrorCode.CANCELLED, "Interrupted", e); + return SpannerExceptionFactory.newSpannerException( + ErrorCode.CANCELLED, "Interrupted", e, reqId); } /** @@ -112,13 +132,27 @@ public static SpannerException asSpannerException(Throwable t) { * #newSpannerException(ErrorCode, String)} instead of this method. */ public static SpannerException newSpannerException(Throwable cause) { - return newSpannerException(null, cause); + return newSpannerException(null, cause, null); + } + + public static SpannerException newSpannerException(Throwable cause, XGoogSpannerRequestId reqId) { + return newSpannerException(null, cause, reqId); } public static SpannerBatchUpdateException newSpannerBatchUpdateException( ErrorCode code, String message, long[] updateCounts) { + return newSpannerBatchUpdateException(code, message, updateCounts, null); + } + + public static SpannerBatchUpdateException newSpannerBatchUpdateException( + ErrorCode code, String message, long[] updateCounts, @Nullable XGoogSpannerRequestId reqId) { DoNotConstructDirectly token = DoNotConstructDirectly.ALLOWED; - return new SpannerBatchUpdateException(token, code, message, updateCounts); + SpannerException cause = null; + if (isTransactionMutationLimitException(code, message)) { + cause = + new TransactionMutationLimitExceededException(token, code, message, null, null, reqId); + } + return new SpannerBatchUpdateException(token, code, message, updateCounts, cause, reqId); } /** Constructs a specific error that */ @@ -169,6 +203,10 @@ public static SpannerBatchUpdateException newSpannerBatchUpdateException( cause); } + public static SpannerException newSpannerException(@Nullable Context context, Throwable cause) { + return newSpannerException(context, cause, null); + } + /** * Creates a new exception based on {@code cause}. If {@code cause} indicates cancellation, {@code * context} will be inspected to establish the type of cancellation. @@ -176,21 +214,22 @@ public static SpannerBatchUpdateException newSpannerBatchUpdateException( *

Intended for internal library use; user code should use {@link * #newSpannerException(ErrorCode, String)} instead of this method. */ - public static SpannerException newSpannerException(@Nullable Context context, Throwable cause) { + public static SpannerException newSpannerException( + @Nullable Context context, Throwable cause, @Nullable XGoogSpannerRequestId reqId) { if (cause instanceof SpannerException) { SpannerException e = (SpannerException) cause; - return newSpannerExceptionPreformatted(e.getErrorCode(), e.getMessage(), e); + return newSpannerExceptionPreformatted(e.getErrorCode(), e.getMessage(), e, null, reqId); } else if (cause instanceof CancellationException) { - return newSpannerExceptionForCancellation(context, cause); + return newSpannerExceptionForCancellation(context, cause, reqId); } else if (cause instanceof ApiException) { - return fromApiException((ApiException) cause); + return fromApiException((ApiException) cause, reqId); } // Extract gRPC status. This will produce "UNKNOWN" for non-gRPC exceptions. Status status = Status.fromThrowable(cause); if (status.getCode() == Status.Code.CANCELLED) { - return newSpannerExceptionForCancellation(context, cause); + return newSpannerExceptionForCancellation(context, cause, reqId); } - return newSpannerException(ErrorCode.fromGrpcStatus(status), cause.getMessage(), cause); + return newSpannerException(ErrorCode.fromGrpcStatus(status), cause.getMessage(), cause, reqId); } public static RuntimeException causeAsRunTimeException(ExecutionException executionException) { @@ -215,6 +254,11 @@ static SpannerException newRetryOnDifferentGrpcChannelException( static SpannerException newSpannerExceptionForCancellation( @Nullable Context context, @Nullable Throwable cause) { + return newSpannerExceptionForCancellation(context, cause, null); + } + + static SpannerException newSpannerExceptionForCancellation( + @Nullable Context context, @Nullable Throwable cause, @Nullable XGoogSpannerRequestId reqId) { if (context != null && context.isCancelled()) { Throwable cancellationCause = context.cancellationCause(); Throwable throwable = @@ -223,13 +267,14 @@ static SpannerException newSpannerExceptionForCancellation( : MoreObjects.firstNonNull(cause, cancellationCause); if (cancellationCause instanceof TimeoutException) { return newSpannerException( - ErrorCode.DEADLINE_EXCEEDED, "Current context exceeded deadline", throwable); + ErrorCode.DEADLINE_EXCEEDED, "Current context exceeded deadline", throwable, reqId); } else { - return newSpannerException(ErrorCode.CANCELLED, "Current context was cancelled", throwable); + return newSpannerException( + ErrorCode.CANCELLED, "Current context was cancelled", throwable, reqId); } } return newSpannerException( - ErrorCode.CANCELLED, cause == null ? "Cancelled" : cause.getMessage(), cause); + ErrorCode.CANCELLED, cause == null ? "Cancelled" : cause.getMessage(), cause, reqId); } private static String formatMessage(ErrorCode code, @Nullable String message) { @@ -301,12 +346,13 @@ static SpannerException newSpannerExceptionPreformatted( ErrorCode code, @Nullable String message, @Nullable Throwable cause, - @Nullable ApiException apiException) { + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { // This is the one place in the codebase that is allowed to call constructors directly. DoNotConstructDirectly token = DoNotConstructDirectly.ALLOWED; switch (code) { case ABORTED: - return new AbortedException(token, message, cause, apiException); + return new AbortedException(token, message, cause, apiException, reqId); case RESOURCE_EXHAUSTED: ErrorInfo info = extractErrorInfo(cause); if (info != null @@ -315,7 +361,8 @@ static SpannerException newSpannerExceptionPreformatted( && AdminRequestsPerMinuteExceededException.ADMIN_REQUESTS_LIMIT_VALUE.equals( info.getMetadataMap() .get(AdminRequestsPerMinuteExceededException.ADMIN_REQUESTS_LIMIT_KEY))) { - return new AdminRequestsPerMinuteExceededException(token, message, cause, apiException); + return new AdminRequestsPerMinuteExceededException( + token, message, cause, apiException, reqId); } case NOT_FOUND: ResourceInfo resourceInfo = extractResourceInfo(cause); @@ -323,36 +370,39 @@ static SpannerException newSpannerExceptionPreformatted( switch (resourceInfo.getResourceType()) { case SESSION_RESOURCE_TYPE: return new SessionNotFoundException( - token, message, resourceInfo, cause, apiException); + token, message, resourceInfo, cause, apiException, reqId); case DATABASE_RESOURCE_TYPE: return new DatabaseNotFoundException( - token, message, resourceInfo, cause, apiException); + token, message, resourceInfo, cause, apiException, reqId); case INSTANCE_RESOURCE_TYPE: return new InstanceNotFoundException( - token, message, resourceInfo, cause, apiException); + token, message, resourceInfo, cause, apiException, reqId); } } case INVALID_ARGUMENT: if (isTransactionMutationLimitException(cause)) { return new TransactionMutationLimitExceededException( - token, code, message, cause, apiException); + token, code, message, cause, apiException, reqId); } if (isMissingDefaultSequenceKindException(apiException)) { - return new MissingDefaultSequenceKindException(token, code, message, cause, apiException); + return new MissingDefaultSequenceKindException( + token, code, message, cause, apiException, reqId); } // Fall through to the default. default: return new SpannerException( - token, code, isRetryable(code, cause), message, cause, apiException); + token, code, isRetryable(code, cause), message, cause, apiException, reqId); } } static SpannerException newSpannerExceptionPreformatted( ErrorCode code, @Nullable String message, @Nullable Throwable cause) { - return newSpannerExceptionPreformatted(code, message, cause, null); + return newSpannerExceptionPreformatted( + code, message, cause, null, (XGoogSpannerRequestId) (null)); } - private static SpannerException fromApiException(ApiException exception) { + private static SpannerException fromApiException( + ApiException exception, @Nullable XGoogSpannerRequestId reqId) { Status.Code code; if (exception.getStatusCode() instanceof GrpcStatusCode) { code = ((GrpcStatusCode) exception.getStatusCode()).getTransportCode(); @@ -367,7 +417,8 @@ private static SpannerException fromApiException(ApiException exception) { errorCode, formatMessage(errorCode, exception.getMessage()), exception.getCause(), - exception); + exception, + reqId); } private static boolean isRetryable(ErrorCode code, @Nullable Throwable cause) { 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 695e156dfc3..8a9c5050d13 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 @@ -27,6 +27,7 @@ import com.google.api.gax.core.GaxProperties; import com.google.api.gax.grpc.GrpcCallContext; import com.google.api.gax.grpc.GrpcInterceptorProvider; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.api.gax.longrunning.OperationTimedPollAlgorithm; import com.google.api.gax.retrying.RetrySettings; import com.google.api.gax.rpc.ApiCallContext; @@ -848,6 +849,10 @@ default boolean isEnableBuiltInMetrics() { return true; } + default boolean isEnableGRPCBuiltInMetrics() { + return false; + } + default boolean isEnableEndToEndTracing() { return false; } @@ -878,6 +883,8 @@ private static class SpannerEnvironmentImpl implements SpannerEnvironment { private static final String SPANNER_ENABLE_END_TO_END_TRACING = "SPANNER_ENABLE_END_TO_END_TRACING"; private static final String SPANNER_DISABLE_BUILTIN_METRICS = "SPANNER_DISABLE_BUILTIN_METRICS"; + private static final String SPANNER_DISABLE_DIRECT_ACCESS_GRPC_BUILTIN_METRICS = + "SPANNER_DISABLE_DIRECT_ACCESS_GRPC_BUILTIN_METRICS"; private static final String SPANNER_MONITORING_HOST = "SPANNER_MONITORING_HOST"; private SpannerEnvironmentImpl() {} @@ -910,6 +917,12 @@ public boolean isEnableBuiltInMetrics() { return !Boolean.parseBoolean(System.getenv(SPANNER_DISABLE_BUILTIN_METRICS)); } + @Override + public boolean isEnableGRPCBuiltInMetrics() { + return "false" + .equalsIgnoreCase(System.getenv(SPANNER_DISABLE_DIRECT_ACCESS_GRPC_BUILTIN_METRICS)); + } + @Override public boolean isEnableEndToEndTracing() { return Boolean.parseBoolean(System.getenv(SPANNER_ENABLE_END_TO_END_TRACING)); @@ -1971,6 +1984,13 @@ public ApiTracerFactory getApiTracerFactory() { return createApiTracerFactory(false, false); } + public void enablegRPCMetrics(InstantiatingGrpcChannelProvider.Builder channelProviderBuilder) { + if (SpannerOptions.environment.isEnableGRPCBuiltInMetrics()) { + this.builtInMetricsProvider.enableGrpcMetrics( + channelProviderBuilder, this.getProjectId(), getCredentials(), this.monitoringHost); + } + } + public ApiTracerFactory getApiTracerFactory(boolean isAdminClient, boolean isEmulatorEnabled) { return createApiTracerFactory(isAdminClient, isEmulatorEnabled); } @@ -2018,8 +2038,7 @@ private ApiTracerFactory createMetricsApiTracerFactory() { return openTelemetry != null ? new BuiltInMetricsTracerFactory( new BuiltInMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME), - builtInMetricsProvider.createClientAttributes( - this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass()))) + new HashMap<>()) : null; } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerRetryHelper.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerRetryHelper.java index 5fb35513222..48aff4cbee7 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerRetryHelper.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerRetryHelper.java @@ -120,7 +120,8 @@ public TimedAttemptSettings createNextAttempt( public boolean shouldRetry(Throwable prevThrowable, T prevResponse) throws CancellationException { if (Context.current().isCancelled()) { - throw SpannerExceptionFactory.newSpannerExceptionForCancellation(Context.current(), null); + throw SpannerExceptionFactory.newSpannerExceptionForCancellation( + Context.current(), null, null); } return prevThrowable instanceof AbortedException || prevThrowable instanceof com.google.api.gax.rpc.AbortedException; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerTypeConverter.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerTypeConverter.java new file mode 100644 index 00000000000..02c0cc213d6 --- /dev/null +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerTypeConverter.java @@ -0,0 +1,111 @@ +/* + * Copyright 2025 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 + * + * https://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.cloud.Date; +import com.google.protobuf.ListValue; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +final class SpannerTypeConverter { + + private static final ZoneId UTC_ZONE = ZoneId.of("UTC"); + private static final DateTimeFormatter ISO_8601_DATE_FORMATTER = + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX"); + + static Value createUntypedArrayValue(Stream stream) { + List values = + stream + .map( + val -> + com.google.protobuf.Value.newBuilder() + .setStringValue(String.valueOf(val)) + .build()) + .collect(Collectors.toList()); + return Value.untyped( + com.google.protobuf.Value.newBuilder() + .setListValue(ListValue.newBuilder().addAllValues(values).build()) + .build()); + } + + static String convertToISO8601(T dateTime) { + return ISO_8601_DATE_FORMATTER.format(dateTime); + } + + static Value createUntypedStringValue(T value) { + return Value.untyped( + com.google.protobuf.Value.newBuilder().setStringValue(String.valueOf(value)).build()); + } + + static Iterable convertToTypedIterable( + Function func, T val, Iterator iterator) { + List values = new ArrayList<>(); + SpannerTypeConverter.processIterable(val, iterator, func, values::add); + return values; + } + + static Iterable convertToTypedIterable(T val, Iterator iterator) { + return convertToTypedIterable(v -> v, val, iterator); + } + + @SuppressWarnings("unchecked") + static void processIterable( + T val, Iterator iterator, Function func, Consumer consumer) { + consumer.accept(func.apply(val)); + iterator.forEachRemaining(values -> consumer.accept(func.apply((T) values))); + } + + static Date convertLocalDateToSpannerDate(LocalDate date) { + return Date.fromYearMonthDay(date.getYear(), date.getMonthValue(), date.getDayOfMonth()); + } + + static Value createUntypedIterableValue( + T value, Iterator iterator, Function func) { + ListValue.Builder listValueBuilder = ListValue.newBuilder(); + SpannerTypeConverter.processIterable( + value, + iterator, + (val) -> com.google.protobuf.Value.newBuilder().setStringValue(func.apply(val)).build(), + listValueBuilder::addValues); + return Value.untyped( + com.google.protobuf.Value.newBuilder().setListValue(listValueBuilder.build()).build()); + } + + static ZonedDateTime atUTC(LocalDateTime localDateTime) { + return atUTC(localDateTime.atZone(ZoneId.systemDefault())); + } + + static ZonedDateTime atUTC(OffsetDateTime localDateTime) { + return localDateTime.atZoneSameInstant(UTC_ZONE); + } + + static ZonedDateTime atUTC(ZonedDateTime localDateTime) { + return localDateTime.withZoneSameInstant(UTC_ZONE); + } +} 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 a89c7c048fc..9c4b1707c2f 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 @@ -20,7 +20,10 @@ import static com.google.common.base.Preconditions.checkState; import com.google.cloud.spanner.ReadContext.QueryAnalyzeMode; +import com.google.cloud.spanner.connection.AbstractStatementParser; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParametersInfo; 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; @@ -140,7 +143,12 @@ Builder handle(Value value) { /** Creates a {@code Statement} with the given SQL text {@code sql}. */ public static Statement of(String sql) { - return newBuilder(sql).build(); + return new Statement(sql, ImmutableMap.of(), /*queryOptions=*/ null); + } + + /** Creates a {@link Statement} with the given SQL text and parameters. */ + public static Statement of(String sql, ImmutableMap parameters) { + return new Statement(sql, parameters, /*queryOptions=*/ null); } /** Creates a new statement builder with the SQL text {@code sql}. */ @@ -245,4 +253,103 @@ StringBuilder toString(StringBuilder b) { } return b; } + + /** + * Factory for creating {@link Statement}s with unnamed parameters. + * + *

This class is primarily intended for framework developers who want to integrate the Spanner + * client with a framework that uses unnamed parameters. Developers who want to use the Spanner + * client in their application, should use named parameters. + * + *

+ * + *

Usage Example

+ * + * Simple SQL query + * + *
{@code
+   * Statement statement = databaseClient.getStatementFactory()
+   *     .withUnnamedParameters("SELECT * FROM TABLE WHERE ID = ?", 10L)
+   * }
+ * + * SQL query with multiple parameters + * + *
{@code
+   * long id = 10L;
+   * String name = "google";
+   * List phoneNumbers = Arrays.asList("1234567890", "0987654321");
+   * Statement statement = databaseClient.getStatementFactory()
+   *      .withUnnamedParameters("INSERT INTO TABLE (ID, name, phonenumbers) VALUES(?, ?, ?)", id, name, phoneNumbers)
+   * }
+ * + * How to use arrays with the IN operator + * + *
{@code
+   * long[] ids = {10L, 12L, 1483L};
+   * Statement statement = databaseClient.getStatementFactory()
+   *     .withUnnamedParameters("SELECT * FROM TABLE WHERE ID = UNNEST(?)", ids)
+   * }
+ * + * @see DatabaseClient#getStatementFactory() + * @see StatementFactory#withUnnamedParameters(String, Object...) + */ + public static final class StatementFactory { + private final Dialect dialect; + + StatementFactory(Dialect dialect) { + this.dialect = dialect; + } + + public Statement of(String sql) { + return Statement.of(sql); + } + + /** + * This function accepts a SQL statement with unnamed parameters (?) and accepts a list of + * objects that should be used as the values for those parameters. Primitive types are + * supported. + * + *

For parameters of type DATE, the following types are supported + * + *

    + *
  • {@link java.time.LocalDate} + *
  • {@link com.google.cloud.Date} + *
+ * + *

For parameters of type TIMESTAMP, the following types are supported. Note that Spanner + * stores all timestamps in UTC. Instances of ZonedDateTime and OffsetDateTime that use other + * timezones than UTC, will be converted to the corresponding UTC values before being sent to + * Spanner. Instances of LocalDateTime will be converted to a ZonedDateTime using the system + * default timezone, and then converted to UTC before being sent to Spanner. + * + *

    + *
  • {@link java.time.LocalDateTime} + *
  • {@link java.time.OffsetDateTime} + *
  • {@link java.time.ZonedDateTime} + *
+ * + *

+ * + * @param sql SQL statement with unnamed parameters denoted as ? + * @param values positional list of values for the unnamed parameters in the SQL string + * @return Statement a statement that can be executed on Spanner + * @see DatabaseClient#getStatementFactory + */ + public Statement withUnnamedParameters(String sql, Object... values) { + Map parameters = getUnnamedParametersMap(values); + AbstractStatementParser statementParser = AbstractStatementParser.getInstance(this.dialect); + ParametersInfo parametersInfo = + statementParser.convertPositionalParametersToNamedParameters('?', sql); + return new Statement(parametersInfo.sqlWithNamedParameters, parameters, null); + } + + private Map getUnnamedParametersMap(Object[] values) { + Map parameters = new HashMap<>(); + int index = 1; + for (Object value : values) { + parameters.put("p" + (index++), Value.toValue(value)); + } + return parameters; + } + } } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionMutationLimitExceededException.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionMutationLimitExceededException.java index 1b63861bcd1..1fab7346ca7 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionMutationLimitExceededException.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionMutationLimitExceededException.java @@ -26,20 +26,27 @@ public class TransactionMutationLimitExceededException extends SpannerException { private static final long serialVersionUID = 1L; + private static final String ERROR_MESSAGE = "The transaction contains too many mutations."; + /** Private constructor. Use {@link SpannerExceptionFactory} to create instances. */ TransactionMutationLimitExceededException( DoNotConstructDirectly token, ErrorCode errorCode, String message, Throwable cause, - @Nullable ApiException apiException) { - super(token, errorCode, /*retryable = */ false, message, cause, apiException); + @Nullable ApiException apiException, + @Nullable XGoogSpannerRequestId reqId) { + super(token, errorCode, /*retryable = */ false, message, cause, apiException, reqId); + } + + static boolean isTransactionMutationLimitException(ErrorCode code, String message) { + return code == ErrorCode.INVALID_ARGUMENT && message != null && message.contains(ERROR_MESSAGE); } static boolean isTransactionMutationLimitException(Throwable cause) { if (cause == null || cause.getMessage() == null - || !cause.getMessage().contains("The transaction contains too many mutations.")) { + || !cause.getMessage().contains(ERROR_MESSAGE)) { return false; } // Spanner includes a hint that points to the Spanner limits documentation page when the error diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java index 038fb4b52eb..a715fae0fad 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionRunnerImpl.java @@ -685,7 +685,8 @@ options, getPreviousTransactionId()))) } throw se; } catch (InterruptedException e) { - throw SpannerExceptionFactory.newSpannerExceptionForCancellation(null, e); + throw SpannerExceptionFactory.newSpannerExceptionForCancellation( + null, e, null /*TODO: requestId*/); } } // There is already a transactionId available. Include that id as the transaction to use. @@ -1070,11 +1071,12 @@ public long[] batchUpdate(Iterable statements, UpdateOption... update // In all other cases, we should throw a BatchUpdateException. if (response.getStatus().getCode() == Code.ABORTED_VALUE) { throw createAbortedExceptionForBatchDml(response); - } else if (response.getStatus().getCode() != 0) { + } else if (response.getStatus().getCode() != Code.OK_VALUE) { throw newSpannerBatchUpdateException( ErrorCode.fromRpcStatus(response.getStatus()), response.getStatus().getMessage(), - results); + results, + null /*TODO: requestId*/); } return results; } catch (Throwable e) { @@ -1137,11 +1139,12 @@ public ApiFuture batchUpdateAsync( // In all other cases, we should throw a BatchUpdateException. if (batchDmlResponse.getStatus().getCode() == Code.ABORTED_VALUE) { throw createAbortedExceptionForBatchDml(batchDmlResponse); - } else if (batchDmlResponse.getStatus().getCode() != 0) { + } else if (batchDmlResponse.getStatus().getCode() != Code.OK_VALUE) { throw newSpannerBatchUpdateException( ErrorCode.fromRpcStatus(batchDmlResponse.getStatus()), batchDmlResponse.getStatus().getMessage(), - results); + results, + null /*TODO: requestId*/); } return results; }, 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 6cb68eeee4a..5befba04e57 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 @@ -16,6 +16,14 @@ package com.google.cloud.spanner; +import static com.google.cloud.spanner.SpannerTypeConverter.atUTC; +import static com.google.cloud.spanner.SpannerTypeConverter.convertLocalDateToSpannerDate; +import static com.google.cloud.spanner.SpannerTypeConverter.convertToISO8601; +import static com.google.cloud.spanner.SpannerTypeConverter.convertToTypedIterable; +import static com.google.cloud.spanner.SpannerTypeConverter.createUntypedArrayValue; +import static com.google.cloud.spanner.SpannerTypeConverter.createUntypedIterableValue; +import static com.google.cloud.spanner.SpannerTypeConverter.createUntypedStringValue; + import com.google.cloud.ByteArray; import com.google.cloud.Date; import com.google.cloud.Timestamp; @@ -39,16 +47,22 @@ import java.io.Serializable; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.BitSet; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; @@ -824,6 +838,159 @@ public static Value structArray(Type elementType, @Nullable Iterable v) private Value() {} + static Value toValue(Object value) { + if (value == null) { + return Value.untyped(NULL_PROTO); + } + if (value instanceof Value) { + return (Value) value; + } + if (value instanceof Boolean) { + return Value.bool((Boolean) value); + } + if (value instanceof Long || value instanceof Integer) { + return createUntypedStringValue(String.valueOf(value)); + } + if (value instanceof Float) { + return Value.float32((Float) value); + } + if (value instanceof Double) { + return Value.float64((Double) value); + } + if (value instanceof BigDecimal) { + return Value.numeric((BigDecimal) value); + } + if (value instanceof ByteArray) { + return Value.bytes((ByteArray) value); + } + if (value instanceof byte[]) { + return Value.bytes(ByteArray.copyFrom((byte[]) value)); + } + if (value instanceof Date) { + return Value.date((Date) value); + } + if (value instanceof LocalDate) { + return Value.date(convertLocalDateToSpannerDate((LocalDate) value)); + } + if (value instanceof LocalDateTime) { + return createUntypedStringValue(convertToISO8601(atUTC((LocalDateTime) value))); + } + if (value instanceof OffsetDateTime) { + return createUntypedStringValue(convertToISO8601(atUTC((OffsetDateTime) value))); + } + if (value instanceof ZonedDateTime) { + return createUntypedStringValue(convertToISO8601(atUTC((ZonedDateTime) value))); + } + if (value instanceof ProtocolMessageEnum) { + return Value.protoEnum((ProtocolMessageEnum) value); + } + if (value instanceof AbstractMessage) { + return Value.protoMessage((AbstractMessage) value); + } + if (value instanceof Interval) { + return Value.interval((Interval) value); + } + if (value instanceof Struct) { + return Value.struct((Struct) value); + } + if (value instanceof Timestamp) { + return Value.timestamp((Timestamp) value); + } + if (value instanceof Iterable) { + Iterator iterator = ((Iterable) value).iterator(); + if (!iterator.hasNext()) { + return createUntypedArrayValue(Stream.empty()); + } + Object object = iterator.next(); + if (object instanceof Boolean) { + return Value.boolArray(convertToTypedIterable((Boolean) object, iterator)); + } + if (object instanceof Integer) { + return createUntypedIterableValue((Integer) object, iterator, String::valueOf); + } + if (object instanceof Long) { + return createUntypedIterableValue((Long) object, iterator, String::valueOf); + } + if (object instanceof Float) { + return Value.float32Array(convertToTypedIterable((Float) object, iterator)); + } + if (object instanceof Double) { + return Value.float64Array(convertToTypedIterable((Double) object, iterator)); + } + if (object instanceof BigDecimal) { + return Value.numericArray(convertToTypedIterable((BigDecimal) object, iterator)); + } + if (object instanceof ByteArray) { + return Value.bytesArray(convertToTypedIterable((ByteArray) object, iterator)); + } + if (object instanceof byte[]) { + return Value.bytesArray( + SpannerTypeConverter.convertToTypedIterable( + ByteArray::copyFrom, (byte[]) object, iterator)); + } + if (object instanceof Interval) { + return Value.intervalArray(convertToTypedIterable((Interval) object, iterator)); + } + if (object instanceof Timestamp) { + return Value.timestampArray(convertToTypedIterable((Timestamp) object, iterator)); + } + if (object instanceof Date) { + return Value.dateArray(convertToTypedIterable((Date) object, iterator)); + } + if (object instanceof LocalDate) { + return Value.dateArray( + SpannerTypeConverter.convertToTypedIterable( + SpannerTypeConverter::convertLocalDateToSpannerDate, (LocalDate) object, iterator)); + } + if (object instanceof LocalDateTime) { + return createUntypedIterableValue( + (LocalDateTime) object, iterator, val -> convertToISO8601(atUTC(val))); + } + if (object instanceof OffsetDateTime) { + return createUntypedIterableValue( + (OffsetDateTime) object, iterator, val -> convertToISO8601(atUTC(val))); + } + if (object instanceof ZonedDateTime) { + return createUntypedIterableValue( + (ZonedDateTime) object, iterator, val -> convertToISO8601(atUTC(val))); + } + } + + // array and primitive array + if (value instanceof Boolean[]) { + return Value.boolArray(Arrays.asList((Boolean[]) value)); + } + if (value instanceof boolean[]) { + return Value.boolArray((boolean[]) value); + } + if (value instanceof Float[]) { + return Value.float32Array(Arrays.asList((Float[]) value)); + } + if (value instanceof float[]) { + return Value.float32Array((float[]) value); + } + if (value instanceof Double[]) { + return Value.float64Array(Arrays.asList((Double[]) value)); + } + if (value instanceof double[]) { + return Value.float64Array((double[]) value); + } + if (value instanceof Long[]) { + return createUntypedArrayValue(Arrays.stream((Long[]) value)); + } + if (value instanceof long[]) { + return createUntypedArrayValue(Arrays.stream((long[]) value).boxed()); + } + if (value instanceof Integer[]) { + return createUntypedArrayValue(Arrays.stream((Integer[]) value)); + } + if (value instanceof int[]) { + return createUntypedArrayValue(Arrays.stream((int[]) value).boxed()); + } + + return createUntypedStringValue(value); + } + /** Returns the type of this value. This will return a type even if {@code isNull()} is true. */ public abstract Type getType(); 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 f04026429f5..5f4facf1489 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 @@ -317,7 +317,7 @@ ResponseT getWithStatementTimeout( } catch (TimeoutException e) { throw SpannerExceptionFactory.newSpannerException( ErrorCode.DEADLINE_EXCEEDED, - "Statement execution timeout occurred for " + statement.getSqlWithoutComments(), + "Statement execution timeout occurred for " + statement.getSql(), e); } catch (ExecutionException e) { Throwable cause = e.getCause(); @@ -331,7 +331,7 @@ ResponseT getWithStatementTimeout( } throw SpannerExceptionFactory.newSpannerException( ErrorCode.fromGrpcStatus(Status.fromThrowable(e)), - "Statement execution failed for " + statement.getSqlWithoutComments(), + "Statement execution failed for " + statement.getSql(), e); } catch (InterruptedException e) { throw SpannerExceptionFactory.newSpannerException( 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 406622586d8..652bc9b5e7b 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 @@ -27,10 +27,13 @@ import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.connection.AbstractBaseUnitOfWork.InterceptorsUsage; +import com.google.cloud.spanner.connection.SimpleParser.Result; import com.google.cloud.spanner.connection.StatementResult.ClientSideStatementType; import com.google.cloud.spanner.connection.UnitOfWork.CallType; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.base.Suppliers; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheStats; @@ -38,13 +41,16 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; +import java.nio.CharBuffer; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; +import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; @@ -179,24 +185,24 @@ public static class ParsedStatement { private final StatementType type; private final ClientSideStatementImpl clientSideStatement; private final Statement statement; - private final String sqlWithoutComments; - private final boolean returningClause; + private final Supplier sqlWithoutComments; + private final Supplier returningClause; private final ReadQueryUpdateTransactionOption[] optionsFromHints; private static ParsedStatement clientSideStatement( ClientSideStatementImpl clientSideStatement, Statement statement, - String sqlWithoutComments) { + Supplier sqlWithoutComments) { return new ParsedStatement(clientSideStatement, statement, sqlWithoutComments); } - private static ParsedStatement ddl(Statement statement, String sqlWithoutComments) { + private static ParsedStatement ddl(Statement statement, Supplier sqlWithoutComments) { return new ParsedStatement(StatementType.DDL, statement, sqlWithoutComments); } private static ParsedStatement query( Statement statement, - String sqlWithoutComments, + Supplier sqlWithoutComments, QueryOptions defaultQueryOptions, ReadQueryUpdateTransactionOption[] optionsFromHints) { return new ParsedStatement( @@ -205,57 +211,66 @@ private static ParsedStatement query( statement, sqlWithoutComments, defaultQueryOptions, - false, + Suppliers.ofInstance(false), optionsFromHints); } private static ParsedStatement update( Statement statement, - String sqlWithoutComments, - boolean returningClause, + Supplier sqlWithoutComments, + Supplier returningClause, ReadQueryUpdateTransactionOption[] optionsFromHints) { return new ParsedStatement( StatementType.UPDATE, statement, sqlWithoutComments, returningClause, optionsFromHints); } - private static ParsedStatement unknown(Statement statement, String sqlWithoutComments) { + private static ParsedStatement unknown( + Statement statement, Supplier sqlWithoutComments) { return new ParsedStatement(StatementType.UNKNOWN, statement, sqlWithoutComments); } private ParsedStatement( ClientSideStatementImpl clientSideStatement, Statement statement, - String sqlWithoutComments) { + Supplier sqlWithoutComments) { Preconditions.checkNotNull(clientSideStatement); Preconditions.checkNotNull(statement); this.type = StatementType.CLIENT_SIDE; this.clientSideStatement = clientSideStatement; this.statement = statement; - this.sqlWithoutComments = Preconditions.checkNotNull(sqlWithoutComments); - this.returningClause = false; + this.sqlWithoutComments = sqlWithoutComments; + this.returningClause = Suppliers.ofInstance(false); this.optionsFromHints = EMPTY_OPTIONS; } private ParsedStatement( StatementType type, Statement statement, - String sqlWithoutComments, - boolean returningClause, + Supplier sqlWithoutComments, + Supplier returningClause, ReadQueryUpdateTransactionOption[] optionsFromHints) { this(type, null, statement, sqlWithoutComments, null, returningClause, optionsFromHints); } - private ParsedStatement(StatementType type, Statement statement, String sqlWithoutComments) { - this(type, null, statement, sqlWithoutComments, null, false, EMPTY_OPTIONS); + private ParsedStatement( + StatementType type, Statement statement, Supplier sqlWithoutComments) { + this( + type, + null, + statement, + sqlWithoutComments, + null, + Suppliers.ofInstance(false), + EMPTY_OPTIONS); } private ParsedStatement( StatementType type, ClientSideStatementImpl clientSideStatement, Statement statement, - String sqlWithoutComments, + Supplier sqlWithoutComments, QueryOptions defaultQueryOptions, - boolean returningClause, + Supplier returningClause, ReadQueryUpdateTransactionOption[] optionsFromHints) { Preconditions.checkNotNull(type); this.type = type; @@ -315,7 +330,7 @@ public StatementType getType() { /** @return whether the statement has a returning clause or not. */ @InternalApi public boolean hasReturningClause() { - return this.returningClause; + return this.returningClause.get(); } @InternalApi @@ -410,10 +425,20 @@ Statement mergeQueryOptions(Statement statement, QueryOptions defaultQueryOption .build(); } - /** @return the SQL statement with all comments removed from the SQL string. */ + /** @return the original SQL statement */ + @InternalApi + public String getSql() { + return statement.getSql(); + } + + /** + * @return the SQL statement with all comments removed from the SQL string. + * @deprecated use {@link #getSql()} instead + */ + @Deprecated @InternalApi public String getSqlWithoutComments() { - return sqlWithoutComments; + return sqlWithoutComments.get(); } ClientSideStatement getClientSideStatement() { @@ -464,7 +489,7 @@ private static boolean isRecordStatementCacheStats() { // We do length*2 because Java uses 2 bytes for each char. .weigher( (Weigher) - (key, value) -> 2 * key.length() + 2 * value.sqlWithoutComments.length()) + (key, value) -> 2 * key.length() + 2 * value.statement.getSql().length()) .concurrencyLevel(Runtime.getRuntime().availableProcessors()); if (isRecordStatementCacheStats()) { cacheBuilder.recordStats(); @@ -511,9 +536,9 @@ ParsedStatement parse(Statement statement, QueryOptions defaultQueryOptions) { return parsedStatement.copy(statement, defaultQueryOptions); } - private ParsedStatement internalParse(Statement statement, QueryOptions defaultQueryOptions) { - StatementHintParser statementHintParser = - new StatementHintParser(getDialect(), statement.getSql()); + ParsedStatement internalParse(Statement statement, QueryOptions defaultQueryOptions) { + String sql = statement.getSql(); + StatementHintParser statementHintParser = new StatementHintParser(getDialect(), sql); ReadQueryUpdateTransactionOption[] optionsFromHints = EMPTY_OPTIONS; if (statementHintParser.hasStatementHints() && !statementHintParser.getClientSideStatementHints().isEmpty()) { @@ -521,18 +546,52 @@ private ParsedStatement internalParse(Statement statement, QueryOptions defaultQ statement.toBuilder().replace(statementHintParser.getSqlWithoutClientSideHints()).build(); optionsFromHints = convertHintsToOptions(statementHintParser.getClientSideStatementHints()); } - String sql = removeCommentsAndTrim(statement.getSql()); - ClientSideStatementImpl client = parseClientSideStatement(sql); + // Create a supplier that will actually remove all comments and hints from the SQL string to be + // backwards compatible with anything that really needs the SQL string without comments. + Supplier sqlWithoutCommentsSupplier = + Suppliers.memoize(() -> removeCommentsAndTrim(sql)); + + // Get rid of any spaces/comments at the start of the string. + SimpleParser simpleParser = new SimpleParser(getDialect(), sql); + simpleParser.skipWhitespaces(); + // Create a wrapper around the SQL string from the point after the first whitespace. + CharBuffer charBuffer = CharBuffer.wrap(sql, simpleParser.getPos(), sql.length()); + ClientSideStatementImpl client = parseClientSideStatement(charBuffer); + if (client != null) { - return ParsedStatement.clientSideStatement(client, statement, sql); - } else if (isQuery(sql)) { - return ParsedStatement.query(statement, sql, defaultQueryOptions, optionsFromHints); - } else if (isUpdateStatement(sql)) { - return ParsedStatement.update(statement, sql, checkReturningClause(sql), optionsFromHints); - } else if (isDdlStatement(sql)) { - return ParsedStatement.ddl(statement, sql); + return ParsedStatement.clientSideStatement(client, statement, sqlWithoutCommentsSupplier); + } else { + // Find the first keyword in the SQL statement. + Result keywordResult = simpleParser.eatNextKeyword(); + if (keywordResult.isValid()) { + // Determine the statement type based on the first keyword. + String keyword = keywordResult.getValue().toUpperCase(); + if (keywordResult.isInParenthesis()) { + // If the first keyword is inside one or more parentheses, then only a subset of all + // keywords are allowed. + if (SELECT_STATEMENTS_ALLOWING_PRECEDING_BRACKETS.contains(keyword)) { + return ParsedStatement.query( + statement, sqlWithoutCommentsSupplier, defaultQueryOptions, optionsFromHints); + } + } else { + if (selectStatements.contains(keyword)) { + return ParsedStatement.query( + statement, sqlWithoutCommentsSupplier, defaultQueryOptions, optionsFromHints); + } else if (dmlStatements.contains(keyword)) { + return ParsedStatement.update( + statement, + sqlWithoutCommentsSupplier, + // TODO: Make the returning clause check work without removing comments + Suppliers.memoize(() -> checkReturningClause(sqlWithoutCommentsSupplier.get())), + optionsFromHints); + } else if (ddlStatements.contains(keyword)) { + return ParsedStatement.ddl(statement, sqlWithoutCommentsSupplier); + } + } + } } - return ParsedStatement.unknown(statement, sql); + // Fallthrough: Return an unknown statement. + return ParsedStatement.unknown(statement, sqlWithoutCommentsSupplier); } /** @@ -546,7 +605,7 @@ private ParsedStatement internalParse(Statement statement, QueryOptions defaultQ * statement. */ @VisibleForTesting - ClientSideStatementImpl parseClientSideStatement(String sql) { + ClientSideStatementImpl parseClientSideStatement(CharSequence sql) { for (ClientSideStatementImpl css : statements) { if (css.matches(sql)) { return css; @@ -563,8 +622,10 @@ ClientSideStatementImpl parseClientSideStatement(String sql) { * @param sql The statement to check (without any comments). * @return true if the statement is a DDL statement (i.e. starts with 'CREATE', * 'ALTER' or 'DROP'). + * @deprecated Use {@link #parse(Statement)} instead */ @InternalApi + @Deprecated public boolean isDdlStatement(String sql) { return statementStartsWith(sql, ddlStatements); } @@ -576,8 +637,10 @@ public boolean isDdlStatement(String sql) { * * @param sql The statement to check (without any comments). * @return true if the statement is a SELECT statement (i.e. starts with 'SELECT'). + * @deprecated Use {@link #parse(Statement)} instead */ @InternalApi + @Deprecated 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 @@ -600,8 +663,10 @@ public boolean isQuery(String sql) { * @param sql The statement to check (without any comments). * @return true if the statement is a DML update statement (i.e. starts with * 'INSERT', 'UPDATE' or 'DELETE'). + * @deprecated Use {@link #parse(Statement)} instead */ @InternalApi + @Deprecated public boolean isUpdateStatement(String sql) { // Skip any query hints at the beginning of the query. if (sql.startsWith("@")) { @@ -610,20 +675,16 @@ 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); - int checkIndex = 0; - if (supportsExplain() && tokens[0].equalsIgnoreCase("EXPLAIN")) { - checkIndex = 1; - } - if (tokens.length > checkIndex) { - for (String check : checkStatements) { - if (tokens[checkIndex].equalsIgnoreCase(check)) { - return true; - } + Iterator tokens = Splitter.onPattern("\\s+").split(sql).iterator(); + if (!tokens.hasNext()) { + return false; + } + String token = tokens.next(); + for (String check : checkStatements) { + if (token.equalsIgnoreCase(check)) { + return true; } } return false; @@ -929,7 +990,8 @@ int skipQuoted( appendIfNotNull(result, startQuote); appendIfNotNull(result, startQuote); } - while (currentIndex < sql.length()) { + int length = sql.length(); + while (currentIndex < length) { char currentChar = sql.charAt(currentIndex); if (currentChar == startQuote) { if (supportsDollarQuotedStrings() && currentChar == DOLLAR) { @@ -940,7 +1002,7 @@ int skipQuoted( return currentIndex + tag.length() + 2; } } else if (supportsEscapeQuoteWithQuote() - && sql.length() > currentIndex + 1 + && length > currentIndex + 1 && sql.charAt(currentIndex + 1) == startQuote) { // This is an escaped quote (e.g. 'foo''bar') appendIfNotNull(result, currentChar); @@ -949,7 +1011,7 @@ int skipQuoted( continue; } else if (isTripleQuoted) { // Check if this is the end of the triple-quoted string. - if (sql.length() > currentIndex + 2 + if (length > currentIndex + 2 && sql.charAt(currentIndex + 1) == startQuote && sql.charAt(currentIndex + 2) == startQuote) { appendIfNotNull(result, currentChar); @@ -963,7 +1025,7 @@ int skipQuoted( } } else if (supportsBackslashEscape() && currentChar == BACKSLASH - && sql.length() > currentIndex + 1 + && length > currentIndex + 1 && sql.charAt(currentIndex + 1) == startQuote) { // This is an escaped quote (e.g. 'foo\'bar'). // Note that in raw strings, the \ officially does not start an escape sequence, but the diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementBeginExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementBeginExecutor.java index d1b01526724..7f854c0ccab 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementBeginExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementBeginExecutor.java @@ -46,8 +46,7 @@ class ClientSideStatementBeginExecutor implements ClientSideStatementExecutor { @Override public StatementResult execute(ConnectionStatementExecutor connection, ParsedStatement statement) throws Exception { - return (StatementResult) - method.invoke(connection, getParameterValue(statement.getSqlWithoutComments())); + return (StatementResult) method.invoke(connection, getParameterValue(statement.getSql())); } IsolationLevel getParameterValue(String sql) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExplainExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExplainExecutor.java index 767d6917be6..43b84f48123 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExplainExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementExplainExecutor.java @@ -50,8 +50,7 @@ class ClientSideStatementExplainExecutor implements ClientSideStatementExecutor @Override public StatementResult execute(ConnectionStatementExecutor connection, ParsedStatement statement) throws Exception { - return (StatementResult) - method.invoke(connection, getParameterValue(statement.getSqlWithoutComments())); + return (StatementResult) method.invoke(connection, getParameterValue(statement.getSql())); } String getParameterValue(String sql) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java index f9ecba6652a..4cd4902a865 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementImpl.java @@ -193,7 +193,7 @@ public ClientSideStatementType getStatementType() { return statementType; } - boolean matches(String statement) { + boolean matches(CharSequence statement) { Preconditions.checkState(pattern != null, "This statement has not been compiled"); return pattern.matcher(statement).matches(); } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPartitionExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPartitionExecutor.java index 0307ff517bb..c96ee155341 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPartitionExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPartitionExecutor.java @@ -49,7 +49,7 @@ public StatementResult execute( } String getParameterValue(ParsedStatement parsedStatement) { - Matcher matcher = statement.getPattern().matcher(parsedStatement.getSqlWithoutComments()); + Matcher matcher = statement.getPattern().matcher(parsedStatement.getSql()); if (matcher.find() && matcher.groupCount() >= 2) { String space = matcher.group(1); String value = matcher.group(2); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPgBeginExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPgBeginExecutor.java index c1d00d81b55..fae41de18c1 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPgBeginExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementPgBeginExecutor.java @@ -45,8 +45,7 @@ class ClientSideStatementPgBeginExecutor implements ClientSideStatementExecutor @Override public StatementResult execute(ConnectionStatementExecutor connection, ParsedStatement statement) throws Exception { - return (StatementResult) - method.invoke(connection, getParameterValue(statement.getSqlWithoutComments())); + return (StatementResult) method.invoke(connection, getParameterValue(statement.getSql())); } PgTransactionMode getParameterValue(String sql) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionExecutor.java index 1534f04b3a4..7e3c30d9f70 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionExecutor.java @@ -65,7 +65,7 @@ String getParameterValue(ParsedStatement parsedStatement) { // 2. If the matcher matches and returns zero groups, we know that the statement is valid, but // that it does not contain a partition-id in the SQL statement. The partition-id must then // be included in the statement as a query parameter. - Matcher matcher = statement.getPattern().matcher(parsedStatement.getSqlWithoutComments()); + Matcher matcher = statement.getPattern().matcher(parsedStatement.getSql()); if (matcher.find() && matcher.groupCount() >= 1) { String value = matcher.group(1); if (!Strings.isNullOrEmpty(value)) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionedQueryExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionedQueryExecutor.java index ba42db1f9d3..c95f2203fc8 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionedQueryExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementRunPartitionedQueryExecutor.java @@ -50,7 +50,7 @@ public StatementResult execute( } String getParameterValue(ParsedStatement parsedStatement) { - Matcher matcher = statement.getPattern().matcher(parsedStatement.getSqlWithoutComments()); + Matcher matcher = statement.getPattern().matcher(parsedStatement.getSql()); if (matcher.find() && matcher.groupCount() >= 2) { // Include the spacing group in case the query is enclosed in parentheses like this: // `run partitioned query(select * from foo)` diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java index 38c7c364106..5bb0a4c8d3b 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ClientSideStatementSetExecutor.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.connection; import com.google.cloud.Tuple; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; import com.google.cloud.spanner.SpannerExceptionFactory; import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; @@ -27,6 +28,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.nio.CharBuffer; import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -104,8 +106,8 @@ public StatementResult execute(ConnectionStatementExecutor connection, ParsedSta try { value = this.cache.get( - statement.getSqlWithoutComments(), - () -> getParameterValue(statement.getSqlWithoutComments())); + statement.getSql(), + () -> getParameterValue(connection.getDialect(), statement.getSql())); } catch (ExecutionException | UncheckedExecutionException executionException) { throw SpannerExceptionFactory.asSpannerException(executionException.getCause()); } @@ -115,8 +117,13 @@ public StatementResult execute(ConnectionStatementExecutor connection, ParsedSta return (StatementResult) method.invoke(connection, value.x()); } - Tuple getParameterValue(String sql) { - Matcher matcher = allowedValuesPattern.matcher(sql); + Tuple getParameterValue(Dialect dialect, String sql) { + // Get rid of any spaces/comments at the start of the string. + SimpleParser simpleParser = new SimpleParser(dialect, sql); + simpleParser.skipWhitespaces(); + // Create a wrapper around the SQL string from the point after the first whitespace. + CharBuffer sqlAfterWhitespaces = CharBuffer.wrap(sql, simpleParser.getPos(), sql.length()); + Matcher matcher = allowedValuesPattern.matcher(sqlAfterWhitespaces); if (matcher.find() && matcher.groupCount() >= 2) { boolean local = matcher.group(1) != null && "local".equalsIgnoreCase(matcher.group(1).trim()); String value = matcher.group(2); @@ -130,7 +137,7 @@ Tuple getParameterValue(String sql) { "Unknown value for %s: %s", this.statement.getSetStatement().getPropertyName(), value)); } else { - Matcher invalidMatcher = this.statement.getPattern().matcher(sql); + Matcher invalidMatcher = this.statement.getPattern().matcher(sqlAfterWhitespaces); int valueGroup = this.supportsLocal ? 2 : 1; if (invalidMatcher.find() && invalidMatcher.groupCount() == valueGroup) { String invalidValue = invalidMatcher.group(valueGroup); 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 9ce1162bbf2..c1e8839534f 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 @@ -382,6 +382,7 @@ public Spanner getSpanner() { private DdlClient createDdlClient() { return DdlClient.newBuilder() .setDatabaseAdminClient(spanner.getDatabaseAdminClient()) + .setDialectSupplier(this::getDialect) .setProjectId(options.getProjectId()) .setInstanceId(options.getInstanceId()) .setDatabaseName(options.getDatabaseName()) @@ -859,6 +860,27 @@ public void setTransactionMode(TransactionMode transactionMode) { this.unitOfWorkType = UnitOfWorkType.of(transactionMode); } + IsolationLevel getTransactionIsolationLevel() { + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState(!isDdlBatchActive(), "This connection is in a DDL batch"); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + return this.transactionIsolationLevel; + } + + void setTransactionIsolationLevel(IsolationLevel isolationLevel) { + Preconditions.checkNotNull(isolationLevel); + ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); + ConnectionPreconditions.checkState( + !isBatchActive(), "Cannot set transaction isolation level while in a batch"); + ConnectionPreconditions.checkState(isInTransaction(), "This connection has no transaction"); + ConnectionPreconditions.checkState( + !isTransactionStarted(), + "The transaction isolation level cannot be set after the transaction has started"); + + this.transactionBeginMarked = true; + this.transactionIsolationLevel = isolationLevel; + } + @Override public String getTransactionTag() { ConnectionPreconditions.checkState(!isClosed(), CLOSED_ERROR_MSG); @@ -1403,8 +1425,7 @@ private StatementResult internalExecute( default: } throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Unknown statement: " + parsedStatement.getSqlWithoutComments()); + ErrorCode.INVALID_ARGUMENT, "Unknown statement: " + parsedStatement.getSql()); } @VisibleForTesting @@ -1449,8 +1470,7 @@ private static ResultType getResultType(ParsedStatement parsedStatement) { case UNKNOWN: default: throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Unknown statement: " + parsedStatement.getSqlWithoutComments()); + ErrorCode.INVALID_ARGUMENT, "Unknown statement: " + parsedStatement.getSql()); } } @@ -1482,8 +1502,7 @@ public AsyncStatementResult executeAsync(Statement statement) { default: } throw SpannerExceptionFactory.newSpannerException( - ErrorCode.INVALID_ARGUMENT, - "Unknown statement: " + parsedStatement.getSqlWithoutComments()); + ErrorCode.INVALID_ARGUMENT, "Unknown statement: " + parsedStatement.getSql()); } @Override @@ -1678,7 +1697,7 @@ private ResultSet parseAndExecuteQuery( throw SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "DML statement with returning clause cannot be executed in read-only mode: " - + parsedStatement.getSqlWithoutComments()); + + parsedStatement.getSql()); } return internalExecuteQuery(callType, parsedStatement, analyzeMode, options); } @@ -1689,8 +1708,7 @@ private ResultSet parseAndExecuteQuery( } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not a query or DML with returning clause: " - + parsedStatement.getSqlWithoutComments()); + "Statement is not a query or DML with returning clause: " + parsedStatement.getSql()); } private AsyncResultSet parseAndExecuteQueryAsync(Statement query, QueryOption... options) { @@ -1720,7 +1738,7 @@ private AsyncResultSet parseAndExecuteQueryAsync(Statement query, QueryOption... throw SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "DML statement with returning clause cannot be executed in read-only mode: " - + parsedStatement.getSqlWithoutComments()); + + parsedStatement.getSql()); } return internalExecuteQueryAsync( CallType.ASYNC, parsedStatement, AnalyzeMode.NONE, options); @@ -1732,8 +1750,7 @@ private AsyncResultSet parseAndExecuteQueryAsync(Statement query, QueryOption... } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not a query or DML with returning clause: " - + parsedStatement.getSqlWithoutComments()); + "Statement is not a query or DML with returning clause: " + parsedStatement.getSql()); } private boolean isInternalMetadataQuery(QueryOption... options) { @@ -1760,7 +1777,7 @@ public long executeUpdate(Statement update) { throw SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "DML statement with returning clause cannot be executed using executeUpdate: " - + parsedStatement.getSqlWithoutComments() + + parsedStatement.getSql() + ". Please use executeQuery instead."); } return get(internalExecuteUpdateAsync(CallType.SYNC, parsedStatement)); @@ -1773,7 +1790,7 @@ public long executeUpdate(Statement update) { } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); + "Statement is not an update statement: " + parsedStatement.getSql()); } @Override @@ -1788,7 +1805,7 @@ public ApiFuture executeUpdateAsync(Statement update) { throw SpannerExceptionFactory.newSpannerException( ErrorCode.FAILED_PRECONDITION, "DML statement with returning clause cannot be executed using executeUpdateAsync: " - + parsedStatement.getSqlWithoutComments() + + parsedStatement.getSql() + ". Please use executeQueryAsync instead."); } return internalExecuteUpdateAsync(CallType.ASYNC, parsedStatement); @@ -1801,7 +1818,7 @@ public ApiFuture executeUpdateAsync(Statement update) { } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); + "Statement is not an update statement: " + parsedStatement.getSql()); } @Override @@ -1824,7 +1841,7 @@ public ResultSetStats analyzeUpdate(Statement update, QueryAnalyzeMode analyzeMo } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); + "Statement is not an update statement: " + parsedStatement.getSql()); } @Override @@ -1846,7 +1863,7 @@ public ResultSet analyzeUpdateStatement( } throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, - "Statement is not an update statement: " + parsedStatement.getSqlWithoutComments()); + "Statement is not an update statement: " + parsedStatement.getSql()); } @Override @@ -1878,7 +1895,7 @@ private List parseUpdateStatements(Iterable updates) throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, "The batch update list contains a statement that is not an update statement: " - + parsedStatement.getSqlWithoutComments()); + + parsedStatement.getSql()); } } return parsedStatements; diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java index c26ea372514..b8f4676fa76 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutor.java @@ -16,6 +16,7 @@ package com.google.cloud.spanner.connection; +import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Options.RpcPriority; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TimestampBound; @@ -36,6 +37,7 @@ *

The client side statements are defined in the ClientSideStatements.json file. */ interface ConnectionStatementExecutor { + Dialect getDialect(); StatementResult statementSetAutocommit(Boolean autocommit); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java index 08c6852fcc3..1f4d8f5cf22 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionStatementExecutorImpl.java @@ -154,6 +154,11 @@ ConnectionImpl getConnection() { return connection; } + @Override + public Dialect getDialect() { + return getConnection().getDialect(); + } + @Override public StatementResult statementSetAutocommit(Boolean autocommit) { Preconditions.checkNotNull(autocommit); @@ -490,6 +495,11 @@ public StatementResult statementSetTransactionMode(TransactionMode mode) { @Override public StatementResult statementSetPgTransactionMode(PgTransactionMode transactionMode) { + if (transactionMode.getIsolationLevel() != null) { + getConnection() + .setTransactionIsolationLevel( + transactionMode.getIsolationLevel().getSpannerIsolationLevel()); + } if (transactionMode.getAccessMode() != null) { switch (transactionMode.getAccessMode()) { case READ_ONLY_TRANSACTION: 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 813f5d6e45b..c448695afd2 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 @@ -191,13 +191,11 @@ public ApiFuture executeDdlAsync(CallType callType, ParsedStatement ddl) { "The batch is no longer active and cannot be used for further statements"); Preconditions.checkArgument( ddl.getType() == StatementType.DDL, - "Only DDL statements are allowed. \"" - + ddl.getSqlWithoutComments() - + "\" is not a DDL-statement."); + "Only DDL statements are allowed. \"" + ddl.getSql() + "\" is not a DDL-statement."); Preconditions.checkArgument( - !DdlClient.isCreateDatabaseStatement(ddl.getSqlWithoutComments()), + !DdlClient.isCreateDatabaseStatement(dbClient.getDialect(), ddl.getSql()), "CREATE DATABASE is not supported in DDL batches."); - statements.add(ddl.getSqlWithoutComments()); + statements.add(ddl.getSql()); return ApiFutures.immediateFuture(null); } @@ -268,7 +266,7 @@ public ApiFuture runBatchAsync(CallType callType) { } catch (SpannerException e) { long[] updateCounts = extractUpdateCounts(operationReference.get()); throw SpannerExceptionFactory.newSpannerBatchUpdateException( - e.getErrorCode(), e.getMessage(), updateCounts); + e.getErrorCode(), e.getMessage(), updateCounts, null /* TODO: requestId */); } } catch (Throwable t) { span.setStatus(StatusCode.ERROR); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java index a3dc286acb4..ef7ad7e5cdb 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/DdlClient.java @@ -34,6 +34,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +import java.util.function.Supplier; /** * Convenience class for executing Data Definition Language statements on transactions that support @@ -41,12 +42,14 @@ */ class DdlClient { private final DatabaseAdminClient dbAdminClient; + private final Supplier dialectSupplier; private final String projectId; private final String instanceId; private final String databaseName; static class Builder { private DatabaseAdminClient dbAdminClient; + private Supplier dialectSupplier; private String projectId; private String instanceId; private String databaseName; @@ -59,6 +62,11 @@ Builder setDatabaseAdminClient(DatabaseAdminClient client) { return this; } + Builder setDialectSupplier(Supplier dialectSupplier) { + this.dialectSupplier = Preconditions.checkNotNull(dialectSupplier); + return this; + } + Builder setProjectId(String projectId) { Preconditions.checkArgument( !Strings.isNullOrEmpty(projectId), "Empty projectId is not allowed"); @@ -82,6 +90,7 @@ Builder setDatabaseName(String name) { DdlClient build() { Preconditions.checkState(dbAdminClient != null, "No DatabaseAdminClient specified"); + Preconditions.checkState(dialectSupplier != null, "No dialect supplier specified"); Preconditions.checkState(!Strings.isNullOrEmpty(projectId), "No ProjectId specified"); Preconditions.checkState(!Strings.isNullOrEmpty(instanceId), "No InstanceId specified"); Preconditions.checkArgument( @@ -96,6 +105,7 @@ static Builder newBuilder() { private DdlClient(Builder builder) { this.dbAdminClient = builder.dbAdminClient; + this.dialectSupplier = builder.dialectSupplier; this.projectId = builder.projectId; this.instanceId = builder.instanceId; this.databaseName = builder.databaseName; @@ -103,7 +113,7 @@ private DdlClient(Builder builder) { OperationFuture executeCreateDatabase( String createStatement, Dialect dialect) { - Preconditions.checkArgument(isCreateDatabaseStatement(createStatement)); + Preconditions.checkArgument(isCreateDatabaseStatement(dialect, createStatement)); return dbAdminClient.createDatabase( instanceId, createStatement, dialect, Collections.emptyList()); } @@ -116,7 +126,8 @@ OperationFuture executeDdl(String ddl, byte[] p /** Execute a list of DDL statements as one operation. */ OperationFuture executeDdl( List statements, byte[] protoDescriptors) { - if (statements.stream().anyMatch(DdlClient::isCreateDatabaseStatement)) { + if (statements.stream() + .anyMatch(sql -> isCreateDatabaseStatement(this.dialectSupplier.get(), sql))) { throw SpannerExceptionFactory.newSpannerException( ErrorCode.INVALID_ARGUMENT, "CREATE DATABASE is not supported in a DDL batch"); } @@ -130,11 +141,9 @@ OperationFuture executeDdl( } /** Returns true if the statement is a `CREATE DATABASE ...` statement. */ - static boolean isCreateDatabaseStatement(String statement) { - String[] tokens = statement.split("\\s+", 3); - return tokens.length >= 2 - && tokens[0].equalsIgnoreCase("CREATE") - && tokens[1].equalsIgnoreCase("DATABASE"); + static boolean isCreateDatabaseStatement(Dialect dialect, String statement) { + SimpleParser parser = new SimpleParser(dialect, statement); + return parser.eatKeyword("create", "database"); } void runWithRetryForMissingDefaultSequenceKind( 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 1f5e72acee2..c1df52a49ca 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 @@ -204,9 +204,7 @@ public ApiFuture executeUpdateAsync( "The batch is no longer active and cannot be used for further statements"); Preconditions.checkArgument( update.getType() == StatementType.UPDATE, - "Only DML statements are allowed. \"" - + update.getSqlWithoutComments() - + "\" is not a DML-statement."); + "Only DML statements are allowed. \"" + update.getSql() + "\" is not a DML-statement."); long updateCount = getUpdateCount(); this.statements.add(update); this.updateCounts = Arrays.copyOf(this.updateCounts, this.updateCounts.length + 1); @@ -233,9 +231,7 @@ public ApiFuture executeBatchUpdateAsync( for (ParsedStatement update : updates) { Preconditions.checkArgument( update.getType() == StatementType.UPDATE, - "Only DML statements are allowed. \"" - + update.getSqlWithoutComments() - + "\" is not a DML-statement."); + "Only DML statements are allowed. \"" + update.getSql() + "\" is not a DML-statement."); } long[] updateCountArray = new long[Iterables.size(updates)]; Arrays.fill(updateCountArray, getUpdateCount()); 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 index 4f39c549de9..60b64b0cd4f 100644 --- 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 @@ -46,15 +46,6 @@ Dialect getDialect() { return Dialect.POSTGRESQL; } - /** - * Indicates whether the parser supports the {@code EXPLAIN} clause. The PostgreSQL parser does - * not support it. - */ - @Override - protected boolean supportsExplain() { - return false; - } - @Override boolean supportsNestedComments() { return true; @@ -125,7 +116,8 @@ String removeCommentsAndTrimInternal(String sql) { int multiLineCommentStartIdx = -1; StringBuilder res = new StringBuilder(sql.length()); int index = 0; - while (index < sql.length()) { + int length = sql.length(); + while (index < length) { char c = sql.charAt(index); if (isInSingleLineComment) { if (c == '\n') { @@ -134,10 +126,10 @@ String removeCommentsAndTrimInternal(String sql) { res.append(c); } } else if (multiLineCommentLevel > 0) { - if (sql.length() > index + 1 && c == ASTERISK && sql.charAt(index + 1) == SLASH) { + if (length > index + 1 && c == ASTERISK && sql.charAt(index + 1) == SLASH) { multiLineCommentLevel--; if (multiLineCommentLevel == 0) { - if (!whitespaceBeforeOrAfterMultiLineComment && (sql.length() > index + 2)) { + if (!whitespaceBeforeOrAfterMultiLineComment && (length > index + 2)) { whitespaceBeforeOrAfterMultiLineComment = Character.isWhitespace(sql.charAt(index + 2)); } @@ -145,23 +137,23 @@ String removeCommentsAndTrimInternal(String sql) { // neither at the start nor at the end of SQL string, append an extra space. if (!whitespaceBeforeOrAfterMultiLineComment && (multiLineCommentStartIdx != 0) - && (index != sql.length() - 2)) { + && (index != length - 2)) { res.append(' '); } } index++; - } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERISK) { + } else if (length > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERISK) { 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) { + if (length > index + 1 && c == HYPHEN && sql.charAt(index + 1) == HYPHEN) { // This is a single line comment. isInSingleLineComment = true; index += 2; continue; - } else if (sql.length() > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERISK) { + } else if (length > index + 1 && c == SLASH && sql.charAt(index + 1) == ASTERISK) { multiLineCommentLevel++; if (index >= 1) { whitespaceBeforeOrAfterMultiLineComment = Character.isWhitespace(sql.charAt(index - 1)); 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 3e4e98b16c0..828c17141a4 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 @@ -785,8 +785,7 @@ public ApiFuture executeBatchUpdateAsync( final List updateStatements = new LinkedList<>(); for (ParsedStatement update : updates) { Preconditions.checkArgument( - update.isUpdate(), - "Statement is not an update statement: " + update.getSqlWithoutComments()); + update.isUpdate(), "Statement is not an update statement: " + update.getSql()); updateStatements.add(update.getStatement()); } checkOrCreateValidTransaction(Iterables.getFirst(updates, null), callType); diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SimpleParser.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SimpleParser.java index 0af86892dde..acfb4aa070a 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SimpleParser.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SimpleParser.java @@ -33,16 +33,23 @@ class SimpleParser { * if so, what the value was. */ static class Result { - static final Result NOT_FOUND = new Result(null); + static final Result NOT_FOUND = new Result(null, false); static Result found(String value) { - return new Result(Preconditions.checkNotNull(value)); + return new Result(Preconditions.checkNotNull(value), false); + } + + static Result found(String value, boolean inParenthesis) { + return new Result(Preconditions.checkNotNull(value), inParenthesis); } private final String value; - private Result(String value) { + private final boolean inParenthesis; + + private Result(String value, boolean inParenthesis) { this.value = value; + this.inParenthesis = inParenthesis; } @Override @@ -55,7 +62,8 @@ public boolean equals(Object o) { if (!(o instanceof Result)) { return false; } - return Objects.equals(this.value, ((Result) o).value); + return Objects.equals(this.value, ((Result) o).value) + && Objects.equals(this.inParenthesis, ((Result) o).inParenthesis); } @Override @@ -73,6 +81,10 @@ boolean isValid() { String getValue() { return this.value; } + + boolean isInParenthesis() { + return this.inParenthesis; + } } // TODO: Replace this with a direct reference to the dialect, and move the isXYZSupported methods @@ -81,6 +93,9 @@ String getValue() { private final String sql; + // TODO: Use this length field instead of repeatedly calling sql.length() + private final int length; + private final boolean treatHintCommentsAsTokens; private int pos; @@ -100,6 +115,7 @@ String getValue() { !(treatHintCommentsAsTokens && dialect != Dialect.POSTGRESQL), "treatHintCommentsAsTokens can only be enabled for PostgreSQL"); this.sql = sql; + this.length = sql.length(); this.pos = pos; this.statementParser = AbstractStatementParser.getInstance(dialect); this.treatHintCommentsAsTokens = treatHintCommentsAsTokens; @@ -117,12 +133,54 @@ int getPos() { return this.pos; } + void skipHint() { + // We don't need to do anything special for PostgreSQL, as hints in PostgreSQL are inside + // comments and comments are automatically skipped by all methods. + if (getDialect() == Dialect.GOOGLE_STANDARD_SQL && eatTokens('@', '{')) { + while (pos < length && !eatToken('}')) { + pos += statementParser.skip(sql, pos, /*result=*/ null); + } + } + } + + Result eatNextKeyword() { + skipHint(); + boolean inParenthesis = false; + while (pos < length && eatToken('(')) { + inParenthesis = true; + } + return eatKeyword(inParenthesis); + } + /** Returns true if this parser has more tokens. Advances the position to the first next token. */ boolean hasMoreTokens() { skipWhitespaces(); return pos < sql.length(); } + /** Eats and returns the keyword at the current position. */ + Result eatKeyword() { + return eatKeyword(false); + } + + /** + * Eats and returns the keyword at the current position and returns a result that indicates that + * the keyword is inside one or more parentheses. + */ + Result eatKeyword(boolean inParenthesis) { + if (!hasMoreTokens()) { + return Result.NOT_FOUND; + } + if (!Character.isLetter(sql.charAt(pos))) { + return Result.NOT_FOUND; + } + int startPos = pos; + while (pos < length && Character.isLetter(sql.charAt(pos))) { + pos++; + } + return Result.found(sql.substring(startPos, pos), inParenthesis); + } + /** * Eats and returns the identifier at the current position. This implementation does not support * quoted identifiers. @@ -219,6 +277,55 @@ boolean eatToken(char token) { return false; } + boolean eatKeyword(String... keywords) { + return eat(true, true, keywords); + } + + boolean eat(boolean skipWhitespaceBefore, boolean requireWhitespaceAfter, String... keywords) { + boolean result = true; + for (String keyword : keywords) { + result &= internalEat(keyword, skipWhitespaceBefore, requireWhitespaceAfter, true); + } + return result; + } + + private boolean internalEat( + String keyword, + boolean skipWhitespaceBefore, + boolean requireWhitespaceAfter, + boolean updatePos) { + int originalPos = pos; + if (skipWhitespaceBefore) { + skipWhitespaces(); + } + if (pos + keyword.length() > sql.length()) { + if (!updatePos) { + pos = originalPos; + } + return false; + } + if (sql.substring(pos, pos + keyword.length()).equalsIgnoreCase(keyword) + && (!requireWhitespaceAfter || isValidEndOfKeyword(pos + keyword.length()))) { + if (updatePos) { + pos = pos + keyword.length(); + } else { + pos = originalPos; + } + return true; + } + if (!updatePos) { + pos = originalPos; + } + return false; + } + + private boolean isValidEndOfKeyword(int index) { + if (sql.length() == index) { + return true; + } + return !isValidIdentifierChar(sql.charAt(index)); + } + /** * Returns true if the given character is valid as the first character of an identifier. That * means that it can be used as the first character of an unquoted identifier. 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 123b71ff014..85cef17f9de 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 @@ -386,13 +386,13 @@ public ApiFuture executeDdlAsync(CallType callType, final ParsedStatement Callable callable = () -> { try { - if (isCreateDatabaseStatement(ddl.getSqlWithoutComments())) { + if (isCreateDatabaseStatement(dbClient.getDialect(), ddl.getSql())) { executeCreateDatabase(ddl); } else { ddlClient.runWithRetryForMissingDefaultSequenceKind( restartIndex -> { OperationFuture operation = - ddlClient.executeDdl(ddl.getSqlWithoutComments(), protoDescriptors); + ddlClient.executeDdl(ddl.getSql(), protoDescriptors); getWithStatementTimeout(operation, ddl); }, connectionState.getValue(DEFAULT_SEQUENCE_KIND).getValue(), @@ -413,7 +413,7 @@ public ApiFuture executeDdlAsync(CallType callType, final ParsedStatement private void executeCreateDatabase(ParsedStatement ddl) { OperationFuture operation = - ddlClient.executeCreateDatabase(ddl.getSqlWithoutComments(), dbClient.getDialect()); + ddlClient.executeCreateDatabase(ddl.getSql(), dbClient.getDialect()); getWithStatementTimeout(operation, ddl); } @@ -474,8 +474,7 @@ public ApiFuture executeBatchUpdateAsync( Preconditions.checkNotNull(updates); for (ParsedStatement update : updates) { Preconditions.checkArgument( - update.isUpdate(), - "Statement is not an update statement: " + update.getSqlWithoutComments()); + update.isUpdate(), "Statement is not an update statement: " + update.getSql()); } ConnectionPreconditions.checkState( !isReadOnly(), "Batch update statements are not allowed in read-only mode"); 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 index fdd10bbf5ae..2689145b7ac 100644 --- 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 @@ -46,15 +46,6 @@ Dialect getDialect() { return 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; - } - @Override boolean supportsNestedComments() { return false; 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 0e540ea7926..2a0ac1839dd 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 @@ -280,6 +280,8 @@ public class GapicSpannerRpc implements SpannerRpc { private Supplier directPathEnabledSupplier = () -> false; + private final GrpcCallContext baseGrpcCallContext; + public static GapicSpannerRpc create(SpannerOptions options) { return new GapicSpannerRpc(options); } @@ -333,6 +335,7 @@ public GapicSpannerRpc(final SpannerOptions options) { this.endToEndTracingEnabled = options.isEndToEndTracingEnabled(); this.numChannels = options.getNumChannels(); this.isGrpcGcpExtensionEnabled = options.isGrpcGcpExtensionEnabled(); + this.baseGrpcCallContext = createBaseCallContext(); if (initializeStubs) { // First check if SpannerOptions provides a TransportChannelProvider. Create one @@ -370,6 +373,9 @@ public GapicSpannerRpc(final SpannerOptions options) { defaultChannelProviderBuilder.setAttemptDirectPath(true); defaultChannelProviderBuilder.setAttemptDirectPathXds(); } + + options.enablegRPCMetrics(defaultChannelProviderBuilder); + if (options.isUseVirtualThreads()) { ExecutorService executor = tryCreateVirtualThreadPerTaskExecutor("spanner-virtual-grpc-executor"); @@ -1974,10 +1980,24 @@ private static T get(final Future future) throws SpannerException { future.cancel(true); throw SpannerExceptionFactory.propagateInterrupt(e); } catch (Exception e) { - throw newSpannerException(context, e); + throw newSpannerException(context, e, null); } } + private GrpcCallContext createBaseCallContext() { + GrpcCallContext context = GrpcCallContext.createDefault(); + if (compressorName != null) { + // This sets the compressor for Client -> Server. + context = context.withCallOptions(context.getCallOptions().withCompression(compressorName)); + } + if (endToEndTracingEnabled) { + context = context.withExtraHeaders(metadataProvider.newEndToEndTracingHeader()); + } + return context + .withStreamWaitTimeoutDuration(waitTimeout) + .withStreamIdleTimeoutDuration(idleTimeout); + } + // Before removing this method, please verify with a code owner that it is not used // in any internal testing infrastructure. @VisibleForTesting @@ -2002,7 +2022,7 @@ GrpcCallContext newCallContext( ReqT request, MethodDescriptor method, boolean routeToLeader) { - GrpcCallContext context = GrpcCallContext.createDefault(); + GrpcCallContext context = this.baseGrpcCallContext; if (options != null) { if (this.isGrpcGcpExtensionEnabled) { // Set channel affinity in gRPC-GCP. @@ -2019,17 +2039,10 @@ GrpcCallContext newCallContext( context = context.withChannelAffinity(Option.CHANNEL_HINT.getLong(options).intValue()); } } - if (compressorName != null) { - // This sets the compressor for Client -> Server. - context = context.withCallOptions(context.getCallOptions().withCompression(compressorName)); - } context = context.withExtraHeaders(metadataProvider.newExtraHeaders(resource, projectName)); if (routeToLeader && leaderAwareRoutingEnabled) { context = context.withExtraHeaders(metadataProvider.newRouteToLeaderHeader()); } - if (endToEndTracingEnabled) { - context = context.withExtraHeaders(metadataProvider.newEndToEndTracingHeader()); - } if (callCredentialsProvider != null) { CallCredentials callCredentials = callCredentialsProvider.getCallCredentials(); if (callCredentials != null) { @@ -2037,10 +2050,6 @@ GrpcCallContext newCallContext( context.withCallOptions(context.getCallOptions().withCallCredentials(callCredentials)); } } - context = - context - .withStreamWaitTimeoutDuration(waitTimeout) - .withStreamIdleTimeoutDuration(idleTimeout); CallContextConfigurator configurator = SpannerOptions.CALL_CONTEXT_CONFIGURATOR_KEY.get(); ApiCallContext apiCallContextFromContext = null; if (configurator != null) { diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java index dba3b38e92f..b972ecdcef4 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java @@ -87,6 +87,8 @@ class HeaderInterceptor implements ClientInterceptor { CacheBuilder.newBuilder().maximumSize(1000).build(); private final Cache> builtInAttributesCache = CacheBuilder.newBuilder().maximumSize(1000).build(); + private final Cache> keyCache = + CacheBuilder.newBuilder().maximumSize(1000).build(); // Get the global singleton Tagger object. private static final Tagger TAGGER = Tags.getTagger(); @@ -116,7 +118,7 @@ public void start(Listener responseListener, Metadata headers) { try { Span span = Span.current(); DatabaseName databaseName = extractDatabaseName(headers); - String key = databaseName + method.getFullMethodName(); + String key = extractKey(databaseName, method.getFullMethodName()); TagContext tagContext = getTagContext(key, method.getFullMethodName(), databaseName); Attributes attributes = getMetricAttributes(key, method.getFullMethodName(), databaseName); @@ -201,6 +203,13 @@ private Map parseServerTimingHeader(String serverTiming) { return serverTimingMetrics; } + private String extractKey(DatabaseName databaseName, String methodName) + throws ExecutionException { + Cache keys = + keyCache.get(databaseName, () -> CacheBuilder.newBuilder().maximumSize(1000).build()); + return keys.get(methodName, () -> databaseName + methodName); + } + private DatabaseName extractDatabaseName(Metadata headers) throws ExecutionException { String googleResourcePrefix = headers.get(GOOGLE_CLOUD_RESOURCE_PREFIX_KEY); if (googleResourcePrefix != null) { 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 0fb4af2e8c7..70209917f0b 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 @@ -4896,6 +4896,144 @@ public void testMetadataUnknownTypes() { } } + @Test + public void testStatementWithUnnamedParameters() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client.getStatementFactory().withUnnamedParameters("select id from test where b=?", true); + Statement generatedStatement = + Statement.newBuilder("select id from test where b=@p1").bind("p1").to(true).build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + + @Test + public void testStatementWithUnnamedParametersAndSingleLineComment() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client + .getStatementFactory() + .withUnnamedParameters( + "-- comment about ? in the statement\nselect id from test where b=?", true); + Statement generatedStatement = + Statement.newBuilder("-- comment about ? in the statement\nselect id from test where b=@p1") + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + + @Test + public void testStatementWithUnnamedParametersAndSingleLineCommentWithHash() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client + .getStatementFactory() + .withUnnamedParameters( + "# comment about ? in the statement\nselect id from test where b=?", true); + Statement generatedStatement = + Statement.newBuilder("# comment about ? in the statement\nselect id from test where b=@p1") + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + + @Test + public void testStatementWithUnnamedParametersAndMultiLineComment() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client + .getStatementFactory() + .withUnnamedParameters( + "# comment about ? in the statement\nselect id from test\n /* This is a ? comment \n about ? */ \n where b=? # this is a inline command about ?", + true); + Statement generatedStatement = + Statement.newBuilder( + "# comment about ? in the statement\nselect id from test\n /* This is a ? comment \n about ? */ \n where b=@p1 # this is a inline command about ?") + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + + @Test + public void testStatementWithUnnamedParametersAndStringLiteralWithQuestionMark() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client + .getStatementFactory() + .withUnnamedParameters("select id from test where name = \"abc?\" AND b=?", true); + Statement generatedStatement = + Statement.newBuilder("select id from test where name = \"abc?\" AND b=@p1") + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + + @Test + public void testStatementWithUnnamedParametersAndHint() { + DatabaseClient client = + spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE)); + + Statement statement = + client + .getStatementFactory() + .withUnnamedParameters("@{FORCE_INDEX=ABCDEF} select id from test where b=?", true); + Statement generatedStatement = + Statement.newBuilder("@{FORCE_INDEX=ABCDEF} select id from test where b=@p1") + .bind("p1") + .to(true) + .build(); + mockSpanner.putStatementResult(StatementResult.query(generatedStatement, SELECT1_RESULTSET)); + + try (ResultSet resultSet = client.singleUse().executeQuery(statement)) { + assertTrue(resultSet.next()); + assertEquals(1L, resultSet.getLong(0)); + assertFalse(resultSet.next()); + } + } + @Test public void testStatementWithBytesArrayParameter() { Statement statement = diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java index f0c13b0f389..d2db2e4bca0 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java @@ -91,18 +91,12 @@ public static void setup() { String client_name = "spanner-java/"; openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build(); - attributes = provider.createClientAttributes("test-project", client_name); + attributes = provider.createClientAttributes(); expectedCommonBaseAttributes = Attributes.builder() - .put(BuiltInMetricsConstant.PROJECT_ID_KEY, "test-project") - .put(BuiltInMetricsConstant.INSTANCE_CONFIG_ID_KEY, "unknown") - .put( - BuiltInMetricsConstant.LOCATION_ID_KEY, - BuiltInMetricsProvider.detectClientLocation()) .put(BuiltInMetricsConstant.CLIENT_NAME_KEY, client_name) .put(BuiltInMetricsConstant.CLIENT_UID_KEY, attributes.get("client_uid")) - .put(BuiltInMetricsConstant.CLIENT_HASH_KEY, attributes.get("client_hash")) .put(BuiltInMetricsConstant.INSTANCE_ID_KEY, "i") .put(BuiltInMetricsConstant.DATABASE_KEY, "d") .put(BuiltInMetricsConstant.DIRECT_PATH_ENABLED_KEY, "false") diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterTest.java index f9a6e9df9a6..84a8cf4460c 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterTest.java @@ -16,7 +16,6 @@ package com.google.cloud.spanner; -import static com.google.cloud.spanner.BuiltInMetricsConstant.ATTEMPT_COUNT_NAME; import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_HASH_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_NAME_KEY; import static com.google.cloud.spanner.BuiltInMetricsConstant.CLIENT_UID_KEY; @@ -32,7 +31,6 @@ import static com.google.cloud.spanner.BuiltInMetricsConstant.PROJECT_ID_KEY; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -47,7 +45,6 @@ import com.google.monitoring.v3.TimeSeries; import com.google.protobuf.Empty; import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.InstrumentationScopeInfo; import io.opentelemetry.sdk.metrics.InstrumentType; import io.opentelemetry.sdk.metrics.data.AggregationTemporality; @@ -81,7 +78,7 @@ public class SpannerCloudMonitoringExporterTest { private static final String instanceId = "fake-instance"; private static final String locationId = "global"; private static final String databaseId = "fake-database"; - private static final String clientName = "spanner-java"; + private static final String clientName = "spanner-java/"; private static final String clientHash = "spanner-test"; private static final String instanceConfigId = "fake-instance-config-id"; @@ -93,28 +90,38 @@ public class SpannerCloudMonitoringExporterTest { private SpannerCloudMonitoringExporter exporter; private Attributes attributes; + + private Attributes resourceAttributes; private Resource resource; private InstrumentationScopeInfo scope; + private String client_uid; + @Before public void setUp() { fakeMetricServiceClient = new FakeMetricServiceClient(mockMetricServiceStub); exporter = new SpannerCloudMonitoringExporter(projectId, fakeMetricServiceClient); + this.client_uid = BuiltInMetricsProvider.INSTANCE.createClientAttributes().get("client_uid"); + attributes = Attributes.builder() - .put(PROJECT_ID_KEY, projectId) .put(INSTANCE_ID_KEY, instanceId) - .put(LOCATION_ID_KEY, locationId) - .put(INSTANCE_CONFIG_ID_KEY, instanceConfigId) .put(DATABASE_KEY, databaseId) .put(CLIENT_NAME_KEY, clientName) - .put(CLIENT_HASH_KEY, clientHash) + .put(CLIENT_UID_KEY, this.client_uid) .put(String.valueOf(DIRECT_PATH_ENABLED_KEY), true) .put(String.valueOf(DIRECT_PATH_USED_KEY), true) .build(); - resource = Resource.create(Attributes.empty()); + resourceAttributes = + Attributes.builder() + .put(PROJECT_ID_KEY, projectId) + .put(LOCATION_ID_KEY, locationId) + .put(CLIENT_HASH_KEY, clientHash) + .put(INSTANCE_CONFIG_ID_KEY, instanceConfigId) + .build(); + resource = Resource.create(resourceAttributes); scope = InstrumentationScopeInfo.create(GAX_METER_NAME); } @@ -177,8 +184,10 @@ public void testExportingSumData() { DIRECT_PATH_ENABLED_KEY.getKey(), "true", DIRECT_PATH_USED_KEY.getKey(), - "true"); - assertThat(timeSeries.getMetric().getLabelsMap()).hasSize(4); + "true", + CLIENT_UID_KEY.getKey(), + this.client_uid); + assertThat(timeSeries.getMetric().getLabelsMap()).hasSize(5); assertThat(timeSeries.getPoints(0).getValue().getInt64Value()).isEqualTo(fakeValue); assertThat(timeSeries.getPoints(0).getInterval().getStartTime().getNanos()) @@ -239,7 +248,7 @@ public void testExportingHistogramData() { INSTANCE_CONFIG_ID_KEY.getKey(), instanceConfigId, CLIENT_HASH_KEY.getKey(), clientHash); - assertThat(timeSeries.getMetric().getLabelsMap()).hasSize(4); + assertThat(timeSeries.getMetric().getLabelsMap()).hasSize(5); assertThat(timeSeries.getMetric().getLabelsMap()) .containsExactly( DATABASE_KEY.getKey(), @@ -249,7 +258,9 @@ public void testExportingHistogramData() { DIRECT_PATH_ENABLED_KEY.getKey(), "true", DIRECT_PATH_USED_KEY.getKey(), - "true"); + "true", + CLIENT_UID_KEY.getKey(), + this.client_uid); Distribution distribution = timeSeries.getPoints(0).getValue().getDistributionValue(); assertThat(distribution.getCount()).isEqualTo(3); @@ -274,11 +285,7 @@ public void testExportingSumDataInBatches() { Collection toExport = new ArrayList<>(); for (int i = 0; i < 250; i++) { LongPointData longPointData = - ImmutableLongPointData.create( - startEpoch, - endEpoch, - attributes.toBuilder().put(CLIENT_UID_KEY, "client_uid" + i).build(), - i); + ImmutableLongPointData.create(startEpoch, endEpoch, attributes, i); MetricData longData = ImmutableMetricData.createLongSum( @@ -331,7 +338,7 @@ public void testExportingSumDataInBatches() { DIRECT_PATH_USED_KEY.getKey(), "true", CLIENT_UID_KEY.getKey(), - "client_uid" + i); + this.client_uid); assertThat(timeSeries.getPoints(0).getValue().getInt64Value()).isEqualTo(i); assertThat(timeSeries.getPoints(0).getInterval().getStartTime().getNanos()) @@ -348,56 +355,6 @@ public void getAggregationTemporality() throws IOException { .isEqualTo(AggregationTemporality.CUMULATIVE); } - @Test - public void testSkipExportingDataIfMissingInstanceId() throws IOException { - Attributes attributesWithoutInstanceId = - Attributes.builder().putAll(attributes).remove(INSTANCE_ID_KEY).build(); - - SpannerCloudMonitoringExporter actualExporter = - SpannerCloudMonitoringExporter.create(projectId, null, null); - assertThat(actualExporter.getAggregationTemporality(InstrumentType.COUNTER)) - .isEqualTo(AggregationTemporality.CUMULATIVE); - ArgumentCaptor argumentCaptor = - ArgumentCaptor.forClass(CreateTimeSeriesRequest.class); - - UnaryCallable mockCallable = Mockito.mock(UnaryCallable.class); - Mockito.when(mockMetricServiceStub.createServiceTimeSeriesCallable()).thenReturn(mockCallable); - ApiFuture future = ApiFutures.immediateFuture(Empty.getDefaultInstance()); - Mockito.when(mockCallable.futureCall(argumentCaptor.capture())).thenReturn(future); - - long fakeValue = 11L; - - long startEpoch = 10; - long endEpoch = 15; - LongPointData longPointData = - ImmutableLongPointData.create(startEpoch, endEpoch, attributesWithoutInstanceId, fakeValue); - - MetricData operationLongData = - ImmutableMetricData.createLongSum( - resource, - scope, - "spanner.googleapis.com/internal/client/" + OPERATION_COUNT_NAME, - "description", - "1", - ImmutableSumData.create( - true, AggregationTemporality.CUMULATIVE, ImmutableList.of(longPointData))); - - MetricData attemptLongData = - ImmutableMetricData.createLongSum( - resource, - scope, - "spanner.googleapis.com/internal/client/" + ATTEMPT_COUNT_NAME, - "description", - "1", - ImmutableSumData.create( - true, AggregationTemporality.CUMULATIVE, ImmutableList.of(longPointData))); - - CompletableResultCode resultCode = - exporter.export(Arrays.asList(operationLongData, attemptLongData)); - assertTrue(resultCode.isSuccess()); - assertTrue(exporter.lastExportSkippedData()); - } - private static class FakeMetricServiceClient extends MetricServiceClient { protected FakeMetricServiceClient(MetricServiceStub stub) { diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerExceptionFactoryTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerExceptionFactoryTest.java index 2c4801bd0d7..9f0ee04e858 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerExceptionFactoryTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/SpannerExceptionFactoryTest.java @@ -250,4 +250,17 @@ private Metadata createResourceTypeMetadata(String resourceType, String resource return trailers; } + + @Test + public void withRequestId() { + XGoogSpannerRequestId reqIdIn = XGoogSpannerRequestId.of(1, 2, 3, 4); + Status status = Status.fromCodeValue(Status.Code.ABORTED.value()); + Exception exc = new StatusRuntimeException(status); + SpannerException spannerExceptionWithReqId = + SpannerExceptionFactory.newSpannerException(exc, reqIdIn); + assertThat(spannerExceptionWithReqId.getRequestId()).isEqualTo(reqIdIn.toString()); + SpannerException spannerExceptionWithoutReqId = + SpannerExceptionFactory.newSpannerException(exc); + assertThat(spannerExceptionWithoutReqId.getRequestId()).isEqualTo(""); + } } 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 d5b5a3ec619..e4a036673bc 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 @@ -18,6 +18,8 @@ import static com.google.common.testing.SerializableTester.reserializeAndAssert; 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.assertThrows; @@ -42,6 +44,17 @@ public void basic() { reserializeAndAssert(stmt); } + @Test + public void basicWithParameters() { + String sql = "SELECT @name"; + Statement stmt = Statement.of(sql, ImmutableMap.of("name", Value.string("hello"))); + assertEquals(sql, stmt.getSql()); + assertFalse(stmt.getParameters().isEmpty()); + assertEquals(Value.string("hello"), stmt.getParameters().get("name")); + assertEquals(sql + " {name: hello}", stmt.toString()); + reserializeAndAssert(stmt); + } + @Test public void serialization() { Statement stmt = 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 3c96a482340..f88d7683967 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 @@ -42,16 +42,28 @@ import com.google.common.testing.EqualsTester; import com.google.protobuf.ListValue; import com.google.protobuf.NullValue; +import com.google.protobuf.ProtocolMessageEnum; +import com.google.spanner.v1.PartialResultSet; +import com.google.spanner.v1.TransactionOptions.IsolationLevel; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Random; +import java.util.Set; +import java.util.TimeZone; import java.util.function.Supplier; import java.util.stream.Collectors; import org.junit.Test; @@ -2496,6 +2508,306 @@ public void verifyBrokenSerialization() { reserializeAndAssert(BrokenSerializationList.of(1, 2, 3)); } + @Test + public void testToValue() { + Value value = Value.toValue(null); + assertNull(value.getType()); + assertEquals("NULL", value.getAsString()); + + int i = 10; + value = Value.toValue(i); + assertNull(value.getType()); + assertEquals("10", value.getAsString()); + + Integer j = 10; + value = Value.toValue(j); + assertNull(value.getType()); + assertEquals("10", value.getAsString()); + + long k = 10L; + value = Value.toValue(k); + assertNull(value.getType()); + assertEquals("10", value.getAsString()); + + Long l = 10L; + value = Value.toValue(i); + assertNull(value.getType()); + assertEquals("10", value.getAsString()); + + boolean m = true; + value = Value.toValue(m); + assertEquals(Type.bool(), value.getType()); + assertTrue(value.getBool()); + + Boolean n = true; + value = Value.toValue(n); + assertEquals(Type.bool(), value.getType()); + assertTrue(value.getBool()); + + Float o = 0.3f; + value = Value.toValue(o); + assertEquals(Type.float32(), value.getType()); + assertEquals(0.3f, value.getFloat32(), 0); + + float p = 0.3f; + value = Value.toValue(p); + assertEquals(Type.float32(), value.getType()); + assertEquals(0.3f, value.getFloat32(), 0); + + Double q = 0.4d; + value = Value.toValue(q); + assertEquals(Type.float64(), value.getType()); + assertEquals(0.4d, value.getFloat64(), 0); + + double s = 0.5d; + value = Value.toValue(s); + assertEquals(Type.float64(), value.getType()); + assertEquals(0.5d, value.getFloat64(), 0); + + BigDecimal t = BigDecimal.valueOf(0.6d); + value = Value.toValue(t); + assertEquals(Type.numeric(), value.getType()); + assertEquals(t, value.getNumeric()); + + ByteArray bytes = ByteArray.copyFrom("hello"); + value = Value.toValue(bytes); + assertEquals(Type.bytes(), value.getType()); + assertEquals(bytes, value.getBytes()); + + byte[] byteArray = "hello".getBytes(); + value = Value.toValue(byteArray); + assertEquals(Type.bytes(), value.getType()); + assertEquals(bytes, value.getBytes()); + + Date date = Date.fromYearMonthDay(2018, 2, 26); + value = Value.toValue(date); + assertEquals(Type.date(), value.getType()); + assertEquals(date, value.getDate()); + + LocalDate localDate = LocalDate.of(2018, 2, 26); + value = Value.toValue(localDate); + assertEquals(Type.date(), value.getType()); + assertEquals(date, value.getDate()); + + TimeZone defaultTimezone = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("Europe/Paris")); + LocalDateTime localDateTime = LocalDateTime.of(2018, 2, 26, 11, 30, 10); + value = Value.toValue(localDateTime); + assertNull(value.getType()); + assertEquals("2018-02-26T10:30:10.000Z", value.getAsString()); + TimeZone.setDefault(defaultTimezone); + + OffsetDateTime offsetDateTime = OffsetDateTime.of(localDateTime, ZoneOffset.ofHours(10)); + value = Value.toValue(offsetDateTime); + assertNull(value.getType()); + assertEquals("2018-02-26T01:30:10.000Z", value.getAsString()); + + ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Asia/Kolkata")); + value = Value.toValue(zonedDateTime); + assertNull(value.getType()); + assertEquals("2018-02-26T06:00:10.000Z", value.getAsString()); + + ProtocolMessageEnum protocolMessageEnum = IsolationLevel.SERIALIZABLE; + value = Value.toValue(protocolMessageEnum); + assertEquals( + Type.protoEnum("google.spanner.v1.TransactionOptions.IsolationLevel"), value.getType()); + assertEquals( + protocolMessageEnum, + value.getProtoEnum( + (val -> { + switch (val) { + case 1: + return IsolationLevel.SERIALIZABLE; + case 2: + return IsolationLevel.REPEATABLE_READ; + default: + return IsolationLevel.ISOLATION_LEVEL_UNSPECIFIED; + } + }))); + + PartialResultSet partialResultSet = + PartialResultSet.newBuilder() + .addValues(com.google.protobuf.Value.newBuilder().setStringValue("hello").build()) + .build(); + value = Value.toValue(partialResultSet); + assertEquals(Type.proto("google.spanner.v1.PartialResultSet"), value.getType()); + assertEquals(partialResultSet, value.getProtoMessage(PartialResultSet.getDefaultInstance())); + + Interval interval = Interval.ofDays(10); + value = Value.toValue(interval); + assertEquals(Type.interval(), value.getType()); + assertEquals(interval, value.getInterval()); + + Struct struct = Struct.newBuilder().set("name").to(10L).build(); + value = Value.toValue(struct); + assertEquals(Type.struct(StructField.of("name", Type.int64())), value.getType()); + assertEquals(struct, value.getStruct()); + + Timestamp timestamp = Timestamp.now(); + value = Value.toValue(timestamp); + assertEquals(Type.timestamp(), value.getType()); + assertEquals(timestamp, value.getTimestamp()); + + List expectedBoolArray = Arrays.asList(true, false); + boolean[] bools1 = {true, false}; + value = Value.toValue(bools1); + assertEquals(Type.array(Type.bool()), value.getType()); + assertEquals(expectedBoolArray, value.getBoolArray()); + + Boolean[] bools2 = {true, false}; + value = Value.toValue(bools2); + assertEquals(Type.array(Type.bool()), value.getType()); + assertEquals(expectedBoolArray, value.getBoolArray()); + + List expectedFloatArray = Arrays.asList(0.1f, 0.2f, 0.3f); + Float[] floats1 = {0.1f, 0.2f, 0.3f}; + value = Value.toValue(floats1); + assertEquals(Type.array(Type.float32()), value.getType()); + assertEquals(expectedFloatArray, value.getFloat32Array()); + + float[] floats2 = {0.1f, 0.2f, 0.3f}; + value = Value.toValue(floats2); + assertEquals(Type.array(Type.float32()), value.getType()); + assertEquals(expectedFloatArray, value.getFloat32Array()); + + List expectedDoubleArray = Arrays.asList(0.1d, 0.2d, 0.3d, 0.4d); + Double[] doubles1 = {0.1d, 0.2d, 0.3d, 0.4d}; + value = Value.toValue(doubles1); + assertEquals(Type.array(Type.float64()), value.getType()); + assertEquals(expectedDoubleArray, value.getFloat64Array()); + + double[] doubles2 = {0.1d, 0.2d, 0.3d, 0.4d}; + value = Value.toValue(doubles2); + assertEquals(Type.array(Type.float64()), value.getType()); + assertEquals(expectedDoubleArray, value.getFloat64Array()); + + List expectedIntLongArray = Arrays.asList("1", "2", "3"); + int[] ints1 = {1, 2, 3}; + value = Value.toValue(ints1); + assertNull(value.getType()); + assertEquals(expectedIntLongArray, value.getAsStringList()); + + Integer[] ints2 = {1, 2, 3}; + value = Value.toValue(ints2); + assertNull(value.getType()); + assertEquals(expectedIntLongArray, value.getAsStringList()); + + Long[] longs1 = {1L, 2L, 3L}; + value = Value.toValue(longs1); + assertNull(value.getType()); + assertEquals(expectedIntLongArray, value.getAsStringList()); + + long[] longs2 = {1L, 2L, 3L}; + value = Value.toValue(longs2); + assertNull(value.getType()); + assertEquals(expectedIntLongArray, value.getAsStringList()); + + String string = "hello"; + value = Value.toValue(string); + assertNull(value.getType()); + assertEquals("hello", value.getAsString()); + } + + @Test + public void testToValueIterable() { + List booleans = Arrays.asList(true, false); + Value value = Value.toValue(booleans); + assertEquals(Type.array(Type.bool()), value.getType()); + assertEquals(booleans, value.getBoolArray()); + + List ints = Arrays.asList(1, 2, 3); + value = Value.toValue(ints); + assertNull(value.getType()); + assertEquals(Arrays.asList("1", "2", "3"), value.getAsStringList()); + + List longs = Arrays.asList(1L, 2L, 3L); + value = Value.toValue(longs); + assertNull(value.getType()); + assertEquals(Arrays.asList("1", "2", "3"), value.getAsStringList()); + + Set floats = new HashSet<>(Arrays.asList(0.1f, 0.2f, 0.3f)); + value = Value.toValue(floats); + assertEquals(Type.array(Type.float32()), value.getType()); + assertEquals(Arrays.asList(0.1f, 0.2f, 0.3f), value.getFloat32Array()); + + List doubles = Arrays.asList(0.1d, 0.2d, 0.3d, 0.4d); + value = Value.toValue(doubles); + assertEquals(Type.array(Type.float64()), value.getType()); + assertEquals(doubles, value.getFloat64Array()); + + List bigDecimals = + Arrays.asList(BigDecimal.valueOf(0.1d), BigDecimal.valueOf(0.2d)); + value = Value.toValue(bigDecimals); + assertEquals(Type.array(Type.numeric()), value.getType()); + assertEquals(bigDecimals, value.getNumericArray()); + + List byteArrays = + Arrays.asList(ByteArray.copyFrom("hello"), ByteArray.copyFrom("world")); + value = Value.toValue(byteArrays); + assertEquals(Type.array(Type.bytes()), value.getType()); + assertEquals(byteArrays, value.getBytesArray()); + + List bytes = Arrays.asList("hello".getBytes(), "world".getBytes()); + value = Value.toValue(bytes); + assertEquals(Type.array(Type.bytes()), value.getType()); + assertEquals(byteArrays, value.getBytesArray()); + + List intervals = Arrays.asList(Interval.ofDays(10), Interval.ofDays(20)); + value = Value.toValue(intervals); + assertEquals(Type.array(Type.interval()), value.getType()); + assertEquals(intervals, value.getIntervalArray()); + + List timestamps = Arrays.asList(Timestamp.now(), Timestamp.now()); + value = Value.toValue(timestamps); + assertEquals(Type.array(Type.timestamp()), value.getType()); + assertEquals(timestamps, value.getTimestampArray()); + + List dates = + Arrays.asList(Date.fromYearMonthDay(2024, 8, 23), Date.fromYearMonthDay(2024, 12, 27)); + value = Value.toValue(dates); + assertEquals(Type.array(Type.date()), value.getType()); + assertEquals(dates, value.getDateArray()); + + List localDates = + Arrays.asList(LocalDate.of(2024, 8, 23), LocalDate.of(2024, 12, 27)); + value = Value.toValue(localDates); + assertEquals(Type.array(Type.date()), value.getType()); + assertEquals(dates, value.getDateArray()); + + TimeZone defaultTimezone = TimeZone.getDefault(); + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Kolkata")); + List localDateTimes = + Arrays.asList( + LocalDateTime.of(2024, 8, 23, 1, 49, 52, 10), + LocalDateTime.of(2024, 12, 27, 1, 49, 52, 10)); + value = Value.toValue(localDateTimes); + assertNull(value.getType()); + assertEquals( + Arrays.asList("2024-08-22T20:19:52.000Z", "2024-12-26T20:19:52.000Z"), + value.getAsStringList()); + TimeZone.setDefault(defaultTimezone); + + List offsetDateTimes = + Arrays.asList( + LocalDateTime.of(2024, 8, 23, 1, 49, 52, 10).atOffset(ZoneOffset.ofHours(1)), + LocalDateTime.of(2024, 12, 27, 1, 49, 52, 10).atOffset(ZoneOffset.ofHours(1))); + value = Value.toValue(offsetDateTimes); + assertNull(value.getType()); + assertEquals( + Arrays.asList("2024-08-23T00:49:52.000Z", "2024-12-27T00:49:52.000Z"), + value.getAsStringList()); + + List zonedDateTimes = + Arrays.asList( + LocalDateTime.of(2024, 8, 23, 1, 49, 52, 10).atZone(ZoneId.of("UTC")), + LocalDateTime.of(2024, 12, 27, 1, 49, 52, 10).atZone(ZoneId.of("UTC"))); + value = Value.toValue(zonedDateTimes); + assertNull(value.getType()); + assertEquals( + Arrays.asList("2024-08-23T01:49:52.000Z", "2024-12-27T01:49:52.000Z"), + value.getAsStringList()); + } + private static class BrokenSerializationList extends ForwardingList implements Serializable { private static final long serialVersionUID = 1L; 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 fa208e799f9..4055f8e949c 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 @@ -18,8 +18,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.ErrorCode; @@ -64,6 +66,13 @@ private static String getScriptFile(Dialect dialect) { } } + @Test + public void testIsQuery() { + AbstractStatementParser parser = AbstractStatementParser.getInstance(dialect); + ParsedStatement parsedStatement = parser.parse(Statement.of("show/spanner.statement_tag;")); + assertTrue(parsedStatement.isQuery()); + } + @Test public void testExecuteClientSideStatementsScript() throws Exception { SqlScriptVerifier verifier = new SqlScriptVerifier(new TestConnectionProvider(dialect)); @@ -145,6 +154,7 @@ public void testSetStatementTimeout() { new DurationTestData("set statement_timeout = " + resetValue + " ", Duration.ZERO), }) { ConnectionStatementExecutor executor = mock(ConnectionStatementExecutor.class); + when(executor.getDialect()).thenReturn(dialect); ParsedStatement statement = parser.parse(Statement.of(data.sql)); assertEquals( ClientSideStatementType.SET_STATEMENT_TIMEOUT, statement.getClientSideStatementType()); @@ -188,6 +198,7 @@ public void testSetMaxCommitDelay() { new DurationTestData("set " + prefix + "max_commit_delay = null ", Duration.ZERO), }) { ConnectionStatementExecutor executor = mock(ConnectionStatementExecutor.class); + when(executor.getDialect()).thenReturn(dialect); ParsedStatement statement = parser.parse(Statement.of(data.sql)); assertEquals( ClientSideStatementType.SET_MAX_COMMIT_DELAY, statement.getClientSideStatementType()); @@ -293,7 +304,7 @@ private static void generateTestStatements( log( statement.getExamplePrerequisiteStatements(), withInvalidSuffix(sql), - parser.isQuery(withInvalidSuffix(sql)) + parser.parse(Statement.of(withInvalidSuffix(sql))).isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); } @@ -313,13 +324,13 @@ private static void generateTestStatements( log( statement.getExamplePrerequisiteStatements(), withSuffix(replacement, sql), - parser.isQuery(withSuffix(replacement, sql)) + parser.parse(Statement.of(withSuffix(replacement, sql))).isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); log( statement.getExamplePrerequisiteStatements(), replaceLastSpaceWith(replacement, sql), - parser.isQuery(replaceLastSpaceWith(replacement, sql)) + parser.parse(Statement.of(replaceLastSpaceWith(replacement, sql))).isQuery() ? ErrorCode.UNIMPLEMENTED : ErrorCode.INVALID_ARGUMENT); } 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 72a8e64ae4c..0c86da54de1 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 @@ -64,6 +64,7 @@ public void testExecuteSetAutocommit() { ParsedStatement subject = parser.parse(Statement.of("set autocommit = true")); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetAutocommit(any(Boolean.class))).thenCallRealMethod(); for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { @@ -80,6 +81,7 @@ public void testExecuteSetReadOnly() { parser.parse(Statement.of(String.format("set %sreadonly = true", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetReadOnly(any(Boolean.class))).thenCallRealMethod(); for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { @@ -98,6 +100,7 @@ public void testExecuteSetReadOnlyTo() { parser.parse(Statement.of(String.format("set %sreadonly to true", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetReadOnly(any(Boolean.class))).thenCallRealMethod(); for (Boolean mode : new Boolean[] {Boolean.FALSE, Boolean.TRUE}) { @@ -116,6 +119,7 @@ public void testExecuteSetAutocommitDmlMode() { Statement.of(String.format("set %sautocommit_dml_mode='foo'", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetAutocommitDmlMode(any(AutocommitDmlMode.class))).thenCallRealMethod(); for (AutocommitDmlMode mode : AutocommitDmlMode.values()) { @@ -135,6 +139,7 @@ public void testExecuteSetStatementTimeout() { ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); when(executor.statementSetStatementTimeout(any(Duration.class))).thenCallRealMethod(); ConnectionImpl connection = mock(ConnectionImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); for (TimeUnit unit : ReadOnlyStalenessUtil.SUPPORTED_UNITS) { for (Long val : new Long[] {1L, 100L, 999L}) { @@ -173,6 +178,7 @@ public void testExecuteSetReadOnlyStaleness() { Statement.of(String.format("set %sread_only_staleness='foo'", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetReadOnlyStaleness(any(TimestampBound.class))).thenCallRealMethod(); for (TimestampBound val : @@ -219,6 +225,7 @@ public void testExecuteSetOptimizerVersion() { Statement.of(String.format("set %soptimizer_version='foo'", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetOptimizerVersion(any(String.class))).thenCallRealMethod(); for (String version : new String[] {"1", "200", "", "LATEST"}) { @@ -239,6 +246,7 @@ public void testExecuteSetOptimizerStatisticsPackage() { String.format("set %soptimizer_statistics_package='foo'", getNamespace(dialect)))); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = mock(ConnectionStatementExecutorImpl.class); + when(executor.getDialect()).thenReturn(dialect); when(executor.getConnection()).thenReturn(connection); when(executor.statementSetOptimizerStatisticsPackage(any(String.class))).thenCallRealMethod(); for (String statisticsPackage : new String[] {"custom-package", ""}) { @@ -259,6 +267,7 @@ public void testExecuteSetTransaction() { ParsedStatement subject = parser.parse(Statement.of("set transaction read_only")); ConnectionImpl connection = mock(ConnectionImpl.class); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); + when(executor.getDialect()).thenReturn(dialect); for (TransactionMode mode : TransactionMode.values()) { subject .getClientSideStatement() 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 4d582e09007..e500851b275 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 @@ -135,6 +135,7 @@ private DdlBatch createSubject(DdlClient ddlClient) { } private DdlBatch createSubject(DdlClient ddlClient, DatabaseClient dbClient) { + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); return DdlBatch.newBuilder() .setDdlClient(ddlClient) .setDatabaseClient(dbClient) @@ -273,7 +274,7 @@ public void testGetStateAndIsActive() { assertThat(batch.isActive(), is(true)); ParsedStatement statement = mock(ParsedStatement.class); when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + when(statement.getSql()).thenReturn("CREATE TABLE FOO"); when(statement.getType()).thenReturn(StatementType.DDL); batch.executeDdlAsync(CallType.SYNC, statement); try { @@ -319,7 +320,7 @@ public void testRunBatch() { ParsedStatement statement = mock(ParsedStatement.class); when(statement.getType()).thenReturn(StatementType.DDL); when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + when(statement.getSql()).thenReturn("CREATE TABLE FOO"); client = createDefaultMockDdlClient(); batch = createSubject(client); @@ -382,10 +383,12 @@ public void testRunBatch() { // verify when protoDescriptors is null client = createDefaultMockDdlClient(); + DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); batch = DdlBatch.newBuilder() .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) + .setDatabaseClient(dbClient) .withStatementExecutor(new StatementExecutor()) .setSpan(Span.getInvalid()) .setProtoDescriptors(null) @@ -412,7 +415,7 @@ public void testRunBatch() { batch = DdlBatch.newBuilder() .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) + .setDatabaseClient(dbClient) .withStatementExecutor(new StatementExecutor()) .setSpan(Span.getInvalid()) .setProtoDescriptors(protoDescriptors) @@ -442,11 +445,13 @@ public void testUpdateCount() throws InterruptedException, ExecutionException { when(operationFuture.getMetadata()).thenReturn(metadataFuture); when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull())) .thenReturn(operationFuture); + DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); DdlBatch batch = DdlBatch.newBuilder() .withStatementExecutor(new StatementExecutor()) .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) + .setDatabaseClient(dbClient) .setSpan(Span.getInvalid()) .setConnectionState(new ConnectionState(new HashMap<>())) .build(); @@ -486,11 +491,13 @@ public void testFailedUpdateCount() throws InterruptedException, ExecutionExcept .runWithRetryForMissingDefaultSequenceKind(any(), any(), any(), any()); when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull())) .thenReturn(operationFuture); + DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); DdlBatch batch = DdlBatch.newBuilder() .withStatementExecutor(new StatementExecutor()) .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) + .setDatabaseClient(dbClient) .setSpan(Span.getInvalid()) .setConnectionState(new ConnectionState(new HashMap<>())) .build(); @@ -534,11 +541,13 @@ public void testFailedAfterFirstStatement() throws InterruptedException, Executi when(operationFuture.getMetadata()).thenReturn(metadataFuture); when(client.executeDdl(argThat(isListOfStringsWithSize(2)), isNull())) .thenReturn(operationFuture); + DatabaseClient dbClient = mock(DatabaseClient.class); + when(dbClient.getDialect()).thenReturn(Dialect.GOOGLE_STANDARD_SQL); DdlBatch batch = DdlBatch.newBuilder() .withStatementExecutor(new StatementExecutor()) .setDdlClient(client) - .setDatabaseClient(mock(DatabaseClient.class)) + .setDatabaseClient(dbClient) .setSpan(Span.getInvalid()) .setConnectionState(new ConnectionState(new HashMap<>())) .build(); @@ -572,7 +581,7 @@ public void testAbort() { ParsedStatement statement = mock(ParsedStatement.class); when(statement.getType()).thenReturn(StatementType.DDL); when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + when(statement.getSql()).thenReturn("CREATE TABLE FOO"); client = createDefaultMockDdlClient(); batch = createSubject(client); @@ -611,7 +620,7 @@ public void testCancel() { ParsedStatement statement = mock(ParsedStatement.class); when(statement.getType()).thenReturn(StatementType.DDL); when(statement.getStatement()).thenReturn(Statement.of("CREATE TABLE FOO")); - when(statement.getSqlWithoutComments()).thenReturn("CREATE TABLE FOO"); + when(statement.getSql()).thenReturn("CREATE TABLE FOO"); DdlClient client = createDefaultMockDdlClient(10000L); final DdlBatch batch = createSubject(client); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java index c61635fce23..3a25437354f 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/DdlClientTests.java @@ -32,7 +32,9 @@ 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.SpannerExceptionFactory; +import com.google.common.base.Suppliers; import com.google.common.io.ByteStreams; import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata; import java.io.InputStream; @@ -53,6 +55,7 @@ public class DdlClientTests { private DdlClient createSubject(DatabaseAdminClient client) { return DdlClient.newBuilder() + .setDialectSupplier(Suppliers.ofInstance(Dialect.GOOGLE_STANDARD_SQL)) .setProjectId(projectId) .setInstanceId(instanceId) .setDatabaseName(databaseId) @@ -108,20 +111,22 @@ public void testExecuteDdl() throws InterruptedException, ExecutionException { @Test public void testIsCreateDatabase() { - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE foo")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE \"foo\"")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE `foo`")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE\tfoo")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE\n foo")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE\t\n foo")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE DATABASE")); - assertTrue(DdlClient.isCreateDatabaseStatement("CREATE\t \n DATABASE foo")); - assertTrue(DdlClient.isCreateDatabaseStatement("create\t \n DATABASE foo")); - assertTrue(DdlClient.isCreateDatabaseStatement("create database foo")); + for (Dialect dialect : Dialect.values()) { + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE foo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE \"foo\"")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE `foo`")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE\tfoo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE\n foo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE\t\n foo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASE")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "CREATE\t \n DATABASE foo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "create\t \n DATABASE foo")); + assertTrue(DdlClient.isCreateDatabaseStatement(dialect, "create database foo")); - assertFalse(DdlClient.isCreateDatabaseStatement("CREATE VIEW foo")); - assertFalse(DdlClient.isCreateDatabaseStatement("CREATE DATABAS foo")); - assertFalse(DdlClient.isCreateDatabaseStatement("CREATE DATABASEfoo")); - assertFalse(DdlClient.isCreateDatabaseStatement("CREATE foo")); + assertFalse(DdlClient.isCreateDatabaseStatement(dialect, "CREATE VIEW foo")); + assertFalse(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABAS foo")); + assertFalse(DdlClient.isCreateDatabaseStatement(dialect, "CREATE DATABASEfoo")); + assertFalse(DdlClient.isCreateDatabaseStatement(dialect, "CREATE foo")); + } } } 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 629ae41daf4..ab04bb61a54 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 @@ -177,7 +177,7 @@ public void testGetStateAndIsActive() { assertThat(batch.isActive(), is(true)); ParsedStatement statement = mock(ParsedStatement.class); when(statement.getStatement()).thenReturn(Statement.of("UPDATE TEST SET COL1=2")); - when(statement.getSqlWithoutComments()).thenReturn("UPDATE TEST SET COL1=2"); + when(statement.getSql()).thenReturn("UPDATE TEST SET COL1=2"); when(statement.getType()).thenReturn(StatementType.UPDATE); get(batch.executeUpdateAsync(CallType.SYNC, statement)); boolean exception = false; 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 5feb10ebaaf..6a4731dbbda 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 @@ -128,7 +128,7 @@ protected boolean shouldAbort(String statement, ExecutionStep step) { @Override public void intercept( ParsedStatement statement, StatementExecutionStep step, UnitOfWork transaction) { - if (shouldAbort(statement.getSqlWithoutComments(), ExecutionStep.of(step))) { + if (shouldAbort(statement.getSql(), ExecutionStep.of(step))) { // ugly hack warning: inject the aborted state into the transaction manager to simulate an // abort if (transaction instanceof ReadWriteTransaction) { 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 e243fbd620a..0c592d85804 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 @@ -287,7 +287,7 @@ public void testExecuteQuery() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of("SELECT * FROM FOO"); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); ReadOnlyTransaction transaction = createSubject(staleness); ResultSet rs = @@ -306,7 +306,7 @@ public void testExecuteQueryWithOptionsTest() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of(sql); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); DatabaseClient client = mock(DatabaseClient.class); com.google.cloud.spanner.ReadOnlyTransaction tx = mock(com.google.cloud.spanner.ReadOnlyTransaction.class); @@ -344,7 +344,7 @@ public void testPlanQuery() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of("SELECT * FROM FOO"); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); ReadOnlyTransaction transaction = createSubject(staleness); ResultSet rs = @@ -366,7 +366,7 @@ public void testProfileQuery() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of("SELECT * FROM FOO"); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); ReadOnlyTransaction transaction = createSubject(staleness); ResultSet rs = @@ -388,7 +388,7 @@ public void testGetReadTimestamp() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of("SELECT * FROM FOO"); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); ReadOnlyTransaction transaction = createSubject(staleness); boolean expectedException = false; @@ -423,7 +423,7 @@ public void testState() { when(parsedStatement.isQuery()).thenReturn(true); Statement statement = Statement.of("SELECT * FROM FOO"); when(parsedStatement.getStatement()).thenReturn(statement); - when(parsedStatement.getSqlWithoutComments()).thenReturn(statement.getSql()); + when(parsedStatement.getSql()).thenReturn(statement.getSql()); ReadOnlyTransaction transaction = createSubject(); assertThat( diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java index 610a1a99cbe..c1af1e3f9dc 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; @@ -26,6 +27,7 @@ import com.google.cloud.spanner.MockSpannerServiceImpl; import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime; import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.SpannerBatchUpdateException; import com.google.cloud.spanner.SpannerException; import com.google.cloud.spanner.Statement; import com.google.cloud.spanner.TransactionMutationLimitExceededException; @@ -34,6 +36,7 @@ import com.google.rpc.Help.Link; import com.google.spanner.v1.BeginTransactionRequest; import com.google.spanner.v1.CommitRequest; +import com.google.spanner.v1.ExecuteBatchDmlRequest; import com.google.spanner.v1.ExecuteSqlRequest; import io.grpc.Metadata; import io.grpc.Status; @@ -219,4 +222,29 @@ public void testSqlStatements() { } } } + + @Test + public void testTransactionMutationLimitExceeded_isWrappedAsCauseOfBatchUpdateException() { + String sql = "update test set value=1 where true"; + Statement statement = Statement.of(sql); + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.exception( + statement, createTransactionMutationLimitExceededException())); + + try (Connection connection = createConnection()) { + connection.setAutocommit(true); + assertEquals(AutocommitDmlMode.TRANSACTIONAL, connection.getAutocommitDmlMode()); + + connection.startBatchDml(); + connection.execute(statement); + SpannerBatchUpdateException batchUpdateException = + assertThrows(SpannerBatchUpdateException.class, connection::runBatch); + assertNotNull(batchUpdateException.getCause()); + assertEquals( + TransactionMutationLimitExceededException.class, + batchUpdateException.getCause().getClass()); + } + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class)); + assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class)); + } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetPgSessionCharacteristicsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetPgSessionCharacteristicsTest.java index 96381281ca5..4b4331e5f3a 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetPgSessionCharacteristicsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SetPgSessionCharacteristicsTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import com.google.cloud.spanner.Dialect; import com.google.cloud.spanner.Statement; @@ -41,6 +42,7 @@ public class SetPgSessionCharacteristicsTest { @Test public void testSetIsolationLevelDefault() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = "set session characteristics as transaction isolation level default"; @@ -55,6 +57,7 @@ public void testSetIsolationLevelDefault() { @Test public void testSetIsolationLevelSerializable() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = "set session characteristics as transaction isolation level serializable"; @@ -69,6 +72,7 @@ public void testSetIsolationLevelSerializable() { @Test public void testSetIsolationLevelRepeatableRead() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = "set session characteristics as transaction isolation level repeatable read"; @@ -83,6 +87,7 @@ public void testSetIsolationLevelRepeatableRead() { @Test public void testSetIsolationLevelReadOnly() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = "set\tsession\ncharacteristics as transaction read only"; @@ -98,6 +103,7 @@ public void testSetIsolationLevelReadOnly() { @Test public void testSetIsolationLevelReadWrite() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = "set session characteristics as transaction read write"; @@ -113,6 +119,7 @@ public void testSetIsolationLevelReadWrite() { @Test public void testSetIsolationLevelSerializableReadWrite() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = @@ -129,6 +136,7 @@ public void testSetIsolationLevelSerializableReadWrite() { @Test public void testSetIsolationLevelSerializableReadOnly() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = @@ -144,6 +152,7 @@ public void testSetIsolationLevelSerializableReadOnly() { @Test public void testSetMultipleTransactionModes() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String sql = @@ -160,6 +169,7 @@ public void testSetMultipleTransactionModes() { @Test public void testDefaultTransactionIsolation() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); int count = 0; @@ -189,6 +199,7 @@ public void testDefaultTransactionIsolation() { @Test public void testDefaultTransactionReadOnlyTrue() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String[] statements = new String[] { @@ -223,6 +234,7 @@ public void testDefaultTransactionReadOnlyTrue() { @Test public void testDefaultTransactionReadOnlyFalse() { ConnectionImpl connection = mock(ConnectionImpl.class); + when(connection.getDialect()).thenReturn(Dialect.POSTGRESQL); ConnectionStatementExecutorImpl executor = new ConnectionStatementExecutorImpl(connection); String[] statements = new String[] { 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 5ac926d5956..76ace88d77a 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 @@ -500,7 +500,7 @@ private ParsedStatement createParsedDdl(String sql) { ParsedStatement statement = mock(ParsedStatement.class); when(statement.getType()).thenReturn(StatementType.DDL); when(statement.getStatement()).thenReturn(Statement.of(sql)); - when(statement.getSqlWithoutComments()).thenReturn(sql); + when(statement.getSql()).thenReturn(sql); return statement; } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserBenchmark.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserBenchmark.java new file mode 100644 index 00000000000..e028f8027cf --- /dev/null +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/StatementParserBenchmark.java @@ -0,0 +1,81 @@ +/* + * Copyright 2025 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.spanner.Dialect; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement; +import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(value = 1, warmups = 0) +@Warmup(iterations = 1, time = 5) +@Measurement(iterations = 5, time = 5) +public class StatementParserBenchmark { + private static final Dialect dialect = Dialect.POSTGRESQL; + private static final AbstractStatementParser PARSER = + AbstractStatementParser.getInstance(dialect); + + private static final String LONG_QUERY_TEXT = + generateLongStatement("SELECT * FROM foo WHERE 1", 100 * 1024); // 100kb + + private static final String LONG_DML_TEXT = + generateLongStatement("update foo set bar=1 WHERE 1", 100 * 1024); // 100kb + + /** Generates a long SQL-looking string. */ + private static String generateLongStatement(String prefix, int length) { + StringBuilder sb = new StringBuilder(length + 50); + sb.append(prefix); + while (sb.length() < length) { + sb.append(" OR abcdefghijklmnopqrstuvwxyz='abcdefghijklmnopqrstuvwxyz'"); + } + return sb.toString(); + } + + @Benchmark + public ParsedStatement isQueryTest() { + return PARSER.internalParse( + Statement.of("CREATE TABLE FOO (ID INT64, NAME STRING(100)) PRIMARY KEY (ID)"), + QueryOptions.getDefaultInstance()); + } + + @Benchmark + public ParsedStatement longQueryTest() { + return PARSER.internalParse(Statement.of(LONG_QUERY_TEXT), QueryOptions.getDefaultInstance()); + } + + @Benchmark + public ParsedStatement longDmlTest() { + return PARSER.internalParse(Statement.of(LONG_DML_TEXT), QueryOptions.getDefaultInstance()); + } + + public static void main(String[] args) throws Exception { + for (int i = 0; i < 100000; i++) { + if (PARSER.internalParse(Statement.of(LONG_QUERY_TEXT), QueryOptions.getDefaultInstance()) + == null) { + throw new AssertionError(); + } + if (PARSER.internalParse(Statement.of(LONG_DML_TEXT), QueryOptions.getDefaultInstance()) + == null) { + throw new AssertionError(); + } + } + } +} 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 fda4797871f..529ee258217 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 @@ -17,7 +17,6 @@ package com.google.cloud.spanner.connection; import static com.google.common.truth.Truth.assertThat; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; @@ -1714,6 +1713,16 @@ public void testStatementCache_ParameterizedStatement() { assertEquals(1, stats.hitCount()); } + @Test + public void testClientSideStatementWithComment() { + String sql = "-- Null (no timeout)\n" + "SET STATEMENT_TIMEOUT=null"; + ParsedStatement parsedStatement = parser.parse(Statement.of(sql)); + assertEquals(StatementType.CLIENT_SIDE, parsedStatement.getType()); + assertEquals( + ClientSideStatementType.SET_STATEMENT_TIMEOUT, + parsedStatement.getClientSideStatementType()); + } + static void assertUnclosedLiteral(AbstractStatementParser parser, String sql) { SpannerException exception = assertThrows( diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TransactionMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TransactionMockServerTest.java index d4cd1d37e1b..9f809dea4e4 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TransactionMockServerTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/TransactionMockServerTest.java @@ -122,12 +122,13 @@ public void testBatchDml() { } @Test - public void testTransactionIsolationLevel() { + public void testBeginTransactionIsolationLevel() { + SpannerPool.closeSpannerPool(); for (Dialect dialect : new Dialect[] {Dialect.POSTGRESQL, Dialect.GOOGLE_STANDARD_SQL}) { mockSpanner.putStatementResult( MockSpannerServiceImpl.StatementResult.detectDialectResult(dialect)); - try (Connection connection = createConnection()) { + try (Connection connection = super.createConnection()) { for (IsolationLevel isolationLevel : new IsolationLevel[] {IsolationLevel.REPEATABLE_READ, IsolationLevel.SERIALIZABLE}) { for (boolean useSql : new boolean[] {true, false}) { @@ -158,4 +159,41 @@ public void testTransactionIsolationLevel() { SpannerPool.closeSpannerPool(); } } + + @Test + public void testSetTransactionIsolationLevel() { + SpannerPool.closeSpannerPool(); + mockSpanner.putStatementResult( + MockSpannerServiceImpl.StatementResult.detectDialectResult(Dialect.POSTGRESQL)); + + try (Connection connection = super.createConnection()) { + for (boolean autocommit : new boolean[] {true, false}) { + connection.setAutocommit(autocommit); + + for (IsolationLevel isolationLevel : + new IsolationLevel[] {IsolationLevel.REPEATABLE_READ, IsolationLevel.SERIALIZABLE}) { + // Manually start a transaction if autocommit is enabled. + if (autocommit) { + connection.execute(Statement.of("begin")); + } + connection.execute( + Statement.of( + "set transaction isolation level " + isolationLevel.name().replace("_", " "))); + connection.executeUpdate(INSERT_STATEMENT); + connection.commit(); + + assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class)); + ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0); + assertTrue(request.getTransaction().hasBegin()); + assertTrue(request.getTransaction().getBegin().hasReadWrite()); + assertEquals(isolationLevel, request.getTransaction().getBegin().getIsolationLevel()); + assertFalse(request.getLastStatement()); + assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class)); + + mockSpanner.clearRequests(); + } + } + } + SpannerPool.closeSpannerPool(); + } } diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java index 5bf8e42ccb6..7eda6677764 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java @@ -17,6 +17,7 @@ package com.google.cloud.spanner.it; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assume.assumeFalse; import com.google.cloud.monitoring.v3.MetricServiceClient; import com.google.cloud.spanner.Database; @@ -24,6 +25,7 @@ import com.google.cloud.spanner.IntegrationTestEnv; import com.google.cloud.spanner.ParallelIntegrationTest; import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.testing.EmulatorSpannerHelper; import com.google.common.base.Stopwatch; import com.google.monitoring.v3.ListTimeSeriesRequest; import com.google.monitoring.v3.ListTimeSeriesResponse; @@ -34,9 +36,9 @@ import java.time.Duration; import java.time.Instant; import java.util.concurrent.TimeUnit; +import org.junit.After; 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; @@ -44,7 +46,6 @@ @Category(ParallelIntegrationTest.class) @RunWith(JUnit4.class) -@Ignore("Built-in Metrics are not GA'ed yet. Enable this test once the metrics are released") public class ITBuiltInMetricsTest { private static Database db; @@ -54,14 +55,26 @@ public class ITBuiltInMetricsTest { private static MetricServiceClient metricClient; + private static String[] METRICS = { + "operation_latencies", "attempt_latencies", "operation_count", "attempt_count", + }; + @BeforeClass public static void setUp() throws IOException { + assumeFalse("This test requires credentials", EmulatorSpannerHelper.isUsingEmulator()); metricClient = MetricServiceClient.create(); // Enable BuiltinMetrics when the metrics are GA'ed db = env.getTestHelper().createTestDatabase(); client = env.getTestHelper().getDatabaseClient(db); } + @After + public void tearDown() { + if (metricClient != null) { + metricClient.close(); + } + } + @Test public void testBuiltinMetricsWithDefaultOTEL() throws Exception { // This stopwatch is used for to limit fetching of metric data in verifyMetrics @@ -80,36 +93,36 @@ public void testBuiltinMetricsWithDefaultOTEL() throws Exception { .readWriteTransaction() .run(transaction -> transaction.executeQuery(Statement.of("Select 1"))); - String metricFilter = - String.format( - "metric.type=\"spanner.googleapis.com/client/%s\"" - + " AND resource.type=\"spanner_instance\"" - + " AND metric.labels.method=\"Spanner.Commit\"" - + " AND resource.labels.instance_id=\"%s\"" - + " AND metric.labels.database=\"%s\"", - "operation_latencies", - db.getId().getInstanceId().getInstance(), - db.getId().getDatabase()); - - ListTimeSeriesRequest.Builder requestBuilder = - ListTimeSeriesRequest.newBuilder() - .setName(name.toString()) - .setFilter(metricFilter) - .setInterval(interval) - .setView(ListTimeSeriesRequest.TimeSeriesView.FULL); - - ListTimeSeriesRequest request = requestBuilder.build(); - - ListTimeSeriesResponse response = metricClient.listTimeSeriesCallable().call(request); - while (response.getTimeSeriesCount() == 0 - && metricsPollingStopwatch.elapsed(TimeUnit.MINUTES) < 3) { - // Call listTimeSeries every minute - Thread.sleep(Duration.ofMinutes(1).toMillis()); - response = metricClient.listTimeSeriesCallable().call(request); + for (String metric : METRICS) { + String metricFilter = + String.format( + "metric.type=\"spanner.googleapis.com/client/%s\"" + + " AND resource.type=\"spanner_instance\"" + + " AND metric.labels.method=\"Spanner.Commit\"" + + " AND resource.labels.instance_id=\"%s\"" + + " AND metric.labels.database=\"%s\"", + metric, db.getId().getInstanceId().getInstance(), db.getId().getDatabase()); + + ListTimeSeriesRequest.Builder requestBuilder = + ListTimeSeriesRequest.newBuilder() + .setName(name.toString()) + .setFilter(metricFilter) + .setInterval(interval) + .setView(ListTimeSeriesRequest.TimeSeriesView.FULL); + + ListTimeSeriesRequest request = requestBuilder.build(); + + ListTimeSeriesResponse response = metricClient.listTimeSeriesCallable().call(request); + while (response.getTimeSeriesCount() == 0 + && metricsPollingStopwatch.elapsed(TimeUnit.MINUTES) < 3) { + // Call listTimeSeries every minute + Thread.sleep(Duration.ofMinutes(1).toMillis()); + response = metricClient.listTimeSeriesCallable().call(request); + } + + assertWithMessage("Metric" + metric + "didn't return any data.") + .that(response.getTimeSeriesCount()) + .isGreaterThan(0); } - - assertWithMessage("View operation_latencies didn't return any data.") - .that(response.getTimeSeriesCount()) - .isGreaterThan(0); } } 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 9a8f0096348..0cad83a0f6a 100644 --- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql +++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql @@ -160,15 +160,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:22.725000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:22.725000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.520000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.520000000Z' 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 2025-03-20T20:03:22.725000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.520000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -510,15 +510,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:22.871000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:22.871000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.643000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.643000000Z' 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 2025-03-20T20:03:22.871000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.643000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -950,8 +950,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:22.997000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:22.997000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.735000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.735000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -961,7 +961,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:22.997000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.735000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1462,8 +1462,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.134000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.134000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.842000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.842000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -1473,7 +1473,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.134000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.842000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1876,15 +1876,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.248000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.248000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.941000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.941000000Z' 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 2025-03-20T20:03:23.248000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.941000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.333000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.021000000Z'; 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 2025-03-20T20:03:23.333000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.021000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2600,13 +2600,13 @@ SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.430000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.095000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.430000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.095000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2910,14 +2910,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.517000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.517000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.166000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.166000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.517000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.166000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -3245,15 +3245,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.631000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.631000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.237000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.237000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.631000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.237000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.718000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.718000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.293000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.293000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -3672,7 +3672,7 @@ START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.718000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.293000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.807000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.349000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.807000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.349000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4438,13 +4438,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.882000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.399000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.882000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.399000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.959000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.959000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.457000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.457000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.959000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.457000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5288,15 +5288,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.045000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.045000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.519000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.519000000Z' 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 2025-03-20T20:03:24.045000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.519000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5641,15 +5641,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.120000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.120000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.567000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.567000000Z' 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 2025-03-20T20:03:24.120000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.567000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6088,8 +6088,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.291000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.291000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.620000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.620000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -6099,7 +6099,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.291000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.620000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6607,8 +6607,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.435000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.435000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.695000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.695000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -6618,7 +6618,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.435000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.695000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7023,15 +7023,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.574000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.574000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.760000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.760000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.574000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.760000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.650000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.811000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.650000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.811000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7756,13 +7756,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.743000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.869000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.743000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.869000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8075,14 +8075,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.828000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.828000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.925000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.925000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.828000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.925000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8392,13 +8392,13 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.906000000Z'; +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.983000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.906000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.983000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8753,8 +8753,8 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.973000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.973000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.034000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.034000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.973000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.034000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9200,8 +9200,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.054000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.054000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.086000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.086000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -9209,8 +9209,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.054000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.054000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.086000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.086000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -9596,15 +9596,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.140000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.140000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.141000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.141000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.140000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.141000000Z'; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9958,15 +9958,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.214000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.214000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.190000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.190000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.214000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.214000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.190000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.190000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -10329,15 +10329,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.292000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.292000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.241000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.241000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.292000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.292000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.241000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.241000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -10730,16 +10730,16 @@ SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.376000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.376000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.294000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.294000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.376000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.376000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.294000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.294000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -11125,15 +11125,15 @@ NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.454000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.454000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.345000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.345000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.454000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.454000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.345000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.345000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -11466,14 +11466,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.539000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.539000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.396000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.396000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.539000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.539000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.396000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.396000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=FALSE; @@ -11796,15 +11796,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.607000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.607000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.441000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.441000000Z' 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 2025-03-20T20:03:25.607000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.607000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.441000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.441000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -12211,8 +12211,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.688000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.688000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.490000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.490000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -12220,8 +12220,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.688000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.688000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.490000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.490000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -12604,15 +12604,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.778000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.778000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.541000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.541000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.778000000Z'; +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.541000000Z'; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -12950,15 +12950,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.853000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.853000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.588000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.588000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.853000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.853000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.588000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.588000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -13305,15 +13305,15 @@ NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.929000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.929000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.639000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.639000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.929000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.929000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.639000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.639000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; @@ -13630,14 +13630,14 @@ SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:26.002000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:26.002000000Z' +SET READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.688000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.688000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:26.002000000Z'; -@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:26.002000000Z' +SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.688000000Z'; +@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.688000000Z' SHOW VARIABLE READ_ONLY_STALENESS; NEW_CONNECTION; SET READONLY=TRUE; diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql index 210200b2a87..04b2c5286e0 100644 --- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql +++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ClientSideStatementsTest.sql @@ -41,7 +41,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -50,7 +50,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -59,7 +59,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -68,7 +68,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -77,7 +77,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -86,7 +86,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -95,7 +95,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -104,7 +104,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -113,7 +113,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -122,7 +122,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -131,7 +131,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -140,7 +140,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -149,7 +149,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -158,7 +158,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -167,7 +167,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -176,7 +176,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -185,7 +185,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#autocommit; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -194,7 +194,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show autocommit/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-autocommit; NEW_CONNECTION; show variable autocommit; @@ -438,7 +438,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -447,7 +447,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -456,7 +456,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -465,7 +465,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -474,7 +474,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -483,7 +483,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -492,7 +492,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -501,7 +501,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -510,7 +510,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -519,7 +519,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -528,7 +528,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -537,7 +537,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -546,7 +546,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -555,7 +555,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -564,7 +564,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -573,7 +573,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -582,7 +582,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.readonly; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -591,7 +591,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.readonly/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.readonly; NEW_CONNECTION; show variable spanner.readonly; @@ -869,7 +869,7 @@ show spanner.retry_aborts_internally%; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -884,7 +884,7 @@ show spanner.retry_aborts_internally_; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -899,7 +899,7 @@ show spanner.retry_aborts_internally&; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -914,7 +914,7 @@ show spanner.retry_aborts_internally$; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -929,7 +929,7 @@ show spanner.retry_aborts_internally@; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -944,7 +944,7 @@ show spanner.retry_aborts_internally!; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -959,7 +959,7 @@ show spanner.retry_aborts_internally*; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -974,7 +974,7 @@ show spanner.retry_aborts_internally(; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -989,7 +989,7 @@ show spanner.retry_aborts_internally); NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1004,7 +1004,7 @@ show spanner.retry_aborts_internally-; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1019,7 +1019,7 @@ show spanner.retry_aborts_internally+; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1034,7 +1034,7 @@ show spanner.retry_aborts_internally-#; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1049,7 +1049,7 @@ show spanner.retry_aborts_internally/; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1064,7 +1064,7 @@ show spanner.retry_aborts_internally\; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1079,7 +1079,7 @@ show spanner.retry_aborts_internally?; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1094,7 +1094,7 @@ show spanner.retry_aborts_internally-/; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1109,7 +1109,7 @@ show spanner.retry_aborts_internally/#; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1124,7 +1124,7 @@ show spanner.retry_aborts_internally/-; NEW_CONNECTION; set spanner.readonly=false; set autocommit=false; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.retry_aborts_internally; NEW_CONNECTION; set spanner.readonly=false; @@ -1504,7 +1504,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1513,7 +1513,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1522,7 +1522,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1531,7 +1531,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1540,7 +1540,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1549,7 +1549,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1558,7 +1558,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1567,7 +1567,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1576,7 +1576,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1585,7 +1585,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1594,7 +1594,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1603,7 +1603,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1612,7 +1612,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1621,7 +1621,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1630,7 +1630,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1639,7 +1639,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1648,7 +1648,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.autocommit_dml_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1657,7 +1657,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.autocommit_dml_mode/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.autocommit_dml_mode; NEW_CONNECTION; show variable spanner.autocommit_dml_mode; @@ -1901,7 +1901,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1910,7 +1910,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1919,7 +1919,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1928,7 +1928,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1937,7 +1937,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1946,7 +1946,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1955,7 +1955,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1964,7 +1964,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1973,7 +1973,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1982,7 +1982,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -1991,7 +1991,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2000,7 +2000,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2009,7 +2009,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2018,7 +2018,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2027,7 +2027,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2036,7 +2036,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2045,7 +2045,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#statement_timeout; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -2054,7 +2054,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show statement_timeout/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-statement_timeout; NEW_CONNECTION; show variable statement_timeout; @@ -2332,7 +2332,7 @@ show spanner.read_timestamp%; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2347,7 +2347,7 @@ show spanner.read_timestamp_; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2362,7 +2362,7 @@ show spanner.read_timestamp&; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2377,7 +2377,7 @@ show spanner.read_timestamp$; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2392,7 +2392,7 @@ show spanner.read_timestamp@; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2407,7 +2407,7 @@ show spanner.read_timestamp!; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2422,7 +2422,7 @@ show spanner.read_timestamp*; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2437,7 +2437,7 @@ show spanner.read_timestamp(; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2452,7 +2452,7 @@ show spanner.read_timestamp); NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2467,7 +2467,7 @@ show spanner.read_timestamp-; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2482,7 +2482,7 @@ show spanner.read_timestamp+; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2497,7 +2497,7 @@ show spanner.read_timestamp-#; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2512,7 +2512,7 @@ show spanner.read_timestamp/; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2527,7 +2527,7 @@ show spanner.read_timestamp\; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2542,7 +2542,7 @@ show spanner.read_timestamp?; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2557,7 +2557,7 @@ show spanner.read_timestamp-/; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2572,7 +2572,7 @@ show spanner.read_timestamp/#; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2587,7 +2587,7 @@ show spanner.read_timestamp/-; NEW_CONNECTION; set spanner.readonly = true; SELECT 1 AS TEST; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.read_timestamp; NEW_CONNECTION; set spanner.readonly = true; @@ -2984,7 +2984,7 @@ update foo set bar=1; show spanner.commit_timestamp%; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -2996,7 +2996,7 @@ update foo set bar=1; show spanner.commit_timestamp_; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3008,7 +3008,7 @@ update foo set bar=1; show spanner.commit_timestamp&; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3020,7 +3020,7 @@ update foo set bar=1; show spanner.commit_timestamp$; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3032,7 +3032,7 @@ update foo set bar=1; show spanner.commit_timestamp@; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3044,7 +3044,7 @@ update foo set bar=1; show spanner.commit_timestamp!; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3056,7 +3056,7 @@ update foo set bar=1; show spanner.commit_timestamp*; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3068,7 +3068,7 @@ update foo set bar=1; show spanner.commit_timestamp(; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3080,7 +3080,7 @@ update foo set bar=1; show spanner.commit_timestamp); NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3092,7 +3092,7 @@ update foo set bar=1; show spanner.commit_timestamp-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3104,7 +3104,7 @@ update foo set bar=1; show spanner.commit_timestamp+; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3116,7 +3116,7 @@ update foo set bar=1; show spanner.commit_timestamp-#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3128,7 +3128,7 @@ update foo set bar=1; show spanner.commit_timestamp/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3140,7 +3140,7 @@ update foo set bar=1; show spanner.commit_timestamp\; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3152,7 +3152,7 @@ update foo set bar=1; show spanner.commit_timestamp?; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3164,7 +3164,7 @@ update foo set bar=1; show spanner.commit_timestamp-/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3176,7 +3176,7 @@ update foo set bar=1; show spanner.commit_timestamp/#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3188,7 +3188,7 @@ update foo set bar=1; show spanner.commit_timestamp/-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.commit_timestamp; NEW_CONNECTION; update foo set bar=1; @@ -3500,7 +3500,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3509,7 +3509,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3518,7 +3518,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3527,7 +3527,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3536,7 +3536,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3545,7 +3545,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3554,7 +3554,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3563,7 +3563,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3572,7 +3572,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3581,7 +3581,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3590,7 +3590,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3599,7 +3599,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3608,7 +3608,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3617,7 +3617,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3626,7 +3626,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3635,7 +3635,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3644,7 +3644,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.read_only_staleness; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3653,7 +3653,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.read_only_staleness/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.read_only_staleness; NEW_CONNECTION; show variable spanner.read_only_staleness; @@ -3897,7 +3897,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3906,7 +3906,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3915,7 +3915,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3924,7 +3924,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3933,7 +3933,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3942,7 +3942,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3951,7 +3951,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3960,7 +3960,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3969,7 +3969,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3978,7 +3978,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3987,7 +3987,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -3996,7 +3996,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4005,7 +4005,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4014,7 +4014,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4023,7 +4023,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4032,7 +4032,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4041,7 +4041,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.directed_read; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4050,7 +4050,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.directed_read/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.directed_read; NEW_CONNECTION; show variable spanner.directed_read; @@ -4294,7 +4294,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4303,7 +4303,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4312,7 +4312,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4321,7 +4321,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4330,7 +4330,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4339,7 +4339,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4348,7 +4348,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4357,7 +4357,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4366,7 +4366,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4375,7 +4375,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4384,7 +4384,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4393,7 +4393,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4402,7 +4402,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4411,7 +4411,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4420,7 +4420,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4429,7 +4429,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4438,7 +4438,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.optimizer_version; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4447,7 +4447,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_version/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.optimizer_version; NEW_CONNECTION; show variable spanner.optimizer_version; @@ -4691,7 +4691,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4700,7 +4700,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4709,7 +4709,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4718,7 +4718,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4727,7 +4727,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4736,7 +4736,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4745,7 +4745,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4754,7 +4754,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4763,7 +4763,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4772,7 +4772,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4781,7 +4781,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4790,7 +4790,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4799,7 +4799,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4808,7 +4808,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4817,7 +4817,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4826,7 +4826,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4835,7 +4835,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.optimizer_statistics_package; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -4844,7 +4844,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.optimizer_statistics_package/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.optimizer_statistics_package; NEW_CONNECTION; show variable spanner.optimizer_statistics_package; @@ -5088,7 +5088,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5097,7 +5097,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5106,7 +5106,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5115,7 +5115,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5124,7 +5124,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5133,7 +5133,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5142,7 +5142,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5151,7 +5151,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5160,7 +5160,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5169,7 +5169,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5178,7 +5178,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5187,7 +5187,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5196,7 +5196,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5205,7 +5205,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5214,7 +5214,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5223,7 +5223,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5232,7 +5232,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.return_commit_stats; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5241,7 +5241,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.return_commit_stats/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.return_commit_stats; NEW_CONNECTION; show variable spanner.return_commit_stats; @@ -5485,7 +5485,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5494,7 +5494,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5503,7 +5503,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5512,7 +5512,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5521,7 +5521,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5530,7 +5530,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5539,7 +5539,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5548,7 +5548,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5557,7 +5557,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5566,7 +5566,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5575,7 +5575,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5584,7 +5584,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5593,7 +5593,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5602,7 +5602,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5611,7 +5611,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5620,7 +5620,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5629,7 +5629,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.max_commit_delay; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -5638,7 +5638,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_commit_delay/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.max_commit_delay; NEW_CONNECTION; show variable spanner.max_commit_delay; @@ -5899,7 +5899,7 @@ update foo set bar=1; show spanner.commit_response%; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5911,7 +5911,7 @@ update foo set bar=1; show spanner.commit_response_; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5923,7 +5923,7 @@ update foo set bar=1; show spanner.commit_response&; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5935,7 +5935,7 @@ update foo set bar=1; show spanner.commit_response$; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5947,7 +5947,7 @@ update foo set bar=1; show spanner.commit_response@; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5959,7 +5959,7 @@ update foo set bar=1; show spanner.commit_response!; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5971,7 +5971,7 @@ update foo set bar=1; show spanner.commit_response*; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5983,7 +5983,7 @@ update foo set bar=1; show spanner.commit_response(; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -5995,7 +5995,7 @@ update foo set bar=1; show spanner.commit_response); NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6007,7 +6007,7 @@ update foo set bar=1; show spanner.commit_response-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6019,7 +6019,7 @@ update foo set bar=1; show spanner.commit_response+; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6031,7 +6031,7 @@ update foo set bar=1; show spanner.commit_response-#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6043,7 +6043,7 @@ update foo set bar=1; show spanner.commit_response/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6055,7 +6055,7 @@ update foo set bar=1; show spanner.commit_response\; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6067,7 +6067,7 @@ update foo set bar=1; show spanner.commit_response?; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6079,7 +6079,7 @@ update foo set bar=1; show spanner.commit_response-/; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6091,7 +6091,7 @@ update foo set bar=1; show spanner.commit_response/#; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6103,7 +6103,7 @@ update foo set bar=1; show spanner.commit_response/-; NEW_CONNECTION; update foo set bar=1; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.commit_response; NEW_CONNECTION; update foo set bar=1; @@ -6415,7 +6415,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6424,7 +6424,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6433,7 +6433,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6442,7 +6442,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6451,7 +6451,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6460,7 +6460,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6469,7 +6469,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6478,7 +6478,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6487,7 +6487,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6496,7 +6496,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6505,7 +6505,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6514,7 +6514,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6523,7 +6523,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6532,7 +6532,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6541,7 +6541,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6550,7 +6550,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6559,7 +6559,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.statement_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6568,7 +6568,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.statement_tag/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.statement_tag; NEW_CONNECTION; show variable spanner.statement_tag; @@ -6812,7 +6812,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6821,7 +6821,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6830,7 +6830,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6839,7 +6839,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6848,7 +6848,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6857,7 +6857,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6866,7 +6866,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6875,7 +6875,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6884,7 +6884,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6893,7 +6893,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6902,7 +6902,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6911,7 +6911,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6920,7 +6920,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6929,7 +6929,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6938,7 +6938,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6947,7 +6947,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6956,7 +6956,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.transaction_tag; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -6965,7 +6965,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.transaction_tag/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.transaction_tag; NEW_CONNECTION; show variable spanner.transaction_tag; @@ -7209,7 +7209,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7218,7 +7218,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7227,7 +7227,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7236,7 +7236,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7245,7 +7245,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7254,7 +7254,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7263,7 +7263,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7272,7 +7272,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7281,7 +7281,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7290,7 +7290,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7299,7 +7299,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7308,7 +7308,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7317,7 +7317,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7326,7 +7326,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7335,7 +7335,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7344,7 +7344,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7353,7 +7353,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.exclude_txn_from_change_streams; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7362,7 +7362,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.exclude_txn_from_change_streams/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.exclude_txn_from_change_streams; NEW_CONNECTION; show variable spanner.exclude_txn_from_change_streams; @@ -7606,7 +7606,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7615,7 +7615,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7624,7 +7624,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7633,7 +7633,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7642,7 +7642,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7651,7 +7651,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7660,7 +7660,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7669,7 +7669,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7678,7 +7678,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7687,7 +7687,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7696,7 +7696,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7705,7 +7705,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7714,7 +7714,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7723,7 +7723,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7732,7 +7732,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7741,7 +7741,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7750,7 +7750,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.rpc_priority; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -7759,7 +7759,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.rpc_priority/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.rpc_priority; NEW_CONNECTION; show variable spanner.rpc_priority; @@ -8003,7 +8003,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8012,7 +8012,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8021,7 +8021,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8030,7 +8030,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8039,7 +8039,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8048,7 +8048,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8057,7 +8057,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8066,7 +8066,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8075,7 +8075,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8084,7 +8084,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8093,7 +8093,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8102,7 +8102,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8111,7 +8111,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8120,7 +8120,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8129,7 +8129,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8138,7 +8138,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8147,7 +8147,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.savepoint_support; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8156,7 +8156,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.savepoint_support/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.savepoint_support; NEW_CONNECTION; show variable spanner.savepoint_support; @@ -8400,7 +8400,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8409,7 +8409,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8418,7 +8418,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8427,7 +8427,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8436,7 +8436,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8445,7 +8445,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8454,7 +8454,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8463,7 +8463,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8472,7 +8472,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8481,7 +8481,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8490,7 +8490,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8499,7 +8499,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8508,7 +8508,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8517,7 +8517,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8526,7 +8526,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8535,7 +8535,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8544,7 +8544,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8553,7 +8553,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.delay_transaction_start_until_first_write/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.delay_transaction_start_until_first_write; NEW_CONNECTION; show variable spanner.delay_transaction_start_until_first_write; @@ -8797,7 +8797,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8806,7 +8806,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8815,7 +8815,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8824,7 +8824,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8833,7 +8833,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8842,7 +8842,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8851,7 +8851,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8860,7 +8860,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8869,7 +8869,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8878,7 +8878,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8887,7 +8887,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8896,7 +8896,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8905,7 +8905,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8914,7 +8914,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8923,7 +8923,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8932,7 +8932,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8941,7 +8941,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.keep_transaction_alive; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -8950,7 +8950,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.keep_transaction_alive/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.keep_transaction_alive; NEW_CONNECTION; show variable spanner.keep_transaction_alive; @@ -9194,7 +9194,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9203,7 +9203,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9212,7 +9212,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9221,7 +9221,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9230,7 +9230,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9239,7 +9239,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9248,7 +9248,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9257,7 +9257,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9266,7 +9266,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9275,7 +9275,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9284,7 +9284,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9293,7 +9293,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9302,7 +9302,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9311,7 +9311,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9320,7 +9320,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9329,7 +9329,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9338,7 +9338,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.auto_batch_dml; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9347,7 +9347,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.auto_batch_dml; NEW_CONNECTION; show variable spanner.auto_batch_dml; @@ -9591,7 +9591,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9600,7 +9600,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9609,7 +9609,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9618,7 +9618,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9627,7 +9627,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9636,7 +9636,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9645,7 +9645,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9654,7 +9654,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9663,7 +9663,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9672,7 +9672,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9681,7 +9681,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9690,7 +9690,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9699,7 +9699,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9708,7 +9708,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9717,7 +9717,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9726,7 +9726,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9735,7 +9735,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.auto_batch_dml_update_count; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9744,7 +9744,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.auto_batch_dml_update_count; NEW_CONNECTION; show variable spanner.auto_batch_dml_update_count; @@ -9988,7 +9988,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -9997,7 +9997,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10006,7 +10006,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10015,7 +10015,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10024,7 +10024,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10033,7 +10033,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10042,7 +10042,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10051,7 +10051,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10060,7 +10060,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10069,7 +10069,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10078,7 +10078,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10087,7 +10087,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10096,7 +10096,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10105,7 +10105,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10114,7 +10114,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10123,7 +10123,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10132,7 +10132,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -10141,7 +10141,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_batch_dml_update_count_verification/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.auto_batch_dml_update_count_verification; NEW_CONNECTION; show variable spanner.auto_batch_dml_update_count_verification; @@ -62930,6 +62930,276 @@ set autocommit = false; @EXPECT EXCEPTION INVALID_ARGUMENT set transaction isolation level/-serializable; NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; + set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; + set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; + + + +set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read ; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read ; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read + +; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +set +transaction +isolation +level +repeatable +read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read bar; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read%; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable%read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read_; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable_read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read&; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable&read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read$; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable$read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read@; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable@read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read!; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable!read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read*; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable*read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read(; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable(read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read); +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable)read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable-read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read+; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable+read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read-#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable-#read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable/read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read\; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable\read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read?; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable?read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read-/; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable-/read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read/#; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable/#read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set transaction isolation level repeatable read; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable read/-; +NEW_CONNECTION; +set autocommit = false; +@EXPECT EXCEPTION INVALID_ARGUMENT +set transaction isolation level repeatable/-read; +NEW_CONNECTION; set session characteristics as transaction read only; NEW_CONNECTION; SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY; @@ -63744,6 +64014,211 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT set session characteristics as transaction isolation level/-serializable; NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL REPEATABLE READ; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; + set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; + set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; + + + +set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read ; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read ; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read + +; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +set +session +characteristics +as +transaction +isolation +level +repeatable +read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable%read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable_read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable&read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable$read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable@read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable!read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable*read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable(read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable)read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable-read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable+read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable-#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable\read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable?read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable-/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable/#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set session characteristics as transaction isolation level repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable read/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set session characteristics as transaction isolation level repeatable/-read; +NEW_CONNECTION; set default_transaction_isolation=serializable; NEW_CONNECTION; SET DEFAULT_TRANSACTION_ISOLATION=SERIALIZABLE; @@ -64742,6 +65217,1007 @@ NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT set default_transaction_isolation =/-"SERIALIZABLE"; NEW_CONNECTION; +set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +SET DEFAULT_TRANSACTION_ISOLATION=REPEATABLE READ; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read; +NEW_CONNECTION; + set default_transaction_isolation=repeatable read; +NEW_CONNECTION; + set default_transaction_isolation=repeatable read; +NEW_CONNECTION; + + + +set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read ; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read ; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read + +; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +set +default_transaction_isolation=repeatable +read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable%read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable_read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable&read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable$read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable@read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable!read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable*read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable(read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable)read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable-read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable+read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable-#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable\read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable?read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable-/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable/#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set default_transaction_isolation=repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable read/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation=repeatable/-read; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +SET DEFAULT_TRANSACTION_ISOLATION TO REPEATABLE READ; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read; +NEW_CONNECTION; + set default_transaction_isolation to repeatable read; +NEW_CONNECTION; + set default_transaction_isolation to repeatable read; +NEW_CONNECTION; + + + +set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read ; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read ; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read + +; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +set +default_transaction_isolation +to +repeatable +read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable%read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable_read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable&read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable$read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable@read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable!read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable*read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable(read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable)read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable-read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable+read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable-#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable\read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable?read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable-/read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable/#read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set default_transaction_isolation to repeatable read; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable read/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to repeatable/-read; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +SET DEFAULT_TRANSACTION_ISOLATION TO 'REPEATABLE READ'; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; + set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; + set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; + + + +set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read' ; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read' ; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read' + +; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +set +default_transaction_isolation +to +'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable%read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable_read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable&read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable$read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable@read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable!read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable*read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable(read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable)read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable-read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable+read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable-#read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable/read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable\read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable?read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable-/read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable/#read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set default_transaction_isolation to 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable read'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation to 'repeatable/-read'; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +SET DEFAULT_TRANSACTION_ISOLATION = 'REPEATABLE READ'; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; + set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; + set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; + + + +set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read' ; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read' ; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read' + +; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +set +default_transaction_isolation += +'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read' bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable%read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable_read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable&read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable$read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable@read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable!read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable*read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable(read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable)read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable-read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable+read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable-#read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable/read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable\read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable?read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable-/read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable/#read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set default_transaction_isolation = 'repeatable read'; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable read'/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = 'repeatable/-read'; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +SET DEFAULT_TRANSACTION_ISOLATION = "REPEATABLE READ"; +NEW_CONNECTION; +set default_transaction_isolation = "repeatable read"; +NEW_CONNECTION; + set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; + set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; + + + +set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ" ; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ" ; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ" + +; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +set +default_transaction_isolation += +"REPEATABLE +READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +foo set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ" bar; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +%set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"%; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE%READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +_set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"_; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE_READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +&set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"&; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE&READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +$set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"$; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE$READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +@set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"@; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE@READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +!set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"!; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE!READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +*set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"*; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE*READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +(set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"(; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE(READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +)set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"); +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE)READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE-READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT ++set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"+; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE+READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-#set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"-#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE-#READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE/READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +\set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"\; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE\READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +?set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"?; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE?READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +-/set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"-/; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE-/READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/#set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"/#; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE/#READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +/-set default_transaction_isolation = "REPEATABLE READ"; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE READ"/-; +NEW_CONNECTION; +@EXPECT EXCEPTION INVALID_ARGUMENT +set default_transaction_isolation = "REPEATABLE/-READ"; +NEW_CONNECTION; set default_transaction_isolation = DEFAULT; NEW_CONNECTION; SET DEFAULT_TRANSACTION_ISOLATION = DEFAULT; @@ -90975,7 +92451,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -90984,7 +92460,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -90993,7 +92469,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91002,7 +92478,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91011,7 +92487,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91020,7 +92496,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91029,7 +92505,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91038,7 +92514,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91047,7 +92523,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91056,7 +92532,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91065,7 +92541,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91074,7 +92550,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91083,7 +92559,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91092,7 +92568,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91101,7 +92577,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91110,7 +92586,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91119,7 +92595,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.data_boost_enabled; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -91128,7 +92604,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.data_boost_enabled/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.data_boost_enabled; NEW_CONNECTION; show variable spanner.data_boost_enabled; @@ -92172,7 +93648,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92181,7 +93657,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92190,7 +93666,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92199,7 +93675,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92208,7 +93684,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92217,7 +93693,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92226,7 +93702,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92235,7 +93711,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92244,7 +93720,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92253,7 +93729,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92262,7 +93738,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92271,7 +93747,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92280,7 +93756,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92289,7 +93765,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92298,7 +93774,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92307,7 +93783,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92316,7 +93792,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.auto_partition_mode; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -92325,7 +93801,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.auto_partition_mode/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.auto_partition_mode; NEW_CONNECTION; show variable spanner.auto_partition_mode; @@ -93369,7 +94845,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93378,7 +94854,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93387,7 +94863,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93396,7 +94872,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93405,7 +94881,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93414,7 +94890,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93423,7 +94899,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93432,7 +94908,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93441,7 +94917,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93450,7 +94926,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93459,7 +94935,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93468,7 +94944,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93477,7 +94953,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93486,7 +94962,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93495,7 +94971,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93504,7 +94980,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93513,7 +94989,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.max_partitions; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -93522,7 +94998,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitions/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.max_partitions; NEW_CONNECTION; show variable spanner.max_partitions; @@ -94566,7 +96042,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism%; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show%spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94575,7 +96051,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism_; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show_spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94584,7 +96060,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism&; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show&spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94593,7 +96069,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism$; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show$spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94602,7 +96078,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism@; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show@spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94611,7 +96087,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism!; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show!spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94620,7 +96096,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism*; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show*spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94629,7 +96105,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism(; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show(spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94638,7 +96114,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism); NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show)spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94647,7 +96123,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94656,7 +96132,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism+; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show+spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94665,7 +96141,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism-#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-#spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94674,7 +96150,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94683,7 +96159,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism\; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show\spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94692,7 +96168,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism?; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show?spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94701,7 +96177,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism-/; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show-/spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94710,7 +96186,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism/#; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/#spanner.max_partitioned_parallelism; NEW_CONNECTION; @EXPECT EXCEPTION INVALID_ARGUMENT @@ -94719,7 +96195,7 @@ NEW_CONNECTION; @EXPECT EXCEPTION UNIMPLEMENTED show spanner.max_partitioned_parallelism/-; NEW_CONNECTION; -@EXPECT EXCEPTION INVALID_ARGUMENT +@EXPECT EXCEPTION UNIMPLEMENTED show/-spanner.max_partitioned_parallelism; NEW_CONNECTION; show variable spanner.max_partitioned_parallelism; diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql index 2d4e0c31dbc..974533738a0 100644 --- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql +++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql @@ -160,15 +160,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:22.808000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:22.808000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.586000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.586000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:22.808000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.586000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -510,15 +510,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:22.929000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:22.929000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.690000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.690000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:22.929000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.690000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -950,8 +950,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.071000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.071000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.791000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.791000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -961,7 +961,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.071000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.791000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1462,8 +1462,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.196000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.196000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.896000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.896000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -1473,7 +1473,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.196000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.896000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -1876,15 +1876,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.289000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.289000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:31.986000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:31.986000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.289000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:31.986000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.383000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.060000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.383000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.060000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2600,13 +2600,13 @@ SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.475000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.126000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.475000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.126000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -2910,14 +2910,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.563000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.563000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.195000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.195000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.563000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.195000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=FALSE; @@ -3245,15 +3245,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.672000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.672000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.266000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.266000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.672000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.266000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.764000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:23.764000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.323000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.323000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -3672,7 +3672,7 @@ START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); RUN BATCH; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.764000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.323000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.844000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.373000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.844000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.373000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4438,13 +4438,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:23.920000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.424000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:23.920000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.424000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.002000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.002000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.491000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.491000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.002000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.491000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5288,15 +5288,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.079000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.079000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.542000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.542000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.079000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.542000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -5641,15 +5641,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.168000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.168000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.591000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.591000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s'; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.168000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.591000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6088,8 +6088,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; ROLLBACK; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.374000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.374000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.656000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.656000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -6099,7 +6099,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; ROLLBACK; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.374000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.656000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -6607,8 +6607,8 @@ BEGIN TRANSACTION; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.524000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.524000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.731000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.731000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -6618,7 +6618,7 @@ BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.524000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.731000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7023,15 +7023,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.609000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.609000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.784000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.784000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.609000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.784000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.698000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.839000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.698000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.839000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -7756,13 +7756,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.786000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.898000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; SELECT 1 AS TEST; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.786000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.898000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8075,14 +8075,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.872000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:24.872000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:32.958000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:32.958000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.872000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:32.958000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=FALSE; @@ -8392,13 +8392,13 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:24.939000000Z'; +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.007000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; START BATCH DDL; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:24.939000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.007000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -8753,8 +8753,8 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.011000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.011000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.057000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.057000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SET TRANSACTION READ ONLY; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.011000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.057000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9200,8 +9200,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.096000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.096000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.115000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.115000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -9209,8 +9209,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; UPDATE foo SET bar=1; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.096000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.096000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.115000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.115000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -9596,15 +9596,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.178000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.178000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.165000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.165000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.178000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.165000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @@ -9958,15 +9958,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.254000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.254000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.216000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.216000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id); -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.254000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.254000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.216000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.216000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -10329,15 +10329,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.337000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.337000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.268000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.268000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; UPDATE foo SET bar=1; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.337000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.337000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.268000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.268000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -10730,16 +10730,16 @@ SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.415000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.415000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.320000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.320000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; @EXPECT RESULT_SET 'TEST',1 SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.415000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.415000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.320000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.320000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -11125,15 +11125,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.498000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.498000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.371000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.371000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.498000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.498000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.371000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.371000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -11466,14 +11466,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.573000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.573000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.419000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.419000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.573000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.573000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.419000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.419000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=FALSE; @@ -11796,15 +11796,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.642000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.642000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.465000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.465000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s'; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.642000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.642000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.465000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.465000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -12211,8 +12211,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.738000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.738000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.517000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.517000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -12220,8 +12220,8 @@ SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; SELECT 1 AS TEST; COMMIT; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.738000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.738000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.517000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.517000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -12604,15 +12604,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.814000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.814000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.565000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.565000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; BEGIN TRANSACTION; @EXPECT EXCEPTION FAILED_PRECONDITION -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.814000000Z'; +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.565000000Z'; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; @@ -12950,15 +12950,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.892000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.892000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.614000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.614000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.892000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.892000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.614000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.614000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -13305,15 +13305,15 @@ NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:25.967000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:25.967000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.664000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.664000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; SELECT 1 AS TEST; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:25.967000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:25.967000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.664000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.664000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; @@ -13630,14 +13630,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-03-20T20:03:26.036000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-03-20T20:03:26.036000000Z' +SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2025-04-08T18:15:33.710000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2025-04-08T18:15:33.710000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; SET AUTOCOMMIT=TRUE; -SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-03-20T20:03:26.036000000Z'; -@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-03-20T20:03:26.036000000Z' +SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2025-04-08T18:15:33.710000000Z'; +@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2025-04-08T18:15:33.710000000Z' SHOW VARIABLE SPANNER.READ_ONLY_STALENESS; NEW_CONNECTION; SET SPANNER.READONLY=TRUE; diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml index bbf98966c03..077b75ea822 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.90.0 + 6.91.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.90.0 + 6.91.0 diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml index 56eb9cc9f60..a6886ab7e5c 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.90.0 + 6.91.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.90.0 + 6.91.0 diff --git a/grpc-google-cloud-spanner-executor-v1/pom.xml b/grpc-google-cloud-spanner-executor-v1/pom.xml index a5fddea5aac..d408c03cb91 100644 --- a/grpc-google-cloud-spanner-executor-v1/pom.xml +++ b/grpc-google-cloud-spanner-executor-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc grpc-google-cloud-spanner-executor-v1 - 6.90.0 + 6.91.0 grpc-google-cloud-spanner-executor-v1 GRPC library for google-cloud-spanner com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml index a665e89aa85..593671c7e17 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.90.0 + 6.91.0 grpc-google-cloud-spanner-v1 GRPC library for grpc-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/pom.xml b/pom.xml index f30555e1927..3d5198c6557 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.google.cloud google-cloud-spanner-parent pom - 6.90.0 + 6.91.0 Google Cloud Spanner Parent https://github.com/googleapis/java-spanner @@ -61,47 +61,47 @@ com.google.api.grpc proto-google-cloud-spanner-admin-instance-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-executor-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-executor-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-v1 - 6.90.0 + 6.91.0 com.google.api.grpc proto-google-cloud-spanner-admin-database-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-admin-instance-v1 - 6.90.0 + 6.91.0 com.google.api.grpc grpc-google-cloud-spanner-admin-database-v1 - 6.90.0 + 6.91.0 com.google.cloud google-cloud-spanner - 6.90.0 + 6.91.0 diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml index 3ee55ff0aea..085ef085551 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.90.0 + 6.91.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.90.0 + 6.91.0 diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml index d38fcc9b31f..e46c4b9efcc 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.90.0 + 6.91.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.90.0 + 6.91.0 diff --git a/proto-google-cloud-spanner-executor-v1/pom.xml b/proto-google-cloud-spanner-executor-v1/pom.xml index 7f1887937f7..ce5af9706ca 100644 --- a/proto-google-cloud-spanner-executor-v1/pom.xml +++ b/proto-google-cloud-spanner-executor-v1/pom.xml @@ -4,13 +4,13 @@ 4.0.0 com.google.api.grpc proto-google-cloud-spanner-executor-v1 - 6.90.0 + 6.91.0 proto-google-cloud-spanner-executor-v1 Proto library for google-cloud-spanner com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml index c37f83359b0..cf10ceaf6ca 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.90.0 + 6.91.0 proto-google-cloud-spanner-v1 PROTO library for proto-google-cloud-spanner-v1 com.google.cloud google-cloud-spanner-parent - 6.90.0 + 6.91.0 diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml index 0fcc9820799..6b531c8794d 100644 --- a/samples/snapshot/pom.xml +++ b/samples/snapshot/pom.xml @@ -32,7 +32,7 @@ com.google.cloud google-cloud-spanner - 6.90.0 + 6.91.0 diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml index 7b617e29306..71949e27f82 100644 --- a/samples/snippets/pom.xml +++ b/samples/snippets/pom.xml @@ -34,7 +34,7 @@ com.google.cloud libraries-bom - 26.54.0 + 26.57.0 pom import diff --git a/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java b/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java new file mode 100644 index 00000000000..05c650dbfb7 --- /dev/null +++ b/samples/snippets/src/main/java/com/example/spanner/DatabaseAddSplitPointsSample.java @@ -0,0 +1,125 @@ +/* + * Copyright 2025 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.example.spanner; + +// [START spanner_database_add_split_points] + +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerException; +import com.google.cloud.spanner.SpannerOptions; +import com.google.cloud.spanner.admin.database.v1.DatabaseAdminClient; +import com.google.protobuf.ListValue; +import com.google.protobuf.Value; +import com.google.spanner.admin.database.v1.DatabaseName; +import com.google.spanner.admin.database.v1.SplitPoints; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DatabaseAddSplitPointsSample { + + /*** + * Assume DDL for the underlying database: + *

{@code
+   * CREATE TABLE Singers (
+   * SingerId INT64 NOT NULL,
+   * FirstName STRING(1024),
+   * LastName STRING(1024),
+   *  SingerInfo BYTES(MAX),
+   * ) PRIMARY KEY(SingerId);
+   *
+   *
+   * CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
+   * }
+ */ + + static void addSplitPoints() throws IOException { + // TODO(developer): Replace these variables before running the sample. + String projectId = "my-project"; + String instanceId = "my-instance"; + String databaseId = "my-database"; + addSplitPoints(projectId, instanceId, databaseId); + } + + static void addSplitPoints(String projectId, String instanceId, String databaseId) + throws IOException { + try (Spanner spanner = + SpannerOptions.newBuilder().setProjectId(projectId).build().getService(); + DatabaseAdminClient databaseAdminClient = spanner.createDatabaseAdminClient()) { + List splitPoints = new ArrayList<>(); + + // table key + com.google.spanner.admin.database.v1.SplitPoints splitPointForTable = + SplitPoints.newBuilder() + .setTable("Singers") + .setKeys( + 0, + com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder() + .setKeyParts( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("42").build()) + .build())) + .build(); + + // index key without table key part + com.google.spanner.admin.database.v1.SplitPoints splitPointForIndex = + SplitPoints.newBuilder() + .setIndex("SingersByFirstLastName") + .setKeys( + 0, + com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder() + .setKeyParts( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("John").build()) + .addValues(Value.newBuilder().setStringValue("Doe").build()) + .build())) + .build(); + + // index key with table key part, first key is the index key and second is the table key + com.google.spanner.admin.database.v1.SplitPoints splitPointForIndexWitTableKey = + SplitPoints.newBuilder() + .setIndex("SingersByFirstLastName") + .setKeys( + 0, + com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder() + .setKeyParts( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("Jane").build()) + .addValues(Value.newBuilder().setStringValue("Doe").build()) + .build())) + .setKeys( + 1, + com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder() + .setKeyParts( + ListValue.newBuilder() + .addValues(Value.newBuilder().setStringValue("38").build()) + .build())) + .build(); + + splitPoints.add(splitPointForTable); + splitPoints.add(splitPointForIndex); + splitPoints.add(splitPointForIndexWitTableKey); + databaseAdminClient.addSplitPoints( + DatabaseName.of(projectId, instanceId, databaseId), splitPoints); + + } catch (Exception e) { + // If the operation failed during execution, expose the cause. + throw (SpannerException) e.getCause(); + } + } +} +// [END spanner_database_add_split_points] diff --git a/samples/snippets/src/test/java/com/example/spanner/DatabaseAddSplitPointsIT.java b/samples/snippets/src/test/java/com/example/spanner/DatabaseAddSplitPointsIT.java new file mode 100644 index 00000000000..7b2be314250 --- /dev/null +++ b/samples/snippets/src/test/java/com/example/spanner/DatabaseAddSplitPointsIT.java @@ -0,0 +1,56 @@ +/* + * Copyright 2025 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.example.spanner; + +import static org.junit.Assert.assertTrue; + +import com.google.cloud.spanner.DatabaseId; +import com.google.common.collect.ImmutableList; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.Test; + +public class DatabaseAddSplitPointsIT extends SampleTestBase { + private static String databaseId; + + @Before + public void setup() throws ExecutionException, InterruptedException { + databaseId = idGenerator.generateDatabaseId(); + databaseAdminClient + .createDatabase( + databaseAdminClient + .newDatabaseBuilder(DatabaseId.of(projectId, instanceId, databaseId)) + .build(), + ImmutableList.of( + "CREATE TABLE Singers (" + + " SingerId INT64 NOT NULL," + + " FirstName STRING(1024)," + + " LastName STRING(1024)" + + ") PRIMARY KEY (SingerId)", + " CREATE INDEX IF NOT EXISTS SingersByFirstLastName ON Singers(FirstName," + + " LastName)")) + .get(); + } + + @Test + public void testAddSplits() throws Exception { + final String out = + SampleRunner.runSample( + () -> DatabaseAddSplitPointsSample.addSplitPoints(projectId, instanceId, databaseId)); + assertTrue(out.contains("")); + } +} diff --git a/versions.txt b/versions.txt index 6d4f2289cd4..d442de9dad6 100644 --- a/versions.txt +++ b/versions.txt @@ -1,13 +1,13 @@ # Format: # module:released-version:current-version -proto-google-cloud-spanner-admin-instance-v1:6.90.0:6.90.0 -proto-google-cloud-spanner-v1:6.90.0:6.90.0 -proto-google-cloud-spanner-admin-database-v1:6.90.0:6.90.0 -grpc-google-cloud-spanner-v1:6.90.0:6.90.0 -grpc-google-cloud-spanner-admin-instance-v1:6.90.0:6.90.0 -grpc-google-cloud-spanner-admin-database-v1:6.90.0:6.90.0 -google-cloud-spanner:6.90.0:6.90.0 -google-cloud-spanner-executor:6.90.0:6.90.0 -proto-google-cloud-spanner-executor-v1:6.90.0:6.90.0 -grpc-google-cloud-spanner-executor-v1:6.90.0:6.90.0 +proto-google-cloud-spanner-admin-instance-v1:6.91.0:6.91.0 +proto-google-cloud-spanner-v1:6.91.0:6.91.0 +proto-google-cloud-spanner-admin-database-v1:6.91.0:6.91.0 +grpc-google-cloud-spanner-v1:6.91.0:6.91.0 +grpc-google-cloud-spanner-admin-instance-v1:6.91.0:6.91.0 +grpc-google-cloud-spanner-admin-database-v1:6.91.0:6.91.0 +google-cloud-spanner:6.91.0:6.91.0 +google-cloud-spanner-executor:6.91.0:6.91.0 +proto-google-cloud-spanner-executor-v1:6.91.0:6.91.0 +grpc-google-cloud-spanner-executor-v1:6.91.0:6.91.0