Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import com.google.api.core.InternalExtensionOnly;
import com.google.cloud.Service;
import com.google.cloud.datastore.models.ExplainOptions;
import com.google.common.collect.ImmutableList;
import com.google.datastore.v1.RequestOptions;
import com.google.datastore.v1.TransactionOptions;
import java.util.Iterator;
import java.util.List;
Expand All @@ -44,6 +46,24 @@ public interface Datastore extends Service<DatastoreOptions>, DatastoreReaderWri
*/
Transaction newTransaction();

/**
* Returns a new Datastore transaction with specified {@link DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
Transaction newTransaction(DatastoreExecutionOptions executionOptions);

/**
* Returns a new Datastore transaction with specified {@link TransactionOptions} and {@link
* DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
Transaction newTransaction(
TransactionOptions options, DatastoreExecutionOptions executionOptions);
Comment thread
rahulmane-goog marked this conversation as resolved.

/**
* A callback for running with a transactional {@link
* com.google.cloud.datastore.DatastoreReaderWriter}. The associated transaction will be committed
Expand Down Expand Up @@ -179,6 +199,17 @@ interface TransactionCallable<T> {
*/
List<Key> allocateId(IncompleteKey... keys);



/**
* Returns a list of keys using the allocated ids with specified {@link
* DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
List<Key> allocateId(DatastoreExecutionOptions executionOptions, IncompleteKey... keys);

/**
* Reserve one or more keys, preventing them from being automatically allocated by Datastore.
*
Expand All @@ -196,6 +227,14 @@ interface TransactionCallable<T> {
*/
List<Key> reserveIds(Key... keys);

/**
* Reserve one or more keys with specified {@link DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
List<Key> reserveIds(DatastoreExecutionOptions executionOptions, Key... keys);

/**
* {@inheritDoc}
*
Expand Down Expand Up @@ -226,6 +265,16 @@ interface TransactionCallable<T> {
@Override
Entity add(FullEntity<?> entity);

/**
* Datastore add operation: inserts the provided entity with specified {@link
* DatastoreExecutionOptions}. This method will automatically allocate an id if necessary.
*
* @throws DatastoreException upon failure
* @throws IllegalArgumentException if the given entity is missing a key
*/
@BetaApi
Entity add(FullEntity<?> entity, DatastoreExecutionOptions executionOptions);

/**
* {@inheritDoc}
*
Expand Down Expand Up @@ -264,6 +313,17 @@ interface TransactionCallable<T> {
@Override
List<Entity> add(FullEntity<?>... entities);

/**
* Datastore add operation: inserts the provided entities with specified {@link
* DatastoreExecutionOptions}. This method will automatically allocate id for any entity with an
* incomplete key.
*
* @throws DatastoreException upon failure
* @throws IllegalArgumentException if any of the given entities is missing a key
*/
@BetaApi
List<Entity> add(DatastoreExecutionOptions executionOptions, FullEntity<?>... entities);

/**
* {@inheritDoc}
*
Expand All @@ -290,6 +350,15 @@ interface TransactionCallable<T> {
@Override
void update(Entity... entities);

/**
* A Datastore update operation with specified {@link DatastoreExecutionOptions}. The operation
* will fail if an entity with the same key does not already exist.
*
* @throws DatastoreException upon failure
*/
@BetaApi
void update(DatastoreExecutionOptions executionOptions, Entity... entities);

/**
* {@inheritDoc}
*
Expand All @@ -309,31 +378,18 @@ interface TransactionCallable<T> {
@Override
Entity put(FullEntity<?> entity);

@Override
List<Entity> put(FullEntity<?>... entities);



/**
* {@inheritDoc}
*
* <p>Example of putting multiple entities.
*
* <pre>{@code
* String keyName1 = "my_key_name1";
* String keyName2 = "my_key_name2";
* Key key1 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName1);
* Entity.Builder entityBuilder1 = Entity.newBuilder(key1);
* entityBuilder1.set("propertyName", "value1");
* Entity entity1 = entityBuilder1.build();
*
* Key key2 = datastore.newKeyFactory().setKind("MyKind").newKey(keyName2);
* Entity.Builder entityBuilder2 = Entity.newBuilder(key2);
* entityBuilder2.set("propertyName", "value2");
* Entity entity2 = entityBuilder2.build();
*
* datastore.put(entity1, entity2);
* }</pre>
* {@inheritDoc} with specified {@link DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@Override
List<Entity> put(FullEntity<?>... entities);
@BetaApi
List<Entity> put(DatastoreExecutionOptions executionOptions, FullEntity<?>... entities);

/**
* {@inheritDoc}
Expand All @@ -353,6 +409,14 @@ interface TransactionCallable<T> {
@Override
void delete(Key... keys);

/**
* A datastore delete operation with specified {@link DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
void delete(DatastoreExecutionOptions executionOptions, Key... keys);

/**
* Returns a new KeyFactory for this service
*
Expand Down Expand Up @@ -381,6 +445,15 @@ interface TransactionCallable<T> {
*/
Entity get(Key key, ReadOption... options);

/**
* Returns an {@link Entity} for the given {@link Key} with specified {@link
* DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
Entity get(Key key, DatastoreExecutionOptions executionOptions);

/**
* Returns an {@link Entity} for each given {@link Key} that exists in the Datastore. The order of
* the result is unspecified. Results are loaded lazily, so it is possible to get a {@code
Expand Down Expand Up @@ -409,6 +482,15 @@ interface TransactionCallable<T> {
*/
Iterator<Entity> get(Iterable<Key> keys, ReadOption... options);

/**
* Returns an {@link Entity} for each given {@link Key} with specified {@link
* DatastoreExecutionOptions}.
*
* @throws DatastoreException upon failure
*/
@BetaApi
Iterator<Entity> get(Iterable<Key> keys, DatastoreExecutionOptions executionOptions);

/**
* Returns a list with a value for each given key (ordered by input). {@code null} values are
* returned for nonexistent keys. When possible prefer using {@link #get(Key...)} to avoid eagerly
Expand All @@ -430,6 +512,13 @@ interface TransactionCallable<T> {
*/
List<Entity> fetch(Iterable<Key> keys, ReadOption... options);

/**
* Returns a list with a value for each given key with specified {@link
* DatastoreExecutionOptions}.
*/
@BetaApi
List<Entity> fetch(Iterable<Key> keys, DatastoreExecutionOptions executionOptions);

/**
* Submits a {@link Query} and returns its result. {@link ReadOption}s can be specified if
* desired.
Expand Down Expand Up @@ -492,6 +581,12 @@ interface TransactionCallable<T> {
@BetaApi
<T> QueryResults<T> run(Query<T> query, ExplainOptions explainOptions, ReadOption... options);

/**
* Submits a {@link Query} with specified {@link DatastoreExecutionOptions} and returns its result.
*/
@BetaApi
<T> QueryResults<T> run(Query<T> query, DatastoreExecutionOptions executionOptions);

/**
* Submits a {@link AggregationQuery} and returns {@link AggregationResults}. {@link ReadOption}s
* can be specified if desired.
Expand Down Expand Up @@ -564,6 +659,14 @@ interface TransactionCallable<T> {
AggregationResults runAggregation(
AggregationQuery query, ExplainOptions explainOptions, ReadOption... options);

/**
* Submits an {@link AggregationQuery} with specified {@link DatastoreExecutionOptions} and returns
* {@link AggregationResults}.
*/
@BetaApi
AggregationResults runAggregation(
AggregationQuery query, DatastoreExecutionOptions executionOptions);

/**
* Closes the gRPC channels associated with this instance and frees up their resources. This
* method blocks until all channels are closed. Once this method is called, this Datastore client
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright 2026 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.datastore;

import com.google.api.core.BetaApi;
import com.google.cloud.datastore.models.ExplainOptions;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.datastore.v1.RequestOptions;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
* Class representing options for query execution in Google Cloud Datastore. Combines {@link
* ExplainOptions}, {@link RequestOptions}, and {@link ReadOption}s.
*/
@BetaApi
public class DatastoreExecutionOptions {

private final ExplainOptions explainOptions;
private final RequestOptions requestOptions;
private final List<ReadOption> readOptions;

private DatastoreExecutionOptions(Builder builder) {
this.explainOptions = builder.explainOptions;
this.requestOptions = builder.requestOptions;
this.readOptions = ImmutableList.copyOf(builder.readOptions);
}

public ExplainOptions getExplainOptions() {
return explainOptions;
}

public RequestOptions getRequestOptions() {
return requestOptions;
}

public List<ReadOption> getReadOptions() {
return readOptions;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof DatastoreExecutionOptions)) return false;
DatastoreExecutionOptions that = (DatastoreExecutionOptions) o;
return Objects.equal(explainOptions, that.explainOptions)
&& Objects.equal(requestOptions, that.requestOptions)
&& Objects.equal(readOptions, that.readOptions);
}

@Override
public int hashCode() {
return Objects.hashCode(explainOptions, requestOptions, readOptions);
}

public static Builder newBuilder() {
return new Builder();
}

public static DatastoreExecutionOptions of(RequestOptions requestOptions) {
return newBuilder().setRequestOptions(requestOptions).build();
}

public static DatastoreExecutionOptions of(ExplainOptions explainOptions) {
return newBuilder().setExplainOptions(explainOptions).build();
}

public static DatastoreExecutionOptions of(List<ReadOption> readOptions) {
return newBuilder().setReadOptions(readOptions).build();
}

public static DatastoreExecutionOptions of(
RequestOptions requestOptions, List<ReadOption> readOptions) {
return newBuilder().setRequestOptions(requestOptions).setReadOptions(readOptions).build();
}

public static DatastoreExecutionOptions of(
ExplainOptions explainOptions, RequestOptions requestOptions) {
return newBuilder().setExplainOptions(explainOptions).setRequestOptions(requestOptions).build();
}

public static DatastoreExecutionOptions of(
ExplainOptions explainOptions, RequestOptions requestOptions, List<ReadOption> readOptions) {
return newBuilder()
.setExplainOptions(explainOptions)
.setRequestOptions(requestOptions)
.setReadOptions(readOptions)
.build();
}

/** Builder for {@link DatastoreExecutionOptions}. */
public static class Builder {
private ExplainOptions explainOptions;
private RequestOptions requestOptions;
private List<ReadOption> readOptions = Collections.emptyList();

private Builder() {}

public Builder setExplainOptions(ExplainOptions explainOptions) {
this.explainOptions = explainOptions;
return this;
}

public Builder setRequestOptions(RequestOptions requestOptions) {
this.requestOptions = requestOptions;
return this;
}

public Builder setReadOptions(List<ReadOption> readOptions) {
this.readOptions = readOptions != null ? readOptions : Collections.emptyList();
return this;
}

public DatastoreExecutionOptions build() {
return new DatastoreExecutionOptions(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static List<Entity> fetch(Datastore reader, Key[] keys, ReadOption... options) {
return compileEntities(keys, reader.get(Arrays.asList(keys), options));
}

private static List<Entity> compileEntities(Key[] keys, Iterator<Entity> entities) {
static List<Entity> compileEntities(Key[] keys, Iterator<Entity> entities) {
Map<Key, Entity> map = Maps.newHashMapWithExpectedSize(keys.length);
while (entities.hasNext()) {
Entity entity = entities.next();
Expand Down
Loading
Loading