diff --git a/google-cloud-spanner/clirr-ignored-differences.xml b/google-cloud-spanner/clirr-ignored-differences.xml
index ec13415790c..bae308f2b50 100644
--- a/google-cloud-spanner/clirr-ignored-differences.xml
+++ b/google-cloud-spanner/clirr-ignored-differences.xml
@@ -791,4 +791,22 @@
boolean isAutoBatchDmlUpdateCountVerification()
+
+
+ 7012
+ com/google/cloud/spanner/connection/TransactionRetryListener
+ void retryDmlAsPartitionedDmlStarting(java.util.UUID, com.google.cloud.spanner.Statement, com.google.cloud.spanner.TransactionMutationLimitExceededException)
+
+
+ 7012
+ com/google/cloud/spanner/connection/TransactionRetryListener
+ void retryDmlAsPartitionedDmlFinished(java.util.UUID, com.google.cloud.spanner.Statement, long)
+
+
+ 7012
+ com/google/cloud/spanner/connection/TransactionRetryListener
+ void retryDmlAsPartitionedDmlFailed(java.util.UUID, com.google.cloud.spanner.Statement, java.lang.Throwable)
+
+
+
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 b672b3b8fa4..2dd70ce108e 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
@@ -16,8 +16,11 @@
package com.google.cloud.spanner;
+import static com.google.cloud.spanner.TransactionMutationLimitExceededException.isTransactionMutationLimitException;
+
import com.google.api.gax.grpc.GrpcStatusCode;
import com.google.api.gax.rpc.ApiException;
+import com.google.api.gax.rpc.ErrorDetails;
import com.google.api.gax.rpc.WatchdogTimeoutException;
import com.google.cloud.spanner.SpannerException.DoNotConstructDirectly;
import com.google.common.base.MoreObjects;
@@ -256,6 +259,18 @@ private static ErrorInfo extractErrorInfo(Throwable cause) {
return null;
}
+ static ErrorDetails extractErrorDetails(Throwable cause) {
+ Throwable prevCause = null;
+ while (cause != null && cause != prevCause) {
+ if (cause instanceof ApiException) {
+ return ((ApiException) cause).getErrorDetails();
+ }
+ prevCause = cause;
+ cause = cause.getCause();
+ }
+ return null;
+ }
+
/**
* Creates a {@link StatusRuntimeException} that contains a {@link RetryInfo} with the specified
* retry delay.
@@ -313,6 +328,11 @@ static SpannerException newSpannerExceptionPreformatted(
token, message, resourceInfo, cause, apiException);
}
}
+ case INVALID_ARGUMENT:
+ if (isTransactionMutationLimitException(cause)) {
+ return new TransactionMutationLimitExceededException(
+ token, code, message, cause, apiException);
+ }
// Fall through to the default.
default:
return new SpannerException(
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
new file mode 100644
index 00000000000..1b63861bcd1
--- /dev/null
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionMutationLimitExceededException.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner;
+
+import static com.google.cloud.spanner.SpannerExceptionFactory.extractErrorDetails;
+
+import com.google.api.gax.rpc.ApiException;
+import com.google.api.gax.rpc.ErrorDetails;
+import javax.annotation.Nullable;
+
+/** Exception thrown by Spanner when the transaction mutation limit has been exceeded. */
+public class TransactionMutationLimitExceededException extends SpannerException {
+ private static final long serialVersionUID = 1L;
+
+ /** 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);
+ }
+
+ static boolean isTransactionMutationLimitException(Throwable cause) {
+ if (cause == null
+ || cause.getMessage() == null
+ || !cause.getMessage().contains("The transaction contains too many mutations.")) {
+ return false;
+ }
+ // Spanner includes a hint that points to the Spanner limits documentation page when the error
+ // was that the transaction mutation limit was exceeded. We use that here to identify the error,
+ // as there is no other specific metadata in the error that identifies it (other than the error
+ // message).
+ ErrorDetails errorDetails = extractErrorDetails(cause);
+ if (errorDetails != null && errorDetails.getHelp() != null) {
+ return errorDetails.getHelp().getLinksCount() == 1
+ && errorDetails
+ .getHelp()
+ .getLinks(0)
+ .getDescription()
+ .equals("Cloud Spanner limits documentation.")
+ && errorDetails
+ .getHelp()
+ .getLinks(0)
+ .getUrl()
+ .equals("https://cloud.google.com/spanner/docs/limits");
+ }
+ return false;
+ }
+}
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 9e431dbc0ba..58143523b65 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
@@ -39,6 +39,7 @@
import com.google.cloud.spanner.Struct;
import com.google.cloud.spanner.Type.StructField;
import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement;
+import com.google.cloud.spanner.connection.ReadWriteTransaction.Builder;
import com.google.cloud.spanner.connection.StatementExecutor.StatementTimeout;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -75,6 +76,7 @@ abstract class AbstractBaseUnitOfWork implements UnitOfWork {
private final StatementExecutor statementExecutor;
private final StatementTimeout statementTimeout;
protected final String transactionTag;
+ protected final List transactionRetryListeners;
protected final boolean excludeTxnFromChangeStreams;
protected final RpcPriority rpcPriority;
protected final Span span;
@@ -110,6 +112,7 @@ abstract static class Builder, T extends AbstractBaseUni
private StatementExecutor statementExecutor;
private StatementTimeout statementTimeout = new StatementTimeout();
private String transactionTag;
+ private List transactionRetryListeners;
private boolean excludeTxnFromChangeStreams;
private RpcPriority rpcPriority;
@@ -134,6 +137,16 @@ B setStatementTimeout(StatementTimeout timeout) {
return self();
}
+ B setTransactionRetryListeners(List listeners) {
+ Preconditions.checkNotNull(listeners);
+ this.transactionRetryListeners = listeners;
+ return self();
+ }
+
+ boolean hasTransactionRetryListeners() {
+ return this.transactionRetryListeners != null;
+ }
+
B setTransactionTag(@Nullable String tag) {
this.transactionTag = tag;
return self();
@@ -162,6 +175,7 @@ B setSpan(@Nullable Span span) {
this.statementExecutor = builder.statementExecutor;
this.statementTimeout = builder.statementTimeout;
this.transactionTag = builder.transactionTag;
+ this.transactionRetryListeners = builder.transactionRetryListeners;
this.excludeTxnFromChangeStreams = builder.excludeTxnFromChangeStreams;
this.rpcPriority = builder.rpcPriority;
this.span = Preconditions.checkNotNull(builder.span);
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AutocommitDmlMode.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AutocommitDmlMode.java
index 8710bdd01d1..4d6becfe1bd 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AutocommitDmlMode.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/AutocommitDmlMode.java
@@ -18,8 +18,18 @@
/** Enum used to define the behavior of DML statements in autocommit mode */
public enum AutocommitDmlMode {
+ /** TRANSACTIONAL: DML statements use a standard atomic transaction. */
TRANSACTIONAL,
- PARTITIONED_NON_ATOMIC;
+ /** PARTITIONED_NON_ATOMIC: DML statements use a Partitioned DML transaction. */
+ PARTITIONED_NON_ATOMIC,
+ /**
+ * TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC: DML statements are first executed with a
+ * standard atomic transaction. If that fails due to the mutation limit being exceeded, the
+ * statement will automatically be retried using a Partitioned DML transaction. These statements
+ * are not guaranteed to be atomic. The corresponding {@link TransactionRetryListener} methods
+ * will be invoked when a DML statement falls back to Partitioned DML.
+ */
+ TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC;
private final String statementString;
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 37dcd3f9aac..0b2d0b6b3a0 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
@@ -2125,6 +2125,7 @@ UnitOfWork createNewUnitOfWork(
.setReadOnly(getConnectionPropertyValue(READONLY))
.setReadOnlyStaleness(getConnectionPropertyValue(READ_ONLY_STALENESS))
.setAutocommitDmlMode(getConnectionPropertyValue(AUTOCOMMIT_DML_MODE))
+ .setTransactionRetryListeners(transactionRetryListeners)
.setReturnCommitStats(getConnectionPropertyValue(RETURN_COMMIT_STATS))
.setExcludeTxnFromChangeStreams(excludeTxnFromChangeStreams)
.setMaxCommitDelay(getConnectionPropertyValue(MAX_COMMIT_DELAY))
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 e174a73b701..4ae0ae00608 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
@@ -153,7 +153,6 @@ class ReadWriteTransaction extends AbstractMultiUseTransaction {
private final SavepointSupport savepointSupport;
private int transactionRetryAttempts;
private int successfulRetries;
- private final List transactionRetryListeners;
private volatile ApiFuture txContextFuture;
private boolean canUseSingleUseRead;
private volatile SettableApiFuture commitResponseFuture;
@@ -203,7 +202,6 @@ static class Builder extends AbstractMultiUseTransaction.Builder transactionRetryListeners;
private Builder() {}
@@ -253,19 +251,13 @@ Builder setSavepointSupport(SavepointSupport savepointSupport) {
return this;
}
- Builder setTransactionRetryListeners(List listeners) {
- Preconditions.checkNotNull(listeners);
- this.transactionRetryListeners = listeners;
- return this;
- }
-
@Override
ReadWriteTransaction build() {
Preconditions.checkState(dbClient != null, "No DatabaseClient client specified");
Preconditions.checkState(
retryAbortsInternally != null, "RetryAbortsInternally is not specified");
Preconditions.checkState(
- transactionRetryListeners != null, "TransactionRetryListeners are not specified");
+ hasTransactionRetryListeners(), "TransactionRetryListeners are not specified");
Preconditions.checkState(savepointSupport != null, "SavepointSupport is not specified");
return new ReadWriteTransaction(this);
}
@@ -301,7 +293,6 @@ private ReadWriteTransaction(Builder builder) {
this.keepAliveLock = this.keepTransactionAlive ? new ReentrantLock() : null;
this.retryAbortsInternally = builder.retryAbortsInternally;
this.savepointSupport = builder.savepointSupport;
- this.transactionRetryListeners = builder.transactionRetryListeners;
this.transactionOptions = extractOptions(builder);
}
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 53a1bb03b10..3c533cb9a7a 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
@@ -20,6 +20,7 @@
import static com.google.cloud.spanner.connection.AbstractStatementParser.RUN_BATCH_STATEMENT;
import com.google.api.core.ApiFuture;
+import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.core.SettableApiFuture;
import com.google.api.gax.longrunning.OperationFuture;
@@ -42,11 +43,10 @@
import com.google.cloud.spanner.SpannerException;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.TimestampBound;
+import com.google.cloud.spanner.TransactionMutationLimitExceededException;
import com.google.cloud.spanner.TransactionRunner;
-import com.google.cloud.spanner.Type;
import com.google.cloud.spanner.connection.AbstractStatementParser.ParsedStatement;
import com.google.cloud.spanner.connection.AbstractStatementParser.StatementType;
-import com.google.cloud.spanner.connection.ReadWriteTransaction.Builder;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -56,6 +56,7 @@
import io.opentelemetry.context.Scope;
import java.time.Duration;
import java.util.Arrays;
+import java.util.UUID;
import java.util.concurrent.Callable;
import javax.annotation.Nonnull;
@@ -219,6 +220,11 @@ public boolean supportsDirectedReads(ParsedStatement parsedStatement) {
return parsedStatement.isQuery();
}
+ private boolean isRetryDmlAsPartitionedDml() {
+ return this.autocommitDmlMode
+ == AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC;
+ }
+
private void checkAndMarkUsed() {
Preconditions.checkState(!used, "This single-use transaction has already been used");
used = true;
@@ -434,6 +440,7 @@ public ApiFuture executeUpdateAsync(
ApiFuture res;
switch (autocommitDmlMode) {
case TRANSACTIONAL:
+ case TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC:
res =
ApiFutures.transform(
executeTransactionalUpdateAsync(callType, update, AnalyzeMode.NONE, options),
@@ -561,11 +568,89 @@ private ApiFuture> executeTransactionalUpdateAsync(
throw t;
}
};
- return executeStatementAsync(
- callType,
- update,
- callable,
- ImmutableList.of(SpannerGrpc.getExecuteSqlMethod(), SpannerGrpc.getCommitMethod()));
+ ApiFuture> transactionalResult =
+ executeStatementAsync(
+ callType,
+ update,
+ callable,
+ ImmutableList.of(SpannerGrpc.getExecuteSqlMethod(), SpannerGrpc.getCommitMethod()));
+ // Retry as Partitioned DML if the statement fails due to exceeding the mutation limit if that
+ // option has been enabled.
+ if (isRetryDmlAsPartitionedDml()) {
+ return addRetryUpdateAsPartitionedDmlCallback(transactionalResult, callType, update, options);
+ }
+ return transactionalResult;
+ }
+
+ /**
+ * Adds a callback to the given future that retries the update statement using Partitioned DML if
+ * the original statement fails with a {@link TransactionMutationLimitExceededException}.
+ */
+ private ApiFuture> addRetryUpdateAsPartitionedDmlCallback(
+ ApiFuture> transactionalResult,
+ CallType callType,
+ final ParsedStatement update,
+ final UpdateOption... options) {
+ // Catch TransactionMutationLimitExceededException and retry as Partitioned DML. All other
+ // exceptions are just propagated.
+ return ApiFutures.catchingAsync(
+ transactionalResult,
+ TransactionMutationLimitExceededException.class,
+ mutationLimitExceededException -> {
+ UUID executionId = UUID.randomUUID();
+ // Invoke the retryDmlAsPartitionedDmlStarting method for the TransactionRetryListeners
+ // that have been registered for the connection.
+ for (TransactionRetryListener listener : this.transactionRetryListeners) {
+ listener.retryDmlAsPartitionedDmlStarting(
+ executionId, update.getStatement(), mutationLimitExceededException);
+ }
+ // Try to execute the DML statement as Partitioned DML.
+ ApiFuture> partitionedResult =
+ ApiFutures.transform(
+ executePartitionedUpdateAsync(callType, update, options),
+ lowerBoundUpdateCount -> Tuple.of(lowerBoundUpdateCount, null),
+ MoreExecutors.directExecutor());
+
+ // Add a callback to the future that invokes the TransactionRetryListeners after the
+ // Partitioned DML statement finished. This will invoke either the Finished or Failed
+ // method on the listeners.
+ ApiFutures.addCallback(
+ partitionedResult,
+ new ApiFutureCallback>() {
+ @Override
+ public void onFailure(Throwable throwable) {
+ for (TransactionRetryListener listener :
+ SingleUseTransaction.this.transactionRetryListeners) {
+ listener.retryDmlAsPartitionedDmlFailed(
+ executionId, update.getStatement(), throwable);
+ }
+ }
+
+ @Override
+ public void onSuccess(Tuple result) {
+ for (TransactionRetryListener listener :
+ SingleUseTransaction.this.transactionRetryListeners) {
+ listener.retryDmlAsPartitionedDmlFinished(
+ executionId, update.getStatement(), result.x());
+ }
+ }
+ },
+ MoreExecutors.directExecutor());
+
+ // Catch any exception from the Partitioned DML execution and throw the original
+ // TransactionMutationLimitExceededException instead.
+ // The exception that is returned for the Partitioned DML statement is added to the
+ // exception as a suppressed exception.
+ return ApiFutures.catching(
+ partitionedResult,
+ Throwable.class,
+ input -> {
+ mutationLimitExceededException.addSuppressed(input);
+ throw mutationLimitExceededException;
+ },
+ MoreExecutors.directExecutor());
+ },
+ MoreExecutors.directExecutor());
}
private ApiFuture analyzeTransactionalUpdateAsync(
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListener.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListener.java
index d622d8fde36..ba2613ffd86 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListener.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListener.java
@@ -20,6 +20,9 @@
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.AbortedDueToConcurrentModificationException;
import com.google.cloud.spanner.AbortedException;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.TransactionMutationLimitExceededException;
+import java.util.UUID;
/**
* Cloud Spanner can abort any read/write transaction because of potential deadlocks or other
@@ -87,4 +90,42 @@ void retryFinished(
long transactionId,
int retryAttempt,
TransactionRetryListener.RetryResult result);
+
+ /**
+ * This method is called when an atomic DML statement is retried as a Partitioned DML statement.
+ *
+ * @param executionId a generated, unique ID for this execution. The same ID is passed in to the
+ * methods {@link #retryDmlAsPartitionedDmlFinished(UUID, Statement, long)} and {@link
+ * #retryDmlAsPartitionedDmlFailed(UUID, Statement, Throwable)} when the execution finishes or
+ * fails.
+ * @param statement the statement that is being retried as Partitioned DML
+ * @param exception the mutation-limit-exceeded exception that was returned by Spanner during the
+ * initial execution.
+ */
+ default void retryDmlAsPartitionedDmlStarting(
+ UUID executionId, Statement statement, TransactionMutationLimitExceededException exception) {}
+
+ /**
+ * This method is called when an atomic DML statement has been successfully retried as a
+ * Partitioned DML statement.
+ *
+ * @param executionId the unique ID of this statement execution
+ * @param statement the statement that was successfully retried as Partitioned DML
+ * @param lowerBoundUpdateCount the lower-bound update count returned by Spanner after executing
+ * the statement as Partitioned DML
+ */
+ default void retryDmlAsPartitionedDmlFinished(
+ UUID executionId, Statement statement, long lowerBoundUpdateCount) {}
+
+ /**
+ * This method is called when an atomic DML statement failed to be retried as a Partitioned DML
+ * statement.
+ *
+ * @param executionId the unique ID of this statement execution
+ * @param statement the statement that failed to be retried as Partitioned DML
+ * @param exception the exception that was returned when the statement was executed as Partitioned
+ * DML
+ */
+ default void retryDmlAsPartitionedDmlFailed(
+ UUID executionId, Statement statement, Throwable exception) {}
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListenerImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListenerImpl.java
new file mode 100644
index 00000000000..42497564b95
--- /dev/null
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/TransactionRetryListenerImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection;
+
+import com.google.cloud.Timestamp;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.TransactionMutationLimitExceededException;
+import java.util.UUID;
+
+/** Default (no-op) implementation for {@link TransactionRetryListener}. */
+public abstract class TransactionRetryListenerImpl implements TransactionRetryListener {
+
+ @Override
+ public void retryStarting(Timestamp transactionStarted, long transactionId, int retryAttempt) {}
+
+ @Override
+ public void retryFinished(
+ Timestamp transactionStarted, long transactionId, int retryAttempt, RetryResult result) {}
+
+ @Override
+ public void retryDmlAsPartitionedDmlStarting(
+ UUID executionId, Statement statement, TransactionMutationLimitExceededException exception) {}
+
+ @Override
+ public void retryDmlAsPartitionedDmlFinished(
+ UUID executionId, Statement statement, long lowerBoundUpdateCount) {}
+
+ @Override
+ public void retryDmlAsPartitionedDmlFailed(
+ UUID executionId, Statement statement, Throwable exception) {}
+}
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
index 2f6c272ab17..31e8d4efd1d 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/ClientSideStatements.json
@@ -371,17 +371,17 @@
}
},
{
- "name": "SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'",
+ "name": "SET AUTOCOMMIT_DML_MODE = 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'|'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'",
"executorName": "ClientSideStatementSetExecutor",
"resultType": "NO_RESULT",
"statementType": "SET_AUTOCOMMIT_DML_MODE",
"regex": "(?is)\\A\\s*set\\s+autocommit_dml_mode\\s*(?:=)\\s*(.*)\\z",
"method": "statementSetAutocommitDmlMode",
- "exampleStatements": ["set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'", "set autocommit_dml_mode='TRANSACTIONAL'"],
+ "exampleStatements": ["set autocommit_dml_mode='PARTITIONED_NON_ATOMIC'", "set autocommit_dml_mode='TRANSACTIONAL'", "set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'"],
"setStatement": {
"propertyName": "AUTOCOMMIT_DML_MODE",
"separator": "=",
- "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL)'",
+ "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL|TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC)'",
"converterName": "ClientSideStatementValueConverters$AutocommitDmlModeConverter"
}
},
diff --git a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
index afb5b4a3855..969487142e1 100644
--- a/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
+++ b/google-cloud-spanner/src/main/resources/com/google/cloud/spanner/connection/PG_ClientSideStatements.json
@@ -420,7 +420,7 @@
}
},
{
- "name": "SET SPANNER.AUTOCOMMIT_DML_MODE =|TO 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'",
+ "name": "SET SPANNER.AUTOCOMMIT_DML_MODE =|TO 'PARTITIONED_NON_ATOMIC'|'TRANSACTIONAL'|'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'",
"executorName": "ClientSideStatementSetExecutor",
"resultType": "NO_RESULT",
"statementType": "SET_AUTOCOMMIT_DML_MODE",
@@ -429,13 +429,15 @@
"exampleStatements": [
"set spanner.autocommit_dml_mode='PARTITIONED_NON_ATOMIC'",
"set spanner.autocommit_dml_mode='TRANSACTIONAL'",
+ "set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'",
"set spanner.autocommit_dml_mode to 'PARTITIONED_NON_ATOMIC'",
- "set spanner.autocommit_dml_mode to 'TRANSACTIONAL'"
+ "set spanner.autocommit_dml_mode to 'TRANSACTIONAL'",
+ "set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'"
],
"setStatement": {
"propertyName": "SPANNER.AUTOCOMMIT_DML_MODE",
"separator": "(?:=|\\s+TO\\s+)",
- "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL)'",
+ "allowedValues": "'(PARTITIONED_NON_ATOMIC|TRANSACTIONAL|TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC)'",
"converterName": "ClientSideStatementValueConverters$AutocommitDmlModeConverter"
}
},
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
new file mode 100644
index 00000000000..022c9a92f1f
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.ErrorCode;
+import com.google.cloud.spanner.MockSpannerServiceImpl;
+import com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime;
+import com.google.cloud.spanner.ResultSet;
+import com.google.cloud.spanner.SpannerException;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.TransactionMutationLimitExceededException;
+import com.google.protobuf.Any;
+import com.google.rpc.Help;
+import com.google.rpc.Help.Link;
+import com.google.spanner.v1.BeginTransactionRequest;
+import com.google.spanner.v1.CommitRequest;
+import com.google.spanner.v1.ExecuteSqlRequest;
+import io.grpc.Metadata;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class RetryDmlAsPartitionedDmlMockServerTest extends AbstractMockServerTest {
+
+ static StatusRuntimeException createTransactionMutationLimitExceededException() {
+ Metadata.Key key =
+ Metadata.Key.of("grpc-status-details-bin", Metadata.BINARY_BYTE_MARSHALLER);
+ Help help =
+ Help.newBuilder()
+ .addLinks(
+ Link.newBuilder()
+ .setDescription("Cloud Spanner limits documentation.")
+ .setUrl("https://cloud.google.com/spanner/docs/limits")
+ .build())
+ .build();
+ com.google.rpc.Status status =
+ com.google.rpc.Status.newBuilder().addDetails(Any.pack(help)).build();
+
+ Metadata trailers = new Metadata();
+ trailers.put(key, status.toByteArray());
+
+ return Status.INVALID_ARGUMENT
+ .withDescription("The transaction contains too many mutations.")
+ .asRuntimeException(trailers);
+ }
+
+ @Test
+ public void testTransactionMutationLimitExceeded_isNotRetriedByDefault() {
+ mockSpanner.setExecuteSqlExecutionTime(
+ SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException()));
+
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ assertEquals(AutocommitDmlMode.TRANSACTIONAL, connection.getAutocommitDmlMode());
+
+ TransactionMutationLimitExceededException exception =
+ assertThrows(
+ TransactionMutationLimitExceededException.class,
+ () -> connection.executeUpdate(Statement.of("update test set value=1 where true")));
+ assertEquals(0, exception.getSuppressed().length);
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testTransactionMutationLimitExceeded_canBeRetriedAsPDML() {
+ Statement statement = Statement.of("update test set value=1 where true");
+ mockSpanner.setExecuteSqlExecutionTime(
+ SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException()));
+ mockSpanner.putStatementResult(
+ MockSpannerServiceImpl.StatementResult.update(statement, 100000L));
+
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(
+ AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC);
+
+ long updateCount = connection.executeUpdate(statement);
+ assertEquals(100000L, updateCount);
+ }
+ // Verify that the request is retried as Partitioned DML.
+ assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ // The transactional request uses inline-begin.
+ ExecuteSqlRequest transactionalRequest =
+ mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite());
+
+ // Partitioned DML uses an explicit BeginTransaction RPC.
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ BeginTransactionRequest beginRequest =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0);
+ assertTrue(beginRequest.getOptions().hasPartitionedDml());
+ ExecuteSqlRequest partitionedDmlRequest =
+ mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1);
+ assertTrue(partitionedDmlRequest.getTransaction().hasId());
+
+ // Partitioned DML transactions are not committed.
+ assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testTransactionMutationLimitExceeded_retryAsPDMLFails() {
+ Statement statement = Statement.of("insert into test (id, value) select -id, value from test");
+ // The transactional update statement uses ExecuteSql(..).
+ mockSpanner.setExecuteSqlExecutionTime(
+ SimulatedExecutionTime.ofException(createTransactionMutationLimitExceededException()));
+ mockSpanner.putStatementResult(
+ MockSpannerServiceImpl.StatementResult.exception(
+ statement,
+ Status.INVALID_ARGUMENT
+ .withDescription("This statement is not supported with Partitioned DML")
+ .asRuntimeException()));
+
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(
+ AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC);
+
+ // The connection throws TransactionMutationLimitExceededException if the retry using
+ // partitioned DML fails. The exception from the failed retry is returned as a suppressed
+ // exception of the TransactionMutationLimitExceededException.
+ TransactionMutationLimitExceededException exception =
+ assertThrows(
+ TransactionMutationLimitExceededException.class,
+ () -> connection.executeUpdate(statement));
+ assertEquals(1, exception.getSuppressed().length);
+ assertEquals(SpannerException.class, exception.getSuppressed()[0].getClass());
+ SpannerException spannerException = (SpannerException) exception.getSuppressed()[0];
+ assertEquals(ErrorCode.INVALID_ARGUMENT, spannerException.getErrorCode());
+ assertTrue(
+ spannerException.getMessage(),
+ spannerException
+ .getMessage()
+ .contains("This statement is not supported with Partitioned DML"));
+ }
+ // Verify that the request was retried as Partitioned DML.
+ assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ // The transactional request uses inline-begin.
+ ExecuteSqlRequest transactionalRequest =
+ mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite());
+
+ // Partitioned DML uses an explicit BeginTransaction RPC.
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ BeginTransactionRequest beginRequest =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0);
+ assertTrue(beginRequest.getOptions().hasPartitionedDml());
+ ExecuteSqlRequest partitionedDmlRequest =
+ mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1);
+ assertTrue(partitionedDmlRequest.getTransaction().hasId());
+
+ // Partitioned DML transactions are not committed.
+ assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testSqlStatements() {
+ for (Dialect dialect : Dialect.values()) {
+ SpannerPool.closeSpannerPool();
+ mockSpanner.putStatementResult(
+ MockSpannerServiceImpl.StatementResult.detectDialectResult(dialect));
+ String prefix = dialect == Dialect.POSTGRESQL ? "SPANNER." : "";
+
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ try (ResultSet resultSet =
+ connection.executeQuery(
+ Statement.of(String.format("show variable %sautocommit_dml_mode", prefix)))) {
+ assertTrue(resultSet.next());
+ assertEquals(
+ AutocommitDmlMode.TRANSACTIONAL.name(),
+ resultSet.getString(String.format("%sAUTOCOMMIT_DML_MODE", prefix)));
+ assertFalse(resultSet.next());
+ }
+ connection.execute(
+ Statement.of(
+ String.format(
+ "set %sautocommit_dml_mode = 'transactional_with_fallback_to_partitioned_non_atomic'",
+ prefix)));
+ try (ResultSet resultSet =
+ connection.executeQuery(
+ Statement.of(String.format("show variable %sautocommit_dml_mode", prefix)))) {
+ assertTrue(resultSet.next());
+ assertEquals(
+ AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC.name(),
+ resultSet.getString(String.format("%sAUTOCOMMIT_DML_MODE", prefix)));
+ assertFalse(resultSet.next());
+ }
+ }
+ }
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITRetryDmlAsPartitionedDmlTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITRetryDmlAsPartitionedDmlTest.java
new file mode 100644
index 00000000000..4a7c2ce26c1
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITRetryDmlAsPartitionedDmlTest.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner.connection.it;
+
+import static com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
+
+import com.google.api.core.SettableApiFuture;
+import com.google.cloud.spanner.DatabaseClient;
+import com.google.cloud.spanner.ErrorCode;
+import com.google.cloud.spanner.Mutation;
+import com.google.cloud.spanner.ParallelIntegrationTest;
+import com.google.cloud.spanner.SpannerException;
+import com.google.cloud.spanner.Statement;
+import com.google.cloud.spanner.TransactionMutationLimitExceededException;
+import com.google.cloud.spanner.connection.AutocommitDmlMode;
+import com.google.cloud.spanner.connection.Connection;
+import com.google.cloud.spanner.connection.ITAbstractSpannerTest;
+import com.google.cloud.spanner.connection.TransactionRetryListenerImpl;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@Category(ParallelIntegrationTest.class)
+@RunWith(JUnit4.class)
+public class ITRetryDmlAsPartitionedDmlTest extends ITAbstractSpannerTest {
+ private static final int NUM_ROWS = 100000;
+
+ @BeforeClass
+ public static void setup() {
+ // This shadows the setup() method in the super class and prevents it from being executed.
+ // That allows us to have a custom setup method in this class.
+ }
+
+ @BeforeClass
+ public static void setupTestData() {
+ assumeFalse("The emulator does not enforce the mutation limit", isUsingEmulator());
+
+ database =
+ env.getTestHelper()
+ .createTestDatabase(
+ "CREATE TABLE TEST (ID INT64 NOT NULL, NAME STRING(100) NOT NULL) PRIMARY KEY (ID)");
+ DatabaseClient client = env.getTestHelper().getClient().getDatabaseClient(database.getId());
+ int rowsCreated = 0;
+ int batchSize = 5000;
+ while (rowsCreated < NUM_ROWS) {
+ List mutations = new ArrayList<>(batchSize);
+ for (int row = rowsCreated; row < rowsCreated + batchSize; row++) {
+ mutations.add(
+ Mutation.newInsertOrUpdateBuilder("TEST")
+ .set("id")
+ .to(row)
+ .set("name")
+ .to("Row " + row)
+ .build());
+ }
+ client.writeAtLeastOnce(mutations);
+ rowsCreated += batchSize;
+ }
+ }
+
+ @Test
+ public void testDmlFailsIfMutationLimitExceeded() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ assertThrows(
+ TransactionMutationLimitExceededException.class,
+ () ->
+ connection.executeUpdate(
+ Statement.of("update test set name=name || ' - updated' where true")));
+ }
+ }
+
+ @Test
+ public void testRetryDmlAsPartitionedDml() throws Exception {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(
+ AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC);
+
+ // Set up a listener that gets a callback when a DML statement is retried as Partitioned DML.
+ SettableApiFuture startExecutionIdFuture = SettableApiFuture.create();
+ SettableApiFuture finishedExecutionIdFuture = SettableApiFuture.create();
+ SettableApiFuture lowerBoundUpdateCountFuture = SettableApiFuture.create();
+ connection.addTransactionRetryListener(
+ new TransactionRetryListenerImpl() {
+ @Override
+ public void retryDmlAsPartitionedDmlStarting(
+ UUID executionId,
+ Statement statement,
+ TransactionMutationLimitExceededException exception) {
+ startExecutionIdFuture.set(executionId);
+ }
+
+ @Override
+ public void retryDmlAsPartitionedDmlFinished(
+ UUID executionId, Statement statement, long updateCount) {
+ finishedExecutionIdFuture.set(executionId);
+ lowerBoundUpdateCountFuture.set(updateCount);
+ }
+ });
+
+ long updateCount =
+ connection.executeUpdate(
+ Statement.of("update test set name=name || ' - updated' where true"));
+ assertEquals(NUM_ROWS, updateCount);
+ assertEquals(
+ startExecutionIdFuture.get(1, TimeUnit.SECONDS),
+ finishedExecutionIdFuture.get(1, TimeUnit.SECONDS));
+ assertEquals(updateCount, lowerBoundUpdateCountFuture.get(1, TimeUnit.SECONDS).longValue());
+ }
+ }
+
+ @Test
+ public void testRetryDmlAsPartitionedDml_failsForLargeInserts() throws Exception {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(
+ AutocommitDmlMode.TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC);
+
+ // Set up a listener that gets a callback when a DML statement is retried as Partitioned DML.
+ SettableApiFuture startExecutionIdFuture = SettableApiFuture.create();
+ SettableApiFuture failedExecutionIdFuture = SettableApiFuture.create();
+ SettableApiFuture executionExceptionFuture = SettableApiFuture.create();
+ connection.addTransactionRetryListener(
+ new TransactionRetryListenerImpl() {
+ @Override
+ public void retryDmlAsPartitionedDmlStarting(
+ UUID executionId,
+ Statement statement,
+ TransactionMutationLimitExceededException exception) {
+ startExecutionIdFuture.set(executionId);
+ }
+
+ @Override
+ public void retryDmlAsPartitionedDmlFailed(
+ UUID executionId, Statement statement, Throwable exception) {
+ failedExecutionIdFuture.set(executionId);
+ executionExceptionFuture.set(exception);
+ }
+ });
+
+ // Note that the executeUpdate method throws the original
+ // TransactionMutationLimitExceededException, and not the exception that is thrown when the
+ // statement is retried as Partitioned DML.
+ TransactionMutationLimitExceededException mutationLimitExceededException =
+ assertThrows(
+ TransactionMutationLimitExceededException.class,
+ () ->
+ connection.executeUpdate(
+ Statement.of("insert into test (id, name) select -id, name from test")));
+ assertEquals(
+ startExecutionIdFuture.get(1, TimeUnit.SECONDS),
+ failedExecutionIdFuture.get(1, TimeUnit.SECONDS));
+ Throwable executionException = executionExceptionFuture.get(1L, TimeUnit.SECONDS);
+ assertEquals(SpannerException.class, executionException.getClass());
+ SpannerException spannerException = (SpannerException) executionException;
+ // Verify that this exception indicates that the INSERT statement could not be executed as
+ // Partitioned DML.
+ assertEquals(ErrorCode.INVALID_ARGUMENT, spannerException.getErrorCode());
+ assertTrue(
+ spannerException.getMessage(),
+ spannerException.getMessage().contains("INSERT is not supported for Partitioned DML."));
+ assertEquals(1, mutationLimitExceededException.getSuppressed().length);
+ assertSame(spannerException, mutationLimitExceededException.getSuppressed()[0]);
+ }
+ }
+}
diff --git a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
index 2a63d9b3faf..552e75f1097 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ClientSideStatementsTest.sql
@@ -10291,6 +10291,204 @@ NEW_CONNECTION;
@EXPECT EXCEPTION INVALID_ARGUMENT
set/-autocommit_dml_mode='TRANSACTIONAL';
NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set autocommit_dml_mode='transactional_with_fallback_to_partitioned_non_atomic';
+NEW_CONNECTION;
+ set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+ set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+
+
+
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+
+;
+NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set
+autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set%autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set_autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set&autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set$autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set@autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set!autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set*autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set(autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC');
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set)autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set+autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-#autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set\autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set?autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-/autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/#autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/-autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
set statement_timeout=null;
NEW_CONNECTION;
SET STATEMENT_TIMEOUT=NULL;
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 b693a70a0c9..5985ba92479 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/ConnectionImplGeneratedSqlScriptTest.sql
@@ -160,15 +160,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.550000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.550000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.066000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.066000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.550000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.066000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -510,15 +510,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.692000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.692000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.187000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.187000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.692000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.187000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -950,8 +950,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.809000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.809000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.294000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.294000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -961,7 +961,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.809000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.294000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1462,8 +1462,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.921000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.921000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.413000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.413000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -1473,7 +1473,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.921000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.413000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1876,15 +1876,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.018000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.018000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.523000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.523000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.018000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.523000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.103000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.613000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.103000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.613000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2600,13 +2600,13 @@ SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.198000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.705000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.198000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.705000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2910,14 +2910,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.286000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.286000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.790000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.790000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.286000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.790000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -3245,15 +3245,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.382000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.382000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.890000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.890000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.382000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.890000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.470000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.470000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.965000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.965000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -3672,7 +3672,7 @@ START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.470000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.965000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.556000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.043000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.556000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.043000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4438,13 +4438,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.640000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.113000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.640000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.113000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.717000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.717000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.181000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.181000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.717000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.181000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5288,15 +5288,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.806000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.806000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.260000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.260000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.806000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.260000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5641,15 +5641,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.877000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.877000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.330000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.330000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.877000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.330000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6088,8 +6088,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.956000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.956000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.402000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.402000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -6099,7 +6099,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.956000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.402000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6607,8 +6607,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.068000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.068000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.495000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.495000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -6618,7 +6618,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.068000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.495000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7023,15 +7023,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.160000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.160000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.578000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.578000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.160000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.578000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.241000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.654000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.241000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.654000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7756,13 +7756,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.324000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.734000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.324000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.734000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8075,14 +8075,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.398000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.398000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.805000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.805000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.398000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.805000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8392,13 +8392,13 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.466000000Z';
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.865000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.466000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.865000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -8753,8 +8753,8 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.529000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.529000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.924000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.924000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.529000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.924000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9064,6 +9064,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9197,8 +9200,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.604000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.604000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.991000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.991000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -9206,8 +9209,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.604000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.604000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.991000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:11.991000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -9593,15 +9596,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.688000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.688000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.064000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.064000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.688000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.064000000Z';
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9851,6 +9854,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9952,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 2024-10-11T16:42:29.757000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.757000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.125000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.125000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.757000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.757000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.125000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.125000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -10219,6 +10225,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -10320,15 +10329,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.831000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.831000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.193000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.193000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.831000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.831000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.193000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.193000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -10601,6 +10610,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -10718,16 +10730,16 @@ SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.905000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.905000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.262000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.262000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.905000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.905000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.262000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.262000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11009,6 +11021,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -11110,15 +11125,15 @@ NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.979000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.979000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.330000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.330000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.979000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.979000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.330000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.330000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11363,6 +11378,9 @@ SHOW VARIABLE AUTOCOMMIT_DML_MODE;
SET AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE AUTOCOMMIT_DML_MODE;
+SET AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -11448,14 +11466,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.047000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.047000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.396000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.396000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.047000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.047000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.396000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.396000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=FALSE;
@@ -11778,15 +11796,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.108000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.108000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.456000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.456000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.108000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.108000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.456000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.456000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12193,8 +12211,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.171000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.171000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.519000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.519000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12202,8 +12220,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.171000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.171000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.519000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.519000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -12586,15 +12604,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.242000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.242000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.586000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.586000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.242000000Z';
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.586000000Z';
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
@@ -12932,15 +12950,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.304000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.304000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.650000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.650000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.304000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.304000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.650000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.650000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -13287,15 +13305,15 @@ NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.372000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.372000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.715000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.715000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.372000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.372000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.715000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.715000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
@@ -13612,14 +13630,14 @@ SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.435000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.435000000Z'
+SET READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.778000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.778000000Z'
SHOW VARIABLE READ_ONLY_STALENESS;
NEW_CONNECTION;
SET READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.435000000Z';
-@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.435000000Z'
+SET READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.778000000Z';
+@EXPECT RESULT_SET 'READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.778000000Z'
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 068210495fa..aea0bf4b808 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
@@ -50288,6 +50288,204 @@ NEW_CONNECTION;
@EXPECT EXCEPTION INVALID_ARGUMENT
set/-spanner.autocommit_dml_mode='TRANSACTIONAL';
NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='transactional_with_fallback_to_partitioned_non_atomic';
+NEW_CONNECTION;
+ set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+ set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+
+
+
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+
+;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set
+spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set%spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set_spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set&spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set$spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set@spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set!spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set*spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set(spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC');
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set)spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set+spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-#spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set\spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set?spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set-/spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/#spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set/-spanner.autocommit_dml_mode='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
set spanner.autocommit_dml_mode to 'PARTITIONED_NON_ATOMIC';
NEW_CONNECTION;
SET SPANNER.AUTOCOMMIT_DML_MODE TO 'PARTITIONED_NON_ATOMIC';
@@ -50688,6 +50886,206 @@ NEW_CONNECTION;
@EXPECT EXCEPTION INVALID_ARGUMENT
set spanner.autocommit_dml_mode to/-'TRANSACTIONAL';
NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+SET SPANNER.AUTOCOMMIT_DML_MODE TO 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'transactional_with_fallback_to_partitioned_non_atomic';
+NEW_CONNECTION;
+ set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+ set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+
+
+
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' ;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+
+;
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+set
+spanner.autocommit_dml_mode
+to
+'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+foo set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC' bar;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+%set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'%;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to%'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+_set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'_;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to_'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+&set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'&;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to&'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+$set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'$;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to$'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+@set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'@;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to@'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+!set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'!;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to!'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+*set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'*;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to*'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+(set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'(;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to('TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+)set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC');
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to)'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to-'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
++set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'+;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to+'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-#set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to-#'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to/'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+\set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'\;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to\'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+?set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'?;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to?'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+-/set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'-/;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to-/'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/#set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/#;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to/#'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+/-set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to 'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'/-;
+NEW_CONNECTION;
+@EXPECT EXCEPTION INVALID_ARGUMENT
+set spanner.autocommit_dml_mode to/-'TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+NEW_CONNECTION;
set statement_timeout=default;
NEW_CONNECTION;
SET STATEMENT_TIMEOUT=DEFAULT;
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 75a6a00549c..3db3bda388b 100644
--- a/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql
+++ b/google-cloud-spanner/src/test/resources/com/google/cloud/spanner/connection/postgresql/ConnectionImplGeneratedSqlScriptTest.sql
@@ -160,15 +160,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.628000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.628000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.130000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.130000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.628000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.130000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -510,15 +510,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.747000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.747000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.240000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.240000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.747000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.240000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -950,8 +950,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.869000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.869000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.352000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.352000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -961,7 +961,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.869000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.352000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1462,8 +1462,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:27.973000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:27.973000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.472000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.472000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -1473,7 +1473,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:27.973000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.472000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -1876,15 +1876,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.061000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.061000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.566000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.566000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.061000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.566000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2243,14 +2243,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.152000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.661000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.152000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.661000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2600,13 +2600,13 @@ SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.247000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.751000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.247000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.751000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -2910,14 +2910,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.320000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.320000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.827000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.827000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.320000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.827000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=FALSE;
@@ -3245,15 +3245,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.423000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.423000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:10.925000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:10.925000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.423000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:10.925000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -3662,8 +3662,8 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.515000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.515000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.005000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.005000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -3672,7 +3672,7 @@ START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
RUN BATCH;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.515000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.005000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4081,14 +4081,14 @@ SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.604000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.078000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.604000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.078000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4438,13 +4438,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.673000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.144000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.673000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.144000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -4877,8 +4877,8 @@ SET TRANSACTION READ ONLY;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.765000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.765000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.224000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.224000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -4888,7 +4888,7 @@ SET TRANSACTION READ ONLY;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.765000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.224000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5288,15 +5288,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.842000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.842000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.296000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.296000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.842000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.296000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -5641,15 +5641,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:28.915000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:28.915000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.363000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.363000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SET SPANNER.READ_ONLY_STALENESS='EXACT_STALENESS 10s';
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:28.915000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.363000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6088,8 +6088,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
ROLLBACK;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.005000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.005000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.444000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.444000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -6099,7 +6099,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
ROLLBACK;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.005000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.444000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -6607,8 +6607,8 @@ BEGIN TRANSACTION;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.117000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.117000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.539000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.539000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -6618,7 +6618,7 @@ BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.117000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.539000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7023,15 +7023,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.203000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.203000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.614000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.614000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.203000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.614000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7394,14 +7394,14 @@ SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.282000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.693000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.282000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.693000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -7756,13 +7756,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.362000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.771000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
SELECT 1 AS TEST;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.362000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.771000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8075,14 +8075,14 @@ SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.433000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.433000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.836000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.836000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.433000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.836000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=FALSE;
@@ -8392,13 +8392,13 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.497000000Z';
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.894000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
START BATCH DDL;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.497000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.894000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -8753,8 +8753,8 @@ SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.562000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.562000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:11.953000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:11.953000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -8762,7 +8762,7 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SET TRANSACTION READ ONLY;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.562000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:11.953000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9064,6 +9064,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9197,8 +9200,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.651000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.651000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.028000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.028000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -9206,8 +9209,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
UPDATE foo SET bar=1;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.651000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.651000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.028000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.028000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -9593,15 +9596,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.721000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.721000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.093000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.093000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.721000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.093000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9851,6 +9854,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -9952,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 2024-10-11T16:42:29.792000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.792000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.159000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.159000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
CREATE TABLE foo (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY (id);
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.792000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.792000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.159000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.159000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -10219,6 +10225,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -10320,15 +10329,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:29.868000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.868000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.227000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.227000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
UPDATE foo SET bar=1;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.868000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.868000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.227000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.227000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -10601,6 +10610,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -10718,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 2024-10-11T16:42:29.942000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:29.942000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.296000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.296000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@EXPECT RESULT_SET 'TEST',1
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:29.942000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:29.942000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.296000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.296000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11009,6 +11021,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -11110,15 +11125,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.014000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.014000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.365000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.365000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.014000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.014000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.365000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.365000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11363,6 +11378,9 @@ SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
SET SPANNER.AUTOCOMMIT_DML_MODE='PARTITIONED_NON_ATOMIC';
@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','PARTITIONED_NON_ATOMIC'
SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
+SET SPANNER.AUTOCOMMIT_DML_MODE='TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC';
+@EXPECT RESULT_SET 'SPANNER.AUTOCOMMIT_DML_MODE','TRANSACTIONAL_WITH_FALLBACK_TO_PARTITIONED_NON_ATOMIC'
+SHOW VARIABLE SPANNER.AUTOCOMMIT_DML_MODE;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
@@ -11448,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 2024-10-11T16:42:30.077000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.077000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.427000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.427000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.077000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.077000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.427000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.427000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=FALSE;
@@ -11778,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 2024-10-11T16:42:30.138000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.138000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.485000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.485000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SET SPANNER.READ_ONLY_STALENESS='MAX_STALENESS 10s';
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.138000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.138000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.485000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.485000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12193,8 +12211,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.208000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.208000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.555000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.555000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12202,8 +12220,8 @@ SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
SELECT 1 AS TEST;
COMMIT;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.208000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.208000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.555000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.555000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -12586,15 +12604,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.272000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.272000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.615000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.615000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
BEGIN TRANSACTION;
@EXPECT EXCEPTION FAILED_PRECONDITION
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.272000000Z';
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.615000000Z';
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
@@ -12932,15 +12950,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.339000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.339000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.682000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.682000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.339000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.339000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.682000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.682000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -13287,15 +13305,15 @@ NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-10-11T16:42:30.405000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.405000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.747000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.747000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
SELECT 1 AS TEST;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.405000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.405000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.747000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.747000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
@@ -13612,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 2024-10-11T16:42:30.465000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-10-11T16:42:30.465000000Z'
+SET SPANNER.READ_ONLY_STALENESS='READ_TIMESTAMP 2024-11-25T10:49:12.807000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','READ_TIMESTAMP 2024-11-25T10:49:12.807000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;
SET AUTOCOMMIT=TRUE;
-SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-10-11T16:42:30.465000000Z';
-@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-10-11T16:42:30.465000000Z'
+SET SPANNER.READ_ONLY_STALENESS='MIN_READ_TIMESTAMP 2024-11-25T10:49:12.807000000Z';
+@EXPECT RESULT_SET 'SPANNER.READ_ONLY_STALENESS','MIN_READ_TIMESTAMP 2024-11-25T10:49:12.807000000Z'
SHOW VARIABLE SPANNER.READ_ONLY_STALENESS;
NEW_CONNECTION;
SET SPANNER.READONLY=TRUE;