attributes) {
+ Preconditions.checkNotNull(attributes, "Attributes map cannot be null");
+ AttributesBuilder attributesBuilder = Attributes.builder();
+ attributes.forEach(attributesBuilder::put);
+ return attributesBuilder.build();
+ }
+}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracer.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracer.java
new file mode 100644
index 00000000000..6faff5ad6d7
--- /dev/null
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracer.java
@@ -0,0 +1,156 @@
+/*
+ * 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 com.google.api.gax.rpc.ApiException;
+import com.google.api.gax.rpc.StatusCode;
+import com.google.api.gax.tracing.ApiTracer;
+import com.google.api.gax.tracing.MethodName;
+import com.google.api.gax.tracing.MetricsTracer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CancellationException;
+import javax.annotation.Nullable;
+
+/**
+ * Implements built-in metrics tracer.
+ *
+ * This class extends the {@link MetricsTracer} which computes generic metrics that can be
+ * observed in the lifecycle of an RPC operation.
+ */
+class BuiltInMetricsTracer extends MetricsTracer implements ApiTracer {
+
+ private final BuiltInMetricsRecorder builtInOpenTelemetryMetricsRecorder;
+ // These are RPC specific attributes and pertain to a specific API Trace
+ private final Map attributes = new HashMap<>();
+
+ private Long gfeLatency = null;
+
+ BuiltInMetricsTracer(
+ MethodName methodName, BuiltInMetricsRecorder builtInOpenTelemetryMetricsRecorder) {
+ super(methodName, builtInOpenTelemetryMetricsRecorder);
+ this.builtInOpenTelemetryMetricsRecorder = builtInOpenTelemetryMetricsRecorder;
+ this.attributes.put(METHOD_ATTRIBUTE, methodName.toString());
+ }
+
+ /**
+ * Adds an annotation that the attempt succeeded. Successful attempt add "OK" value to the status
+ * attribute key.
+ */
+ @Override
+ public void attemptSucceeded() {
+ super.attemptSucceeded();
+ if (gfeLatency != null) {
+ attributes.put(STATUS_ATTRIBUTE, StatusCode.Code.OK.toString());
+ builtInOpenTelemetryMetricsRecorder.recordGFELatency(gfeLatency, attributes);
+ }
+ }
+
+ /**
+ * Add an annotation that the attempt was cancelled by the user. Cancelled attempt add "CANCELLED"
+ * to the status attribute key.
+ */
+ @Override
+ public void attemptCancelled() {
+ super.attemptCancelled();
+ if (gfeLatency != null) {
+ attributes.put(STATUS_ATTRIBUTE, StatusCode.Code.CANCELLED.toString());
+ builtInOpenTelemetryMetricsRecorder.recordGFELatency(gfeLatency, attributes);
+ }
+ }
+
+ /**
+ * Adds an annotation that the attempt failed, but another attempt will be made after the delay.
+ *
+ * @param error the error that caused the attempt to fail.
+ * @param delay the amount of time to wait before the next attempt will start.
+ * Failed attempt extracts the error from the throwable and adds it to the status attribute
+ * key.
+ */
+ @Override
+ public void attemptFailedDuration(Throwable error, java.time.Duration delay) {
+ super.attemptFailedDuration(error, delay);
+ if (gfeLatency != null) {
+ attributes.put(STATUS_ATTRIBUTE, extractStatus(error));
+ builtInOpenTelemetryMetricsRecorder.recordGFELatency(gfeLatency, attributes);
+ }
+ }
+
+ /**
+ * Adds an annotation that the attempt failed and that no further attempts will be made because
+ * retry limits have been reached. This extracts the error from the throwable and adds it to the
+ * status attribute key.
+ *
+ * @param error the last error received before retries were exhausted.
+ */
+ @Override
+ public void attemptFailedRetriesExhausted(Throwable error) {
+ super.attemptFailedRetriesExhausted(error);
+ if (gfeLatency != null) {
+ attributes.put(STATUS_ATTRIBUTE, extractStatus(error));
+ builtInOpenTelemetryMetricsRecorder.recordGFELatency(gfeLatency, attributes);
+ }
+ }
+
+ /**
+ * Adds an annotation that the attempt failed and that no further attempts will be made because
+ * the last error was not retryable. This extracts the error from the throwable and adds it to the
+ * status attribute key.
+ *
+ * @param error the error that caused the final attempt to fail.
+ */
+ @Override
+ public void attemptPermanentFailure(Throwable error) {
+ super.attemptPermanentFailure(error);
+ if (gfeLatency != null) {
+ attributes.put(STATUS_ATTRIBUTE, extractStatus(error));
+ builtInOpenTelemetryMetricsRecorder.recordGFELatency(gfeLatency, attributes);
+ }
+ }
+
+ void recordGFELatency(Long gfeLatency) {
+ this.gfeLatency = gfeLatency;
+ }
+
+ @Override
+ public void addAttributes(Map attributes) {
+ super.addAttributes(attributes);
+ this.attributes.putAll(attributes);
+ };
+
+ @Override
+ public void addAttributes(String key, String value) {
+ super.addAttributes(key, value);
+ this.attributes.put(key, value);
+ }
+
+ private static String extractStatus(@Nullable Throwable error) {
+ final String statusString;
+
+ if (error == null) {
+ return StatusCode.Code.OK.toString();
+ } else if (error instanceof CancellationException) {
+ statusString = StatusCode.Code.CANCELLED.toString();
+ } else if (error instanceof ApiException) {
+ statusString = ((ApiException) error).getStatusCode().getCode().toString();
+ } else {
+ statusString = StatusCode.Code.UNKNOWN.toString();
+ }
+
+ return statusString;
+ }
+}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracerFactory.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracerFactory.java
new file mode 100644
index 00000000000..42c19dd72a0
--- /dev/null
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsTracerFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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 com.google.api.gax.tracing.ApiTracer;
+import com.google.api.gax.tracing.ApiTracerFactory;
+import com.google.api.gax.tracing.MethodName;
+import com.google.api.gax.tracing.MetricsTracer;
+import com.google.api.gax.tracing.MetricsTracerFactory;
+import com.google.api.gax.tracing.SpanName;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+
+/**
+ * A {@link ApiTracerFactory} to build instances of {@link MetricsTracer}.
+ *
+ * This class extends the {@link MetricsTracerFactory} which wraps the {@link
+ * BuiltInMetricsRecorder} and pass it to {@link BuiltInMetricsTracer}. It will be * used to record
+ * metrics in {@link BuiltInMetricsTracer}.
+ *
+ *
This class is expected to be initialized once during client initialization.
+ */
+class BuiltInMetricsTracerFactory extends MetricsTracerFactory {
+
+ protected BuiltInMetricsRecorder builtInMetricsRecorder;
+ private final Map attributes;
+
+ /**
+ * Pass in a Map of client level attributes which will be added to every single MetricsTracer
+ * created from the ApiTracerFactory.
+ */
+ public BuiltInMetricsTracerFactory(
+ BuiltInMetricsRecorder builtInMetricsRecorder, Map attributes) {
+ super(builtInMetricsRecorder, attributes);
+ this.builtInMetricsRecorder = builtInMetricsRecorder;
+ this.attributes = ImmutableMap.copyOf(attributes);
+ }
+
+ @Override
+ public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType operationType) {
+ BuiltInMetricsTracer metricsTracer =
+ new BuiltInMetricsTracer(
+ MethodName.of(spanName.getClientName(), spanName.getMethodName()),
+ builtInMetricsRecorder);
+ metricsTracer.addAttributes(attributes);
+ return metricsTracer;
+ }
+}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsView.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsView.java
similarity index 93%
rename from google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsView.java
rename to google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsView.java
index 4a09c0d856a..e72eeb9425a 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsView.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/BuiltInMetricsView.java
@@ -20,9 +20,9 @@
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
-class BuiltInOpenTelemetryMetricsView {
+class BuiltInMetricsView {
- private BuiltInOpenTelemetryMetricsView() {}
+ private BuiltInMetricsView() {}
/** Register built-in metrics on the {@link SdkMeterProviderBuilder} with credentials. */
static void registerBuiltinMetrics(
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/CompositeTracer.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/CompositeTracer.java
index 60d7081cc1e..5268e9046f8 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/CompositeTracer.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/CompositeTracer.java
@@ -190,4 +190,12 @@ public void addAttributes(Map attributes) {
}
}
}
+
+ public void recordGFELatency(Long gfeLatency) {
+ for (ApiTracer child : children) {
+ if (child instanceof BuiltInMetricsTracer) {
+ ((BuiltInMetricsTracer) child).recordGFELatency(gfeLatency);
+ }
+ }
+ }
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java
index 92971ff320f..ed5b0179349 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/DatabaseClientImpl.java
@@ -124,6 +124,12 @@ private boolean canUseMultiplexedSessionsForRW() {
&& this.multiplexedSessionDatabaseClient.isMultiplexedSessionsForRWSupported();
}
+ private boolean canUseMultiplexedSessionsForPartitionedOps() {
+ return this.useMultiplexedSessionPartitionedOps
+ && this.multiplexedSessionDatabaseClient != null
+ && this.multiplexedSessionDatabaseClient.isMultiplexedSessionsForPartitionedOpsSupported();
+ }
+
@Override
public Dialect getDialect() {
return pool.getDialect();
@@ -323,8 +329,15 @@ public AsyncTransactionManager transactionManagerAsync(TransactionOption... opti
@Override
public long executePartitionedUpdate(final Statement stmt, final UpdateOption... options) {
- if (useMultiplexedSessionPartitionedOps) {
- return getMultiplexedSession().executePartitionedUpdate(stmt, options);
+
+ if (canUseMultiplexedSessionsForPartitionedOps()) {
+ try {
+ return getMultiplexedSession().executePartitionedUpdate(stmt, options);
+ } catch (SpannerException e) {
+ if (!multiplexedSessionDatabaseClient.maybeMarkUnimplementedForPartitionedOps(e)) {
+ throw e;
+ }
+ }
}
return executePartitionedUpdateWithPooledSession(stmt, options);
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java
index 33ddcdeb0cb..235d663360d 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClient.java
@@ -104,6 +104,11 @@ void onError(SpannerException spannerException) {
// UNIMPLEMENTED with error message "Transaction type read_write not supported with
// multiplexed sessions" is returned.
this.client.maybeMarkUnimplementedForRW(spannerException);
+ // Mark multiplexed sessions for Partitioned Ops as unimplemented and fall back to regular
+ // sessions if
+ // UNIMPLEMENTED with error message "Partitioned operations are not supported with multiplexed
+ // sessions".
+ this.client.maybeMarkUnimplementedForPartitionedOps(spannerException);
}
@Override
@@ -214,6 +219,12 @@ public void close() {
*/
@VisibleForTesting final AtomicBoolean unimplementedForRW = new AtomicBoolean(false);
+ /**
+ * This flag is set to true if the server return UNIMPLEMENTED when partitioned transaction is
+ * executed on a multiplexed session. TODO: Remove once this is guaranteed to be available.
+ */
+ @VisibleForTesting final AtomicBoolean unimplementedForPartitionedOps = new AtomicBoolean(false);
+
MultiplexedSessionDatabaseClient(SessionClient sessionClient) {
this(sessionClient, Clock.systemUTC());
}
@@ -316,7 +327,18 @@ && verifyErrorMessage(
}
}
- private boolean verifyErrorMessage(SpannerException spannerException, String message) {
+ boolean maybeMarkUnimplementedForPartitionedOps(SpannerException spannerException) {
+ if (spannerException.getErrorCode() == ErrorCode.UNIMPLEMENTED
+ && verifyErrorMessage(
+ spannerException,
+ "Transaction type partitioned_dml not supported with multiplexed sessions")) {
+ unimplementedForPartitionedOps.set(true);
+ return true;
+ }
+ return false;
+ }
+
+ static boolean verifyErrorMessage(SpannerException spannerException, String message) {
if (spannerException.getCause() == null) {
return false;
}
@@ -391,6 +413,10 @@ boolean isMultiplexedSessionsForRWSupported() {
return !this.unimplementedForRW.get();
}
+ boolean isMultiplexedSessionsForPartitionedOpsSupported() {
+ return !this.unimplementedForPartitionedOps.get();
+ }
+
void close() {
synchronized (this) {
if (!this.isClosed) {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Options.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Options.java
index c062e89ec2b..c8c588f813a 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Options.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/Options.java
@@ -108,6 +108,9 @@ public interface ReadQueryUpdateTransactionOption
/** Marker interface to mark options applicable to Update and Write operations */
public interface UpdateTransactionOption extends UpdateOption, TransactionOption {}
+ /** Marker interface for options that can be used with both executeQuery and executeUpdate. */
+ public interface QueryUpdateOption extends QueryOption, UpdateOption {}
+
/**
* Marker interface to mark options applicable to Create, Update and Delete operations in admin
* API.
@@ -236,6 +239,20 @@ public static DataBoostQueryOption dataBoostEnabled(Boolean dataBoostEnabled) {
return new DataBoostQueryOption(dataBoostEnabled);
}
+ /**
+ * If set to true, this option marks the end of the transaction. The transaction should be
+ * committed or aborted after this statement executes, and attempts to execute any other requests
+ * against this transaction (including reads and queries) will be rejected. Mixing mutations with
+ * statements that are marked as the last statement is not allowed.
+ *
+ * For DML statements, setting this option may cause some error reporting to be deferred until
+ * commit time (e.g. validation of unique constraints). Given this, successful execution of a DML
+ * statement should not be assumed until the transaction commits.
+ */
+ public static QueryUpdateOption lastStatement() {
+ return new LastStatementUpdateOption();
+ }
+
/**
* Specifying this will cause the list operation to start fetching the record from this onwards.
*/
@@ -494,6 +511,7 @@ void appendToOptions(Options options) {
private DecodeMode decodeMode;
private RpcOrderBy orderBy;
private RpcLockHint lockHint;
+ private Boolean lastStatement;
// Construction is via factory methods below.
private Options() {}
@@ -630,6 +648,14 @@ OrderBy orderBy() {
return orderBy == null ? null : orderBy.proto;
}
+ boolean hasLastStatement() {
+ return lastStatement != null;
+ }
+
+ Boolean isLastStatement() {
+ return lastStatement;
+ }
+
boolean hasLockHint() {
return lockHint != null;
}
@@ -694,6 +720,9 @@ public String toString() {
if (orderBy != null) {
b.append("orderBy: ").append(orderBy).append(' ');
}
+ if (lastStatement != null) {
+ b.append("lastStatement: ").append(lastStatement).append(' ');
+ }
if (lockHint != null) {
b.append("lockHint: ").append(lockHint).append(' ');
}
@@ -737,6 +766,7 @@ public boolean equals(Object o) {
&& Objects.equals(dataBoostEnabled(), that.dataBoostEnabled())
&& Objects.equals(directedReadOptions(), that.directedReadOptions())
&& Objects.equals(orderBy(), that.orderBy())
+ && Objects.equals(isLastStatement(), that.isLastStatement())
&& Objects.equals(lockHint(), that.lockHint());
}
@@ -797,6 +827,9 @@ public int hashCode() {
if (orderBy != null) {
result = 31 * result + orderBy.hashCode();
}
+ if (lastStatement != null) {
+ result = 31 * result + lastStatement.hashCode();
+ }
if (lockHint != null) {
result = 31 * result + lockHint.hashCode();
}
@@ -965,4 +998,24 @@ public boolean equals(Object o) {
return Objects.equals(filter, ((FilterOption) o).filter);
}
}
+
+ static final class LastStatementUpdateOption extends InternalOption implements QueryUpdateOption {
+
+ LastStatementUpdateOption() {}
+
+ @Override
+ void appendToOptions(Options options) {
+ options.lastStatement = true;
+ }
+
+ @Override
+ public int hashCode() {
+ return LastStatementUpdateOption.class.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof LastStatementUpdateOption;
+ }
+ }
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java
index 03551640b43..171c10c9c92 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SessionPoolOptions.java
@@ -360,7 +360,7 @@ public boolean getUseMultiplexedSessionForRW() {
@VisibleForTesting
@InternalApi
public boolean getUseMultiplexedSessionPartitionedOps() {
- return useMultiplexedSessionForPartitionedOps;
+ return getUseMultiplexedSession() && useMultiplexedSessionForPartitionedOps;
}
private static Boolean getUseMultiplexedSessionFromEnvVariable() {
@@ -370,9 +370,7 @@ private static Boolean getUseMultiplexedSessionFromEnvVariable() {
@VisibleForTesting
@InternalApi
protected static Boolean getUseMultiplexedSessionFromEnvVariablePartitionedOps() {
- // Checks the value of env, GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS
- // This returns null until Partitioned Operations is supported.
- return null;
+ return parseBooleanEnvVariable("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS");
}
private static Boolean parseBooleanEnvVariable(String variableName) {
@@ -390,7 +388,7 @@ private static Boolean parseBooleanEnvVariable(String variableName) {
private static Boolean getUseMultiplexedSessionForRWFromEnvVariable() {
// Checks the value of env, GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW
// This returns null until RW is supported.
- return null;
+ return parseBooleanEnvVariable("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW");
}
Duration getMultiplexedSessionMaintenanceDuration() {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java
index 21fcba8194d..620430b87df 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerCloudMonitoringExporterUtils.java
@@ -25,6 +25,7 @@
import static com.google.cloud.spanner.BuiltInMetricsConstant.GAX_METER_NAME;
import static com.google.cloud.spanner.BuiltInMetricsConstant.INSTANCE_ID_KEY;
import static com.google.cloud.spanner.BuiltInMetricsConstant.PROJECT_ID_KEY;
+import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_METER_NAME;
import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_PROMOTED_RESOURCE_LABELS;
import static com.google.cloud.spanner.BuiltInMetricsConstant.SPANNER_RESOURCE_TYPE;
@@ -75,8 +76,9 @@ static List convertToSpannerTimeSeries(List collection)
List allTimeSeries = new ArrayList<>();
for (MetricData metricData : collection) {
- // Get common metrics data from GAX library
- if (!metricData.getInstrumentationScopeInfo().getName().equals(GAX_METER_NAME)) {
+ // Get metrics data from GAX library and Spanner library
+ if (!(metricData.getInstrumentationScopeInfo().getName().equals(GAX_METER_NAME)
+ || metricData.getInstrumentationScopeInfo().getName().equals(SPANNER_METER_NAME))) {
// Filter out metric data for instruments that are not part of the spanner metrics list
continue;
}
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 2dd70ce108e..a3f174cda60 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
@@ -265,6 +265,9 @@ static ErrorDetails extractErrorDetails(Throwable cause) {
if (cause instanceof ApiException) {
return ((ApiException) cause).getErrorDetails();
}
+ if (cause instanceof SpannerException) {
+ return ((SpannerException) cause).getErrorDetails();
+ }
prevCause = cause;
cause = cause.getCause();
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
index 42fc0c2d0bd..5b63ff4fe44 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
@@ -33,8 +33,6 @@
import com.google.api.gax.rpc.TransportChannelProvider;
import com.google.api.gax.tracing.ApiTracerFactory;
import com.google.api.gax.tracing.BaseApiTracerFactory;
-import com.google.api.gax.tracing.MetricsTracerFactory;
-import com.google.api.gax.tracing.OpenTelemetryMetricsRecorder;
import com.google.api.gax.tracing.OpencensusTracerFactory;
import com.google.cloud.NoCredentials;
import com.google.cloud.ServiceDefaults;
@@ -144,8 +142,7 @@ public class SpannerOptions extends ServiceOptions {
private final boolean autoThrottleAdministrativeRequests;
private final RetrySettings retryAdministrativeRequestsSettings;
private final boolean trackTransactionStarter;
- private final BuiltInOpenTelemetryMetricsProvider builtInOpenTelemetryMetricsProvider =
- BuiltInOpenTelemetryMetricsProvider.INSTANCE;
+ private final BuiltInMetricsProvider builtInMetricsProvider = BuiltInMetricsProvider.INSTANCE;
/**
* These are the default {@link QueryOptions} defined by the user on this {@link SpannerOptions}.
*/
@@ -1910,13 +1907,13 @@ private ApiTracerFactory getDefaultApiTracerFactory() {
private ApiTracerFactory createMetricsApiTracerFactory() {
OpenTelemetry openTelemetry =
- this.builtInOpenTelemetryMetricsProvider.getOrCreateOpenTelemetry(
+ this.builtInMetricsProvider.getOrCreateOpenTelemetry(
this.getProjectId(), getCredentials(), this.monitoringHost);
return openTelemetry != null
- ? new MetricsTracerFactory(
- new OpenTelemetryMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME),
- builtInOpenTelemetryMetricsProvider.createClientAttributes(
+ ? new BuiltInMetricsTracerFactory(
+ new BuiltInMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME),
+ builtInMetricsProvider.createClientAttributes(
this.getProjectId(), "spanner-java/" + GaxProperties.getLibraryVersion(getClass())))
: null;
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TraceWrapper.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TraceWrapper.java
index 606a54fe8b7..df5874cb3c6 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TraceWrapper.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TraceWrapper.java
@@ -47,6 +47,8 @@ class TraceWrapper {
private static final AttributeKey> DB_STATEMENT_ARRAY_KEY =
AttributeKey.stringArrayKey("db.statement");
private static final AttributeKey DB_TABLE_NAME_KEY = AttributeKey.stringKey("db.table");
+ private static final AttributeKey CLOUD_REGION_KEY =
+ AttributeKey.stringKey("cloud.region");
private static final AttributeKey GCP_CLIENT_SERVICE_KEY =
AttributeKey.stringKey("gcp.client.service");
private static final AttributeKey GCP_CLIENT_VERSION_KEY =
@@ -214,6 +216,7 @@ Attributes createCommonAttributes(DatabaseId db) {
builder.put(GCP_CLIENT_SERVICE_KEY, "spanner");
builder.put(GCP_CLIENT_REPO_KEY, "googleapis/java-spanner");
builder.put(GCP_CLIENT_VERSION_KEY, GaxProperties.getLibraryVersion(TraceWrapper.class));
+ builder.put(CLOUD_REGION_KEY, BuiltInMetricsProvider.detectClientLocation());
return builder.build();
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionManagerImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionManagerImpl.java
index b1d37f3e4cd..bbf34ab5c8f 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionManagerImpl.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/TransactionManagerImpl.java
@@ -80,6 +80,13 @@ public void commit() {
} catch (SpannerException e2) {
txnState = TransactionState.COMMIT_FAILED;
throw e2;
+ } finally {
+ // At this point, if the TransactionState is not ABORTED, then the transaction has reached an
+ // end state.
+ // We can safely call close() to release resources.
+ if (getState() != TransactionState.ABORTED) {
+ close();
+ }
}
}
@@ -92,6 +99,9 @@ public void rollback() {
txn.rollback();
} finally {
txnState = TransactionState.ROLLED_BACK;
+ // At this point, the TransactionState is ROLLED_BACK which is an end state.
+ // We can safely call close() to release resources.
+ close();
}
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java
new file mode 100644
index 00000000000..4f6c0114750
--- /dev/null
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/XGoogSpannerRequestId.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner;
+
+import com.google.api.core.InternalApi;
+import com.google.common.annotations.VisibleForTesting;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+import java.util.Objects;
+
+@InternalApi
+public class XGoogSpannerRequestId {
+ // 1. Generate the random process Id singleton.
+ @VisibleForTesting
+ static final String RAND_PROCESS_ID = XGoogSpannerRequestId.generateRandProcessId();
+
+ @VisibleForTesting
+ static final long VERSION = 1; // The version of the specification being implemented.
+
+ private final long nthClientId;
+ private final long nthChannelId;
+ private final long nthRequest;
+ private long attempt;
+
+ XGoogSpannerRequestId(long nthClientId, long nthChannelId, long nthRequest, long attempt) {
+ this.nthClientId = nthClientId;
+ this.nthChannelId = nthChannelId;
+ this.nthRequest = nthRequest;
+ this.attempt = attempt;
+ }
+
+ public static XGoogSpannerRequestId of(
+ long nthClientId, long nthChannelId, long nthRequest, long attempt) {
+ return new XGoogSpannerRequestId(nthClientId, nthChannelId, nthRequest, attempt);
+ }
+
+ private static String generateRandProcessId() {
+ // Expecting to use 64-bits of randomness to avoid clashes.
+ BigInteger bigInt = new BigInteger(64, new SecureRandom());
+ return String.format("%016x", bigInt);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "%d.%s.%d.%d.%d.%d",
+ XGoogSpannerRequestId.VERSION,
+ XGoogSpannerRequestId.RAND_PROCESS_ID,
+ this.nthClientId,
+ this.nthChannelId,
+ this.nthRequest,
+ this.attempt);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ // instanceof for a null object returns false.
+ if (!(other instanceof XGoogSpannerRequestId)) {
+ return false;
+ }
+
+ XGoogSpannerRequestId otherReqId = (XGoogSpannerRequestId) (other);
+
+ return Objects.equals(this.nthClientId, otherReqId.nthClientId)
+ && Objects.equals(this.nthChannelId, otherReqId.nthChannelId)
+ && Objects.equals(this.nthRequest, otherReqId.nthRequest)
+ && Objects.equals(this.attempt, otherReqId.attempt);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.nthClientId, this.nthChannelId, this.nthRequest, this.attempt);
+ }
+}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java
index 416913e22f7..b91188619aa 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClient.java
@@ -41,6 +41,8 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Timestamp;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupName;
import com.google.spanner.admin.database.v1.BackupSchedule;
@@ -78,6 +80,7 @@
import com.google.spanner.admin.database.v1.ListDatabasesResponse;
import com.google.spanner.admin.database.v1.RestoreDatabaseMetadata;
import com.google.spanner.admin.database.v1.RestoreDatabaseRequest;
+import com.google.spanner.admin.database.v1.SplitPoints;
import com.google.spanner.admin.database.v1.UpdateBackupRequest;
import com.google.spanner.admin.database.v1.UpdateBackupScheduleRequest;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata;
@@ -524,6 +527,25 @@
*
*
*
+ * AddSplitPoints |
+ * Adds split points to specified tables, indexes of a database. |
+ *
+ * Request object method variants only take one parameter, a request object, which must be constructed before the call.
+ *
+ * "Flattened" method variants have converted the fields of the request object into function parameters to enable multiple ways to call the same method.
+ *
+ * addSplitPoints(DatabaseName database, List<SplitPoints> splitPoints)
+ * addSplitPoints(String database, List<SplitPoints> splitPoints)
+ *
+ * Callable method variants take no parameters and return an immutable API callable object, which can be used to initiate calls to the service.
+ *
+ * |
+ *
+ *
* CreateBackupSchedule |
* Creates a new backup schedule. |
*
@@ -4318,6 +4340,137 @@ public final ListDatabaseRolesPagedResponse listDatabaseRoles(ListDatabaseRolesR
return stub.listDatabaseRolesCallable();
}
+ // AUTO-GENERATED DOCUMENTATION AND METHOD.
+ /**
+ * Adds split points to specified tables, indexes of a database.
+ *
+ * Sample code:
+ *
+ * {@code
+ * // This snippet has been automatically generated and should be regarded as a code template only.
+ * // It will require modifications to work:
+ * // - It may require correct/in-range values for request initialization.
+ * // - It may require specifying regional endpoints when creating the service client as shown in
+ * // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
+ * try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
+ * DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]");
+ * List splitPoints = new ArrayList<>();
+ * AddSplitPointsResponse response = databaseAdminClient.addSplitPoints(database, splitPoints);
+ * }
+ * }
+ *
+ * @param database Required. The database on whose tables/indexes split points are to be added.
+ * Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ * @param splitPoints Required. The split points to add.
+ * @throws com.google.api.gax.rpc.ApiException if the remote call fails
+ */
+ public final AddSplitPointsResponse addSplitPoints(
+ DatabaseName database, List splitPoints) {
+ AddSplitPointsRequest request =
+ AddSplitPointsRequest.newBuilder()
+ .setDatabase(database == null ? null : database.toString())
+ .addAllSplitPoints(splitPoints)
+ .build();
+ return addSplitPoints(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD.
+ /**
+ * Adds split points to specified tables, indexes of a database.
+ *
+ * Sample code:
+ *
+ * {@code
+ * // This snippet has been automatically generated and should be regarded as a code template only.
+ * // It will require modifications to work:
+ * // - It may require correct/in-range values for request initialization.
+ * // - It may require specifying regional endpoints when creating the service client as shown in
+ * // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
+ * try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
+ * String database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString();
+ * List splitPoints = new ArrayList<>();
+ * AddSplitPointsResponse response = databaseAdminClient.addSplitPoints(database, splitPoints);
+ * }
+ * }
+ *
+ * @param database Required. The database on whose tables/indexes split points are to be added.
+ * Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ * @param splitPoints Required. The split points to add.
+ * @throws com.google.api.gax.rpc.ApiException if the remote call fails
+ */
+ public final AddSplitPointsResponse addSplitPoints(
+ String database, List splitPoints) {
+ AddSplitPointsRequest request =
+ AddSplitPointsRequest.newBuilder()
+ .setDatabase(database)
+ .addAllSplitPoints(splitPoints)
+ .build();
+ return addSplitPoints(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD.
+ /**
+ * Adds split points to specified tables, indexes of a database.
+ *
+ * Sample code:
+ *
+ * {@code
+ * // This snippet has been automatically generated and should be regarded as a code template only.
+ * // It will require modifications to work:
+ * // - It may require correct/in-range values for request initialization.
+ * // - It may require specifying regional endpoints when creating the service client as shown in
+ * // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
+ * try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
+ * AddSplitPointsRequest request =
+ * AddSplitPointsRequest.newBuilder()
+ * .setDatabase(DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString())
+ * .addAllSplitPoints(new ArrayList())
+ * .setInitiator("initiator-248987089")
+ * .build();
+ * AddSplitPointsResponse response = databaseAdminClient.addSplitPoints(request);
+ * }
+ * }
+ *
+ * @param request The request object containing all of the parameters for the API call.
+ * @throws com.google.api.gax.rpc.ApiException if the remote call fails
+ */
+ public final AddSplitPointsResponse addSplitPoints(AddSplitPointsRequest request) {
+ return addSplitPointsCallable().call(request);
+ }
+
+ // AUTO-GENERATED DOCUMENTATION AND METHOD.
+ /**
+ * Adds split points to specified tables, indexes of a database.
+ *
+ * Sample code:
+ *
+ * {@code
+ * // This snippet has been automatically generated and should be regarded as a code template only.
+ * // It will require modifications to work:
+ * // - It may require correct/in-range values for request initialization.
+ * // - It may require specifying regional endpoints when creating the service client as shown in
+ * // https://cloud.google.com/java/docs/setup#configure_endpoints_for_the_client_library
+ * try (DatabaseAdminClient databaseAdminClient = DatabaseAdminClient.create()) {
+ * AddSplitPointsRequest request =
+ * AddSplitPointsRequest.newBuilder()
+ * .setDatabase(DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]").toString())
+ * .addAllSplitPoints(new ArrayList())
+ * .setInitiator("initiator-248987089")
+ * .build();
+ * ApiFuture future =
+ * databaseAdminClient.addSplitPointsCallable().futureCall(request);
+ * // Do something.
+ * AddSplitPointsResponse response = future.get();
+ * }
+ * }
+ */
+ public final UnaryCallable
+ addSplitPointsCallable() {
+ return stub.addSplitPointsCallable();
+ }
+
// AUTO-GENERATED DOCUMENTATION AND METHOD.
/**
* Creates a new backup schedule.
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminSettings.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminSettings.java
index 097695ebece..399dcbf38c8 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminSettings.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminSettings.java
@@ -44,6 +44,8 @@
import com.google.iam.v1.TestIamPermissionsResponse;
import com.google.longrunning.Operation;
import com.google.protobuf.Empty;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
@@ -312,6 +314,11 @@ public UnaryCallSettings restoreDatabaseSetti
return ((DatabaseAdminStubSettings) getStubSettings()).listDatabaseRolesSettings();
}
+ /** Returns the object with the settings used for calls to addSplitPoints. */
+ public UnaryCallSettings addSplitPointsSettings() {
+ return ((DatabaseAdminStubSettings) getStubSettings()).addSplitPointsSettings();
+ }
+
/** Returns the object with the settings used for calls to createBackupSchedule. */
public UnaryCallSettings
createBackupScheduleSettings() {
@@ -606,6 +613,12 @@ public UnaryCallSettings.Builder restoreDatab
return getStubSettingsBuilder().listDatabaseRolesSettings();
}
+ /** Returns the builder for the settings used for calls to addSplitPoints. */
+ public UnaryCallSettings.Builder
+ addSplitPointsSettings() {
+ return getStubSettingsBuilder().addSplitPointsSettings();
+ }
+
/** Returns the builder for the settings used for calls to createBackupSchedule. */
public UnaryCallSettings.Builder
createBackupScheduleSettings() {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/gapic_metadata.json b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/gapic_metadata.json
index 7d6c894d7b6..96dc31e91d7 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/gapic_metadata.json
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/gapic_metadata.json
@@ -10,6 +10,9 @@
"grpc": {
"libraryClient": "DatabaseAdminClient",
"rpcs": {
+ "AddSplitPoints": {
+ "methods": ["addSplitPoints", "addSplitPoints", "addSplitPoints", "addSplitPointsCallable"]
+ },
"CopyBackup": {
"methods": ["copyBackupAsync", "copyBackupAsync", "copyBackupAsync", "copyBackupAsync", "copyBackupAsync", "copyBackupOperationCallable", "copyBackupCallable"]
},
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStub.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStub.java
index 7250a8c60f6..7926008bab3 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStub.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStub.java
@@ -34,6 +34,8 @@
import com.google.longrunning.Operation;
import com.google.longrunning.stub.OperationsStub;
import com.google.protobuf.Empty;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
@@ -231,6 +233,10 @@ public UnaryCallable restoreDatabaseCallable(
throw new UnsupportedOperationException("Not implemented: listDatabaseRolesCallable()");
}
+ public UnaryCallable addSplitPointsCallable() {
+ throw new UnsupportedOperationException("Not implemented: addSplitPointsCallable()");
+ }
+
public UnaryCallable createBackupScheduleCallable() {
throw new UnsupportedOperationException("Not implemented: createBackupScheduleCallable()");
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStubSettings.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStubSettings.java
index 246e44438ef..b2624c5a9a9 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStubSettings.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/DatabaseAdminStubSettings.java
@@ -64,6 +64,8 @@
import com.google.iam.v1.TestIamPermissionsResponse;
import com.google.longrunning.Operation;
import com.google.protobuf.Empty;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
@@ -240,6 +242,8 @@ public class DatabaseAdminStubSettings extends StubSettings
listDatabaseRolesSettings;
+ private final UnaryCallSettings
+ addSplitPointsSettings;
private final UnaryCallSettings
createBackupScheduleSettings;
private final UnaryCallSettings
@@ -745,6 +749,11 @@ public UnaryCallSettings restoreDatabaseSetti
return listDatabaseRolesSettings;
}
+ /** Returns the object with the settings used for calls to addSplitPoints. */
+ public UnaryCallSettings addSplitPointsSettings() {
+ return addSplitPointsSettings;
+ }
+
/** Returns the object with the settings used for calls to createBackupSchedule. */
public UnaryCallSettings
createBackupScheduleSettings() {
@@ -912,6 +921,7 @@ protected DatabaseAdminStubSettings(Builder settingsBuilder) throws IOException
listDatabaseOperationsSettings = settingsBuilder.listDatabaseOperationsSettings().build();
listBackupOperationsSettings = settingsBuilder.listBackupOperationsSettings().build();
listDatabaseRolesSettings = settingsBuilder.listDatabaseRolesSettings().build();
+ addSplitPointsSettings = settingsBuilder.addSplitPointsSettings().build();
createBackupScheduleSettings = settingsBuilder.createBackupScheduleSettings().build();
getBackupScheduleSettings = settingsBuilder.getBackupScheduleSettings().build();
updateBackupScheduleSettings = settingsBuilder.updateBackupScheduleSettings().build();
@@ -978,6 +988,8 @@ public static class Builder extends StubSettings.Builder
listDatabaseRolesSettings;
+ private final UnaryCallSettings.Builder
+ addSplitPointsSettings;
private final UnaryCallSettings.Builder
createBackupScheduleSettings;
private final UnaryCallSettings.Builder
@@ -1095,6 +1107,7 @@ protected Builder(ClientContext clientContext) {
listBackupOperationsSettings =
PagedCallSettings.newBuilder(LIST_BACKUP_OPERATIONS_PAGE_STR_FACT);
listDatabaseRolesSettings = PagedCallSettings.newBuilder(LIST_DATABASE_ROLES_PAGE_STR_FACT);
+ addSplitPointsSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
createBackupScheduleSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
getBackupScheduleSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
updateBackupScheduleSettings = UnaryCallSettings.newUnaryCallSettingsBuilder();
@@ -1124,6 +1137,7 @@ protected Builder(ClientContext clientContext) {
listDatabaseOperationsSettings,
listBackupOperationsSettings,
listDatabaseRolesSettings,
+ addSplitPointsSettings,
createBackupScheduleSettings,
getBackupScheduleSettings,
updateBackupScheduleSettings,
@@ -1161,6 +1175,7 @@ protected Builder(DatabaseAdminStubSettings settings) {
listDatabaseOperationsSettings = settings.listDatabaseOperationsSettings.toBuilder();
listBackupOperationsSettings = settings.listBackupOperationsSettings.toBuilder();
listDatabaseRolesSettings = settings.listDatabaseRolesSettings.toBuilder();
+ addSplitPointsSettings = settings.addSplitPointsSettings.toBuilder();
createBackupScheduleSettings = settings.createBackupScheduleSettings.toBuilder();
getBackupScheduleSettings = settings.getBackupScheduleSettings.toBuilder();
updateBackupScheduleSettings = settings.updateBackupScheduleSettings.toBuilder();
@@ -1189,6 +1204,7 @@ protected Builder(DatabaseAdminStubSettings settings) {
listDatabaseOperationsSettings,
listBackupOperationsSettings,
listDatabaseRolesSettings,
+ addSplitPointsSettings,
createBackupScheduleSettings,
getBackupScheduleSettings,
updateBackupScheduleSettings,
@@ -1321,6 +1337,11 @@ private static Builder initDefaults(Builder builder) {
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes"))
.setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params"));
+ builder
+ .addSplitPointsSettings()
+ .setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes"))
+ .setRetrySettings(RETRY_PARAM_DEFINITIONS.get("retry_policy_0_params"));
+
builder
.createBackupScheduleSettings()
.setRetryableCodes(RETRYABLE_CODE_DEFINITIONS.get("retry_policy_0_codes"))
@@ -1661,6 +1682,12 @@ public UnaryCallSettings.Builder restoreDatab
return listDatabaseRolesSettings;
}
+ /** Returns the builder for the settings used for calls to addSplitPoints. */
+ public UnaryCallSettings.Builder
+ addSplitPointsSettings() {
+ return addSplitPointsSettings;
+ }
+
/** Returns the builder for the settings used for calls to createBackupSchedule. */
public UnaryCallSettings.Builder
createBackupScheduleSettings() {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/GrpcDatabaseAdminStub.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/GrpcDatabaseAdminStub.java
index 5726370d364..9e6270f3c24 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/GrpcDatabaseAdminStub.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/GrpcDatabaseAdminStub.java
@@ -39,6 +39,8 @@
import com.google.longrunning.Operation;
import com.google.longrunning.stub.GrpcOperationsStub;
import com.google.protobuf.Empty;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
@@ -285,6 +287,17 @@ public class GrpcDatabaseAdminStub extends DatabaseAdminStub {
ProtoUtils.marshaller(ListDatabaseRolesResponse.getDefaultInstance()))
.build();
+ private static final MethodDescriptor
+ addSplitPointsMethodDescriptor =
+ MethodDescriptor.newBuilder()
+ .setType(MethodDescriptor.MethodType.UNARY)
+ .setFullMethodName("google.spanner.admin.database.v1.DatabaseAdmin/AddSplitPoints")
+ .setRequestMarshaller(
+ ProtoUtils.marshaller(AddSplitPointsRequest.getDefaultInstance()))
+ .setResponseMarshaller(
+ ProtoUtils.marshaller(AddSplitPointsResponse.getDefaultInstance()))
+ .build();
+
private static final MethodDescriptor
createBackupScheduleMethodDescriptor =
MethodDescriptor.newBuilder()
@@ -386,6 +399,7 @@ public class GrpcDatabaseAdminStub extends DatabaseAdminStub {
listDatabaseRolesCallable;
private final UnaryCallable
listDatabaseRolesPagedCallable;
+ private final UnaryCallable addSplitPointsCallable;
private final UnaryCallable
createBackupScheduleCallable;
private final UnaryCallable getBackupScheduleCallable;
@@ -645,6 +659,17 @@ protected GrpcDatabaseAdminStub(
return builder.build();
})
.build();
+ GrpcCallSettings
+ addSplitPointsTransportSettings =
+ GrpcCallSettings.newBuilder()
+ .setMethodDescriptor(addSplitPointsMethodDescriptor)
+ .setParamsExtractor(
+ request -> {
+ RequestParamsBuilder builder = RequestParamsBuilder.create();
+ builder.add("database", String.valueOf(request.getDatabase()));
+ return builder.build();
+ })
+ .build();
GrpcCallSettings
createBackupScheduleTransportSettings =
GrpcCallSettings.newBuilder()
@@ -828,6 +853,9 @@ protected GrpcDatabaseAdminStub(
listDatabaseRolesTransportSettings,
settings.listDatabaseRolesSettings(),
clientContext);
+ this.addSplitPointsCallable =
+ callableFactory.createUnaryCallable(
+ addSplitPointsTransportSettings, settings.addSplitPointsSettings(), clientContext);
this.createBackupScheduleCallable =
callableFactory.createUnaryCallable(
createBackupScheduleTransportSettings,
@@ -1036,6 +1064,11 @@ public UnaryCallable restoreDatabaseCallable(
return listDatabaseRolesPagedCallable;
}
+ @Override
+ public UnaryCallable addSplitPointsCallable() {
+ return addSplitPointsCallable;
+ }
+
@Override
public UnaryCallable createBackupScheduleCallable() {
return createBackupScheduleCallable;
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/HttpJsonDatabaseAdminStub.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/HttpJsonDatabaseAdminStub.java
index db4f8c7b960..038c51b144e 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/HttpJsonDatabaseAdminStub.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/database/v1/stub/HttpJsonDatabaseAdminStub.java
@@ -48,6 +48,8 @@
import com.google.longrunning.Operation;
import com.google.protobuf.Empty;
import com.google.protobuf.TypeRegistry;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupMetadata;
@@ -879,6 +881,43 @@ public class HttpJsonDatabaseAdminStub extends DatabaseAdminStub {
.build())
.build();
+ private static final ApiMethodDescriptor
+ addSplitPointsMethodDescriptor =
+ ApiMethodDescriptor.newBuilder()
+ .setFullMethodName("google.spanner.admin.database.v1.DatabaseAdmin/AddSplitPoints")
+ .setHttpMethod("POST")
+ .setType(ApiMethodDescriptor.MethodType.UNARY)
+ .setRequestFormatter(
+ ProtoMessageRequestFormatter.newBuilder()
+ .setPath(
+ "/v1/{database=projects/*/instances/*/databases/*}:addSplitPoints",
+ request -> {
+ Map fields = new HashMap<>();
+ ProtoRestSerializer serializer =
+ ProtoRestSerializer.create();
+ serializer.putPathParam(fields, "database", request.getDatabase());
+ return fields;
+ })
+ .setQueryParamsExtractor(
+ request -> {
+ Map> fields = new HashMap<>();
+ ProtoRestSerializer serializer =
+ ProtoRestSerializer.create();
+ serializer.putQueryParam(fields, "$alt", "json;enum-encoding=int");
+ return fields;
+ })
+ .setRequestBodyExtractor(
+ request ->
+ ProtoRestSerializer.create()
+ .toBody("*", request.toBuilder().clearDatabase().build(), true))
+ .build())
+ .setResponseParser(
+ ProtoMessageResponseParser.newBuilder()
+ .setDefaultInstance(AddSplitPointsResponse.getDefaultInstance())
+ .setDefaultTypeRegistry(typeRegistry)
+ .build())
+ .build();
+
private static final ApiMethodDescriptor
createBackupScheduleMethodDescriptor =
ApiMethodDescriptor.newBuilder()
@@ -1113,6 +1152,7 @@ public class HttpJsonDatabaseAdminStub extends DatabaseAdminStub {
listDatabaseRolesCallable;
private final UnaryCallable
listDatabaseRolesPagedCallable;
+ private final UnaryCallable addSplitPointsCallable;
private final UnaryCallable
createBackupScheduleCallable;
private final UnaryCallable getBackupScheduleCallable;
@@ -1474,6 +1514,18 @@ protected HttpJsonDatabaseAdminStub(
return builder.build();
})
.build();
+ HttpJsonCallSettings
+ addSplitPointsTransportSettings =
+ HttpJsonCallSettings.newBuilder()
+ .setMethodDescriptor(addSplitPointsMethodDescriptor)
+ .setTypeRegistry(typeRegistry)
+ .setParamsExtractor(
+ request -> {
+ RequestParamsBuilder builder = RequestParamsBuilder.create();
+ builder.add("database", String.valueOf(request.getDatabase()));
+ return builder.build();
+ })
+ .build();
HttpJsonCallSettings
createBackupScheduleTransportSettings =
HttpJsonCallSettings.newBuilder()
@@ -1664,6 +1716,9 @@ protected HttpJsonDatabaseAdminStub(
listDatabaseRolesTransportSettings,
settings.listDatabaseRolesSettings(),
clientContext);
+ this.addSplitPointsCallable =
+ callableFactory.createUnaryCallable(
+ addSplitPointsTransportSettings, settings.addSplitPointsSettings(), clientContext);
this.createBackupScheduleCallable =
callableFactory.createUnaryCallable(
createBackupScheduleTransportSettings,
@@ -1722,6 +1777,7 @@ public static List getMethodDescriptors() {
methodDescriptors.add(listDatabaseOperationsMethodDescriptor);
methodDescriptors.add(listBackupOperationsMethodDescriptor);
methodDescriptors.add(listDatabaseRolesMethodDescriptor);
+ methodDescriptors.add(addSplitPointsMethodDescriptor);
methodDescriptors.add(createBackupScheduleMethodDescriptor);
methodDescriptors.add(getBackupScheduleMethodDescriptor);
methodDescriptors.add(updateBackupScheduleMethodDescriptor);
@@ -1903,6 +1959,11 @@ public UnaryCallable restoreDatabaseCallable(
return listDatabaseRolesPagedCallable;
}
+ @Override
+ public UnaryCallable addSplitPointsCallable() {
+ return addSplitPointsCallable;
+ }
+
@Override
public UnaryCallable createBackupScheduleCallable() {
return createBackupScheduleCallable;
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 3c533cb9a7a..a827f82ba36 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
@@ -34,6 +34,7 @@
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.Options;
import com.google.cloud.spanner.Options.QueryOption;
+import com.google.cloud.spanner.Options.QueryUpdateOption;
import com.google.cloud.spanner.Options.UpdateOption;
import com.google.cloud.spanner.PartitionOptions;
import com.google.cloud.spanner.ReadOnlyTransaction;
@@ -298,7 +299,8 @@ private ApiFuture executeDmlReturningAsync(
writeTransaction.run(
transaction ->
DirectExecuteResultSet.ofResultSet(
- transaction.executeQuery(update.getStatement(), options)));
+ transaction.executeQuery(
+ update.getStatement(), appendLastStatement(options))));
state = UnitOfWorkState.COMMITTED;
return resultSet;
} catch (Throwable t) {
@@ -554,11 +556,15 @@ private ApiFuture> executeTransactionalUpdateAsync(
transaction -> {
if (analyzeMode == AnalyzeMode.NONE) {
return Tuple.of(
- transaction.executeUpdate(update.getStatement(), options), null);
+ transaction.executeUpdate(
+ update.getStatement(), appendLastStatement(options)),
+ null);
}
ResultSet resultSet =
transaction.analyzeUpdateStatement(
- update.getStatement(), analyzeMode.getQueryAnalyzeMode(), options);
+ update.getStatement(),
+ analyzeMode.getQueryAnalyzeMode(),
+ appendLastStatement(options));
return Tuple.of(null, resultSet);
});
state = UnitOfWorkState.COMMITTED;
@@ -582,6 +588,29 @@ private ApiFuture> executeTransactionalUpdateAsync(
return transactionalResult;
}
+ private static final QueryUpdateOption[] LAST_STATEMENT_OPTIONS =
+ new QueryUpdateOption[] {Options.lastStatement()};
+
+ private static UpdateOption[] appendLastStatement(UpdateOption[] options) {
+ if (options.length == 0) {
+ return LAST_STATEMENT_OPTIONS;
+ }
+ UpdateOption[] result = new UpdateOption[options.length + 1];
+ System.arraycopy(options, 0, result, 0, options.length);
+ result[result.length - 1] = LAST_STATEMENT_OPTIONS[0];
+ return result;
+ }
+
+ private static QueryOption[] appendLastStatement(QueryOption[] options) {
+ if (options.length == 0) {
+ return LAST_STATEMENT_OPTIONS;
+ }
+ QueryOption[] result = new QueryOption[options.length + 1];
+ System.arraycopy(options, 0, result, 0, options.length);
+ result[result.length - 1] = LAST_STATEMENT_OPTIONS[0];
+ return result;
+ }
+
/**
* Adds a callback to the given future that retries the update statement using Partitioned DML if
* the original statement fails with a {@link TransactionMutationLimitExceededException}.
@@ -719,7 +748,8 @@ private ApiFuture executeTransactionalBatchUpdateAsync(
try {
long[] res =
transaction.batchUpdate(
- Iterables.transform(updates, ParsedStatement::getStatement), options);
+ Iterables.transform(updates, ParsedStatement::getStatement),
+ appendLastStatement(options));
state = UnitOfWorkState.COMMITTED;
return res;
} catch (Throwable t) {
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java
index e4eec68b278..dba3b38e92f 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/HeaderInterceptor.java
@@ -71,9 +71,11 @@ class HeaderInterceptor implements ClientInterceptor {
DatabaseName.of("undefined-project", "undefined-instance", "undefined-database");
private static final Metadata.Key SERVER_TIMING_HEADER_KEY =
Metadata.Key.of("server-timing", Metadata.ASCII_STRING_MARSHALLER);
- private static final String SERVER_TIMING_HEADER_PREFIX = "gfet4t7; dur=";
+ private static final String GFE_TIMING_HEADER = "gfet4t7";
private static final Metadata.Key GOOGLE_CLOUD_RESOURCE_PREFIX_KEY =
Metadata.Key.of("google-cloud-resource-prefix", Metadata.ASCII_STRING_MARSHALLER);
+ private static final Pattern SERVER_TIMING_PATTERN =
+ Pattern.compile("(?[a-zA-Z0-9_-]+);\\s*dur=(?\\d+)");
private static final Pattern GOOGLE_CLOUD_RESOURCE_PREFIX_PATTERN =
Pattern.compile(
".*projects/(?\\p{ASCII}[^/]*)(/instances/(?\\p{ASCII}[^/]*))?(/databases/(?\\p{ASCII}[^/]*))?");
@@ -128,7 +130,7 @@ public void onHeaders(Metadata metadata) {
Boolean isDirectPathUsed =
isDirectPathUsed(getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR));
addDirectPathUsedAttribute(compositeTracer, isDirectPathUsed);
- processHeader(metadata, tagContext, attributes, span);
+ processHeader(metadata, tagContext, attributes, span, compositeTracer);
super.onHeaders(metadata);
}
},
@@ -142,29 +144,61 @@ public void onHeaders(Metadata metadata) {
}
private void processHeader(
- Metadata metadata, TagContext tagContext, Attributes attributes, Span span) {
+ Metadata metadata,
+ TagContext tagContext,
+ Attributes attributes,
+ Span span,
+ CompositeTracer compositeTracer) {
MeasureMap measureMap = STATS_RECORDER.newMeasureMap();
String serverTiming = metadata.get(SERVER_TIMING_HEADER_KEY);
- if (serverTiming != null && serverTiming.startsWith(SERVER_TIMING_HEADER_PREFIX)) {
- try {
- long latency = Long.parseLong(serverTiming.substring(SERVER_TIMING_HEADER_PREFIX.length()));
- measureMap.put(SPANNER_GFE_LATENCY, latency);
+ try {
+ // Previous implementation parsed the GFE latency directly using:
+ // long latency = Long.parseLong(serverTiming.substring("gfet4t7; dur=".length()));
+ // This approach assumed the serverTiming header contained exactly one metric "gfet4t7".
+ // If additional metrics were introduced in the header, older versions of the library
+ // would fail to parse it correctly. To make the parsing more robust, the logic has been
+ // updated to handle multiple metrics gracefully.
+
+ Map serverTimingMetrics = parseServerTimingHeader(serverTiming);
+ if (serverTimingMetrics.containsKey(GFE_TIMING_HEADER)) {
+ long gfeLatency = serverTimingMetrics.get(GFE_TIMING_HEADER);
+
+ measureMap.put(SPANNER_GFE_LATENCY, gfeLatency);
measureMap.put(SPANNER_GFE_HEADER_MISSING_COUNT, 0L);
measureMap.record(tagContext);
- spannerRpcMetrics.recordGfeLatency(latency, attributes);
+ spannerRpcMetrics.recordGfeLatency(gfeLatency, attributes);
spannerRpcMetrics.recordGfeHeaderMissingCount(0L, attributes);
+ if (compositeTracer != null) {
+ compositeTracer.recordGFELatency(gfeLatency);
+ }
if (span != null) {
- span.setAttribute("gfe_latency", String.valueOf(latency));
+ span.setAttribute("gfe_latency", String.valueOf(gfeLatency));
+ }
+ } else {
+ measureMap.put(SPANNER_GFE_HEADER_MISSING_COUNT, 1L).record(tagContext);
+ spannerRpcMetrics.recordGfeHeaderMissingCount(1L, attributes);
+ }
+ } catch (NumberFormatException e) {
+ LOGGER.log(LEVEL, "Invalid server-timing object in header: {}", serverTiming);
+ }
+ }
+
+ private Map parseServerTimingHeader(String serverTiming) {
+ Map serverTimingMetrics = new HashMap<>();
+ if (serverTiming != null) {
+ Matcher matcher = SERVER_TIMING_PATTERN.matcher(serverTiming);
+ while (matcher.find()) {
+ String metricName = matcher.group("metricName");
+ String durationStr = matcher.group("duration");
+
+ if (metricName != null && durationStr != null) {
+ serverTimingMetrics.put(metricName, Long.valueOf(durationStr));
}
- } catch (NumberFormatException e) {
- LOGGER.log(LEVEL, "Invalid server-timing object in header: {}", serverTiming);
}
- } else {
- spannerRpcMetrics.recordGfeHeaderMissingCount(1L, attributes);
- measureMap.put(SPANNER_GFE_HEADER_MISSING_COUNT, 1L).record(tagContext);
}
+ return serverTimingMetrics;
}
private DatabaseName extractDatabaseName(Metadata headers) throws ExecutionException {
diff --git a/google-cloud-spanner/src/main/resources/META-INF/native-image/com.google.cloud.spanner.admin.database.v1/reflect-config.json b/google-cloud-spanner/src/main/resources/META-INF/native-image/com.google.cloud.spanner.admin.database.v1/reflect-config.json
index 15e53bae299..3b456d976d0 100644
--- a/google-cloud-spanner/src/main/resources/META-INF/native-image/com.google.cloud.spanner.admin.database.v1/reflect-config.json
+++ b/google-cloud-spanner/src/main/resources/META-INF/native-image/com.google.cloud.spanner.admin.database.v1/reflect-config.json
@@ -1601,6 +1601,51 @@
"allDeclaredClasses": true,
"allPublicClasses": true
},
+ {
+ "name": "com.google.protobuf.ListValue",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.protobuf.ListValue$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.protobuf.NullValue",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.protobuf.Struct",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.protobuf.Struct$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
{
"name": "com.google.protobuf.Timestamp",
"queryAllDeclaredConstructors": true,
@@ -1619,6 +1664,24 @@
"allDeclaredClasses": true,
"allPublicClasses": true
},
+ {
+ "name": "com.google.protobuf.Value",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.protobuf.Value$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
{
"name": "com.google.rpc.Status",
"queryAllDeclaredConstructors": true,
@@ -1637,6 +1700,42 @@
"allDeclaredClasses": true,
"allPublicClasses": true
},
+ {
+ "name": "com.google.spanner.admin.database.v1.AddSplitPointsRequest",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.AddSplitPointsRequest$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.AddSplitPointsResponse",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.AddSplitPointsResponse$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
{
"name": "com.google.spanner.admin.database.v1.Backup",
"queryAllDeclaredConstructors": true,
@@ -2555,6 +2654,42 @@
"allDeclaredClasses": true,
"allPublicClasses": true
},
+ {
+ "name": "com.google.spanner.admin.database.v1.SplitPoints",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.SplitPoints$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.SplitPoints$Key",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
+ {
+ "name": "com.google.spanner.admin.database.v1.SplitPoints$Key$Builder",
+ "queryAllDeclaredConstructors": true,
+ "queryAllPublicConstructors": true,
+ "queryAllDeclaredMethods": true,
+ "allPublicMethods": true,
+ "allDeclaredClasses": true,
+ "allPublicClasses": true
+ },
{
"name": "com.google.spanner.admin.database.v1.UpdateBackupRequest",
"queryAllDeclaredConstructors": true,
diff --git a/google-cloud-spanner/src/main/resources/META-INF/native-image/native-image.properties b/google-cloud-spanner/src/main/resources/META-INF/native-image/native-image.properties
index 0bcf872e79b..44bcd53941a 100644
--- a/google-cloud-spanner/src/main/resources/META-INF/native-image/native-image.properties
+++ b/google-cloud-spanner/src/main/resources/META-INF/native-image/native-image.properties
@@ -1,4 +1,5 @@
Args = --initialize-at-build-time=com.google.cloud.spanner.IntegrationTestEnv,\
org.junit.experimental.categories.CategoryValidator,\
- org.junit.validator.AnnotationValidator \
+ org.junit.validator.AnnotationValidator,\
+ java.lang.annotation.Annotation \
--features=com.google.cloud.spanner.nativeimage.SpannerFeature
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractNettyMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractNettyMockServerTest.java
new file mode 100644
index 00000000000..8e8da054b08
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractNettyMockServerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner;
+
+import com.google.api.gax.grpc.testing.LocalChannelProvider;
+import com.google.cloud.NoCredentials;
+import io.grpc.ForwardingServerCall;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Metadata;
+import io.grpc.Server;
+import io.grpc.ServerCall;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
+import io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+abstract class AbstractNettyMockServerTest {
+ protected static MockSpannerServiceImpl mockSpanner;
+
+ protected static Server server;
+ protected static InetSocketAddress address;
+ static ExecutorService executor;
+ protected static LocalChannelProvider channelProvider;
+ protected static AtomicInteger fakeServerTiming =
+ new AtomicInteger(new Random().nextInt(1000) + 1);
+
+ protected Spanner spanner;
+
+ @BeforeClass
+ public static void startMockServer() throws IOException {
+ mockSpanner = new MockSpannerServiceImpl();
+ mockSpanner.setAbortProbability(0.0D); // We don't want any unpredictable aborted transactions.
+
+ address = new InetSocketAddress("localhost", 0);
+ server =
+ NettyServerBuilder.forAddress(address)
+ .addService(mockSpanner)
+ .intercept(
+ new ServerInterceptor() {
+ @Override
+ public ServerCall.Listener interceptCall(
+ ServerCall serverCall,
+ Metadata headers,
+ ServerCallHandler serverCallHandler) {
+ return serverCallHandler.startCall(
+ new ForwardingServerCall.SimpleForwardingServerCall(
+ serverCall) {
+ @Override
+ public void sendHeaders(Metadata headers) {
+ headers.put(
+ Metadata.Key.of("server-timing", Metadata.ASCII_STRING_MARSHALLER),
+ String.format("gfet4t7; dur=%d", fakeServerTiming.get()));
+ super.sendHeaders(headers);
+ }
+ },
+ headers);
+ }
+ })
+ .build()
+ .start();
+ executor = Executors.newSingleThreadExecutor();
+ }
+
+ @AfterClass
+ public static void stopMockServer() throws InterruptedException {
+ server.shutdown();
+ server.awaitTermination();
+ executor.shutdown();
+ }
+
+ @Before
+ public void createSpannerInstance() {
+ String endpoint = address.getHostString() + ":" + server.getPort();
+ spanner =
+ SpannerOptions.newBuilder()
+ .setProjectId("test-project")
+ .setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
+ .setHost("http://" + endpoint)
+ .setCredentials(NoCredentials.getInstance())
+ .setSessionPoolOption(SessionPoolOptions.newBuilder().setFailOnSessionLeak().build())
+ .build()
+ .getService();
+ }
+
+ @After
+ public void cleanup() {
+ spanner.close();
+ mockSpanner.reset();
+ mockSpanner.removeAllExecutionTimes();
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
index 8b53bd7efff..eea6658d26d 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AbstractReadContextTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -266,6 +267,42 @@ public void testGetExecuteBatchDmlRequestBuilderWithPriority() {
assertEquals(Priority.PRIORITY_LOW, request.getRequestOptions().getPriority());
}
+ @Test
+ public void testExecuteSqlLastStatement() {
+ assertFalse(
+ context
+ .getExecuteSqlRequestBuilder(
+ Statement.of("insert into test (id) values (1)"),
+ QueryMode.NORMAL,
+ Options.fromUpdateOptions(),
+ false)
+ .getLastStatement());
+ assertTrue(
+ context
+ .getExecuteSqlRequestBuilder(
+ Statement.of("insert into test (id) values (1)"),
+ QueryMode.NORMAL,
+ Options.fromUpdateOptions(Options.lastStatement()),
+ false)
+ .getLastStatement());
+ }
+
+ @Test
+ public void testExecuteBatchDmlLastStatement() {
+ assertFalse(
+ context
+ .getExecuteBatchDmlRequestBuilder(
+ Collections.singleton(Statement.of("insert into test (id) values (1)")),
+ Options.fromUpdateOptions())
+ .getLastStatements());
+ assertTrue(
+ context
+ .getExecuteBatchDmlRequestBuilder(
+ Collections.singleton(Statement.of("insert into test (id) values (1)")),
+ Options.fromUpdateOptions(Options.lastStatement()))
+ .getLastStatements());
+ }
+
public void executeSqlRequestBuilderWithRequestOptions() {
ExecuteSqlRequest request =
context
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncRunnerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncRunnerTest.java
index 72e19e0291f..56d33c54878 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncRunnerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncRunnerTest.java
@@ -60,17 +60,51 @@ public void clearRequests() {
@Test
public void testAsyncRunner_doesNotReturnCommitTimestampBeforeCommit() {
AsyncRunner runner = client().runAsync();
- IllegalStateException e =
- assertThrows(IllegalStateException.class, () -> runner.getCommitTimestamp());
- assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ if (isMultiplexedSessionsEnabledForRW()) {
+ Throwable e = assertThrows(Throwable.class, () -> runner.getCommitTimestamp().get());
+ // If the error occurs within the future, it gets wrapped in an ExecutionException.
+ // This happens when DelayedAsyncRunner is invoked while the multiplexed session is not yet
+ // created.
+ // If the error occurs before the future is created, it may throw an IllegalStateException
+ // instead.
+ assertTrue(e instanceof ExecutionException || e instanceof IllegalStateException);
+ if (e instanceof ExecutionException) {
+ Throwable cause = e.getCause();
+ assertTrue(cause instanceof IllegalStateException);
+ assertTrue(cause.getMessage().contains("runAsync() has not yet been called"));
+ } else {
+ assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ }
+ } else {
+ IllegalStateException e =
+ assertThrows(IllegalStateException.class, () -> runner.getCommitTimestamp());
+ assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ }
}
@Test
public void testAsyncRunner_doesNotReturnCommitResponseBeforeCommit() {
AsyncRunner runner = client().runAsync();
- IllegalStateException e =
- assertThrows(IllegalStateException.class, () -> runner.getCommitResponse());
- assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ if (isMultiplexedSessionsEnabledForRW()) {
+ Throwable e = assertThrows(Throwable.class, () -> runner.getCommitResponse().get());
+ // If the error occurs within the future, it gets wrapped in an ExecutionException.
+ // This happens when DelayedAsyncRunner is invoked while the multiplexed session is not yet
+ // created.
+ // If the error occurs before the future is created, it may throw an IllegalStateException
+ // instead.
+ assertTrue(e instanceof ExecutionException || e instanceof IllegalStateException);
+ if (e instanceof ExecutionException) {
+ Throwable cause = e.getCause();
+ assertTrue(cause instanceof IllegalStateException);
+ assertTrue(cause.getMessage().contains("runAsync() has not yet been called"));
+ } else {
+ assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ }
+ } else {
+ IllegalStateException e =
+ assertThrows(IllegalStateException.class, () -> runner.getCommitResponse());
+ assertTrue(e.getMessage().contains("runAsync() has not yet been called"));
+ }
}
@Test
@@ -558,7 +592,9 @@ public void closeTransactionBeforeEndOfAsyncQuery() throws Exception {
// Wait until at least one row has been fetched. At that moment there should be one session
// checked out.
dataReceived.await();
- assertThat(clientImpl.pool.getNumberOfSessionsInUse()).isEqualTo(1);
+ if (!isMultiplexedSessionsEnabledForRW()) {
+ assertThat(clientImpl.pool.getNumberOfSessionsInUse()).isEqualTo(1);
+ }
assertThat(res.isDone()).isFalse();
dataChecked.countDown();
// Get the data from the transaction.
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerImplTest.java
index 006a926e907..dd13c39abc8 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerImplTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerImplTest.java
@@ -16,18 +16,14 @@
package com.google.cloud.spanner;
-import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.api.core.ApiFutures;
import com.google.cloud.Timestamp;
-import com.google.protobuf.ByteString;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Scope;
import org.junit.Test;
@@ -60,67 +56,4 @@ public void testCommitReturnsCommitStats() {
verify(transaction).commitAsync();
}
}
-
- @Test
- public void testRetryUsesPreviousTransactionIdOnMultiplexedSession() {
- // Set up mock transaction IDs
- final ByteString mockTransactionId = ByteString.copyFromUtf8("mockTransactionId");
- final ByteString mockPreviousTransactionId =
- ByteString.copyFromUtf8("mockPreviousTransactionId");
-
- Span oTspan = mock(Span.class);
- ISpan span = new OpenTelemetrySpan(oTspan);
- when(oTspan.makeCurrent()).thenReturn(mock(Scope.class));
- // Mark the session as multiplexed.
- when(session.getIsMultiplexed()).thenReturn(true);
-
- // Initialize a mock transaction with transactionId = null, previousTransactionId = null.
- transaction = mock(TransactionRunnerImpl.TransactionContextImpl.class);
- when(transaction.ensureTxnAsync()).thenReturn(ApiFutures.immediateFuture(null));
- when(session.newTransaction(eq(Options.fromTransactionOptions(Options.commitStats())), any()))
- .thenReturn(transaction);
-
- // Simulate an ABORTED error being thrown when `commitAsync()` is called.
- doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.ABORTED, ""))
- .when(transaction)
- .commitAsync();
-
- try (AsyncTransactionManagerImpl manager =
- new AsyncTransactionManagerImpl(session, span, Options.commitStats())) {
- manager.beginAsync();
-
- // Verify that for the first transaction attempt, the `previousTransactionId` is
- // ByteString.EMPTY.
- // This is because no transaction has been previously aborted at this point.
- verify(session)
- .newTransaction(Options.fromTransactionOptions(Options.commitStats()), ByteString.EMPTY);
- assertThrows(AbortedException.class, manager::commitAsync);
- clearInvocations(session);
-
- // Mock the transaction object to contain transactionID=null and
- // previousTransactionId=mockPreviousTransactionId
- when(transaction.getPreviousTransactionId()).thenReturn(mockPreviousTransactionId);
- manager.resetForRetryAsync();
- // Verify that in the first retry attempt, the `previousTransactionId`
- // (mockPreviousTransactionId) is passed to the new transaction.
- // This allows Spanner to retry the transaction using the ID of the aborted transaction.
- verify(session)
- .newTransaction(
- Options.fromTransactionOptions(Options.commitStats()), mockPreviousTransactionId);
- assertThrows(AbortedException.class, manager::commitAsync);
- clearInvocations(session);
-
- // Mock the transaction object to contain transactionID=mockTransactionId and
- // previousTransactionId=mockPreviousTransactionId and transactionID = null
- transaction.transactionId = mockTransactionId;
- manager.resetForRetryAsync();
- // Verify that the latest `transactionId` (mockTransactionId) is used in the retry.
- // This ensures the retry logic is working as expected with the latest transaction ID.
- verify(session)
- .newTransaction(Options.fromTransactionOptions(Options.commitStats()), mockTransactionId);
-
- when(transaction.rollbackAsync()).thenReturn(ApiFutures.immediateFuture(null));
- manager.closeAsync();
- }
- }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerTest.java
index 81a94edd980..6a5d77e20e7 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/AsyncTransactionManagerTest.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
@@ -250,6 +251,11 @@ public void asyncTransactionManagerUpdate() throws Exception {
@Test
public void asyncTransactionManagerIsNonBlocking() throws Exception {
+ // TODO: Remove this condition once DelayedAsyncTransactionManager is made non-blocking with
+ // multiplexed sessions.
+ assumeFalse(
+ "DelayedAsyncTransactionManager is currently blocking with multiplexed sessions.",
+ spanner.getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW());
mockSpanner.freeze();
try (AsyncTransactionManager manager = clientWithEmptySessionPool().transactionManagerAsync()) {
TransactionContextFuture transactionContextFuture = manager.beginAsync();
@@ -633,6 +639,11 @@ public void asyncTransactionManagerBatchUpdate() throws Exception {
@Test
public void asyncTransactionManagerIsNonBlockingWithBatchUpdate() throws Exception {
+ // TODO: Remove this condition once DelayedAsyncTransactionManager is made non-blocking with
+ // multiplexed sessions.
+ assumeFalse(
+ "DelayedAsyncTransactionManager is currently blocking with multiplexed sessions.",
+ spanner.getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW());
mockSpanner.freeze();
try (AsyncTransactionManager manager = clientWithEmptySessionPool().transactionManagerAsync()) {
TransactionContextFuture transactionContextFuture = manager.beginAsync();
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchClientImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchClientImplTest.java
index edafc7ddba9..ba508ac8d19 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchClientImplTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BatchClientImplTest.java
@@ -102,6 +102,7 @@ public void setUp() {
@SuppressWarnings("resource")
SpannerImpl spanner = new SpannerImpl(gapicRpc, spannerOptions);
client = new BatchClientImpl(spanner.getSessionClient(db), isMultiplexedSession);
+ BatchClientImpl.unimplementedForPartitionedOps.set(false);
}
@SuppressWarnings("unchecked")
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsProviderTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsProviderTest.java
index 43fe97113d0..73185177de1 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsProviderTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/BuiltInOpenTelemetryMetricsProviderTest.java
@@ -29,31 +29,31 @@ public class BuiltInOpenTelemetryMetricsProviderTest {
@Test
public void testGenerateClientHashWithSimpleUid() {
String clientUid = "testClient";
- verifyHash(BuiltInOpenTelemetryMetricsProvider.generateClientHash(clientUid));
+ verifyHash(BuiltInMetricsProvider.generateClientHash(clientUid));
}
@Test
public void testGenerateClientHashWithEmptyUid() {
String clientUid = "";
- verifyHash(BuiltInOpenTelemetryMetricsProvider.generateClientHash(clientUid));
+ verifyHash(BuiltInMetricsProvider.generateClientHash(clientUid));
}
@Test
public void testGenerateClientHashWithNullUid() {
String clientUid = null;
- verifyHash(BuiltInOpenTelemetryMetricsProvider.generateClientHash(clientUid));
+ verifyHash(BuiltInMetricsProvider.generateClientHash(clientUid));
}
@Test
public void testGenerateClientHashWithLongUid() {
String clientUid = "aVeryLongUniqueClientIdentifierThatIsUnusuallyLong";
- verifyHash(BuiltInOpenTelemetryMetricsProvider.generateClientHash(clientUid));
+ verifyHash(BuiltInMetricsProvider.generateClientHash(clientUid));
}
@Test
public void testGenerateClientHashWithSpecialCharacters() {
String clientUid = "273d60f2-5604-42f1-b687-f5f1b975fd07@2316645@test#";
- verifyHash(BuiltInOpenTelemetryMetricsProvider.generateClientHash(clientUid));
+ verifyHash(BuiltInMetricsProvider.generateClientHash(clientUid));
}
private void verifyHash(String hash) {
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
index 35c2d553b08..3443be192e6 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MockSpannerServiceImpl.java
@@ -2024,14 +2024,6 @@ public void commit(CommitRequest request, StreamObserver respons
return;
}
sessionLastUsed.put(session.getName(), Instant.now());
- if (session.getMultiplexed()
- && !request.hasPrecommitToken()
- && !request.hasSingleUseTransaction()) {
- throw Status.INVALID_ARGUMENT
- .withDescription(
- "A Commit request for a read-write transaction on a multiplexed session must specify a precommit token.")
- .asRuntimeException();
- }
try {
commitExecutionTime.simulateExecutionTime(exceptions, stickyGlobalExceptions, freezeLock);
// Find or start a transaction
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
index d5fa4dd5c37..87877caf21a 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/MultiplexedSessionDatabaseClientMockServerTest.java
@@ -46,20 +46,12 @@
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.protobuf.ByteString;
-import com.google.spanner.v1.BatchWriteRequest;
-import com.google.spanner.v1.BatchWriteResponse;
-import com.google.spanner.v1.BeginTransactionRequest;
-import com.google.spanner.v1.CommitRequest;
-import com.google.spanner.v1.ExecuteSqlRequest;
+import com.google.spanner.v1.*;
import com.google.spanner.v1.RequestOptions.Priority;
import com.google.spanner.v1.Session;
-import com.google.spanner.v1.Transaction;
import io.grpc.Status;
import java.time.Duration;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -1540,6 +1532,89 @@ public void testInitialBeginTransactionWithRW_receivesUnimplemented_fallsBackToR
assertFalse(session2.getMultiplexed());
}
+ // Tests the behavior of the server-side kill switch for read-write multiplexed sessions.
+ @Test
+ public void
+ testInitialBeginTransactionWithPDML_receivesUnimplemented_fallsBackToRegularSession() {
+ mockSpanner.setBeginTransactionExecutionTime(
+ SimulatedExecutionTime.ofExceptions(
+ Arrays.asList(
+ Status.UNIMPLEMENTED
+ .withDescription(
+ "Transaction type partitioned_dml not supported with multiplexed sessions")
+ .asRuntimeException(),
+ Status.UNIMPLEMENTED
+ .withDescription(
+ "Transaction type partitioned_dml not supported with multiplexed sessions")
+ .asRuntimeException())));
+ DatabaseClientImpl client =
+ (DatabaseClientImpl) spanner.getDatabaseClient(DatabaseId.of("p", "i", "d"));
+
+ assertNotNull(client.multiplexedSessionDatabaseClient);
+
+ // Partitioned Ops transaction should fallback to regular sessions
+ assertEquals(UPDATE_COUNT, client.executePartitionedUpdate(UPDATE_STATEMENT));
+
+ // Verify that we received one ExecuteSqlRequest, and it uses a regular session due to fallback.
+ List executeSqlRequests =
+ mockSpanner.getRequestsOfType(ExecuteSqlRequest.class);
+ assertEquals(1, executeSqlRequests.size());
+ // Verify the requests are not executed using multiplexed sessions
+ Session session2 = mockSpanner.getSession(executeSqlRequests.get(0).getSession());
+ assertNotNull(session2);
+ assertFalse(session2.getMultiplexed());
+ assertTrue(client.multiplexedSessionDatabaseClient.unimplementedForPartitionedOps.get());
+ }
+
+ // Tests the behavior of the server-side kill switch for read-write multiplexed sessions.
+ @Test
+ public void testPartitionedQuery_receivesUnimplemented_fallsBackToRegularSession() {
+ mockSpanner.setPartitionQueryExecutionTime(
+ SimulatedExecutionTime.ofException(
+ Status.INVALID_ARGUMENT
+ .withDescription(
+ "Partitioned operations are not supported with multiplexed sessions")
+ .asRuntimeException()));
+ BatchClientImpl client = (BatchClientImpl) spanner.getBatchClient(DatabaseId.of("p", "i", "d"));
+
+ try (BatchReadOnlyTransaction transaction =
+ client.batchReadOnlyTransaction(TimestampBound.strong())) {
+ // Partitioned Query should fail
+ SpannerException spannerException =
+ assertThrows(
+ SpannerException.class,
+ () -> {
+ transaction.partitionQuery(PartitionOptions.getDefaultInstance(), STATEMENT);
+ });
+ assertEquals(ErrorCode.INVALID_ARGUMENT, spannerException.getErrorCode());
+
+ // Verify that we received one PartitionQueryRequest.
+ List partitionQueryRequests =
+ mockSpanner.getRequestsOfType(PartitionQueryRequest.class);
+ assertEquals(1, partitionQueryRequests.size());
+ // Verify the requests were executed using multiplexed sessions
+ Session session2 = mockSpanner.getSession(partitionQueryRequests.get(0).getSession());
+ assertNotNull(session2);
+ assertTrue(session2.getMultiplexed());
+ assertTrue(client.unimplementedForPartitionedOps.get());
+ }
+ try (BatchReadOnlyTransaction transaction =
+ client.batchReadOnlyTransaction(TimestampBound.strong())) {
+ // Partitioned Query should fail
+ transaction.partitionQuery(PartitionOptions.getDefaultInstance(), STATEMENT);
+
+ // // Verify that we received two PartitionQueryRequest. and it uses a regular session due to
+ // fallback.
+ List partitionQueryRequests =
+ mockSpanner.getRequestsOfType(PartitionQueryRequest.class);
+ assertEquals(2, partitionQueryRequests.size());
+ // Verify the requests are not executed using multiplexed sessions
+ Session session2 = mockSpanner.getSession(partitionQueryRequests.get(1).getSession());
+ assertNotNull(session2);
+ assertFalse(session2.getMultiplexed());
+ }
+ }
+
@Test
public void
testReadWriteUnimplementedErrorDuringInitialBeginTransactionRPC_firstReceivesError_secondFallsBackToRegularSessions() {
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java
index 1b6d99260fe..f0c13b0f389 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OpenTelemetryBuiltInMetricsTracerTest.java
@@ -60,7 +60,7 @@
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
-public class OpenTelemetryBuiltInMetricsTracerTest extends AbstractMockServerTest {
+public class OpenTelemetryBuiltInMetricsTracerTest extends AbstractNettyMockServerTest {
private static final Statement SELECT_RANDOM = Statement.of("SELECT * FROM random");
@@ -71,7 +71,8 @@ public class OpenTelemetryBuiltInMetricsTracerTest extends AbstractMockServerTes
private static Map attributes;
- private static Attributes expectedBaseAttributes;
+ private static Attributes expectedCommonBaseAttributes;
+ private static Attributes expectedCommonRequestAttributes;
private static final long MIN_LATENCY = 0;
@@ -81,7 +82,7 @@ public class OpenTelemetryBuiltInMetricsTracerTest extends AbstractMockServerTes
public static void setup() {
metricReader = InMemoryMetricReader.create();
- BuiltInOpenTelemetryMetricsProvider provider = BuiltInOpenTelemetryMetricsProvider.INSTANCE;
+ BuiltInMetricsProvider provider = BuiltInMetricsProvider.INSTANCE;
SdkMeterProviderBuilder meterProvider =
SdkMeterProvider.builder().registerMetricReader(metricReader);
@@ -92,17 +93,23 @@ public static void setup() {
openTelemetry = OpenTelemetrySdk.builder().setMeterProvider(meterProvider.build()).build();
attributes = provider.createClientAttributes("test-project", client_name);
- expectedBaseAttributes =
+ expectedCommonBaseAttributes =
Attributes.builder()
.put(BuiltInMetricsConstant.PROJECT_ID_KEY, "test-project")
.put(BuiltInMetricsConstant.INSTANCE_CONFIG_ID_KEY, "unknown")
.put(
BuiltInMetricsConstant.LOCATION_ID_KEY,
- BuiltInOpenTelemetryMetricsProvider.detectClientLocation())
+ BuiltInMetricsProvider.detectClientLocation())
.put(BuiltInMetricsConstant.CLIENT_NAME_KEY, client_name)
.put(BuiltInMetricsConstant.CLIENT_UID_KEY, attributes.get("client_uid"))
.put(BuiltInMetricsConstant.CLIENT_HASH_KEY, attributes.get("client_hash"))
+ .put(BuiltInMetricsConstant.INSTANCE_ID_KEY, "i")
+ .put(BuiltInMetricsConstant.DATABASE_KEY, "d")
+ .put(BuiltInMetricsConstant.DIRECT_PATH_ENABLED_KEY, "false")
.build();
+
+ expectedCommonRequestAttributes =
+ Attributes.builder().put(BuiltInMetricsConstant.DIRECT_PATH_USED_KEY, "false").build();
}
@BeforeClass
@@ -122,8 +129,8 @@ public void createSpannerInstance() {
SpannerOptions.Builder builder = SpannerOptions.newBuilder();
ApiTracerFactory metricsTracerFactory =
- new MetricsTracerFactory(
- new OpenTelemetryMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME),
+ new BuiltInMetricsTracerFactory(
+ new BuiltInMetricsRecorder(openTelemetry, BuiltInMetricsConstant.METER_NAME),
attributes);
// Set a quick polling algorithm to prevent this from slowing down the test unnecessarily.
builder
@@ -137,10 +144,12 @@ public void createSpannerInstance() {
.setRetryDelayMultiplier(1.0)
.setTotalTimeoutDuration(Duration.ofMinutes(10L))
.build()));
+ String endpoint = address.getHostString() + ":" + server.getPort();
spanner =
- builder
+ SpannerOptions.newBuilder()
.setProjectId("test-project")
- .setChannelProvider(channelProvider)
+ .setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
+ .setHost("http://" + endpoint)
.setCredentials(NoCredentials.getInstance())
.setSessionPoolOption(
SessionPoolOptions.newBuilder()
@@ -167,8 +176,9 @@ public void testMetricsSingleUseQuery() {
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
Attributes expectedAttributes =
- expectedBaseAttributes
+ expectedCommonBaseAttributes
.toBuilder()
+ .putAll(expectedCommonRequestAttributes)
.put(BuiltInMetricsConstant.STATUS_KEY, "OK")
.put(BuiltInMetricsConstant.METHOD_KEY, "Spanner.ExecuteStreamingSql")
.build();
@@ -194,6 +204,11 @@ public void testMetricsSingleUseQuery() {
getMetricData(metricReader, BuiltInMetricsConstant.ATTEMPT_COUNT_NAME);
assertNotNull(attemptCountMetricData);
assertThat(getAggregatedValue(attemptCountMetricData, expectedAttributes)).isEqualTo(1);
+
+ MetricData gfeLatencyMetricData =
+ getMetricData(metricReader, BuiltInMetricsConstant.GFE_LATENCIES_NAME);
+ long gfeLatencyValue = getAggregatedValue(gfeLatencyMetricData, expectedAttributes);
+ assertEquals(fakeServerTiming.get(), gfeLatencyValue, 0);
}
@Test
@@ -210,14 +225,15 @@ public void testMetricsWithGaxRetryUnaryRpc() {
stopwatch.elapsed(TimeUnit.MILLISECONDS);
Attributes expectedAttributesBeginTransactionOK =
- expectedBaseAttributes
+ expectedCommonBaseAttributes
.toBuilder()
+ .putAll(expectedCommonRequestAttributes)
.put(BuiltInMetricsConstant.STATUS_KEY, "OK")
.put(BuiltInMetricsConstant.METHOD_KEY, "Spanner.BeginTransaction")
.build();
Attributes expectedAttributesBeginTransactionFailed =
- expectedBaseAttributes
+ expectedCommonBaseAttributes
.toBuilder()
.put(BuiltInMetricsConstant.STATUS_KEY, "UNAVAILABLE")
.put(BuiltInMetricsConstant.METHOD_KEY, "Spanner.BeginTransaction")
@@ -289,7 +305,7 @@ public void testNoNetworkConnection() {
.setApiTracerFactory(metricsTracerFactory)
.build()
.getService();
- String instance = "test-instance";
+ String instance = "i";
DatabaseClient client = spanner.getDatabaseClient(DatabaseId.of("test-project", instance, "d"));
// Using this client will return UNAVAILABLE, as the server is not reachable and we have
@@ -300,29 +316,24 @@ public void testNoNetworkConnection() {
assertEquals(ErrorCode.UNAVAILABLE, exception.getErrorCode());
Attributes expectedAttributesCreateSessionOK =
- expectedBaseAttributes
+ expectedCommonBaseAttributes
.toBuilder()
+ .putAll(expectedCommonRequestAttributes)
.put(BuiltInMetricsConstant.STATUS_KEY, "OK")
.put(BuiltInMetricsConstant.METHOD_KEY, "Spanner.CreateSession")
// Include the additional attributes that are added by the HeaderInterceptor in the
// filter. Note that the DIRECT_PATH_USED attribute is not added, as the request never
// leaves the client.
- .put(BuiltInMetricsConstant.INSTANCE_ID_KEY, instance)
- .put(BuiltInMetricsConstant.DATABASE_KEY, "d")
- .put(BuiltInMetricsConstant.DIRECT_PATH_ENABLED_KEY, "false")
.build();
Attributes expectedAttributesCreateSessionFailed =
- expectedBaseAttributes
+ expectedCommonBaseAttributes
.toBuilder()
.put(BuiltInMetricsConstant.STATUS_KEY, "UNAVAILABLE")
.put(BuiltInMetricsConstant.METHOD_KEY, "Spanner.CreateSession")
// Include the additional attributes that are added by the HeaderInterceptor in the
// filter. Note that the DIRECT_PATH_USED attribute is not added, as the request never
// leaves the client.
- .put(BuiltInMetricsConstant.INSTANCE_ID_KEY, instance)
- .put(BuiltInMetricsConstant.DATABASE_KEY, "d")
- .put(BuiltInMetricsConstant.DIRECT_PATH_ENABLED_KEY, "false")
.build();
MetricData attemptCountMetricData =
@@ -332,8 +343,6 @@ public void testNoNetworkConnection() {
// Attempt count should have a failed metric point for CreateSession.
assertEquals(
1, getAggregatedValue(attemptCountMetricData, expectedAttributesCreateSessionFailed));
- // There should be no OK metric points for CreateSession.
- assertEquals(0, getAggregatedValue(attemptCountMetricData, expectedAttributesCreateSessionOK));
}
private MetricData getMetricData(InMemoryMetricReader reader, String metricName) {
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OptionsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OptionsTest.java
index f391088589f..17c25558f3b 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OptionsTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/OptionsTest.java
@@ -789,4 +789,22 @@ public void updateOptionsExcludeTxnFromChangeStreams() {
assertNull(option3.withExcludeTxnFromChangeStreams());
assertThat(option3.toString()).doesNotContain("withExcludeTxnFromChangeStreams: true");
}
+
+ @Test
+ public void testLastStatement() {
+ Options option1 = Options.fromUpdateOptions(Options.lastStatement());
+ Options option2 = Options.fromUpdateOptions(Options.lastStatement());
+ Options option3 = Options.fromUpdateOptions();
+
+ assertEquals(option1, option2);
+ assertEquals(option1.hashCode(), option2.hashCode());
+ assertNotEquals(option1, option3);
+ assertNotEquals(option1.hashCode(), option3.hashCode());
+
+ assertTrue(option1.isLastStatement());
+ assertThat(option1.toString()).contains("lastStatement: true");
+
+ assertNull(option3.isLastStatement());
+ assertThat(option3.toString()).doesNotContain("lastStatement: true");
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/XGoogSpannerRequestIdTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/XGoogSpannerRequestIdTest.java
new file mode 100644
index 00000000000..12c9213c7dc
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/XGoogSpannerRequestIdTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.cloud.spanner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class XGoogSpannerRequestIdTest {
+ private static final Pattern REGEX_RAND_PROCESS_ID =
+ Pattern.compile("1.([0-9a-z]{16})(\\.\\d+){3}\\.(\\d+)$");
+
+ @Test
+ public void testEquals() {
+ XGoogSpannerRequestId reqID1 = XGoogSpannerRequestId.of(1, 1, 1, 1);
+ XGoogSpannerRequestId reqID2 = XGoogSpannerRequestId.of(1, 1, 1, 1);
+ assertEquals(reqID1, reqID2);
+ assertEquals(reqID1, reqID1);
+ assertEquals(reqID2, reqID2);
+
+ XGoogSpannerRequestId reqID3 = XGoogSpannerRequestId.of(1, 1, 1, 2);
+ assertNotEquals(reqID1, reqID3);
+ assertNotEquals(reqID3, reqID1);
+ assertEquals(reqID3, reqID3);
+ }
+
+ @Test
+ public void testEnsureHexadecimalFormatForRandProcessID() {
+ String str = XGoogSpannerRequestId.of(1, 2, 3, 4).toString();
+ Matcher m = XGoogSpannerRequestIdTest.REGEX_RAND_PROCESS_ID.matcher(str);
+ assertTrue(m.matches());
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java
index 948d3345143..5d476f914a8 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientHttpJsonTest.java
@@ -46,6 +46,7 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Timestamp;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupName;
import com.google.spanner.admin.database.v1.BackupSchedule;
@@ -67,6 +68,7 @@
import com.google.spanner.admin.database.v1.ListDatabaseRolesResponse;
import com.google.spanner.admin.database.v1.ListDatabasesResponse;
import com.google.spanner.admin.database.v1.RestoreInfo;
+import com.google.spanner.admin.database.v1.SplitPoints;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -2454,6 +2456,92 @@ public void listDatabaseRolesExceptionTest2() throws Exception {
}
}
+ @Test
+ public void addSplitPointsTest() throws Exception {
+ AddSplitPointsResponse expectedResponse = AddSplitPointsResponse.newBuilder().build();
+ mockService.addResponse(expectedResponse);
+
+ DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]");
+ List splitPoints = new ArrayList<>();
+
+ AddSplitPointsResponse actualResponse = client.addSplitPoints(database, splitPoints);
+ Assert.assertEquals(expectedResponse, actualResponse);
+
+ List actualRequests = mockService.getRequestPaths();
+ Assert.assertEquals(1, actualRequests.size());
+
+ String apiClientHeaderKey =
+ mockService
+ .getRequestHeaders()
+ .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey())
+ .iterator()
+ .next();
+ Assert.assertTrue(
+ GaxHttpJsonProperties.getDefaultApiClientHeaderPattern()
+ .matcher(apiClientHeaderKey)
+ .matches());
+ }
+
+ @Test
+ public void addSplitPointsExceptionTest() throws Exception {
+ ApiException exception =
+ ApiExceptionFactory.createException(
+ new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false);
+ mockService.addException(exception);
+
+ try {
+ DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]");
+ List splitPoints = new ArrayList<>();
+ client.addSplitPoints(database, splitPoints);
+ Assert.fail("No exception raised");
+ } catch (InvalidArgumentException e) {
+ // Expected exception.
+ }
+ }
+
+ @Test
+ public void addSplitPointsTest2() throws Exception {
+ AddSplitPointsResponse expectedResponse = AddSplitPointsResponse.newBuilder().build();
+ mockService.addResponse(expectedResponse);
+
+ String database = "projects/project-3102/instances/instance-3102/databases/database-3102";
+ List splitPoints = new ArrayList<>();
+
+ AddSplitPointsResponse actualResponse = client.addSplitPoints(database, splitPoints);
+ Assert.assertEquals(expectedResponse, actualResponse);
+
+ List actualRequests = mockService.getRequestPaths();
+ Assert.assertEquals(1, actualRequests.size());
+
+ String apiClientHeaderKey =
+ mockService
+ .getRequestHeaders()
+ .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey())
+ .iterator()
+ .next();
+ Assert.assertTrue(
+ GaxHttpJsonProperties.getDefaultApiClientHeaderPattern()
+ .matcher(apiClientHeaderKey)
+ .matches());
+ }
+
+ @Test
+ public void addSplitPointsExceptionTest2() throws Exception {
+ ApiException exception =
+ ApiExceptionFactory.createException(
+ new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false);
+ mockService.addException(exception);
+
+ try {
+ String database = "projects/project-3102/instances/instance-3102/databases/database-3102";
+ List splitPoints = new ArrayList<>();
+ client.addSplitPoints(database, splitPoints);
+ Assert.fail("No exception raised");
+ } catch (InvalidArgumentException e) {
+ // Expected exception.
+ }
+ }
+
@Test
public void createBackupScheduleTest() throws Exception {
BackupSchedule expectedResponse =
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java
index 33143d458f6..2424ad7bc27 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/DatabaseAdminClientTest.java
@@ -48,6 +48,8 @@
import com.google.protobuf.Empty;
import com.google.protobuf.FieldMask;
import com.google.protobuf.Timestamp;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupName;
import com.google.spanner.admin.database.v1.BackupSchedule;
@@ -87,6 +89,7 @@
import com.google.spanner.admin.database.v1.ListDatabasesResponse;
import com.google.spanner.admin.database.v1.RestoreDatabaseRequest;
import com.google.spanner.admin.database.v1.RestoreInfo;
+import com.google.spanner.admin.database.v1.SplitPoints;
import com.google.spanner.admin.database.v1.UpdateBackupRequest;
import com.google.spanner.admin.database.v1.UpdateBackupScheduleRequest;
import com.google.spanner.admin.database.v1.UpdateDatabaseDdlRequest;
@@ -2250,6 +2253,82 @@ public void listDatabaseRolesExceptionTest2() throws Exception {
}
}
+ @Test
+ public void addSplitPointsTest() throws Exception {
+ AddSplitPointsResponse expectedResponse = AddSplitPointsResponse.newBuilder().build();
+ mockDatabaseAdmin.addResponse(expectedResponse);
+
+ DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]");
+ List splitPoints = new ArrayList<>();
+
+ AddSplitPointsResponse actualResponse = client.addSplitPoints(database, splitPoints);
+ Assert.assertEquals(expectedResponse, actualResponse);
+
+ List actualRequests = mockDatabaseAdmin.getRequests();
+ Assert.assertEquals(1, actualRequests.size());
+ AddSplitPointsRequest actualRequest = ((AddSplitPointsRequest) actualRequests.get(0));
+
+ Assert.assertEquals(database.toString(), actualRequest.getDatabase());
+ Assert.assertEquals(splitPoints, actualRequest.getSplitPointsList());
+ Assert.assertTrue(
+ channelProvider.isHeaderSent(
+ ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),
+ GaxGrpcProperties.getDefaultApiClientHeaderPattern()));
+ }
+
+ @Test
+ public void addSplitPointsExceptionTest() throws Exception {
+ StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT);
+ mockDatabaseAdmin.addException(exception);
+
+ try {
+ DatabaseName database = DatabaseName.of("[PROJECT]", "[INSTANCE]", "[DATABASE]");
+ List splitPoints = new ArrayList<>();
+ client.addSplitPoints(database, splitPoints);
+ Assert.fail("No exception raised");
+ } catch (InvalidArgumentException e) {
+ // Expected exception.
+ }
+ }
+
+ @Test
+ public void addSplitPointsTest2() throws Exception {
+ AddSplitPointsResponse expectedResponse = AddSplitPointsResponse.newBuilder().build();
+ mockDatabaseAdmin.addResponse(expectedResponse);
+
+ String database = "database1789464955";
+ List splitPoints = new ArrayList<>();
+
+ AddSplitPointsResponse actualResponse = client.addSplitPoints(database, splitPoints);
+ Assert.assertEquals(expectedResponse, actualResponse);
+
+ List actualRequests = mockDatabaseAdmin.getRequests();
+ Assert.assertEquals(1, actualRequests.size());
+ AddSplitPointsRequest actualRequest = ((AddSplitPointsRequest) actualRequests.get(0));
+
+ Assert.assertEquals(database, actualRequest.getDatabase());
+ Assert.assertEquals(splitPoints, actualRequest.getSplitPointsList());
+ Assert.assertTrue(
+ channelProvider.isHeaderSent(
+ ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),
+ GaxGrpcProperties.getDefaultApiClientHeaderPattern()));
+ }
+
+ @Test
+ public void addSplitPointsExceptionTest2() throws Exception {
+ StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT);
+ mockDatabaseAdmin.addException(exception);
+
+ try {
+ String database = "database1789464955";
+ List splitPoints = new ArrayList<>();
+ client.addSplitPoints(database, splitPoints);
+ Assert.fail("No exception raised");
+ } catch (InvalidArgumentException e) {
+ // Expected exception.
+ }
+ }
+
@Test
public void createBackupScheduleTest() throws Exception {
BackupSchedule expectedResponse =
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/MockDatabaseAdminImpl.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/MockDatabaseAdminImpl.java
index 1d904eed413..57ff0fa3819 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/MockDatabaseAdminImpl.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/admin/database/v1/MockDatabaseAdminImpl.java
@@ -25,6 +25,8 @@
import com.google.longrunning.Operation;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.Empty;
+import com.google.spanner.admin.database.v1.AddSplitPointsRequest;
+import com.google.spanner.admin.database.v1.AddSplitPointsResponse;
import com.google.spanner.admin.database.v1.Backup;
import com.google.spanner.admin.database.v1.BackupSchedule;
import com.google.spanner.admin.database.v1.CopyBackupRequest;
@@ -513,6 +515,27 @@ public void listDatabaseRoles(
}
}
+ @Override
+ public void addSplitPoints(
+ AddSplitPointsRequest request, StreamObserver responseObserver) {
+ Object response = responses.poll();
+ if (response instanceof AddSplitPointsResponse) {
+ requests.add(request);
+ responseObserver.onNext(((AddSplitPointsResponse) response));
+ responseObserver.onCompleted();
+ } else if (response instanceof Exception) {
+ responseObserver.onError(((Exception) response));
+ } else {
+ responseObserver.onError(
+ new IllegalArgumentException(
+ String.format(
+ "Unrecognized response type %s for method AddSplitPoints, expected %s or %s",
+ response == null ? "null" : response.getClass().getName(),
+ AddSplitPointsResponse.class.getName(),
+ Exception.class.getName())));
+ }
+ }
+
@Override
public void createBackupSchedule(
CreateBackupScheduleRequest request, StreamObserver responseObserver) {
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java
index ac6a6ecbc77..a9b27f21545 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AbstractMockServerTest.java
@@ -328,6 +328,13 @@ boolean isMultiplexedSessionsEnabled(Spanner spanner) {
return spanner.getOptions().getSessionPoolOptions().getUseMultiplexedSession();
}
+ boolean isMultiplexedSessionsEnabledForPartitionedOps(Spanner spanner) {
+ if (spanner.getOptions() == null || spanner.getOptions().getSessionPoolOptions() == null) {
+ return false;
+ }
+ return spanner.getOptions().getSessionPoolOptions().getUseMultiplexedSessionPartitionedOps();
+ }
+
boolean isMultiplexedSessionsEnabledForRW(Spanner spanner) {
if (spanner.getOptions() == null || spanner.getOptions().getSessionPoolOptions() == null) {
return false;
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutoCommitMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutoCommitMockServerTest.java
new file mode 100644
index 00000000000..c48c6703353
--- /dev/null
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutoCommitMockServerTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.assertTrue;
+
+import com.google.cloud.spanner.ResultSet;
+import com.google.spanner.v1.BeginTransactionRequest;
+import com.google.spanner.v1.CommitRequest;
+import com.google.spanner.v1.ExecuteBatchDmlRequest;
+import com.google.spanner.v1.ExecuteSqlRequest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AutoCommitMockServerTest extends AbstractMockServerTest {
+
+ @Test
+ public void testQuery() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ //noinspection EmptyTryBlock
+ try (ResultSet ignore = connection.executeQuery(SELECT1_STATEMENT)) {}
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.getTransaction().hasSingleUse());
+ assertTrue(request.getTransaction().getSingleUse().hasReadOnly());
+ assertFalse(request.getLastStatement());
+ }
+
+ @Test
+ public void testDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.executeUpdate(INSERT_STATEMENT);
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatement());
+ assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testDmlReturning() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ //noinspection EmptyTryBlock
+ try (ResultSet ignore = connection.executeQuery(INSERT_RETURNING_STATEMENT)) {}
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatement());
+ assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testBatchDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.startBatchDml();
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.runBatch();
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
+ ExecuteBatchDmlRequest request =
+ mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class).get(0);
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatements());
+ assertEquals(1, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testPartitionedDml() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ connection.setAutocommitDmlMode(AutocommitDmlMode.PARTITIONED_NON_ATOMIC);
+ connection.executeUpdate(INSERT_STATEMENT);
+ }
+ assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
+ BeginTransactionRequest beginRequest =
+ mockSpanner.getRequestsOfType(BeginTransactionRequest.class).get(0);
+ assertTrue(beginRequest.getOptions().hasPartitionedDml());
+ assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.getTransaction().hasId());
+ assertFalse(request.getLastStatement());
+ assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testDmlAborted() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ mockSpanner.abortNextTransaction();
+ connection.executeUpdate(INSERT_STATEMENT);
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ for (ExecuteSqlRequest request : mockSpanner.getRequestsOfType(ExecuteSqlRequest.class)) {
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatement());
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testDmlReturningAborted() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ mockSpanner.abortNextTransaction();
+ //noinspection EmptyTryBlock
+ try (ResultSet ignore = connection.executeQuery(INSERT_RETURNING_STATEMENT)) {}
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ for (ExecuteSqlRequest request : mockSpanner.getRequestsOfType(ExecuteSqlRequest.class)) {
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatement());
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+
+ @Test
+ public void testBatchDmlAborted() {
+ try (Connection connection = createConnection()) {
+ connection.setAutocommit(true);
+ mockSpanner.abortNextTransaction();
+ connection.startBatchDml();
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.executeUpdate(INSERT_STATEMENT);
+ connection.runBatch();
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(ExecuteBatchDmlRequest.class));
+ for (ExecuteBatchDmlRequest request :
+ mockSpanner.getRequestsOfType(ExecuteBatchDmlRequest.class)) {
+ assertTrue(request.getTransaction().hasBegin());
+ assertTrue(request.getTransaction().getBegin().hasReadWrite());
+ assertTrue(request.getLastStatements());
+ }
+ assertEquals(2, mockSpanner.countRequestsOfType(CommitRequest.class));
+ }
+}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java
index a66d14a8b76..bb845746e13 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/AutocommitDmlModeTest.java
@@ -18,6 +18,9 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -28,6 +31,7 @@
import com.google.cloud.spanner.BatchClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.Dialect;
+import com.google.cloud.spanner.Options;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.Statement;
import com.google.cloud.spanner.TransactionContext;
@@ -82,12 +86,12 @@ public void testAutocommitDmlModeTransactional() {
.setCredentials(NoCredentials.getInstance())
.setUri(URI)
.build())) {
- assertThat(connection.isAutocommit(), is(true));
- assertThat(connection.isReadOnly(), is(false));
- assertThat(connection.getAutocommitDmlMode(), is(AutocommitDmlMode.TRANSACTIONAL));
+ assertTrue(connection.isAutocommit());
+ assertFalse(connection.isReadOnly());
+ assertEquals(AutocommitDmlMode.TRANSACTIONAL, connection.getAutocommitDmlMode());
connection.execute(Statement.of(UPDATE));
- verify(txContext).executeUpdate(Statement.of(UPDATE));
+ verify(txContext).executeUpdate(Statement.of(UPDATE), Options.lastStatement());
verify(dbClient, never()).executePartitionedUpdate(Statement.of(UPDATE));
}
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
index a81005bbb45..d4b7c035658 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionImplTest.java
@@ -354,7 +354,8 @@ public TransactionRunner answer(InvocationOnMock invocation) {
public T run(TransactionCallable callable) {
commitResponse = new CommitResponse(Timestamp.ofTimeSecondsAndNanos(1, 1));
TransactionContext transaction = mock(TransactionContext.class);
- when(transaction.executeUpdate(Statement.of(UPDATE))).thenReturn(1L);
+ when(transaction.executeUpdate(Statement.of(UPDATE), Options.lastStatement()))
+ .thenReturn(1L);
try {
return callable.run(transaction);
} catch (Exception e) {
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java
index 7bf6a670d9c..988263af9f0 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ITAbstractSpannerTest.java
@@ -22,6 +22,7 @@
import com.google.cloud.spanner.GceTestEnvConfig;
import com.google.cloud.spanner.IntegrationTestEnv;
import com.google.cloud.spanner.ResultSet;
+import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerExceptionFactory;
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.Statement;
@@ -146,6 +147,9 @@ public void intercept(
if (usingMultiplexedsession) {
Field stateField = cls.getDeclaredField("txnState");
stateField.setAccessible(true);
+ if (tx.getState() == null) {
+ return;
+ }
tx.rollback();
stateField.set(tx, TransactionState.ABORTED);
} else {
@@ -368,4 +372,11 @@ protected boolean indexExists(Connection connection, String table, String index)
}
return false;
}
+
+ protected boolean isMultiplexedSessionsEnabledForRW(Spanner spanner) {
+ if (spanner.getOptions() == null || spanner.getOptions().getSessionPoolOptions() == null) {
+ return false;
+ }
+ return spanner.getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW();
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
index 655ca0de586..cdd8b15a38a 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/PartitionedQueryMockServerTest.java
@@ -93,7 +93,9 @@ public void testPartitionQuery() {
assertFalse(resultSet.next());
}
}
- if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
+ if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())) {
+ assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
+ } else if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
assertEquals(3, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
@@ -155,7 +157,9 @@ public void testMixNormalAndPartitionQueryInReadOnlyTransaction() {
readTimestamps.add(connection.getReadTimestamp());
connection.commit();
}
- if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
+ if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())) {
+ assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
+ } else if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
assertEquals(3, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
@@ -228,6 +232,10 @@ public void testRunPartition() {
if (createSessionRequestCounts == expectedCreateSessionsRPC + 1) {
isMultiplexedSessionCreated = true;
}
+ } else if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())
+ && isMultiplexedSessionCreated) {
+ // When multiplexed session will be reused for each iteration.
+ assertEquals(0, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(
expectedCreateSessionsRPC,
@@ -261,6 +269,7 @@ public void testRunPartitionUsingSql() {
String prefix = dialect == Dialect.POSTGRESQL ? "spanner." : "";
int maxPartitions = 5;
+ boolean isMultiplexedSessionCreated = false;
try (Connection connection = createConnection()) {
connection.execute(Statement.of("set autocommit=true"));
assertTrue(connection.isAutocommit());
@@ -284,7 +293,6 @@ public void testRunPartitionUsingSql() {
assertFalse(resultSet.next());
}
- boolean isMultiplexedSessionCreated = false;
for (boolean useLiteral : new boolean[] {true, false}) {
try (ResultSet partitions =
connection.executeQuery(
@@ -328,6 +336,10 @@ public void testRunPartitionUsingSql() {
if (createSessionRequestCounts == expectedCreateSessionsRPC + 1) {
isMultiplexedSessionCreated = true;
}
+ } else if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())
+ && isMultiplexedSessionCreated) {
+ // When multiplexed session will be reused for each iteration.
+ assertEquals(0, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(
expectedCreateSessionsRPC,
@@ -570,7 +582,9 @@ public void testRunPartitionedQueryUsingSql() {
assertEquals(maxPartitions * generatedRowCount, rowCount);
}
}
- if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
+ if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())) {
+ assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
+ } else if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
assertEquals(3, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
@@ -679,7 +693,9 @@ public void testRunPartitionedQueryWithMaxParallelism() {
assertEquals(maxPartitions * generatedRowCount, rowCount);
}
}
- if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
+ if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())) {
+ assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
+ } else if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
assertEquals(6, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(5, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
@@ -758,7 +774,10 @@ public void testAutoPartitionMode() {
exception
.getMessage()
.contains("Partition query is not supported for read/write transaction"));
- if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
+
+ if (isMultiplexedSessionsEnabledForPartitionedOps(connection.getSpanner())) {
+ assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
+ } else if (isMultiplexedSessionsEnabled(connection.getSpanner())) {
assertEquals(3, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
} else {
assertEquals(2, mockSpanner.countRequestsOfType(CreateSessionRequest.class));
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java
index 022c9a92f1f..610a1a99cbe 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/RetryDmlAsPartitionedDmlMockServerTest.java
@@ -83,6 +83,8 @@ public void testTransactionMutationLimitExceeded_isNotRetriedByDefault() {
assertEquals(0, exception.getSuppressed().length);
}
assertEquals(1, mockSpanner.countRequestsOfType(ExecuteSqlRequest.class));
+ ExecuteSqlRequest request = mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
+ assertTrue(request.getLastStatement());
assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
}
@@ -108,6 +110,7 @@ public void testTransactionMutationLimitExceeded_canBeRetriedAsPDML() {
ExecuteSqlRequest transactionalRequest =
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite());
+ assertTrue(transactionalRequest.getLastStatement());
// Partitioned DML uses an explicit BeginTransaction RPC.
assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
@@ -117,6 +120,7 @@ public void testTransactionMutationLimitExceeded_canBeRetriedAsPDML() {
ExecuteSqlRequest partitionedDmlRequest =
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1);
assertTrue(partitionedDmlRequest.getTransaction().hasId());
+ assertFalse(partitionedDmlRequest.getLastStatement());
// Partitioned DML transactions are not committed.
assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
@@ -163,6 +167,7 @@ public void testTransactionMutationLimitExceeded_retryAsPDMLFails() {
ExecuteSqlRequest transactionalRequest =
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(0);
assertTrue(transactionalRequest.getTransaction().getBegin().hasReadWrite());
+ assertTrue(transactionalRequest.getLastStatement());
// Partitioned DML uses an explicit BeginTransaction RPC.
assertEquals(1, mockSpanner.countRequestsOfType(BeginTransactionRequest.class));
@@ -172,6 +177,7 @@ public void testTransactionMutationLimitExceeded_retryAsPDMLFails() {
ExecuteSqlRequest partitionedDmlRequest =
mockSpanner.getRequestsOfType(ExecuteSqlRequest.class).get(1);
assertTrue(partitionedDmlRequest.getTransaction().hasId());
+ assertFalse(partitionedDmlRequest.getLastStatement());
// Partitioned DML transactions are not committed.
assertEquals(0, mockSpanner.countRequestsOfType(CommitRequest.class));
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
index 6edf46b5623..0e2a322023d 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/SingleUseTransactionTest.java
@@ -395,6 +395,8 @@ private SingleUseTransaction createSubject(
final TransactionContext txContext = mock(TransactionContext.class);
when(txContext.executeUpdate(Statement.of(VALID_UPDATE))).thenReturn(VALID_UPDATE_COUNT);
+ when(txContext.executeUpdate(Statement.of(VALID_UPDATE), Options.lastStatement()))
+ .thenReturn(VALID_UPDATE_COUNT);
when(txContext.executeUpdate(Statement.of(SLOW_UPDATE)))
.thenAnswer(
invocation -> {
@@ -404,6 +406,9 @@ private SingleUseTransaction createSubject(
when(txContext.executeUpdate(Statement.of(INVALID_UPDATE)))
.thenThrow(
SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update"));
+ when(txContext.executeUpdate(Statement.of(INVALID_UPDATE), Options.lastStatement()))
+ .thenThrow(
+ SpannerExceptionFactory.newSpannerException(ErrorCode.UNKNOWN, "invalid update"));
SimpleTransactionManager txManager = new SimpleTransactionManager(txContext, commitBehavior);
when(dbClient.transactionManager()).thenReturn(txManager);
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITAsyncTransactionRetryTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITAsyncTransactionRetryTest.java
index 744d7042df4..e25e376ca22 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITAsyncTransactionRetryTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITAsyncTransactionRetryTest.java
@@ -221,6 +221,8 @@ public void testCommitAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
ApiFuture count = getTestRecordCountAsync(connection);
// do an insert
ApiFuture updateCount =
@@ -253,6 +255,8 @@ public void testInsertAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
ApiFuture count = getTestRecordCountAsync(connection);
// indicate that the next statement should abort
interceptor.setProbability(1.0);
@@ -276,6 +280,8 @@ public void testUpdateAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
ApiFuture count = getTestRecordCountAsync(connection);
// insert a test record
connection.executeUpdateAsync(
@@ -309,6 +315,8 @@ public void testQueryAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert a test record
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"));
@@ -359,6 +367,8 @@ public void testNextCallAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert two test records
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
@@ -392,6 +402,8 @@ public void testMultipleAborts() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
ApiFuture count = getTestRecordCountAsync(connection);
// do three inserts which all will abort and retry
interceptor.setProbability(1.0);
@@ -428,6 +440,8 @@ public void testAbortAfterSelect() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
ApiFuture count = getTestRecordCountAsync(connection);
// insert a test record
connection.executeUpdateAsync(
@@ -504,6 +518,8 @@ public void testAbortWithResultSetHalfway() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert two test records
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
@@ -539,6 +555,8 @@ public void testAbortWithResultSetFullyConsumed() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert two test records
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
@@ -581,6 +599,8 @@ public void testAbortWithConcurrentInsert() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert two test records
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
@@ -632,6 +652,8 @@ public void testAbortWithConcurrentDelete() {
AbortInterceptor interceptor = new AbortInterceptor(0);
// first insert two test records
try (ITConnection connection = createConnection()) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
connection.executeUpdateAsync(
@@ -641,6 +663,8 @@ public void testAbortWithConcurrentDelete() {
// open a new connection and select the two test records
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// select the test records and consume the entire result set
try (AsyncResultSet rs =
connection.executeQueryAsync(Statement.of("SELECT * FROM TEST ORDER BY ID"))) {
@@ -694,6 +718,8 @@ public void testAbortWithConcurrentUpdate() {
// open a new connection and select the two test records
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// select the test records and consume the entire result set
try (AsyncResultSet rs =
connection.executeQueryAsync(Statement.of("SELECT * FROM TEST ORDER BY ID"))) {
@@ -744,6 +770,8 @@ public void testAbortWithUnseenConcurrentInsert() throws InterruptedException {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert three test records
connection.executeUpdateAsync(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
@@ -833,6 +861,8 @@ public void testRetryLargeResultSet() {
final long UPDATED_RECORDS = 1000L;
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection = createConnection()) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert test records
for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) {
connection.bufferedWrite(
@@ -845,6 +875,8 @@ public void testRetryLargeResultSet() {
}
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// select the test records and iterate over them
try (AsyncResultSet rs =
connection.executeQueryAsync(Statement.of("SELECT * FROM TEST ORDER BY ID"))) {
@@ -867,6 +899,8 @@ public void testRetryLargeResultSet() {
// Wait until the entire result set has been consumed.
get(finished);
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// Do an update that will abort and retry.
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -898,6 +932,8 @@ public void testRetryHighAbortRate() {
AbortInterceptor interceptor = new AbortInterceptor(0.25D);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert test records
for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) {
connection.bufferedWrite(
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITSqlMusicScriptTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITSqlMusicScriptTest.java
index e7afe957705..745c57cfb2a 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITSqlMusicScriptTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITSqlMusicScriptTest.java
@@ -71,6 +71,8 @@ public void test02_RunAbortedTest() {
long numberOfSongs = 0L;
AbortInterceptor interceptor = new AbortInterceptor(0.0D);
try (ITConnection connection = createConnection(interceptor)) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
connection.setAutocommit(false);
connection.setRetryAbortsInternally(true);
// Read all data from the different music tables in the transaction
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITTransactionRetryTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITTransactionRetryTest.java
index 0cf3abda6bf..54f714a13aa 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITTransactionRetryTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/it/ITTransactionRetryTest.java
@@ -172,6 +172,8 @@ public void testCommitAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// verify that the there is no test record
try (ResultSet rs =
connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) {
@@ -216,6 +218,8 @@ public void testInsertAborted() {
assertThat(rs.getLong("C"), is(equalTo(0L)));
assertThat(rs.next(), is(false));
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// indicate that the next statement should abort
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -241,6 +245,8 @@ public void testUpdateAborted() {
AbortInterceptor interceptor = new AbortInterceptor(0);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// verify that the there is no test record
try (ResultSet rs =
connection.executeQuery(Statement.of("SELECT COUNT(*) AS C FROM TEST WHERE ID=1"))) {
@@ -284,6 +290,8 @@ public void testQueryAborted() {
assertThat(rs.getLong("C"), is(equalTo(0L)));
assertThat(rs.next(), is(false));
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert a test record
connection.executeUpdate(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"));
@@ -321,6 +329,8 @@ public void testNextCallAborted() {
connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')"));
// do a query
try (ResultSet rs = connection.executeQuery(Statement.of("SELECT * FROM TEST ORDER BY ID"))) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// the first record should be accessible without any problems
assertThat(rs.next(), is(true));
assertThat(rs.getLong("ID"), is(equalTo(1L)));
@@ -358,6 +368,8 @@ public void testMultipleAborts() {
assertThat(rs.getLong("C"), is(equalTo(0L)));
assertThat(rs.next(), is(false));
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// do three inserts which all will abort and retry
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -405,6 +417,8 @@ public void testAbortAfterSelect() {
assertThat(rs.getString("NAME"), is(equalTo("test 1")));
assertThat(rs.next(), is(false));
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// do another insert that will abort and retry
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -439,6 +453,8 @@ public void testAbortWithResultSetHalfway() {
// iterate one step
assertThat(rs.next(), is(true));
assertThat(rs.getLong("ID"), is(equalTo(1L)));
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// do another insert that will abort and retry
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -475,6 +491,8 @@ public void testAbortWithResultSetFullyConsumed() {
// do nothing, just consume the result set
}
}
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// do another insert that will abort and retry
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -512,6 +530,8 @@ public void testAbortWithConcurrentInsert() {
}
// now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -551,6 +571,8 @@ public void testAbortWithConcurrentDelete() {
}
// now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -590,6 +612,8 @@ public void testAbortWithConcurrentUpdate() {
}
// now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -629,6 +653,8 @@ public void testAbortWithUnseenConcurrentInsert() {
connection2.commit();
}
// now try to do an insert that will abort. The retry should still succeed.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted;
@@ -714,6 +740,8 @@ private int testAbortWithUnseenConcurrentInsertAbortOnNext(int callsToNext)
// First verify that the transaction has not yet retried.
int currentRetryCount = RETRY_STATISTICS.totalRetryAttemptsStarted;
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
@@ -760,6 +788,8 @@ public void testAbortWithConcurrentInsertAndContinue() {
}
// Now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -807,6 +837,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) {
};
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
connection.executeUpdate(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"));
connection.commit();
@@ -852,6 +884,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) {
};
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
connection.executeUpdate(
Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test aborted')"));
connection.commit();
@@ -906,6 +940,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) {
};
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// Insert two test records.
connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (1, 'test 1')"));
connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (2, 'test 2')"));
@@ -986,6 +1022,8 @@ protected boolean shouldAbort(String statement, ExecutionStep step) {
}
// Now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -1034,6 +1072,8 @@ public void testAbortWithDifferentUpdateCount() {
}
// Now try to do an insert that will abort. The retry should now fail as there has been a
// concurrent modification.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
@@ -1089,6 +1129,8 @@ public void testAbortWithExceptionOnSelect() {
}
}
// now try to do an insert that will abort.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
connection.executeUpdate(Statement.of("INSERT INTO TEST (ID, NAME) VALUES (3, 'test 3')"));
@@ -1147,6 +1189,8 @@ public void testAbortWithExceptionOnSelectAndConcurrentModification() {
}
// Now try to do an insert that will abort. The subsequent retry will fail as the SELECT *
// FROM FOO now returns a result.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
try {
@@ -1213,6 +1257,8 @@ public void testAbortWithExceptionOnInsertAndConcurrentModification() {
}
// Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO
// FOO now succeeds.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
try {
@@ -1281,6 +1327,8 @@ public void testAbortWithDroppedTableConcurrentModification() {
}
// Now try to do an insert that will abort. The subsequent retry will fail as the SELECT *
// FROM FOO now fails.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
try {
@@ -1341,6 +1389,8 @@ public void testAbortWithInsertOnDroppedTableConcurrentModification() {
}
// Now try to do an insert that will abort. The subsequent retry will fail as the INSERT INTO
// FOO now fails.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
try {
@@ -1402,6 +1452,8 @@ public void testAbortWithCursorHalfwayDroppedTableConcurrentModification() {
connection2.execute(Statement.of("DROP TABLE FOO"));
}
// try to continue to consume the result set, but this will now abort.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
try {
@@ -1443,6 +1495,8 @@ public void testRetryLargeResultSet() {
}
}
// Do an update that will abort and retry.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
connection.executeUpdate(
@@ -1467,12 +1521,18 @@ public void testRetryLargeResultSet() {
/** Test the successful retry of a transaction with a high chance of multiple aborts */
@Test
public void testRetryHighAbortRate() {
+ // TODO(sriharshach): Remove this skip once backend support empty transactions to commit.
+ assumeFalse(
+ "Skipping for multiplexed sessions since it does not allow empty transactions to commit",
+ env.getTestHelper().getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW());
final int NUMBER_OF_TEST_RECORDS = 10000;
final long UPDATED_RECORDS = 1000L;
// abort on 25% of all statements
AbortInterceptor interceptor = new AbortInterceptor(0.25D);
try (ITConnection connection =
createConnection(interceptor, new CountTransactionRetryListener())) {
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
// insert test records
for (int i = 0; i < NUMBER_OF_TEST_RECORDS; i++) {
connection.bufferedWrite(
@@ -1539,6 +1599,8 @@ public void testAbortWithConcurrentInsertOnEmptyTable() {
}
// Now try to consume the result set, but the call to next() will throw an AbortedException.
// The retry should still succeed.
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
int currentSuccessfulRetryCount = RETRY_STATISTICS.totalSuccessfulRetries;
@@ -1563,6 +1625,8 @@ public void testAbortWithConcurrentInsertOnEmptyTable() {
connection2.commit();
}
// this time the abort will occur on the call to commit()
+ interceptor.setUsingMultiplexedSession(
+ isMultiplexedSessionsEnabledForRW(connection.getSpanner()));
interceptor.setProbability(1.0);
interceptor.setOnlyInjectOnce(true);
boolean expectedException = false;
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITAsyncExamplesTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITAsyncExamplesTest.java
index dc5abd77afd..b324e39e43e 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITAsyncExamplesTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITAsyncExamplesTest.java
@@ -253,6 +253,12 @@ public void runAsync() throws Exception {
},
executor);
assertThat(insertCount.get()).isEqualTo(1L);
+ if (env.getTestHelper().getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW()) {
+ // The runAsync() method should only be called once on the runner.
+ // However, due to a bug in regular sessions, it can be executed multiple times on the same
+ // runner.
+ runner = client.runAsync();
+ }
ApiFuture deleteCount =
runner.runAsync(
txn ->
@@ -299,6 +305,12 @@ public void runAsyncBatchUpdate() throws Exception {
},
executor);
assertThat(insertCount.get()).asList().containsExactly(1L, 1L, 1L);
+ if (env.getTestHelper().getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW()) {
+ // The runAsync() method should only be called once on the runner.
+ // However, due to a bug in regular sessions, it can be executed multiple times on the same
+ // runner.
+ runner = client.runAsync();
+ }
ApiFuture deleteCount =
runner.runAsync(
txn ->
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchDmlTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchDmlTest.java
index b11e4f613ce..2decef6158e 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchDmlTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchDmlTest.java
@@ -17,6 +17,7 @@
package com.google.cloud.spanner.it;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.spanner.Database;
@@ -84,6 +85,10 @@ public void dropTable() throws Exception {
@Test
public void noStatementsInRequest() {
+ // TODO(sriharshach): Remove this skip once backend support empty transactions to commit.
+ assumeFalse(
+ "Skipping for multiplexed sessions since it does not allow empty transactions to commit",
+ isUsingMultiplexedSessionsForRW());
final TransactionCallable callable =
transaction -> {
List stmts = new ArrayList<>();
@@ -252,4 +257,8 @@ public void largeBatchDml_withNonParameterisedStatements() {
assertThat(actualRowCounts.length).isEqualTo(80);
assertThat(expectedRowCounts).isEqualTo(actualRowCounts);
}
+
+ boolean isUsingMultiplexedSessionsForRW() {
+ return env.getTestHelper().getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW();
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java
index f028fbc2b15..4f68949eab5 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBatchReadTest.java
@@ -181,7 +181,9 @@ public static void setUpDatabase() throws Exception {
totalSize = 0;
}
}
- dbClient.write(mutations);
+ if (!mutations.isEmpty()) {
+ dbClient.write(mutations);
+ }
}
// Our read/queries are executed with some staleness.
Thread.sleep(2 * STALENESS_MILLISEC);
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java
index 258c1230709..5bf8e42ccb6 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBuiltInMetricsTest.java
@@ -82,10 +82,14 @@ public void testBuiltinMetricsWithDefaultOTEL() throws Exception {
String metricFilter =
String.format(
- "metric.type=\"spanner.googleapis.com/client/%s\" "
- + "AND resource.labels.instance=\"%s\" AND metric.labels.method=\"Spanner.ExecuteStreamingSql\""
+ "metric.type=\"spanner.googleapis.com/client/%s\""
+ + " AND resource.type=\"spanner_instance\""
+ + " AND metric.labels.method=\"Spanner.Commit\""
+ + " AND resource.labels.instance_id=\"%s\""
+ " AND metric.labels.database=\"%s\"",
- "operation_latencies", env.getTestHelper().getInstanceId(), db.getId());
+ "operation_latencies",
+ db.getId().getInstanceId().getInstance(),
+ db.getId().getDatabase());
ListTimeSeriesRequest.Builder requestBuilder =
ListTimeSeriesRequest.newBuilder()
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITJsonWriteReadTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITJsonWriteReadTest.java
index e355eaa07a3..026e3649b2e 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITJsonWriteReadTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITJsonWriteReadTest.java
@@ -132,7 +132,14 @@ public void testWriteAndReadInvalidJsonValues() throws IOException {
.to(Value.json(jsonStr))
.build())));
- assertEquals(ErrorCode.FAILED_PRECONDITION, exception.getErrorCode());
+ if (env.getTestHelper()
+ .getOptions()
+ .getSessionPoolOptions()
+ .getUseMultiplexedSessionForRW()) {
+ assertEquals(ErrorCode.INVALID_ARGUMENT, exception.getErrorCode());
+ } else {
+ assertEquals(ErrorCode.FAILED_PRECONDITION, exception.getErrorCode());
+ }
}
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerAsyncTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerAsyncTest.java
index c1e8a903ea5..7ac027bb229 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerAsyncTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionManagerAsyncTest.java
@@ -161,7 +161,16 @@ public void testInvalidInsert() throws InterruptedException {
} catch (ExecutionException e) {
assertThat(e.getCause()).isInstanceOf(SpannerException.class);
SpannerException se = (SpannerException) e.getCause();
- assertThat(se.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ if (env.getTestHelper()
+ .getOptions()
+ .getSessionPoolOptions()
+ .getUseMultiplexedSessionForRW()) {
+ // Backend currently returns INVALID_ARGUMENT, however this will be changed to NOT_FOUND
+ // in future.
+ assertThat(se.getErrorCode()).isAnyOf(ErrorCode.NOT_FOUND, ErrorCode.INVALID_ARGUMENT);
+ } else {
+ assertThat(se.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ }
// expected
break;
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionTest.java
index ea60b9fb649..627523f0555 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITTransactionTest.java
@@ -464,7 +464,10 @@ public void nestedSingleUseReadTxnThrows() {
@Test
public void nestedTxnSucceedsWhenAllowed() {
assumeFalse("Emulator does not support multiple parallel transactions", isUsingEmulator());
-
+ // TODO(sriharshach): Remove this skip once backend support empty transactions to commit.
+ assumeFalse(
+ "Skipping for multiplexed sessions since it does not allow empty transactions to commit",
+ isUsingMultiplexedSessionsForRW());
client
.readWriteTransaction()
.allowNestedTransaction()
@@ -588,4 +591,8 @@ public void testTransactionRunnerReturnsCommitStats() {
// MutationCount = 2 (2 columns).
assertEquals(2L, runner.getCommitResponse().getCommitStats().getMutationCount());
}
+
+ boolean isUsingMultiplexedSessionsForRW() {
+ return env.getTestHelper().getOptions().getSessionPoolOptions().getUseMultiplexedSessionForRW();
+ }
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java
index c5eb9284479..83d27e18e06 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITWriteTest.java
@@ -1043,7 +1043,16 @@ public void tableNotFound() {
.build());
fail("Expected exception");
} catch (SpannerException ex) {
- assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ if (env.getTestHelper()
+ .getOptions()
+ .getSessionPoolOptions()
+ .getUseMultiplexedSessionForRW()) {
+ // Backend currently returns INVALID_ARGUMENT, however this will be changed to NOT_FOUND in
+ // future.
+ assertThat(ex.getErrorCode()).isAnyOf(ErrorCode.NOT_FOUND, ErrorCode.INVALID_ARGUMENT);
+ } else {
+ assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ }
}
}
@@ -1053,7 +1062,16 @@ public void columnNotFound() {
write(baseInsert().set("ColumnThatDoesNotExist").to("V1").build());
fail("Expected exception");
} catch (SpannerException ex) {
- assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ if (env.getTestHelper()
+ .getOptions()
+ .getSessionPoolOptions()
+ .getUseMultiplexedSessionForRW()) {
+ // Backend currently returns INVALID_ARGUMENT, however this will be changed to NOT_FOUND in
+ // future.
+ assertThat(ex.getErrorCode()).isAnyOf(ErrorCode.NOT_FOUND, ErrorCode.INVALID_ARGUMENT);
+ } else {
+ assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
+ }
}
}
@@ -1063,8 +1081,15 @@ public void incorrectType() {
write(baseInsert().set("StringValue").to(1.234).build());
fail("Expected exception");
} catch (SpannerException ex) {
- assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.FAILED_PRECONDITION);
- assertThat(ex.getMessage()).contains("STRING");
+ if (env.getTestHelper()
+ .getOptions()
+ .getSessionPoolOptions()
+ .getUseMultiplexedSessionForRW()) {
+ assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.INVALID_ARGUMENT);
+ } else {
+ assertThat(ex.getErrorCode()).isEqualTo(ErrorCode.FAILED_PRECONDITION);
+ assertThat(ex.getMessage()).contains("STRING");
+ }
}
}
diff --git a/google-cloud-spanner/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner/native-image.properties b/google-cloud-spanner/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner/native-image.properties
new file mode 100644
index 00000000000..383f5390d63
--- /dev/null
+++ b/google-cloud-spanner/src/test/resources/META-INF/native-image/com.google.cloud/google-cloud-spanner/native-image.properties
@@ -0,0 +1,3 @@
+Args=--initialize-at-build-time=org.junit.runner.RunWith \
+ --initialize-at-build-time=org.junit.experimental.categories.Category \
+ --initialize-at-build-time=org.junit.runners.model.FrameworkField
diff --git a/grpc-google-cloud-spanner-admin-database-v1/pom.xml b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
index 11f32d329d0..1ceb1073b98 100644
--- a/grpc-google-cloud-spanner-admin-database-v1/pom.xml
+++ b/grpc-google-cloud-spanner-admin-database-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.86.0
+ 6.87.0
grpc-google-cloud-spanner-admin-database-v1
GRPC library for grpc-google-cloud-spanner-admin-database-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/grpc-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/DatabaseAdminGrpc.java b/grpc-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/DatabaseAdminGrpc.java
index 0089e1c9345..d8ad23a2bdb 100644
--- a/grpc-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/DatabaseAdminGrpc.java
+++ b/grpc-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/DatabaseAdminGrpc.java
@@ -943,6 +943,53 @@ private DatabaseAdminGrpc() {}
return getListDatabaseRolesMethod;
}
+ private static volatile io.grpc.MethodDescriptor<
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>
+ getAddSplitPointsMethod;
+
+ @io.grpc.stub.annotations.RpcMethod(
+ fullMethodName = SERVICE_NAME + '/' + "AddSplitPoints",
+ requestType = com.google.spanner.admin.database.v1.AddSplitPointsRequest.class,
+ responseType = com.google.spanner.admin.database.v1.AddSplitPointsResponse.class,
+ methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
+ public static io.grpc.MethodDescriptor<
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>
+ getAddSplitPointsMethod() {
+ io.grpc.MethodDescriptor<
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>
+ getAddSplitPointsMethod;
+ if ((getAddSplitPointsMethod = DatabaseAdminGrpc.getAddSplitPointsMethod) == null) {
+ synchronized (DatabaseAdminGrpc.class) {
+ if ((getAddSplitPointsMethod = DatabaseAdminGrpc.getAddSplitPointsMethod) == null) {
+ DatabaseAdminGrpc.getAddSplitPointsMethod =
+ getAddSplitPointsMethod =
+ io.grpc.MethodDescriptor
+ .
+ newBuilder()
+ .setType(io.grpc.MethodDescriptor.MethodType.UNARY)
+ .setFullMethodName(generateFullMethodName(SERVICE_NAME, "AddSplitPoints"))
+ .setSampledToLocalTracing(true)
+ .setRequestMarshaller(
+ io.grpc.protobuf.ProtoUtils.marshaller(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest
+ .getDefaultInstance()))
+ .setResponseMarshaller(
+ io.grpc.protobuf.ProtoUtils.marshaller(
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse
+ .getDefaultInstance()))
+ .setSchemaDescriptor(
+ new DatabaseAdminMethodDescriptorSupplier("AddSplitPoints"))
+ .build();
+ }
+ }
+ }
+ return getAddSplitPointsMethod;
+ }
+
private static volatile io.grpc.MethodDescriptor<
com.google.spanner.admin.database.v1.CreateBackupScheduleRequest,
com.google.spanner.admin.database.v1.BackupSchedule>
@@ -1657,6 +1704,21 @@ default void listDatabaseRoles(
getListDatabaseRolesMethod(), responseObserver);
}
+ /**
+ *
+ *
+ *
+ * Adds split points to specified tables, indexes of a database.
+ *
+ */
+ default void addSplitPoints(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest request,
+ io.grpc.stub.StreamObserver
+ responseObserver) {
+ io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(
+ getAddSplitPointsMethod(), responseObserver);
+ }
+
/**
*
*
@@ -2232,6 +2294,23 @@ public void listDatabaseRoles(
responseObserver);
}
+ /**
+ *
+ *
+ *
+ * Adds split points to specified tables, indexes of a database.
+ *
+ */
+ public void addSplitPoints(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest request,
+ io.grpc.stub.StreamObserver
+ responseObserver) {
+ io.grpc.stub.ClientCalls.asyncUnaryCall(
+ getChannel().newCall(getAddSplitPointsMethod(), getCallOptions()),
+ request,
+ responseObserver);
+ }
+
/**
*
*
@@ -2730,6 +2809,19 @@ public com.google.spanner.admin.database.v1.ListDatabaseRolesResponse listDataba
getChannel(), getListDatabaseRolesMethod(), getCallOptions(), request);
}
+ /**
+ *
+ *
+ *
+ * Adds split points to specified tables, indexes of a database.
+ *
+ */
+ public com.google.spanner.admin.database.v1.AddSplitPointsResponse addSplitPoints(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest request) {
+ return io.grpc.stub.ClientCalls.blockingUnaryCall(
+ getChannel(), getAddSplitPointsMethod(), getCallOptions(), request);
+ }
+
/**
*
*
@@ -3221,6 +3313,20 @@ protected DatabaseAdminFutureStub build(
getChannel().newCall(getListDatabaseRolesMethod(), getCallOptions()), request);
}
+ /**
+ *
+ *
+ *
+ * Adds split points to specified tables, indexes of a database.
+ *
+ */
+ public com.google.common.util.concurrent.ListenableFuture<
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>
+ addSplitPoints(com.google.spanner.admin.database.v1.AddSplitPointsRequest request) {
+ return io.grpc.stub.ClientCalls.futureUnaryCall(
+ getChannel().newCall(getAddSplitPointsMethod(), getCallOptions()), request);
+ }
+
/**
*
*
@@ -3315,11 +3421,12 @@ protected DatabaseAdminFutureStub build(
private static final int METHODID_LIST_DATABASE_OPERATIONS = 17;
private static final int METHODID_LIST_BACKUP_OPERATIONS = 18;
private static final int METHODID_LIST_DATABASE_ROLES = 19;
- private static final int METHODID_CREATE_BACKUP_SCHEDULE = 20;
- private static final int METHODID_GET_BACKUP_SCHEDULE = 21;
- private static final int METHODID_UPDATE_BACKUP_SCHEDULE = 22;
- private static final int METHODID_DELETE_BACKUP_SCHEDULE = 23;
- private static final int METHODID_LIST_BACKUP_SCHEDULES = 24;
+ private static final int METHODID_ADD_SPLIT_POINTS = 20;
+ private static final int METHODID_CREATE_BACKUP_SCHEDULE = 21;
+ private static final int METHODID_GET_BACKUP_SCHEDULE = 22;
+ private static final int METHODID_UPDATE_BACKUP_SCHEDULE = 23;
+ private static final int METHODID_DELETE_BACKUP_SCHEDULE = 24;
+ private static final int METHODID_LIST_BACKUP_SCHEDULES = 25;
private static final class MethodHandlers
implements io.grpc.stub.ServerCalls.UnaryMethod,
@@ -3454,6 +3561,13 @@ public void invoke(Req request, io.grpc.stub.StreamObserver responseObserv
com.google.spanner.admin.database.v1.ListDatabaseRolesResponse>)
responseObserver);
break;
+ case METHODID_ADD_SPLIT_POINTS:
+ serviceImpl.addSplitPoints(
+ (com.google.spanner.admin.database.v1.AddSplitPointsRequest) request,
+ (io.grpc.stub.StreamObserver<
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>)
+ responseObserver);
+ break;
case METHODID_CREATE_BACKUP_SCHEDULE:
serviceImpl.createBackupSchedule(
(com.google.spanner.admin.database.v1.CreateBackupScheduleRequest) request,
@@ -3627,6 +3741,13 @@ public static final io.grpc.ServerServiceDefinition bindService(AsyncService ser
com.google.spanner.admin.database.v1.ListDatabaseRolesRequest,
com.google.spanner.admin.database.v1.ListDatabaseRolesResponse>(
service, METHODID_LIST_DATABASE_ROLES)))
+ .addMethod(
+ getAddSplitPointsMethod(),
+ io.grpc.stub.ServerCalls.asyncUnaryCall(
+ new MethodHandlers<
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse>(
+ service, METHODID_ADD_SPLIT_POINTS)))
.addMethod(
getCreateBackupScheduleMethod(),
io.grpc.stub.ServerCalls.asyncUnaryCall(
@@ -3732,6 +3853,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() {
.addMethod(getListDatabaseOperationsMethod())
.addMethod(getListBackupOperationsMethod())
.addMethod(getListDatabaseRolesMethod())
+ .addMethod(getAddSplitPointsMethod())
.addMethod(getCreateBackupScheduleMethod())
.addMethod(getGetBackupScheduleMethod())
.addMethod(getUpdateBackupScheduleMethod())
diff --git a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
index 1df91aad491..3be48a22c4c 100644
--- a/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
+++ b/grpc-google-cloud-spanner-admin-instance-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.86.0
+ 6.87.0
grpc-google-cloud-spanner-admin-instance-v1
GRPC library for grpc-google-cloud-spanner-admin-instance-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/grpc-google-cloud-spanner-executor-v1/pom.xml b/grpc-google-cloud-spanner-executor-v1/pom.xml
index cf50f14bb8f..a1950b288ec 100644
--- a/grpc-google-cloud-spanner-executor-v1/pom.xml
+++ b/grpc-google-cloud-spanner-executor-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.86.0
+ 6.87.0
grpc-google-cloud-spanner-executor-v1
GRPC library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/grpc-google-cloud-spanner-v1/pom.xml b/grpc-google-cloud-spanner-v1/pom.xml
index be66f571723..eb81ef2cd5a 100644
--- a/grpc-google-cloud-spanner-v1/pom.xml
+++ b/grpc-google-cloud-spanner-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.86.0
+ 6.87.0
grpc-google-cloud-spanner-v1
GRPC library for grpc-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/pom.xml b/pom.xml
index 4278401a97d..41909b12055 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
com.google.cloud
google-cloud-spanner-parent
pom
- 6.86.0
+ 6.87.0
Google Cloud Spanner Parent
https://github.com/googleapis/java-spanner
@@ -14,7 +14,7 @@
com.google.cloud
sdk-platform-java-config
- 3.42.0
+ 3.43.0
@@ -61,47 +61,47 @@
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
grpc-google-cloud-spanner-executor-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
grpc-google-cloud-spanner-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-instance-v1
- 6.86.0
+ 6.87.0
com.google.api.grpc
grpc-google-cloud-spanner-admin-database-v1
- 6.86.0
+ 6.87.0
com.google.cloud
google-cloud-spanner
- 6.86.0
+ 6.87.0
diff --git a/proto-google-cloud-spanner-admin-database-v1/pom.xml b/proto-google-cloud-spanner-admin-database-v1/pom.xml
index e69f7050359..59979f00a92 100644
--- a/proto-google-cloud-spanner-admin-database-v1/pom.xml
+++ b/proto-google-cloud-spanner-admin-database-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-admin-database-v1
- 6.86.0
+ 6.87.0
proto-google-cloud-spanner-admin-database-v1
PROTO library for proto-google-cloud-spanner-admin-database-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequest.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequest.java
new file mode 100644
index 00000000000..ebcd880bf0d
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequest.java
@@ -0,0 +1,1414 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+/**
+ *
+ *
+ *
+ * The request for
+ * [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.AddSplitPointsRequest}
+ */
+public final class AddSplitPointsRequest extends com.google.protobuf.GeneratedMessageV3
+ implements
+ // @@protoc_insertion_point(message_implements:google.spanner.admin.database.v1.AddSplitPointsRequest)
+ AddSplitPointsRequestOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use AddSplitPointsRequest.newBuilder() to construct.
+ private AddSplitPointsRequest(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+
+ private AddSplitPointsRequest() {
+ database_ = "";
+ splitPoints_ = java.util.Collections.emptyList();
+ initiator_ = "";
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+ return new AddSplitPointsRequest();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest.class,
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest.Builder.class);
+ }
+
+ public static final int DATABASE_FIELD_NUMBER = 1;
+
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object database_ = "";
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The database.
+ */
+ @java.lang.Override
+ public java.lang.String getDatabase() {
+ java.lang.Object ref = database_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ database_ = s;
+ return s;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The bytes for database.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString getDatabaseBytes() {
+ java.lang.Object ref = database_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ database_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int SPLIT_POINTS_FIELD_NUMBER = 2;
+
+ @SuppressWarnings("serial")
+ private java.util.List splitPoints_;
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public java.util.List getSplitPointsList() {
+ return splitPoints_;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public java.util.List extends com.google.spanner.admin.database.v1.SplitPointsOrBuilder>
+ getSplitPointsOrBuilderList() {
+ return splitPoints_;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public int getSplitPointsCount() {
+ return splitPoints_.size();
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints getSplitPoints(int index) {
+ return splitPoints_.get(index);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPointsOrBuilder getSplitPointsOrBuilder(
+ int index) {
+ return splitPoints_.get(index);
+ }
+
+ public static final int INITIATOR_FIELD_NUMBER = 3;
+
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object initiator_ = "";
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The initiator.
+ */
+ @java.lang.Override
+ public java.lang.String getInitiator() {
+ java.lang.Object ref = initiator_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ initiator_ = s;
+ return s;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The bytes for initiator.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString getInitiatorBytes() {
+ java.lang.Object ref = initiator_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ initiator_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ private byte memoizedIsInitialized = -1;
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(database_)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 1, database_);
+ }
+ for (int i = 0; i < splitPoints_.size(); i++) {
+ output.writeMessage(2, splitPoints_.get(i));
+ }
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(initiator_)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 3, initiator_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(database_)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, database_);
+ }
+ for (int i = 0; i < splitPoints_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream.computeMessageSize(2, splitPoints_.get(i));
+ }
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(initiator_)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(3, initiator_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.google.spanner.admin.database.v1.AddSplitPointsRequest)) {
+ return super.equals(obj);
+ }
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest other =
+ (com.google.spanner.admin.database.v1.AddSplitPointsRequest) obj;
+
+ if (!getDatabase().equals(other.getDatabase())) return false;
+ if (!getSplitPointsList().equals(other.getSplitPointsList())) return false;
+ if (!getInitiator().equals(other.getInitiator())) return false;
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (37 * hash) + DATABASE_FIELD_NUMBER;
+ hash = (53 * hash) + getDatabase().hashCode();
+ if (getSplitPointsCount() > 0) {
+ hash = (37 * hash) + SPLIT_POINTS_FIELD_NUMBER;
+ hash = (53 * hash) + getSplitPointsList().hashCode();
+ }
+ hash = (37 * hash) + INITIATOR_FIELD_NUMBER;
+ hash = (53 * hash) + getInitiator().hashCode();
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseDelimitedFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseDelimitedFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+
+ public static Builder newBuilder(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ *
+ *
+ *
+ * The request for
+ * [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.AddSplitPointsRequest}
+ */
+ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder
+ implements
+ // @@protoc_insertion_point(builder_implements:google.spanner.admin.database.v1.AddSplitPointsRequest)
+ com.google.spanner.admin.database.v1.AddSplitPointsRequestOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest.class,
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest.Builder.class);
+ }
+
+ // Construct using com.google.spanner.admin.database.v1.AddSplitPointsRequest.newBuilder()
+ private Builder() {}
+
+ private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ }
+
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ database_ = "";
+ if (splitPointsBuilder_ == null) {
+ splitPoints_ = java.util.Collections.emptyList();
+ } else {
+ splitPoints_ = null;
+ splitPointsBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000002);
+ initiator_ = "";
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsRequest getDefaultInstanceForType() {
+ return com.google.spanner.admin.database.v1.AddSplitPointsRequest.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsRequest build() {
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsRequest buildPartial() {
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest result =
+ new com.google.spanner.admin.database.v1.AddSplitPointsRequest(this);
+ buildPartialRepeatedFields(result);
+ if (bitField0_ != 0) {
+ buildPartial0(result);
+ }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartialRepeatedFields(
+ com.google.spanner.admin.database.v1.AddSplitPointsRequest result) {
+ if (splitPointsBuilder_ == null) {
+ if (((bitField0_ & 0x00000002) != 0)) {
+ splitPoints_ = java.util.Collections.unmodifiableList(splitPoints_);
+ bitField0_ = (bitField0_ & ~0x00000002);
+ }
+ result.splitPoints_ = splitPoints_;
+ } else {
+ result.splitPoints_ = splitPointsBuilder_.build();
+ }
+ }
+
+ private void buildPartial0(com.google.spanner.admin.database.v1.AddSplitPointsRequest result) {
+ int from_bitField0_ = bitField0_;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.database_ = database_;
+ }
+ if (((from_bitField0_ & 0x00000004) != 0)) {
+ result.initiator_ = initiator_;
+ }
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.setField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+
+ @java.lang.Override
+ public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.google.spanner.admin.database.v1.AddSplitPointsRequest) {
+ return mergeFrom((com.google.spanner.admin.database.v1.AddSplitPointsRequest) other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.google.spanner.admin.database.v1.AddSplitPointsRequest other) {
+ if (other == com.google.spanner.admin.database.v1.AddSplitPointsRequest.getDefaultInstance())
+ return this;
+ if (!other.getDatabase().isEmpty()) {
+ database_ = other.database_;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ }
+ if (splitPointsBuilder_ == null) {
+ if (!other.splitPoints_.isEmpty()) {
+ if (splitPoints_.isEmpty()) {
+ splitPoints_ = other.splitPoints_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ } else {
+ ensureSplitPointsIsMutable();
+ splitPoints_.addAll(other.splitPoints_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.splitPoints_.isEmpty()) {
+ if (splitPointsBuilder_.isEmpty()) {
+ splitPointsBuilder_.dispose();
+ splitPointsBuilder_ = null;
+ splitPoints_ = other.splitPoints_;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ splitPointsBuilder_ =
+ com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders
+ ? getSplitPointsFieldBuilder()
+ : null;
+ } else {
+ splitPointsBuilder_.addAllMessages(other.splitPoints_);
+ }
+ }
+ }
+ if (!other.getInitiator().isEmpty()) {
+ initiator_ = other.initiator_;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10:
+ {
+ database_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 10
+ case 18:
+ {
+ com.google.spanner.admin.database.v1.SplitPoints m =
+ input.readMessage(
+ com.google.spanner.admin.database.v1.SplitPoints.parser(),
+ extensionRegistry);
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ splitPoints_.add(m);
+ } else {
+ splitPointsBuilder_.addMessage(m);
+ }
+ break;
+ } // case 18
+ case 26:
+ {
+ initiator_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000004;
+ break;
+ } // case 26
+ default:
+ {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+
+ private int bitField0_;
+
+ private java.lang.Object database_ = "";
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The database.
+ */
+ public java.lang.String getDatabase() {
+ java.lang.Object ref = database_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ database_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The bytes for database.
+ */
+ public com.google.protobuf.ByteString getDatabaseBytes() {
+ java.lang.Object ref = database_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ database_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @param value The database to set.
+ * @return This builder for chaining.
+ */
+ public Builder setDatabase(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ database_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return This builder for chaining.
+ */
+ public Builder clearDatabase() {
+ database_ = getDefaultInstance().getDatabase();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @param value The bytes for database to set.
+ * @return This builder for chaining.
+ */
+ public Builder setDatabaseBytes(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ checkByteStringIsUtf8(value);
+ database_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+
+ private java.util.List splitPoints_ =
+ java.util.Collections.emptyList();
+
+ private void ensureSplitPointsIsMutable() {
+ if (!((bitField0_ & 0x00000002) != 0)) {
+ splitPoints_ =
+ new java.util.ArrayList(splitPoints_);
+ bitField0_ |= 0x00000002;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints,
+ com.google.spanner.admin.database.v1.SplitPoints.Builder,
+ com.google.spanner.admin.database.v1.SplitPointsOrBuilder>
+ splitPointsBuilder_;
+
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List getSplitPointsList() {
+ if (splitPointsBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(splitPoints_);
+ } else {
+ return splitPointsBuilder_.getMessageList();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public int getSplitPointsCount() {
+ if (splitPointsBuilder_ == null) {
+ return splitPoints_.size();
+ } else {
+ return splitPointsBuilder_.getCount();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints getSplitPoints(int index) {
+ if (splitPointsBuilder_ == null) {
+ return splitPoints_.get(index);
+ } else {
+ return splitPointsBuilder_.getMessage(index);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setSplitPoints(
+ int index, com.google.spanner.admin.database.v1.SplitPoints value) {
+ if (splitPointsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSplitPointsIsMutable();
+ splitPoints_.set(index, value);
+ onChanged();
+ } else {
+ splitPointsBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setSplitPoints(
+ int index, com.google.spanner.admin.database.v1.SplitPoints.Builder builderForValue) {
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ splitPoints_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ splitPointsBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addSplitPoints(com.google.spanner.admin.database.v1.SplitPoints value) {
+ if (splitPointsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSplitPointsIsMutable();
+ splitPoints_.add(value);
+ onChanged();
+ } else {
+ splitPointsBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addSplitPoints(
+ int index, com.google.spanner.admin.database.v1.SplitPoints value) {
+ if (splitPointsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureSplitPointsIsMutable();
+ splitPoints_.add(index, value);
+ onChanged();
+ } else {
+ splitPointsBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addSplitPoints(
+ com.google.spanner.admin.database.v1.SplitPoints.Builder builderForValue) {
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ splitPoints_.add(builderForValue.build());
+ onChanged();
+ } else {
+ splitPointsBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addSplitPoints(
+ int index, com.google.spanner.admin.database.v1.SplitPoints.Builder builderForValue) {
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ splitPoints_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ splitPointsBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addAllSplitPoints(
+ java.lang.Iterable extends com.google.spanner.admin.database.v1.SplitPoints> values) {
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(values, splitPoints_);
+ onChanged();
+ } else {
+ splitPointsBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder clearSplitPoints() {
+ if (splitPointsBuilder_ == null) {
+ splitPoints_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ onChanged();
+ } else {
+ splitPointsBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder removeSplitPoints(int index) {
+ if (splitPointsBuilder_ == null) {
+ ensureSplitPointsIsMutable();
+ splitPoints_.remove(index);
+ onChanged();
+ } else {
+ splitPointsBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Builder getSplitPointsBuilder(
+ int index) {
+ return getSplitPointsFieldBuilder().getBuilder(index);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPointsOrBuilder getSplitPointsOrBuilder(
+ int index) {
+ if (splitPointsBuilder_ == null) {
+ return splitPoints_.get(index);
+ } else {
+ return splitPointsBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List extends com.google.spanner.admin.database.v1.SplitPointsOrBuilder>
+ getSplitPointsOrBuilderList() {
+ if (splitPointsBuilder_ != null) {
+ return splitPointsBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(splitPoints_);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Builder addSplitPointsBuilder() {
+ return getSplitPointsFieldBuilder()
+ .addBuilder(com.google.spanner.admin.database.v1.SplitPoints.getDefaultInstance());
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Builder addSplitPointsBuilder(
+ int index) {
+ return getSplitPointsFieldBuilder()
+ .addBuilder(index, com.google.spanner.admin.database.v1.SplitPoints.getDefaultInstance());
+ }
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List
+ getSplitPointsBuilderList() {
+ return getSplitPointsFieldBuilder().getBuilderList();
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints,
+ com.google.spanner.admin.database.v1.SplitPoints.Builder,
+ com.google.spanner.admin.database.v1.SplitPointsOrBuilder>
+ getSplitPointsFieldBuilder() {
+ if (splitPointsBuilder_ == null) {
+ splitPointsBuilder_ =
+ new com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints,
+ com.google.spanner.admin.database.v1.SplitPoints.Builder,
+ com.google.spanner.admin.database.v1.SplitPointsOrBuilder>(
+ splitPoints_, ((bitField0_ & 0x00000002) != 0), getParentForChildren(), isClean());
+ splitPoints_ = null;
+ }
+ return splitPointsBuilder_;
+ }
+
+ private java.lang.Object initiator_ = "";
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The initiator.
+ */
+ public java.lang.String getInitiator() {
+ java.lang.Object ref = initiator_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ initiator_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The bytes for initiator.
+ */
+ public com.google.protobuf.ByteString getInitiatorBytes() {
+ java.lang.Object ref = initiator_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ initiator_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @param value The initiator to set.
+ * @return This builder for chaining.
+ */
+ public Builder setInitiator(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ initiator_ = value;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return This builder for chaining.
+ */
+ public Builder clearInitiator() {
+ initiator_ = getDefaultInstance().getInitiator();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @param value The bytes for initiator to set.
+ * @return This builder for chaining.
+ */
+ public Builder setInitiatorBytes(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ checkByteStringIsUtf8(value);
+ initiator_ = value;
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+ // @@protoc_insertion_point(builder_scope:google.spanner.admin.database.v1.AddSplitPointsRequest)
+ }
+
+ // @@protoc_insertion_point(class_scope:google.spanner.admin.database.v1.AddSplitPointsRequest)
+ private static final com.google.spanner.admin.database.v1.AddSplitPointsRequest DEFAULT_INSTANCE;
+
+ static {
+ DEFAULT_INSTANCE = new com.google.spanner.admin.database.v1.AddSplitPointsRequest();
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsRequest getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AddSplitPointsRequest parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsRequest getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequestOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequestOrBuilder.java
new file mode 100644
index 00000000000..d03cb8c611d
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsRequestOrBuilder.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+public interface AddSplitPointsRequestOrBuilder
+ extends
+ // @@protoc_insertion_point(interface_extends:google.spanner.admin.database.v1.AddSplitPointsRequest)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The database.
+ */
+ java.lang.String getDatabase();
+ /**
+ *
+ *
+ *
+ * Required. The database on whose tables/indexes split points are to be
+ * added. Values are of the form
+ * `projects/<project>/instances/<instance>/databases/<database>`.
+ *
+ *
+ *
+ * string database = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = { ... }
+ *
+ *
+ * @return The bytes for database.
+ */
+ com.google.protobuf.ByteString getDatabaseBytes();
+
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ java.util.List getSplitPointsList();
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ com.google.spanner.admin.database.v1.SplitPoints getSplitPoints(int index);
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ int getSplitPointsCount();
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ java.util.List extends com.google.spanner.admin.database.v1.SplitPointsOrBuilder>
+ getSplitPointsOrBuilderList();
+ /**
+ *
+ *
+ *
+ * Required. The split points to add.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints split_points = 2 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ com.google.spanner.admin.database.v1.SplitPointsOrBuilder getSplitPointsOrBuilder(int index);
+
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The initiator.
+ */
+ java.lang.String getInitiator();
+ /**
+ *
+ *
+ *
+ * Optional. A user-supplied tag associated with the split points.
+ * For example, "intital_data_load", "special_event_1".
+ * Defaults to "CloudAddSplitPointsAPI" if not specified.
+ * The length of the tag must not exceed 50 characters,else will be trimmed.
+ * Only valid UTF8 characters are allowed.
+ *
+ *
+ * string initiator = 3 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ * @return The bytes for initiator.
+ */
+ com.google.protobuf.ByteString getInitiatorBytes();
+}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponse.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponse.java
new file mode 100644
index 00000000000..a78c8b880e4
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponse.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+/**
+ *
+ *
+ *
+ * The response for
+ * [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.AddSplitPointsResponse}
+ */
+public final class AddSplitPointsResponse extends com.google.protobuf.GeneratedMessageV3
+ implements
+ // @@protoc_insertion_point(message_implements:google.spanner.admin.database.v1.AddSplitPointsResponse)
+ AddSplitPointsResponseOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use AddSplitPointsResponse.newBuilder() to construct.
+ private AddSplitPointsResponse(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+
+ private AddSplitPointsResponse() {}
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+ return new AddSplitPointsResponse();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse.class,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse.Builder.class);
+ }
+
+ private byte memoizedIsInitialized = -1;
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.google.spanner.admin.database.v1.AddSplitPointsResponse)) {
+ return super.equals(obj);
+ }
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse other =
+ (com.google.spanner.admin.database.v1.AddSplitPointsResponse) obj;
+
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseDelimitedFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseDelimitedFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+
+ public static Builder newBuilder(
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ *
+ *
+ *
+ * The response for
+ * [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.AddSplitPointsResponse}
+ */
+ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder
+ implements
+ // @@protoc_insertion_point(builder_implements:google.spanner.admin.database.v1.AddSplitPointsResponse)
+ com.google.spanner.admin.database.v1.AddSplitPointsResponseOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse.class,
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse.Builder.class);
+ }
+
+ // Construct using com.google.spanner.admin.database.v1.AddSplitPointsResponse.newBuilder()
+ private Builder() {}
+
+ private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ }
+
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsResponse getDefaultInstanceForType() {
+ return com.google.spanner.admin.database.v1.AddSplitPointsResponse.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsResponse build() {
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsResponse buildPartial() {
+ com.google.spanner.admin.database.v1.AddSplitPointsResponse result =
+ new com.google.spanner.admin.database.v1.AddSplitPointsResponse(this);
+ onBuilt();
+ return result;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.setField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+
+ @java.lang.Override
+ public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.google.spanner.admin.database.v1.AddSplitPointsResponse) {
+ return mergeFrom((com.google.spanner.admin.database.v1.AddSplitPointsResponse) other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.google.spanner.admin.database.v1.AddSplitPointsResponse other) {
+ if (other == com.google.spanner.admin.database.v1.AddSplitPointsResponse.getDefaultInstance())
+ return this;
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default:
+ {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+
+ @java.lang.Override
+ public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+ // @@protoc_insertion_point(builder_scope:google.spanner.admin.database.v1.AddSplitPointsResponse)
+ }
+
+ // @@protoc_insertion_point(class_scope:google.spanner.admin.database.v1.AddSplitPointsResponse)
+ private static final com.google.spanner.admin.database.v1.AddSplitPointsResponse DEFAULT_INSTANCE;
+
+ static {
+ DEFAULT_INSTANCE = new com.google.spanner.admin.database.v1.AddSplitPointsResponse();
+ }
+
+ public static com.google.spanner.admin.database.v1.AddSplitPointsResponse getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public AddSplitPointsResponse parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.AddSplitPointsResponse getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponseOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponseOrBuilder.java
new file mode 100644
index 00000000000..bc6192ab7b7
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/AddSplitPointsResponseOrBuilder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+public interface AddSplitPointsResponseOrBuilder
+ extends
+ // @@protoc_insertion_point(interface_extends:google.spanner.admin.database.v1.AddSplitPointsResponse)
+ com.google.protobuf.MessageOrBuilder {}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java
index 507aa4a281f..06a130a7002 100644
--- a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SpannerDatabaseAdminProto.java
@@ -124,6 +124,22 @@ public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry r
internal_static_google_spanner_admin_database_v1_ListDatabaseRolesResponse_descriptor;
static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_google_spanner_admin_database_v1_ListDatabaseRolesResponse_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor;
+ static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor;
+ static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor;
+ static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_google_spanner_admin_database_v1_SplitPoints_fieldAccessorTable;
+ static final com.google.protobuf.Descriptors.Descriptor
+ internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor;
+ static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internal_static_google_spanner_admin_database_v1_SplitPoints_Key_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
return descriptor;
@@ -142,301 +158,319 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
+ "roto\032\032google/iam/v1/policy.proto\032#google"
+ "/longrunning/operations.proto\032\033google/pr"
+ "otobuf/empty.proto\032 google/protobuf/fiel"
- + "d_mask.proto\032\037google/protobuf/timestamp."
- + "proto\032-google/spanner/admin/database/v1/"
- + "backup.proto\0326google/spanner/admin/datab"
- + "ase/v1/backup_schedule.proto\032-google/spa"
- + "nner/admin/database/v1/common.proto\"\253\001\n\013"
- + "RestoreInfo\022H\n\013source_type\030\001 \001(\01623.googl"
- + "e.spanner.admin.database.v1.RestoreSourc"
- + "eType\022C\n\013backup_info\030\002 \001(\0132,.google.span"
- + "ner.admin.database.v1.BackupInfoH\000B\r\n\013so"
- + "urce_info\"\312\006\n\010Database\022\021\n\004name\030\001 \001(\tB\003\340A"
- + "\002\022D\n\005state\030\002 \001(\01620.google.spanner.admin."
- + "database.v1.Database.StateB\003\340A\003\0224\n\013creat"
- + "e_time\030\003 \001(\0132\032.google.protobuf.Timestamp"
- + "B\003\340A\003\022H\n\014restore_info\030\004 \001(\0132-.google.spa"
- + "nner.admin.database.v1.RestoreInfoB\003\340A\003\022"
- + "R\n\021encryption_config\030\005 \001(\01322.google.span"
- + "ner.admin.database.v1.EncryptionConfigB\003"
- + "\340A\003\022N\n\017encryption_info\030\010 \003(\01320.google.sp"
- + "anner.admin.database.v1.EncryptionInfoB\003"
- + "\340A\003\022%\n\030version_retention_period\030\006 \001(\tB\003\340"
- + "A\003\022>\n\025earliest_version_time\030\007 \001(\0132\032.goog"
- + "le.protobuf.TimestampB\003\340A\003\022\033\n\016default_le"
- + "ader\030\t \001(\tB\003\340A\003\022P\n\020database_dialect\030\n \001("
- + "\01621.google.spanner.admin.database.v1.Dat"
- + "abaseDialectB\003\340A\003\022\036\n\026enable_drop_protect"
- + "ion\030\013 \001(\010\022\030\n\013reconciling\030\014 \001(\010B\003\340A\003\"M\n\005S"
- + "tate\022\025\n\021STATE_UNSPECIFIED\020\000\022\014\n\010CREATING\020"
- + "\001\022\t\n\005READY\020\002\022\024\n\020READY_OPTIMIZING\020\003:b\352A_\n"
- + "\037spanner.googleapis.com/Database\022\332A\006parent\202\323\344\223\002/\022-/v1/{parent=projec"
- + "ts/*/instances/*}/databases\022\244\002\n\016CreateDa"
- + "tabase\0227.google.spanner.admin.database.v"
- + "1.CreateDatabaseRequest\032\035.google.longrun"
- + "ning.Operation\"\271\001\312Ad\n)google.spanner.adm"
- + "in.database.v1.Database\0227google.spanner."
- + "admin.database.v1.CreateDatabaseMetadata"
- + "\332A\027parent,create_statement\202\323\344\223\0022\"-/v1/{p"
- + "arent=projects/*/instances/*}/databases:"
- + "\001*\022\255\001\n\013GetDatabase\0224.google.spanner.admi"
- + "n.database.v1.GetDatabaseRequest\032*.googl"
- + "e.spanner.admin.database.v1.Database\"<\332A"
- + "\004name\202\323\344\223\002/\022-/v1/{name=projects/*/instan"
- + "ces/*/databases/*}\022\357\001\n\016UpdateDatabase\0227."
- + "google.spanner.admin.database.v1.UpdateD"
- + "atabaseRequest\032\035.google.longrunning.Oper"
- + "ation\"\204\001\312A\"\n\010Database\022\026UpdateDatabaseMet"
- + "adata\332A\024database,update_mask\202\323\344\223\002B26/v1/"
- + "{database.name=projects/*/instances/*/da"
- + "tabases/*}:\010database\022\235\002\n\021UpdateDatabaseD"
- + "dl\022:.google.spanner.admin.database.v1.Up"
- + "dateDatabaseDdlRequest\032\035.google.longrunn"
- + "ing.Operation\"\254\001\312AS\n\025google.protobuf.Emp"
- + "ty\022:google.spanner.admin.database.v1.Upd"
- + "ateDatabaseDdlMetadata\332A\023database,statem"
- + "ents\202\323\344\223\002:25/v1/{database=projects/*/ins"
- + "tances/*/databases/*}/ddl:\001*\022\243\001\n\014DropDat"
- + "abase\0225.google.spanner.admin.database.v1"
- + ".DropDatabaseRequest\032\026.google.protobuf.E"
- + "mpty\"D\332A\010database\202\323\344\223\0023*1/v1/{database=p"
- + "rojects/*/instances/*/databases/*}\022\315\001\n\016G"
- + "etDatabaseDdl\0227.google.spanner.admin.dat"
- + "abase.v1.GetDatabaseDdlRequest\0328.google."
- + "spanner.admin.database.v1.GetDatabaseDdl"
- + "Response\"H\332A\010database\202\323\344\223\0027\0225/v1/{databa"
- + "se=projects/*/instances/*/databases/*}/d"
- + "dl\022\302\002\n\014SetIamPolicy\022\".google.iam.v1.SetI"
- + "amPolicyRequest\032\025.google.iam.v1.Policy\"\366"
- + "\001\332A\017resource,policy\202\323\344\223\002\335\001\">/v1/{resourc"
- + "e=projects/*/instances/*/databases/*}:se"
- + "tIamPolicy:\001*ZA\"/v1/{resource="
- + "projects/*/instances/*/databases/*}:getI"
- + "amPolicy:\001*ZA\"\n\025earl"
+ + "iest_version_time\030\007 \001(\0132\032.google.protobu"
+ + "f.TimestampB\003\340A\003\022\033\n\016default_leader\030\t \001(\t"
+ + "B\003\340A\003\022P\n\020database_dialect\030\n \001(\01621.google"
+ + ".spanner.admin.database.v1.DatabaseDiale"
+ + "ctB\003\340A\003\022\036\n\026enable_drop_protection\030\013 \001(\010\022"
+ + "\030\n\013reconciling\030\014 \001(\010B\003\340A\003\"M\n\005State\022\025\n\021ST"
+ + "ATE_UNSPECIFIED\020\000\022\014\n\010CREATING\020\001\022\t\n\005READY"
+ + "\020\002\022\024\n\020READY_OPTIMIZING\020\003:b\352A_\n\037spanner.g"
+ + "oogleapis.com/Database\022.google.spanner.admin.databa"
- + "se.v1.ListBackupOperationsResponse\"E\332A\006p"
- + "arent\202\323\344\223\0026\0224/v1/{parent=projects/*/inst"
- + "ances/*}/backupOperations\022\334\001\n\021ListDataba"
- + "seRoles\022:.google.spanner.admin.database."
- + "v1.ListDatabaseRolesRequest\032;.google.spa"
- + "nner.admin.database.v1.ListDatabaseRoles"
- + "Response\"N\332A\006parent\202\323\344\223\002?\022=/v1/{parent=p"
- + "rojects/*/instances/*/databases/*}/datab"
- + "aseRoles\022\216\002\n\024CreateBackupSchedule\022=.goog"
- + "le.spanner.admin.database.v1.CreateBacku"
- + "pScheduleRequest\0320.google.spanner.admin."
- + "database.v1.BackupSchedule\"\204\001\332A)parent,b"
- + "ackup_schedule,backup_schedule_id\202\323\344\223\002R\""
- + "?/v1/{parent=projects/*/instances/*/data"
- + "bases/*}/backupSchedules:\017backup_schedul"
- + "e\022\321\001\n\021GetBackupSchedule\022:.google.spanner"
- + ".admin.database.v1.GetBackupScheduleRequ"
- + "est\0320.google.spanner.admin.database.v1.B"
- + "ackupSchedule\"N\332A\004name\202\323\344\223\002A\022?/v1/{name="
- + "projects/*/instances/*/databases/*/backu"
- + "pSchedules/*}\022\220\002\n\024UpdateBackupSchedule\022="
- + ".google.spanner.admin.database.v1.Update"
- + "BackupScheduleRequest\0320.google.spanner.a"
- + "dmin.database.v1.BackupSchedule\"\206\001\332A\033bac"
- + "kup_schedule,update_mask\202\323\344\223\002b2O/v1/{bac"
- + "kup_schedule.name=projects/*/instances/*"
- + "/databases/*/backupSchedules/*}:\017backup_"
- + "schedule\022\275\001\n\024DeleteBackupSchedule\022=.goog"
- + "le.spanner.admin.database.v1.DeleteBacku"
- + "pScheduleRequest\032\026.google.protobuf.Empty"
- + "\"N\332A\004name\202\323\344\223\002A*?/v1/{name=projects/*/in"
- + "stances/*/databases/*/backupSchedules/*}"
- + "\022\344\001\n\023ListBackupSchedules\022<.google.spanne"
- + "r.admin.database.v1.ListBackupSchedulesR"
- + "equest\032=.google.spanner.admin.database.v"
- + "1.ListBackupSchedulesResponse\"P\332A\006parent"
- + "\202\323\344\223\002A\022?/v1/{parent=projects/*/instances"
- + "/*/databases/*}/backupSchedules\032x\312A\026span"
- + "ner.googleapis.com\322A\\https://www.googlea"
- + "pis.com/auth/cloud-platform,https://www."
- + "googleapis.com/auth/spanner.adminB\330\002\n$co"
- + "m.google.spanner.admin.database.v1B\031Span"
- + "nerDatabaseAdminProtoP\001ZFcloud.google.co"
- + "m/go/spanner/admin/database/apiv1/databa"
- + "sepb;databasepb\252\002&Google.Cloud.Spanner.A"
- + "dmin.Database.V1\312\002&Google\\Cloud\\Spanner\\"
- + "Admin\\Database\\V1\352\002+Google::Cloud::Spann"
- + "er::Admin::Database::V1\352AJ\n\037spanner.goog"
- + "leapis.com/Instance\022\'projects/{project}/"
- + "instances/{instance}b\006proto3"
+ + "tabasesRequest\0327.google.spanner.admin.da"
+ + "tabase.v1.ListDatabasesResponse\">\332A\006pare"
+ + "nt\202\323\344\223\002/\022-/v1/{parent=projects/*/instanc"
+ + "es/*}/databases\022\244\002\n\016CreateDatabase\0227.goo"
+ + "gle.spanner.admin.database.v1.CreateData"
+ + "baseRequest\032\035.google.longrunning.Operati"
+ + "on\"\271\001\312Ad\n)google.spanner.admin.database."
+ + "v1.Database\0227google.spanner.admin.databa"
+ + "se.v1.CreateDatabaseMetadata\332A\027parent,cr"
+ + "eate_statement\202\323\344\223\0022\"-/v1/{parent=projec"
+ + "ts/*/instances/*}/databases:\001*\022\255\001\n\013GetDa"
+ + "tabase\0224.google.spanner.admin.database.v"
+ + "1.GetDatabaseRequest\032*.google.spanner.ad"
+ + "min.database.v1.Database\"<\332A\004name\202\323\344\223\002/\022"
+ + "-/v1/{name=projects/*/instances/*/databa"
+ + "ses/*}\022\357\001\n\016UpdateDatabase\0227.google.spann"
+ + "er.admin.database.v1.UpdateDatabaseReque"
+ + "st\032\035.google.longrunning.Operation\"\204\001\312A\"\n"
+ + "\010Database\022\026UpdateDatabaseMetadata\332A\024data"
+ + "base,update_mask\202\323\344\223\002B26/v1/{database.na"
+ + "me=projects/*/instances/*/databases/*}:\010"
+ + "database\022\235\002\n\021UpdateDatabaseDdl\022:.google."
+ + "spanner.admin.database.v1.UpdateDatabase"
+ + "DdlRequest\032\035.google.longrunning.Operatio"
+ + "n\"\254\001\312AS\n\025google.protobuf.Empty\022:google.s"
+ + "panner.admin.database.v1.UpdateDatabaseD"
+ + "dlMetadata\332A\023database,statements\202\323\344\223\002:25"
+ + "/v1/{database=projects/*/instances/*/dat"
+ + "abases/*}/ddl:\001*\022\243\001\n\014DropDatabase\0225.goog"
+ + "le.spanner.admin.database.v1.DropDatabas"
+ + "eRequest\032\026.google.protobuf.Empty\"D\332A\010dat"
+ + "abase\202\323\344\223\0023*1/v1/{database=projects/*/in"
+ + "stances/*/databases/*}\022\315\001\n\016GetDatabaseDd"
+ + "l\0227.google.spanner.admin.database.v1.Get"
+ + "DatabaseDdlRequest\0328.google.spanner.admi"
+ + "n.database.v1.GetDatabaseDdlResponse\"H\332A"
+ + "\010database\202\323\344\223\0027\0225/v1/{database=projects/"
+ + "*/instances/*/databases/*}/ddl\022\302\002\n\014SetIa"
+ + "mPolicy\022\".google.iam.v1.SetIamPolicyRequ"
+ + "est\032\025.google.iam.v1.Policy\"\366\001\332A\017resource"
+ + ",policy\202\323\344\223\002\335\001\">/v1/{resource=projects/*"
+ + "/instances/*/databases/*}:setIamPolicy:\001"
+ + "*ZA\"/v1/{resource=projects/*/i"
+ + "nstances/*/databases/*}:getIamPolicy:\001*Z"
+ + "A\""
+ + ".google.spanner.admin.database.v1.ListBa"
+ + "ckupOperationsResponse\"E\332A\006parent\202\323\344\223\0026\022"
+ + "4/v1/{parent=projects/*/instances/*}/bac"
+ + "kupOperations\022\334\001\n\021ListDatabaseRoles\022:.go"
+ + "ogle.spanner.admin.database.v1.ListDatab"
+ + "aseRolesRequest\032;.google.spanner.admin.d"
+ + "atabase.v1.ListDatabaseRolesResponse\"N\332A"
+ + "\006parent\202\323\344\223\002?\022=/v1/{parent=projects/*/in"
+ + "stances/*/databases/*}/databaseRoles\022\350\001\n"
+ + "\016AddSplitPoints\0227.google.spanner.admin.d"
+ + "atabase.v1.AddSplitPointsRequest\0328.googl"
+ + "e.spanner.admin.database.v1.AddSplitPoin"
+ + "tsResponse\"c\332A\025database,split_points\202\323\344\223"
+ + "\002E\"@/v1/{database=projects/*/instances/*"
+ + "/databases/*}:addSplitPoints:\001*\022\216\002\n\024Crea"
+ + "teBackupSchedule\022=.google.spanner.admin."
+ + "database.v1.CreateBackupScheduleRequest\032"
+ + "0.google.spanner.admin.database.v1.Backu"
+ + "pSchedule\"\204\001\332A)parent,backup_schedule,ba"
+ + "ckup_schedule_id\202\323\344\223\002R\"?/v1/{parent=proj"
+ + "ects/*/instances/*/databases/*}/backupSc"
+ + "hedules:\017backup_schedule\022\321\001\n\021GetBackupSc"
+ + "hedule\022:.google.spanner.admin.database.v"
+ + "1.GetBackupScheduleRequest\0320.google.span"
+ + "ner.admin.database.v1.BackupSchedule\"N\332A"
+ + "\004name\202\323\344\223\002A\022?/v1/{name=projects/*/instan"
+ + "ces/*/databases/*/backupSchedules/*}\022\220\002\n"
+ + "\024UpdateBackupSchedule\022=.google.spanner.a"
+ + "dmin.database.v1.UpdateBackupScheduleReq"
+ + "uest\0320.google.spanner.admin.database.v1."
+ + "BackupSchedule\"\206\001\332A\033backup_schedule,upda"
+ + "te_mask\202\323\344\223\002b2O/v1/{backup_schedule.name"
+ + "=projects/*/instances/*/databases/*/back"
+ + "upSchedules/*}:\017backup_schedule\022\275\001\n\024Dele"
+ + "teBackupSchedule\022=.google.spanner.admin."
+ + "database.v1.DeleteBackupScheduleRequest\032"
+ + "\026.google.protobuf.Empty\"N\332A\004name\202\323\344\223\002A*?"
+ + "/v1/{name=projects/*/instances/*/databas"
+ + "es/*/backupSchedules/*}\022\344\001\n\023ListBackupSc"
+ + "hedules\022<.google.spanner.admin.database."
+ + "v1.ListBackupSchedulesRequest\032=.google.s"
+ + "panner.admin.database.v1.ListBackupSched"
+ + "ulesResponse\"P\332A\006parent\202\323\344\223\002A\022?/v1/{pare"
+ + "nt=projects/*/instances/*/databases/*}/b"
+ + "ackupSchedules\032x\312A\026spanner.googleapis.co"
+ + "m\322A\\https://www.googleapis.com/auth/clou"
+ + "d-platform,https://www.googleapis.com/au"
+ + "th/spanner.adminB\330\002\n$com.google.spanner."
+ + "admin.database.v1B\031SpannerDatabaseAdminP"
+ + "rotoP\001ZFcloud.google.com/go/spanner/admi"
+ + "n/database/apiv1/databasepb;databasepb\252\002"
+ + "&Google.Cloud.Spanner.Admin.Database.V1\312"
+ + "\002&Google\\Cloud\\Spanner\\Admin\\Database\\V1"
+ + "\352\002+Google::Cloud::Spanner::Admin::Databa"
+ + "se::V1\352AJ\n\037spanner.googleapis.com/Instan"
+ + "ce\022\'projects/{project}/instances/{instan"
+ + "ce}b\006proto3"
};
descriptor =
com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(
@@ -451,6 +485,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
com.google.longrunning.OperationsProto.getDescriptor(),
com.google.protobuf.EmptyProto.getDescriptor(),
com.google.protobuf.FieldMaskProto.getDescriptor(),
+ com.google.protobuf.StructProto.getDescriptor(),
com.google.protobuf.TimestampProto.getDescriptor(),
com.google.spanner.admin.database.v1.BackupProto.getDescriptor(),
com.google.spanner.admin.database.v1.BackupScheduleProto.getDescriptor(),
@@ -670,6 +705,38 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
new java.lang.String[] {
"DatabaseRoles", "NextPageToken",
});
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor =
+ getDescriptor().getMessageTypes().get(24);
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_fieldAccessorTable =
+ new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsRequest_descriptor,
+ new java.lang.String[] {
+ "Database", "SplitPoints", "Initiator",
+ });
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor =
+ getDescriptor().getMessageTypes().get(25);
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_fieldAccessorTable =
+ new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_google_spanner_admin_database_v1_AddSplitPointsResponse_descriptor,
+ new java.lang.String[] {});
+ internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor =
+ getDescriptor().getMessageTypes().get(26);
+ internal_static_google_spanner_admin_database_v1_SplitPoints_fieldAccessorTable =
+ new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor,
+ new java.lang.String[] {
+ "Table", "Index", "Keys", "ExpireTime",
+ });
+ internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor =
+ internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor
+ .getNestedTypes()
+ .get(0);
+ internal_static_google_spanner_admin_database_v1_SplitPoints_Key_fieldAccessorTable =
+ new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
+ internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor,
+ new java.lang.String[] {
+ "KeyParts",
+ });
com.google.protobuf.ExtensionRegistry registry =
com.google.protobuf.ExtensionRegistry.newInstance();
registry.add(com.google.api.ClientProto.defaultHost);
@@ -692,6 +759,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
com.google.longrunning.OperationsProto.getDescriptor();
com.google.protobuf.EmptyProto.getDescriptor();
com.google.protobuf.FieldMaskProto.getDescriptor();
+ com.google.protobuf.StructProto.getDescriptor();
com.google.protobuf.TimestampProto.getDescriptor();
com.google.spanner.admin.database.v1.BackupProto.getDescriptor();
com.google.spanner.admin.database.v1.BackupScheduleProto.getDescriptor();
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPoints.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPoints.java
new file mode 100644
index 00000000000..bd01be8bf1e
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPoints.java
@@ -0,0 +1,2437 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+/**
+ *
+ *
+ *
+ * The split points of a table/index.
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.SplitPoints}
+ */
+public final class SplitPoints extends com.google.protobuf.GeneratedMessageV3
+ implements
+ // @@protoc_insertion_point(message_implements:google.spanner.admin.database.v1.SplitPoints)
+ SplitPointsOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use SplitPoints.newBuilder() to construct.
+ private SplitPoints(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+
+ private SplitPoints() {
+ table_ = "";
+ index_ = "";
+ keys_ = java.util.Collections.emptyList();
+ }
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+ return new SplitPoints();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.SplitPoints.class,
+ com.google.spanner.admin.database.v1.SplitPoints.Builder.class);
+ }
+
+ public interface KeyOrBuilder
+ extends
+ // @@protoc_insertion_point(interface_extends:google.spanner.admin.database.v1.SplitPoints.Key)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return Whether the keyParts field is set.
+ */
+ boolean hasKeyParts();
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return The keyParts.
+ */
+ com.google.protobuf.ListValue getKeyParts();
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ com.google.protobuf.ListValueOrBuilder getKeyPartsOrBuilder();
+ }
+ /**
+ *
+ *
+ *
+ * A split key.
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.SplitPoints.Key}
+ */
+ public static final class Key extends com.google.protobuf.GeneratedMessageV3
+ implements
+ // @@protoc_insertion_point(message_implements:google.spanner.admin.database.v1.SplitPoints.Key)
+ KeyOrBuilder {
+ private static final long serialVersionUID = 0L;
+ // Use Key.newBuilder() to construct.
+ private Key(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
+ super(builder);
+ }
+
+ private Key() {}
+
+ @java.lang.Override
+ @SuppressWarnings({"unused"})
+ protected java.lang.Object newInstance(UnusedPrivateParameter unused) {
+ return new Key();
+ }
+
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_Key_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.SplitPoints.Key.class,
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder.class);
+ }
+
+ private int bitField0_;
+ public static final int KEY_PARTS_FIELD_NUMBER = 1;
+ private com.google.protobuf.ListValue keyParts_;
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return Whether the keyParts field is set.
+ */
+ @java.lang.Override
+ public boolean hasKeyParts() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return The keyParts.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ListValue getKeyParts() {
+ return keyParts_ == null ? com.google.protobuf.ListValue.getDefaultInstance() : keyParts_;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public com.google.protobuf.ListValueOrBuilder getKeyPartsOrBuilder() {
+ return keyParts_ == null ? com.google.protobuf.ListValue.getDefaultInstance() : keyParts_;
+ }
+
+ private byte memoizedIsInitialized = -1;
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+ if (((bitField0_ & 0x00000001) != 0)) {
+ output.writeMessage(1, getKeyParts());
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.CodedOutputStream.computeMessageSize(1, getKeyParts());
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.google.spanner.admin.database.v1.SplitPoints.Key)) {
+ return super.equals(obj);
+ }
+ com.google.spanner.admin.database.v1.SplitPoints.Key other =
+ (com.google.spanner.admin.database.v1.SplitPoints.Key) obj;
+
+ if (hasKeyParts() != other.hasKeyParts()) return false;
+ if (hasKeyParts()) {
+ if (!getKeyParts().equals(other.getKeyParts())) return false;
+ }
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ if (hasKeyParts()) {
+ hash = (37 * hash) + KEY_PARTS_FIELD_NUMBER;
+ hash = (53 * hash) + getKeyParts().hashCode();
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseDelimitedFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseDelimitedFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+
+ public static Builder newBuilder(
+ com.google.spanner.admin.database.v1.SplitPoints.Key prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ *
+ *
+ *
+ * A split key.
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.SplitPoints.Key}
+ */
+ public static final class Builder
+ extends com.google.protobuf.GeneratedMessageV3.Builder
+ implements
+ // @@protoc_insertion_point(builder_implements:google.spanner.admin.database.v1.SplitPoints.Key)
+ com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_Key_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.SplitPoints.Key.class,
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder.class);
+ }
+
+ // Construct using com.google.spanner.admin.database.v1.SplitPoints.Key.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
+ getKeyPartsFieldBuilder();
+ }
+ }
+
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ keyParts_ = null;
+ if (keyPartsBuilder_ != null) {
+ keyPartsBuilder_.dispose();
+ keyPartsBuilder_ = null;
+ }
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_Key_descriptor;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.Key getDefaultInstanceForType() {
+ return com.google.spanner.admin.database.v1.SplitPoints.Key.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.Key build() {
+ com.google.spanner.admin.database.v1.SplitPoints.Key result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.Key buildPartial() {
+ com.google.spanner.admin.database.v1.SplitPoints.Key result =
+ new com.google.spanner.admin.database.v1.SplitPoints.Key(this);
+ if (bitField0_ != 0) {
+ buildPartial0(result);
+ }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartial0(com.google.spanner.admin.database.v1.SplitPoints.Key result) {
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.keyParts_ = keyPartsBuilder_ == null ? keyParts_ : keyPartsBuilder_.build();
+ to_bitField0_ |= 0x00000001;
+ }
+ result.bitField0_ |= to_bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.setField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+
+ @java.lang.Override
+ public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field,
+ int index,
+ java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.google.spanner.admin.database.v1.SplitPoints.Key) {
+ return mergeFrom((com.google.spanner.admin.database.v1.SplitPoints.Key) other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.google.spanner.admin.database.v1.SplitPoints.Key other) {
+ if (other == com.google.spanner.admin.database.v1.SplitPoints.Key.getDefaultInstance())
+ return this;
+ if (other.hasKeyParts()) {
+ mergeKeyParts(other.getKeyParts());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10:
+ {
+ input.readMessage(getKeyPartsFieldBuilder().getBuilder(), extensionRegistry);
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 10
+ default:
+ {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+
+ private int bitField0_;
+
+ private com.google.protobuf.ListValue keyParts_;
+ private com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.ListValue,
+ com.google.protobuf.ListValue.Builder,
+ com.google.protobuf.ListValueOrBuilder>
+ keyPartsBuilder_;
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return Whether the keyParts field is set.
+ */
+ public boolean hasKeyParts() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ *
+ * @return The keyParts.
+ */
+ public com.google.protobuf.ListValue getKeyParts() {
+ if (keyPartsBuilder_ == null) {
+ return keyParts_ == null ? com.google.protobuf.ListValue.getDefaultInstance() : keyParts_;
+ } else {
+ return keyPartsBuilder_.getMessage();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setKeyParts(com.google.protobuf.ListValue value) {
+ if (keyPartsBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ keyParts_ = value;
+ } else {
+ keyPartsBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setKeyParts(com.google.protobuf.ListValue.Builder builderForValue) {
+ if (keyPartsBuilder_ == null) {
+ keyParts_ = builderForValue.build();
+ } else {
+ keyPartsBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder mergeKeyParts(com.google.protobuf.ListValue value) {
+ if (keyPartsBuilder_ == null) {
+ if (((bitField0_ & 0x00000001) != 0)
+ && keyParts_ != null
+ && keyParts_ != com.google.protobuf.ListValue.getDefaultInstance()) {
+ getKeyPartsBuilder().mergeFrom(value);
+ } else {
+ keyParts_ = value;
+ }
+ } else {
+ keyPartsBuilder_.mergeFrom(value);
+ }
+ if (keyParts_ != null) {
+ bitField0_ |= 0x00000001;
+ onChanged();
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder clearKeyParts() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ keyParts_ = null;
+ if (keyPartsBuilder_ != null) {
+ keyPartsBuilder_.dispose();
+ keyPartsBuilder_ = null;
+ }
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.protobuf.ListValue.Builder getKeyPartsBuilder() {
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return getKeyPartsFieldBuilder().getBuilder();
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.protobuf.ListValueOrBuilder getKeyPartsOrBuilder() {
+ if (keyPartsBuilder_ != null) {
+ return keyPartsBuilder_.getMessageOrBuilder();
+ } else {
+ return keyParts_ == null ? com.google.protobuf.ListValue.getDefaultInstance() : keyParts_;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The column values making up the split key.
+ *
+ *
+ * .google.protobuf.ListValue key_parts = 1 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ private com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.ListValue,
+ com.google.protobuf.ListValue.Builder,
+ com.google.protobuf.ListValueOrBuilder>
+ getKeyPartsFieldBuilder() {
+ if (keyPartsBuilder_ == null) {
+ keyPartsBuilder_ =
+ new com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.ListValue,
+ com.google.protobuf.ListValue.Builder,
+ com.google.protobuf.ListValueOrBuilder>(
+ getKeyParts(), getParentForChildren(), isClean());
+ keyParts_ = null;
+ }
+ return keyPartsBuilder_;
+ }
+
+ @java.lang.Override
+ public final Builder setUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+ // @@protoc_insertion_point(builder_scope:google.spanner.admin.database.v1.SplitPoints.Key)
+ }
+
+ // @@protoc_insertion_point(class_scope:google.spanner.admin.database.v1.SplitPoints.Key)
+ private static final com.google.spanner.admin.database.v1.SplitPoints.Key DEFAULT_INSTANCE;
+
+ static {
+ DEFAULT_INSTANCE = new com.google.spanner.admin.database.v1.SplitPoints.Key();
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints.Key getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public Key parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException()
+ .setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.Key getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+ }
+
+ private int bitField0_;
+ public static final int TABLE_FIELD_NUMBER = 1;
+
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object table_ = "";
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The table.
+ */
+ @java.lang.Override
+ public java.lang.String getTable() {
+ java.lang.Object ref = table_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ table_ = s;
+ return s;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The bytes for table.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString getTableBytes() {
+ java.lang.Object ref = table_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ table_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int INDEX_FIELD_NUMBER = 2;
+
+ @SuppressWarnings("serial")
+ private volatile java.lang.Object index_ = "";
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The index.
+ */
+ @java.lang.Override
+ public java.lang.String getIndex() {
+ java.lang.Object ref = index_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ index_ = s;
+ return s;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The bytes for index.
+ */
+ @java.lang.Override
+ public com.google.protobuf.ByteString getIndexBytes() {
+ java.lang.Object ref = index_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ index_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ public static final int KEYS_FIELD_NUMBER = 3;
+
+ @SuppressWarnings("serial")
+ private java.util.List keys_;
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public java.util.List getKeysList() {
+ return keys_;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public java.util.List extends com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>
+ getKeysOrBuilderList() {
+ return keys_;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public int getKeysCount() {
+ return keys_.size();
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.Key getKeys(int index) {
+ return keys_.get(index);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder getKeysOrBuilder(int index) {
+ return keys_.get(index);
+ }
+
+ public static final int EXPIRE_TIME_FIELD_NUMBER = 5;
+ private com.google.protobuf.Timestamp expireTime_;
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return Whether the expireTime field is set.
+ */
+ @java.lang.Override
+ public boolean hasExpireTime() {
+ return ((bitField0_ & 0x00000001) != 0);
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return The expireTime.
+ */
+ @java.lang.Override
+ public com.google.protobuf.Timestamp getExpireTime() {
+ return expireTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : expireTime_;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ @java.lang.Override
+ public com.google.protobuf.TimestampOrBuilder getExpireTimeOrBuilder() {
+ return expireTime_ == null ? com.google.protobuf.Timestamp.getDefaultInstance() : expireTime_;
+ }
+
+ private byte memoizedIsInitialized = -1;
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized == 1) return true;
+ if (isInitialized == 0) return false;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ @java.lang.Override
+ public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(table_)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 1, table_);
+ }
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(index_)) {
+ com.google.protobuf.GeneratedMessageV3.writeString(output, 2, index_);
+ }
+ for (int i = 0; i < keys_.size(); i++) {
+ output.writeMessage(3, keys_.get(i));
+ }
+ if (((bitField0_ & 0x00000001) != 0)) {
+ output.writeMessage(5, getExpireTime());
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ @java.lang.Override
+ public int getSerializedSize() {
+ int size = memoizedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(table_)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, table_);
+ }
+ if (!com.google.protobuf.GeneratedMessageV3.isStringEmpty(index_)) {
+ size += com.google.protobuf.GeneratedMessageV3.computeStringSize(2, index_);
+ }
+ for (int i = 0; i < keys_.size(); i++) {
+ size += com.google.protobuf.CodedOutputStream.computeMessageSize(3, keys_.get(i));
+ }
+ if (((bitField0_ & 0x00000001) != 0)) {
+ size += com.google.protobuf.CodedOutputStream.computeMessageSize(5, getExpireTime());
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSize = size;
+ return size;
+ }
+
+ @java.lang.Override
+ public boolean equals(final java.lang.Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof com.google.spanner.admin.database.v1.SplitPoints)) {
+ return super.equals(obj);
+ }
+ com.google.spanner.admin.database.v1.SplitPoints other =
+ (com.google.spanner.admin.database.v1.SplitPoints) obj;
+
+ if (!getTable().equals(other.getTable())) return false;
+ if (!getIndex().equals(other.getIndex())) return false;
+ if (!getKeysList().equals(other.getKeysList())) return false;
+ if (hasExpireTime() != other.hasExpireTime()) return false;
+ if (hasExpireTime()) {
+ if (!getExpireTime().equals(other.getExpireTime())) return false;
+ }
+ if (!getUnknownFields().equals(other.getUnknownFields())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ if (memoizedHashCode != 0) {
+ return memoizedHashCode;
+ }
+ int hash = 41;
+ hash = (19 * hash) + getDescriptor().hashCode();
+ hash = (37 * hash) + TABLE_FIELD_NUMBER;
+ hash = (53 * hash) + getTable().hashCode();
+ hash = (37 * hash) + INDEX_FIELD_NUMBER;
+ hash = (53 * hash) + getIndex().hashCode();
+ if (getKeysCount() > 0) {
+ hash = (37 * hash) + KEYS_FIELD_NUMBER;
+ hash = (53 * hash) + getKeysList().hashCode();
+ }
+ if (hasExpireTime()) {
+ hash = (37 * hash) + EXPIRE_TIME_FIELD_NUMBER;
+ hash = (53 * hash) + getExpireTime().hashCode();
+ }
+ hash = (29 * hash) + getUnknownFields().hashCode();
+ memoizedHashCode = hash;
+ return hash;
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(java.nio.ByteBuffer data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseDelimitedFrom(
+ java.io.InputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseDelimitedFrom(
+ java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseDelimitedWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ com.google.protobuf.CodedInputStream input) throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(PARSER, input);
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return com.google.protobuf.GeneratedMessageV3.parseWithIOException(
+ PARSER, input, extensionRegistry);
+ }
+
+ @java.lang.Override
+ public Builder newBuilderForType() {
+ return newBuilder();
+ }
+
+ public static Builder newBuilder() {
+ return DEFAULT_INSTANCE.toBuilder();
+ }
+
+ public static Builder newBuilder(com.google.spanner.admin.database.v1.SplitPoints prototype) {
+ return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+ }
+
+ @java.lang.Override
+ public Builder toBuilder() {
+ return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
+ }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ *
+ *
+ *
+ * The split points of a table/index.
+ *
+ *
+ * Protobuf type {@code google.spanner.admin.database.v1.SplitPoints}
+ */
+ public static final class Builder extends com.google.protobuf.GeneratedMessageV3.Builder
+ implements
+ // @@protoc_insertion_point(builder_implements:google.spanner.admin.database.v1.SplitPoints)
+ com.google.spanner.admin.database.v1.SplitPointsOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor;
+ }
+
+ @java.lang.Override
+ protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ com.google.spanner.admin.database.v1.SplitPoints.class,
+ com.google.spanner.admin.database.v1.SplitPoints.Builder.class);
+ }
+
+ // Construct using com.google.spanner.admin.database.v1.SplitPoints.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) {
+ getKeysFieldBuilder();
+ getExpireTimeFieldBuilder();
+ }
+ }
+
+ @java.lang.Override
+ public Builder clear() {
+ super.clear();
+ bitField0_ = 0;
+ table_ = "";
+ index_ = "";
+ if (keysBuilder_ == null) {
+ keys_ = java.util.Collections.emptyList();
+ } else {
+ keys_ = null;
+ keysBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ expireTime_ = null;
+ if (expireTimeBuilder_ != null) {
+ expireTimeBuilder_.dispose();
+ expireTimeBuilder_ = null;
+ }
+ return this;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
+ return com.google.spanner.admin.database.v1.SpannerDatabaseAdminProto
+ .internal_static_google_spanner_admin_database_v1_SplitPoints_descriptor;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints getDefaultInstanceForType() {
+ return com.google.spanner.admin.database.v1.SplitPoints.getDefaultInstance();
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints build() {
+ com.google.spanner.admin.database.v1.SplitPoints result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints buildPartial() {
+ com.google.spanner.admin.database.v1.SplitPoints result =
+ new com.google.spanner.admin.database.v1.SplitPoints(this);
+ buildPartialRepeatedFields(result);
+ if (bitField0_ != 0) {
+ buildPartial0(result);
+ }
+ onBuilt();
+ return result;
+ }
+
+ private void buildPartialRepeatedFields(
+ com.google.spanner.admin.database.v1.SplitPoints result) {
+ if (keysBuilder_ == null) {
+ if (((bitField0_ & 0x00000004) != 0)) {
+ keys_ = java.util.Collections.unmodifiableList(keys_);
+ bitField0_ = (bitField0_ & ~0x00000004);
+ }
+ result.keys_ = keys_;
+ } else {
+ result.keys_ = keysBuilder_.build();
+ }
+ }
+
+ private void buildPartial0(com.google.spanner.admin.database.v1.SplitPoints result) {
+ int from_bitField0_ = bitField0_;
+ if (((from_bitField0_ & 0x00000001) != 0)) {
+ result.table_ = table_;
+ }
+ if (((from_bitField0_ & 0x00000002) != 0)) {
+ result.index_ = index_;
+ }
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000008) != 0)) {
+ result.expireTime_ = expireTimeBuilder_ == null ? expireTime_ : expireTimeBuilder_.build();
+ to_bitField0_ |= 0x00000001;
+ }
+ result.bitField0_ |= to_bitField0_;
+ }
+
+ @java.lang.Override
+ public Builder clone() {
+ return super.clone();
+ }
+
+ @java.lang.Override
+ public Builder setField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.setField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder clearField(com.google.protobuf.Descriptors.FieldDescriptor field) {
+ return super.clearField(field);
+ }
+
+ @java.lang.Override
+ public Builder clearOneof(com.google.protobuf.Descriptors.OneofDescriptor oneof) {
+ return super.clearOneof(oneof);
+ }
+
+ @java.lang.Override
+ public Builder setRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, int index, java.lang.Object value) {
+ return super.setRepeatedField(field, index, value);
+ }
+
+ @java.lang.Override
+ public Builder addRepeatedField(
+ com.google.protobuf.Descriptors.FieldDescriptor field, java.lang.Object value) {
+ return super.addRepeatedField(field, value);
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof com.google.spanner.admin.database.v1.SplitPoints) {
+ return mergeFrom((com.google.spanner.admin.database.v1.SplitPoints) other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(com.google.spanner.admin.database.v1.SplitPoints other) {
+ if (other == com.google.spanner.admin.database.v1.SplitPoints.getDefaultInstance())
+ return this;
+ if (!other.getTable().isEmpty()) {
+ table_ = other.table_;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ }
+ if (!other.getIndex().isEmpty()) {
+ index_ = other.index_;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ }
+ if (keysBuilder_ == null) {
+ if (!other.keys_.isEmpty()) {
+ if (keys_.isEmpty()) {
+ keys_ = other.keys_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ } else {
+ ensureKeysIsMutable();
+ keys_.addAll(other.keys_);
+ }
+ onChanged();
+ }
+ } else {
+ if (!other.keys_.isEmpty()) {
+ if (keysBuilder_.isEmpty()) {
+ keysBuilder_.dispose();
+ keysBuilder_ = null;
+ keys_ = other.keys_;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ keysBuilder_ =
+ com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders
+ ? getKeysFieldBuilder()
+ : null;
+ } else {
+ keysBuilder_.addAllMessages(other.keys_);
+ }
+ }
+ }
+ if (other.hasExpireTime()) {
+ mergeExpireTime(other.getExpireTime());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ onChanged();
+ return this;
+ }
+
+ @java.lang.Override
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ @java.lang.Override
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ if (extensionRegistry == null) {
+ throw new java.lang.NullPointerException();
+ }
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ case 10:
+ {
+ table_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000001;
+ break;
+ } // case 10
+ case 18:
+ {
+ index_ = input.readStringRequireUtf8();
+ bitField0_ |= 0x00000002;
+ break;
+ } // case 18
+ case 26:
+ {
+ com.google.spanner.admin.database.v1.SplitPoints.Key m =
+ input.readMessage(
+ com.google.spanner.admin.database.v1.SplitPoints.Key.parser(),
+ extensionRegistry);
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ keys_.add(m);
+ } else {
+ keysBuilder_.addMessage(m);
+ }
+ break;
+ } // case 26
+ case 42:
+ {
+ input.readMessage(getExpireTimeFieldBuilder().getBuilder(), extensionRegistry);
+ bitField0_ |= 0x00000008;
+ break;
+ } // case 42
+ default:
+ {
+ if (!super.parseUnknownField(input, extensionRegistry, tag)) {
+ done = true; // was an endgroup tag
+ }
+ break;
+ } // default:
+ } // switch (tag)
+ } // while (!done)
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.unwrapIOException();
+ } finally {
+ onChanged();
+ } // finally
+ return this;
+ }
+
+ private int bitField0_;
+
+ private java.lang.Object table_ = "";
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The table.
+ */
+ public java.lang.String getTable() {
+ java.lang.Object ref = table_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ table_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The bytes for table.
+ */
+ public com.google.protobuf.ByteString getTableBytes() {
+ java.lang.Object ref = table_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ table_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @param value The table to set.
+ * @return This builder for chaining.
+ */
+ public Builder setTable(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ table_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return This builder for chaining.
+ */
+ public Builder clearTable() {
+ table_ = getDefaultInstance().getTable();
+ bitField0_ = (bitField0_ & ~0x00000001);
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @param value The bytes for table to set.
+ * @return This builder for chaining.
+ */
+ public Builder setTableBytes(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ checkByteStringIsUtf8(value);
+ table_ = value;
+ bitField0_ |= 0x00000001;
+ onChanged();
+ return this;
+ }
+
+ private java.lang.Object index_ = "";
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The index.
+ */
+ public java.lang.String getIndex() {
+ java.lang.Object ref = index_;
+ if (!(ref instanceof java.lang.String)) {
+ com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ index_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The bytes for index.
+ */
+ public com.google.protobuf.ByteString getIndexBytes() {
+ java.lang.Object ref = index_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
+ index_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @param value The index to set.
+ * @return This builder for chaining.
+ */
+ public Builder setIndex(java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ index_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return This builder for chaining.
+ */
+ public Builder clearIndex() {
+ index_ = getDefaultInstance().getIndex();
+ bitField0_ = (bitField0_ & ~0x00000002);
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @param value The bytes for index to set.
+ * @return This builder for chaining.
+ */
+ public Builder setIndexBytes(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ checkByteStringIsUtf8(value);
+ index_ = value;
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return this;
+ }
+
+ private java.util.List keys_ =
+ java.util.Collections.emptyList();
+
+ private void ensureKeysIsMutable() {
+ if (!((bitField0_ & 0x00000004) != 0)) {
+ keys_ =
+ new java.util.ArrayList(keys_);
+ bitField0_ |= 0x00000004;
+ }
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints.Key,
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder,
+ com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>
+ keysBuilder_;
+
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List getKeysList() {
+ if (keysBuilder_ == null) {
+ return java.util.Collections.unmodifiableList(keys_);
+ } else {
+ return keysBuilder_.getMessageList();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public int getKeysCount() {
+ if (keysBuilder_ == null) {
+ return keys_.size();
+ } else {
+ return keysBuilder_.getCount();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Key getKeys(int index) {
+ if (keysBuilder_ == null) {
+ return keys_.get(index);
+ } else {
+ return keysBuilder_.getMessage(index);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setKeys(int index, com.google.spanner.admin.database.v1.SplitPoints.Key value) {
+ if (keysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureKeysIsMutable();
+ keys_.set(index, value);
+ onChanged();
+ } else {
+ keysBuilder_.setMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder setKeys(
+ int index, com.google.spanner.admin.database.v1.SplitPoints.Key.Builder builderForValue) {
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ keys_.set(index, builderForValue.build());
+ onChanged();
+ } else {
+ keysBuilder_.setMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addKeys(com.google.spanner.admin.database.v1.SplitPoints.Key value) {
+ if (keysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureKeysIsMutable();
+ keys_.add(value);
+ onChanged();
+ } else {
+ keysBuilder_.addMessage(value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addKeys(int index, com.google.spanner.admin.database.v1.SplitPoints.Key value) {
+ if (keysBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureKeysIsMutable();
+ keys_.add(index, value);
+ onChanged();
+ } else {
+ keysBuilder_.addMessage(index, value);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addKeys(
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder builderForValue) {
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ keys_.add(builderForValue.build());
+ onChanged();
+ } else {
+ keysBuilder_.addMessage(builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addKeys(
+ int index, com.google.spanner.admin.database.v1.SplitPoints.Key.Builder builderForValue) {
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ keys_.add(index, builderForValue.build());
+ onChanged();
+ } else {
+ keysBuilder_.addMessage(index, builderForValue.build());
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder addAllKeys(
+ java.lang.Iterable extends com.google.spanner.admin.database.v1.SplitPoints.Key> values) {
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(values, keys_);
+ onChanged();
+ } else {
+ keysBuilder_.addAllMessages(values);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder clearKeys() {
+ if (keysBuilder_ == null) {
+ keys_ = java.util.Collections.emptyList();
+ bitField0_ = (bitField0_ & ~0x00000004);
+ onChanged();
+ } else {
+ keysBuilder_.clear();
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public Builder removeKeys(int index) {
+ if (keysBuilder_ == null) {
+ ensureKeysIsMutable();
+ keys_.remove(index);
+ onChanged();
+ } else {
+ keysBuilder_.remove(index);
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Key.Builder getKeysBuilder(int index) {
+ return getKeysFieldBuilder().getBuilder(index);
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder getKeysOrBuilder(
+ int index) {
+ if (keysBuilder_ == null) {
+ return keys_.get(index);
+ } else {
+ return keysBuilder_.getMessageOrBuilder(index);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List extends com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>
+ getKeysOrBuilderList() {
+ if (keysBuilder_ != null) {
+ return keysBuilder_.getMessageOrBuilderList();
+ } else {
+ return java.util.Collections.unmodifiableList(keys_);
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Key.Builder addKeysBuilder() {
+ return getKeysFieldBuilder()
+ .addBuilder(com.google.spanner.admin.database.v1.SplitPoints.Key.getDefaultInstance());
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public com.google.spanner.admin.database.v1.SplitPoints.Key.Builder addKeysBuilder(int index) {
+ return getKeysFieldBuilder()
+ .addBuilder(
+ index, com.google.spanner.admin.database.v1.SplitPoints.Key.getDefaultInstance());
+ }
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ public java.util.List
+ getKeysBuilderList() {
+ return getKeysFieldBuilder().getBuilderList();
+ }
+
+ private com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints.Key,
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder,
+ com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>
+ getKeysFieldBuilder() {
+ if (keysBuilder_ == null) {
+ keysBuilder_ =
+ new com.google.protobuf.RepeatedFieldBuilderV3<
+ com.google.spanner.admin.database.v1.SplitPoints.Key,
+ com.google.spanner.admin.database.v1.SplitPoints.Key.Builder,
+ com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>(
+ keys_, ((bitField0_ & 0x00000004) != 0), getParentForChildren(), isClean());
+ keys_ = null;
+ }
+ return keysBuilder_;
+ }
+
+ private com.google.protobuf.Timestamp expireTime_;
+ private com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.Timestamp,
+ com.google.protobuf.Timestamp.Builder,
+ com.google.protobuf.TimestampOrBuilder>
+ expireTimeBuilder_;
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return Whether the expireTime field is set.
+ */
+ public boolean hasExpireTime() {
+ return ((bitField0_ & 0x00000008) != 0);
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return The expireTime.
+ */
+ public com.google.protobuf.Timestamp getExpireTime() {
+ if (expireTimeBuilder_ == null) {
+ return expireTime_ == null
+ ? com.google.protobuf.Timestamp.getDefaultInstance()
+ : expireTime_;
+ } else {
+ return expireTimeBuilder_.getMessage();
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public Builder setExpireTime(com.google.protobuf.Timestamp value) {
+ if (expireTimeBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ expireTime_ = value;
+ } else {
+ expireTimeBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000008;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public Builder setExpireTime(com.google.protobuf.Timestamp.Builder builderForValue) {
+ if (expireTimeBuilder_ == null) {
+ expireTime_ = builderForValue.build();
+ } else {
+ expireTimeBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000008;
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public Builder mergeExpireTime(com.google.protobuf.Timestamp value) {
+ if (expireTimeBuilder_ == null) {
+ if (((bitField0_ & 0x00000008) != 0)
+ && expireTime_ != null
+ && expireTime_ != com.google.protobuf.Timestamp.getDefaultInstance()) {
+ getExpireTimeBuilder().mergeFrom(value);
+ } else {
+ expireTime_ = value;
+ }
+ } else {
+ expireTimeBuilder_.mergeFrom(value);
+ }
+ if (expireTime_ != null) {
+ bitField0_ |= 0x00000008;
+ onChanged();
+ }
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public Builder clearExpireTime() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ expireTime_ = null;
+ if (expireTimeBuilder_ != null) {
+ expireTimeBuilder_.dispose();
+ expireTimeBuilder_ = null;
+ }
+ onChanged();
+ return this;
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public com.google.protobuf.Timestamp.Builder getExpireTimeBuilder() {
+ bitField0_ |= 0x00000008;
+ onChanged();
+ return getExpireTimeFieldBuilder().getBuilder();
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ public com.google.protobuf.TimestampOrBuilder getExpireTimeOrBuilder() {
+ if (expireTimeBuilder_ != null) {
+ return expireTimeBuilder_.getMessageOrBuilder();
+ } else {
+ return expireTime_ == null
+ ? com.google.protobuf.Timestamp.getDefaultInstance()
+ : expireTime_;
+ }
+ }
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ private com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.Timestamp,
+ com.google.protobuf.Timestamp.Builder,
+ com.google.protobuf.TimestampOrBuilder>
+ getExpireTimeFieldBuilder() {
+ if (expireTimeBuilder_ == null) {
+ expireTimeBuilder_ =
+ new com.google.protobuf.SingleFieldBuilderV3<
+ com.google.protobuf.Timestamp,
+ com.google.protobuf.Timestamp.Builder,
+ com.google.protobuf.TimestampOrBuilder>(
+ getExpireTime(), getParentForChildren(), isClean());
+ expireTime_ = null;
+ }
+ return expireTimeBuilder_;
+ }
+
+ @java.lang.Override
+ public final Builder setUnknownFields(final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.setUnknownFields(unknownFields);
+ }
+
+ @java.lang.Override
+ public final Builder mergeUnknownFields(
+ final com.google.protobuf.UnknownFieldSet unknownFields) {
+ return super.mergeUnknownFields(unknownFields);
+ }
+
+ // @@protoc_insertion_point(builder_scope:google.spanner.admin.database.v1.SplitPoints)
+ }
+
+ // @@protoc_insertion_point(class_scope:google.spanner.admin.database.v1.SplitPoints)
+ private static final com.google.spanner.admin.database.v1.SplitPoints DEFAULT_INSTANCE;
+
+ static {
+ DEFAULT_INSTANCE = new com.google.spanner.admin.database.v1.SplitPoints();
+ }
+
+ public static com.google.spanner.admin.database.v1.SplitPoints getDefaultInstance() {
+ return DEFAULT_INSTANCE;
+ }
+
+ private static final com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ @java.lang.Override
+ public SplitPoints parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ Builder builder = newBuilder();
+ try {
+ builder.mergeFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(builder.buildPartial());
+ } catch (com.google.protobuf.UninitializedMessageException e) {
+ throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(e)
+ .setUnfinishedMessage(builder.buildPartial());
+ }
+ return builder.buildPartial();
+ }
+ };
+
+ public static com.google.protobuf.Parser parser() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ @java.lang.Override
+ public com.google.spanner.admin.database.v1.SplitPoints getDefaultInstanceForType() {
+ return DEFAULT_INSTANCE;
+ }
+}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPointsOrBuilder.java b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPointsOrBuilder.java
new file mode 100644
index 00000000000..5da2a9c837c
--- /dev/null
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/java/com/google/spanner/admin/database/v1/SplitPointsOrBuilder.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2025 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/spanner/admin/database/v1/spanner_database_admin.proto
+
+// Protobuf Java Version: 3.25.5
+package com.google.spanner.admin.database.v1;
+
+public interface SplitPointsOrBuilder
+ extends
+ // @@protoc_insertion_point(interface_extends:google.spanner.admin.database.v1.SplitPoints)
+ com.google.protobuf.MessageOrBuilder {
+
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The table.
+ */
+ java.lang.String getTable();
+ /**
+ *
+ *
+ *
+ * The table to split.
+ *
+ *
+ * string table = 1;
+ *
+ * @return The bytes for table.
+ */
+ com.google.protobuf.ByteString getTableBytes();
+
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The index.
+ */
+ java.lang.String getIndex();
+ /**
+ *
+ *
+ *
+ * The index to split.
+ * If specified, the `table` field must refer to the index's base table.
+ *
+ *
+ * string index = 2;
+ *
+ * @return The bytes for index.
+ */
+ com.google.protobuf.ByteString getIndexBytes();
+
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ java.util.List getKeysList();
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ com.google.spanner.admin.database.v1.SplitPoints.Key getKeys(int index);
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ int getKeysCount();
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ java.util.List extends com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder>
+ getKeysOrBuilderList();
+ /**
+ *
+ *
+ *
+ * Required. The list of split keys, i.e., the split boundaries.
+ *
+ *
+ *
+ * repeated .google.spanner.admin.database.v1.SplitPoints.Key keys = 3 [(.google.api.field_behavior) = REQUIRED];
+ *
+ */
+ com.google.spanner.admin.database.v1.SplitPoints.KeyOrBuilder getKeysOrBuilder(int index);
+
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return Whether the expireTime field is set.
+ */
+ boolean hasExpireTime();
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ *
+ * @return The expireTime.
+ */
+ com.google.protobuf.Timestamp getExpireTime();
+ /**
+ *
+ *
+ *
+ * Optional. The expiration timestamp of the split points.
+ * A timestamp in the past means immediate expiration.
+ * The maximum value can be 30 days in the future.
+ * Defaults to 10 days in the future if not specified.
+ *
+ *
+ * .google.protobuf.Timestamp expire_time = 5 [(.google.api.field_behavior) = OPTIONAL];
+ *
+ */
+ com.google.protobuf.TimestampOrBuilder getExpireTimeOrBuilder();
+}
diff --git a/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto b/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto
index 5df142403e6..27e3206293e 100644
--- a/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto
+++ b/proto-google-cloud-spanner-admin-database-v1/src/main/proto/google/spanner/admin/database/v1/spanner_database_admin.proto
@@ -25,6 +25,7 @@ import "google/iam/v1/policy.proto";
import "google/longrunning/operations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/spanner/admin/database/v1/backup.proto";
import "google/spanner/admin/database/v1/backup_schedule.proto";
@@ -425,6 +426,15 @@ service DatabaseAdmin {
option (google.api.method_signature) = "parent";
}
+ // Adds split points to specified tables, indexes of a database.
+ rpc AddSplitPoints(AddSplitPointsRequest) returns (AddSplitPointsResponse) {
+ option (google.api.http) = {
+ post: "/v1/{database=projects/*/instances/*/databases/*}:addSplitPoints"
+ body: "*"
+ };
+ option (google.api.method_signature) = "database,split_points";
+ }
+
// Creates a new backup schedule.
rpc CreateBackupSchedule(CreateBackupScheduleRequest)
returns (BackupSchedule) {
@@ -1207,3 +1217,59 @@ message ListDatabaseRolesResponse {
// call to fetch more of the matching roles.
string next_page_token = 2;
}
+
+// The request for
+// [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+message AddSplitPointsRequest {
+ // Required. The database on whose tables/indexes split points are to be
+ // added. Values are of the form
+ // `projects//instances//databases/`.
+ string database = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Required. The split points to add.
+ repeated SplitPoints split_points = 2
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. A user-supplied tag associated with the split points.
+ // For example, "intital_data_load", "special_event_1".
+ // Defaults to "CloudAddSplitPointsAPI" if not specified.
+ // The length of the tag must not exceed 50 characters,else will be trimmed.
+ // Only valid UTF8 characters are allowed.
+ string initiator = 3 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The response for
+// [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+message AddSplitPointsResponse {}
+
+// The split points of a table/index.
+message SplitPoints {
+ // A split key.
+ message Key {
+ // Required. The column values making up the split key.
+ google.protobuf.ListValue key_parts = 1
+ [(google.api.field_behavior) = REQUIRED];
+ }
+
+ // The table to split.
+ string table = 1;
+
+ // The index to split.
+ // If specified, the `table` field must refer to the index's base table.
+ string index = 2;
+
+ // Required. The list of split keys, i.e., the split boundaries.
+ repeated Key keys = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The expiration timestamp of the split points.
+ // A timestamp in the past means immediate expiration.
+ // The maximum value can be 30 days in the future.
+ // Defaults to 10 days in the future if not specified.
+ google.protobuf.Timestamp expire_time = 5
+ [(google.api.field_behavior) = OPTIONAL];
+}
diff --git a/proto-google-cloud-spanner-admin-instance-v1/pom.xml b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
index cc71996744e..1c8d7b9c0a9 100644
--- a/proto-google-cloud-spanner-admin-instance-v1/pom.xml
+++ b/proto-google-cloud-spanner-admin-instance-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-admin-instance-v1
- 6.86.0
+ 6.87.0
proto-google-cloud-spanner-admin-instance-v1
PROTO library for proto-google-cloud-spanner-admin-instance-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/proto-google-cloud-spanner-executor-v1/pom.xml b/proto-google-cloud-spanner-executor-v1/pom.xml
index 7ad2f03742b..31dd6136825 100644
--- a/proto-google-cloud-spanner-executor-v1/pom.xml
+++ b/proto-google-cloud-spanner-executor-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-executor-v1
- 6.86.0
+ 6.87.0
proto-google-cloud-spanner-executor-v1
Proto library for google-cloud-spanner
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/proto-google-cloud-spanner-v1/pom.xml b/proto-google-cloud-spanner-v1/pom.xml
index f1b3ca9f1bd..fbe27a10d50 100644
--- a/proto-google-cloud-spanner-v1/pom.xml
+++ b/proto-google-cloud-spanner-v1/pom.xml
@@ -4,13 +4,13 @@
4.0.0
com.google.api.grpc
proto-google-cloud-spanner-v1
- 6.86.0
+ 6.87.0
proto-google-cloud-spanner-v1
PROTO library for proto-google-cloud-spanner-v1
com.google.cloud
google-cloud-spanner-parent
- 6.86.0
+ 6.87.0
diff --git a/samples/snapshot/pom.xml b/samples/snapshot/pom.xml
index c8d127e2c6c..4140f77781c 100644
--- a/samples/snapshot/pom.xml
+++ b/samples/snapshot/pom.xml
@@ -32,7 +32,7 @@
com.google.cloud
google-cloud-spanner
- 6.86.0
+ 6.87.0
diff --git a/samples/snippets/pom.xml b/samples/snippets/pom.xml
index 7873c36902d..7b617e29306 100644
--- a/samples/snippets/pom.xml
+++ b/samples/snippets/pom.xml
@@ -34,7 +34,7 @@
com.google.cloud
libraries-bom
- 26.53.0
+ 26.54.0
pom
import
diff --git a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java
index 0a6e21ea620..4d0793820af 100644
--- a/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java
+++ b/samples/snippets/src/main/java/com/example/spanner/CreateInstanceWithAutoscalingConfigExample.java
@@ -24,6 +24,7 @@
import com.google.spanner.admin.instance.v1.AutoscalingConfig;
import com.google.spanner.admin.instance.v1.CreateInstanceRequest;
import com.google.spanner.admin.instance.v1.Instance;
+import com.google.spanner.admin.instance.v1.Instance.Edition;
import com.google.spanner.admin.instance.v1.InstanceConfigName;
import com.google.spanner.admin.instance.v1.ProjectName;
import java.util.concurrent.ExecutionException;
@@ -66,6 +67,7 @@ static void createInstance(String projectId, String instanceId) {
.setDisplayName(displayName)
.setConfig(
InstanceConfigName.of(projectId, configId).toString())
+ .setEdition(Edition.ENTERPRISE)
.build();
// Creates a new instance
diff --git a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java
index f8a683865ac..0502fba5eda 100644
--- a/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java
+++ b/samples/snippets/src/main/java/com/example/spanner/admin/archived/CreateInstanceWithAutoscalingConfigExample.java
@@ -28,6 +28,7 @@
import com.google.cloud.spanner.SpannerOptions;
import com.google.spanner.admin.instance.v1.AutoscalingConfig;
import com.google.spanner.admin.instance.v1.CreateInstanceMetadata;
+import com.google.spanner.admin.instance.v1.Instance.Edition;
import java.util.concurrent.ExecutionException;
class CreateInstanceWithAutoscalingConfigExample {
@@ -62,6 +63,7 @@ static void createInstance(String projectId, String instanceId) {
.setInstanceConfigId(InstanceConfigId.of(projectId, configId))
.setAutoscalingConfig(autoscalingConfig)
.setDisplayName("Descriptive name")
+ .setEdition(Edition.ENTERPRISE)
.build();
OperationFuture operation =
instanceAdminClient.createInstance(instanceInfo);
diff --git a/versions.txt b/versions.txt
index 644d7810dcb..de3c4756dd0 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,13 +1,13 @@
# Format:
# module:released-version:current-version
-proto-google-cloud-spanner-admin-instance-v1:6.86.0:6.86.0
-proto-google-cloud-spanner-v1:6.86.0:6.86.0
-proto-google-cloud-spanner-admin-database-v1:6.86.0:6.86.0
-grpc-google-cloud-spanner-v1:6.86.0:6.86.0
-grpc-google-cloud-spanner-admin-instance-v1:6.86.0:6.86.0
-grpc-google-cloud-spanner-admin-database-v1:6.86.0:6.86.0
-google-cloud-spanner:6.86.0:6.86.0
-google-cloud-spanner-executor:6.86.0:6.86.0
-proto-google-cloud-spanner-executor-v1:6.86.0:6.86.0
-grpc-google-cloud-spanner-executor-v1:6.86.0:6.86.0
+proto-google-cloud-spanner-admin-instance-v1:6.87.0:6.87.0
+proto-google-cloud-spanner-v1:6.87.0:6.87.0
+proto-google-cloud-spanner-admin-database-v1:6.87.0:6.87.0
+grpc-google-cloud-spanner-v1:6.87.0:6.87.0
+grpc-google-cloud-spanner-admin-instance-v1:6.87.0:6.87.0
+grpc-google-cloud-spanner-admin-database-v1:6.87.0:6.87.0
+google-cloud-spanner:6.87.0:6.87.0
+google-cloud-spanner-executor:6.87.0:6.87.0
+proto-google-cloud-spanner-executor-v1:6.87.0:6.87.0
+grpc-google-cloud-spanner-executor-v1:6.87.0:6.87.0
|