All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.cloud.datastore.StructuredQuery Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2015 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 static com.google.cloud.datastore.BlobValue.of;
import static com.google.cloud.datastore.BooleanValue.of;
import static com.google.cloud.datastore.DoubleValue.of;
import static com.google.cloud.datastore.KeyValue.of;
import static com.google.cloud.datastore.LongValue.of;
import static com.google.cloud.datastore.StringValue.of;
import static com.google.cloud.datastore.TimestampValue.of;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.api.core.ApiFunction;
import com.google.api.core.InternalApi;
import com.google.cloud.StringEnumType;
import com.google.cloud.StringEnumValue;
import com.google.cloud.Timestamp;
import com.google.cloud.datastore.Query.ResultType;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * An implementation of a Google Cloud Datastore Query that can be constructed by providing all the
 * specific query elements.
 *
 * 

A usage example: * *

A simple query that returns all entities for a specific kind * *

{@code
 * Query query = Query.newEntityQueryBuilder().setKind(kind).build();
 * QueryResults results = datastore.run(query);
 * while (results.hasNext()) {
 *   Entity entity = results.next();
 *   ...
 * }
 * }
* *

A simple key-only query of all entities for a specific kind * *

{@code
 * Query keyOnlyQuery =  Query.newKeyQueryBuilder().setKind(KIND1).build();
 * QueryResults results = datastore.run(keyOnlyQuery);
 * ...
 * }
* *

A less trivial example of a projection query that returns the first 10 results of "age" and * "name" properties (sorted and grouped by "age") with an age greater than 18 * *

{@code
 * Query query = Query.newProjectionEntityQueryBuilder()
 *     .setKind(kind)
 *     .setProjection(Projection.property("age"), Projection.first("name"))
 *     .setFilter(PropertyFilter.gt("age", 18))
 *     .setGroupBy("age")
 *     .setOrderBy(OrderBy.asc("age"))
 *     .setLimit(10)
 *     .build();
 * QueryResults results = datastore.run(query);
 * ...
 * }
* * @param the type of the result values this query will produce * @see Datastore * queries */ public abstract class StructuredQuery extends Query implements RecordQuery { private static final long serialVersionUID = 546838955624019594L; static final String KEY_PROPERTY_NAME = "__key__"; private final String kind; private final ImmutableList projection; private final Filter filter; private final ImmutableList distinctOn; private final ImmutableList orderBy; private final Cursor startCursor; private final Cursor endCursor; private final int offset; private final Integer limit; private final ResultType resultType; public abstract static class Filter implements Serializable { private static final long serialVersionUID = -6443285436239990860L; Filter() {} abstract com.google.datastore.v1.Filter toPb(); static Filter fromPb(com.google.datastore.v1.Filter filterPb) { switch (filterPb.getFilterTypeCase()) { case COMPOSITE_FILTER: return CompositeFilter.fromPb(filterPb.getCompositeFilter()); case PROPERTY_FILTER: return PropertyFilter.fromPb(filterPb.getPropertyFilter()); default: throw new AssertionError("Unexpected enum value " + filterPb.getFilterTypeCase()); } } } /** A class representing a filter composed of a combination of other filters. */ public static final class CompositeFilter extends Filter { private static final long serialVersionUID = 3610352685739360009L; private final Operator operator; private final ImmutableList filters; static final class Operator extends StringEnumValue { private static final long serialVersionUID = -4806600805752138487L; private Operator(String constant) { super(constant); } private static final ApiFunction CONSTRUCTOR = new ApiFunction() { @Override public Operator apply(String constant) { return new Operator(constant); } }; private static final StringEnumType type = new StringEnumType(Operator.class, CONSTRUCTOR); static final Operator AND = type.createAndRegister("AND"); static final Operator OR = type.createAndRegister("OR"); com.google.datastore.v1.CompositeFilter.Operator toPb() { return com.google.datastore.v1.CompositeFilter.Operator.valueOf(name()); } static Operator fromPb(com.google.datastore.v1.CompositeFilter.Operator operatorPb) { return valueOf(operatorPb.name()); } /** * Get the Operator for the given String constant, and throw an exception if the constant is * not recognized. */ static Operator valueOfStrict(String constant) { return type.valueOfStrict(constant); } /** Get the Operator for the given String constant, and allow unrecognized values. */ static Operator valueOf(String constant) { return type.valueOf(constant); } /** Return the known values for Operator. */ static Operator[] values() { return type.values(); } } private CompositeFilter(Operator operator, Filter first, Filter... other) { this.operator = operator; this.filters = ImmutableList.builder().add(first).addAll(Arrays.asList(other)).build(); } private CompositeFilter(Operator operator, ImmutableList filters) { this.operator = operator; this.filters = filters; Preconditions.checkArgument(!filters.isEmpty(), "filters list must not be empty"); } @Override public String toString() { ToStringHelper toStringHelper = MoreObjects.toStringHelper(this); toStringHelper.add("operator", operator); toStringHelper.add("filters", filters); return toStringHelper.toString(); } @Override public int hashCode() { return Objects.hash(operator, filters); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof CompositeFilter)) { return false; } CompositeFilter other = (CompositeFilter) obj; return operator.equals(other.operator) && filters.equals(other.filters); } static CompositeFilter fromPb(com.google.datastore.v1.CompositeFilter compositeFilterPb) { Operator operator = Operator.fromPb(compositeFilterPb.getOp()); ImmutableList.Builder filters = ImmutableList.builder(); for (com.google.datastore.v1.Filter filterPb : compositeFilterPb.getFiltersList()) { Filter currFilter = Filter.fromPb(filterPb); if (currFilter != null) { filters.add(currFilter); } } return new CompositeFilter(operator, filters.build()); } public static CompositeFilter and(Filter first, Filter... other) { return new CompositeFilter(Operator.AND, first, other); } public static CompositeFilter or(Filter first, Filter... other) { return new CompositeFilter(Operator.OR, first, other); } @Override com.google.datastore.v1.Filter toPb() { com.google.datastore.v1.Filter.Builder filterPb = com.google.datastore.v1.Filter.newBuilder(); com.google.datastore.v1.CompositeFilter.Builder compositeFilterPb = filterPb.getCompositeFilterBuilder(); compositeFilterPb.setOp(operator.toPb()); for (Filter filter : filters) { compositeFilterPb.addFilters(filter.toPb()); } return filterPb.build(); } } /** A class representing a filter based on a single property or ancestor. */ public static final class PropertyFilter extends Filter { private static final long serialVersionUID = -4514695915258598597L; private final String property; private final Operator operator; private final Value value; static final class Operator extends StringEnumValue { private static final long serialVersionUID = 4105765859141068029L; private Operator(String constant) { super(constant); } private static final ApiFunction CONSTRUCTOR = new ApiFunction() { @Override public Operator apply(String constant) { return new Operator(constant); } }; private static final StringEnumType type = new StringEnumType(Operator.class, CONSTRUCTOR); static final Operator LESS_THAN = type.createAndRegister("LESS_THAN"); static final Operator LESS_THAN_OR_EQUAL = type.createAndRegister("LESS_THAN_OR_EQUAL"); static final Operator GREATER_THAN = type.createAndRegister("GREATER_THAN"); static final Operator GREATER_THAN_OR_EQUAL = type.createAndRegister("GREATER_THAN_OR_EQUAL"); static final Operator EQUAL = type.createAndRegister("EQUAL"); static final Operator IN = type.createAndRegister("IN"); static final Operator NOT_EQUAL = type.createAndRegister("NOT_EQUAL"); static final Operator HAS_ANCESTOR = type.createAndRegister("HAS_ANCESTOR"); static final Operator NOT_IN = type.createAndRegister("NOT_IN"); com.google.datastore.v1.PropertyFilter.Operator toPb() { return com.google.datastore.v1.PropertyFilter.Operator.valueOf(name()); } static Operator fromPb(com.google.datastore.v1.PropertyFilter.Operator operatorPb) { return valueOf(operatorPb.name()); } /** * Get the Operator for the given String constant, and throw an exception if the constant is * not recognized. */ static Operator valueOfStrict(String constant) { return type.valueOfStrict(constant); } /** Get the Operator for the given String constant, and allow unrecognized values. */ static Operator valueOf(String constant) { return type.valueOf(constant); } /** Return the known values for Operator. */ static Operator[] values() { return type.values(); } } private PropertyFilter(String property, Operator operator, Value value) { this.property = checkNotNull(property); this.operator = checkNotNull(operator); this.value = checkNotNull(value); } static PropertyFilter fromPb(com.google.datastore.v1.PropertyFilter propertyFilterPb) { String property = propertyFilterPb.getProperty().getName(); Operator operator = Operator.fromPb(propertyFilterPb.getOp()); Value value = Value.fromPb(propertyFilterPb.getValue()); return new PropertyFilter(property, operator, value); } @Override public String toString() { ToStringHelper toStringHelper = MoreObjects.toStringHelper(this); toStringHelper.add("property", property); toStringHelper.add("operator", operator); toStringHelper.add("value", value); return toStringHelper.toString(); } @Override public int hashCode() { return Objects.hash(property, operator, value); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof PropertyFilter)) { return false; } PropertyFilter other = (PropertyFilter) obj; return property.equals(other.property) && operator.equals(other.operator) && Objects.equals(value, other.value); } public static PropertyFilter lt(String property, Value value) { return new PropertyFilter(property, Operator.LESS_THAN, value); } public static PropertyFilter lt(String property, String value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, long value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, double value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, boolean value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, Timestamp value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, Key value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter lt(String property, Blob value) { return new PropertyFilter(property, Operator.LESS_THAN, of(value)); } public static PropertyFilter le(String property, Value value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, value); } public static PropertyFilter le(String property, String value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, long value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, double value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, boolean value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, Timestamp value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, Key value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter le(String property, Blob value) { return new PropertyFilter(property, Operator.LESS_THAN_OR_EQUAL, of(value)); } public static PropertyFilter gt(String property, Value value) { return new PropertyFilter(property, Operator.GREATER_THAN, value); } public static PropertyFilter gt(String property, String value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, long value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, double value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, boolean value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, Timestamp value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, Key value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter gt(String property, Blob value) { return new PropertyFilter(property, Operator.GREATER_THAN, of(value)); } public static PropertyFilter ge(String property, Value value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, value); } public static PropertyFilter ge(String property, String value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, long value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, double value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, boolean value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, Timestamp value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, Key value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter ge(String property, Blob value) { return new PropertyFilter(property, Operator.GREATER_THAN_OR_EQUAL, of(value)); } public static PropertyFilter eq(String property, Value value) { return new PropertyFilter(property, Operator.EQUAL, value); } public static PropertyFilter eq(String property, String value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, long value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, double value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, boolean value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, Timestamp value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, Key value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter eq(String property, Blob value) { return new PropertyFilter(property, Operator.EQUAL, of(value)); } public static PropertyFilter neq(String property, Value value) { return new PropertyFilter(property, Operator.NOT_EQUAL, value); } public static PropertyFilter neq(String property, String value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, long value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, double value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, boolean value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, Timestamp value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, Key value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter neq(String property, Blob value) { return new PropertyFilter(property, Operator.NOT_EQUAL, of(value)); } public static PropertyFilter in(String property, ListValue value) { return new PropertyFilter(property, Operator.IN, value); } public static PropertyFilter not_in(String property, ListValue value) { return new PropertyFilter(property, Operator.NOT_IN, value); } public static PropertyFilter hasAncestor(Key key) { return new PropertyFilter(KEY_PROPERTY_NAME, Operator.HAS_ANCESTOR, of(key)); } public static PropertyFilter isNull(String property) { return new PropertyFilter(property, Operator.EQUAL, NullValue.of()); } @Override com.google.datastore.v1.Filter toPb() { com.google.datastore.v1.Filter.Builder filterPb = com.google.datastore.v1.Filter.newBuilder(); com.google.datastore.v1.PropertyFilter.Builder propertyFilterPb = filterPb.getPropertyFilterBuilder(); propertyFilterPb.getPropertyBuilder().setName(property); propertyFilterPb.setOp(operator.toPb()); if (value != null) { propertyFilterPb.setValue(value.toPb()); } return filterPb.build(); } } public static final class OrderBy implements Serializable { private static final long serialVersionUID = 4091186784814400031L; private final String property; private final Direction direction; public static final class Direction extends StringEnumValue { private static final long serialVersionUID = -6938125060419556331L; private Direction(String constant) { super(constant); } private static final ApiFunction CONSTRUCTOR = new ApiFunction() { @Override public Direction apply(String constant) { return new Direction(constant); } }; private static final StringEnumType type = new StringEnumType(Direction.class, CONSTRUCTOR); public static final Direction ASCENDING = type.createAndRegister("ASCENDING"); public static final Direction DESCENDING = type.createAndRegister("DESCENDING"); com.google.datastore.v1.PropertyOrder.Direction toPb() { return com.google.datastore.v1.PropertyOrder.Direction.valueOf(name()); } static Direction fromPb(com.google.datastore.v1.PropertyOrder.Direction directionPb) { return valueOf(directionPb.name()); } /** * Get the Direction for the given String constant, and throw an exception if the constant is * not recognized. */ static Direction valueOfStrict(String constant) { return type.valueOfStrict(constant); } /** Get the Direction for the given String constant, and allow unrecognized values. */ static Direction valueOf(String constant) { return type.valueOf(constant); } /** Return the known values for Direction. */ static Direction[] values() { return type.values(); } } public OrderBy(String property, Direction direction) { this.property = checkNotNull(property); this.direction = checkNotNull(direction); } @Override public int hashCode() { return Objects.hash(property, direction); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof OrderBy)) { return false; } OrderBy other = (OrderBy) obj; return property.equals(other.property) && direction.equals(other.direction); } /** Returns the property according to which the query result should be ordered. */ public String getProperty() { return property; } /** Returns the order's direction. */ public Direction getDirection() { return direction; } com.google.datastore.v1.PropertyOrder toPb() { return com.google.datastore.v1.PropertyOrder.newBuilder() .setDirection(direction.toPb()) .setProperty( com.google.datastore.v1.PropertyReference.newBuilder().setName(property).build()) .build(); } public static OrderBy asc(String property) { return new OrderBy(property, OrderBy.Direction.ASCENDING); } public static OrderBy desc(String property) { return new OrderBy(property, OrderBy.Direction.DESCENDING); } static OrderBy fromPb(com.google.datastore.v1.PropertyOrder propertyOrderPb) { String property = propertyOrderPb.getProperty().getName(); Direction direction = Direction.fromPb(propertyOrderPb.getDirection()); return new OrderBy(property, direction); } @Override public String toString() { ToStringHelper toStringHelper = MoreObjects.toStringHelper(this); toStringHelper.add("property", getProperty()); toStringHelper.add("direction", getDirection()); return toStringHelper.toString(); } } /** * Interface for StructuredQuery builders. * * @param the type of result the query returns. */ public interface Builder { /** Sets the namespace for the query. */ Builder setNamespace(String namespace); /** Sets the kind for the query. */ Builder setKind(String kind); /** Sets the start cursor for the query. */ Builder setStartCursor(Cursor startCursor); /** Sets the end cursor for the query. */ Builder setEndCursor(Cursor endCursor); /** Sets the offset for the query. */ Builder setOffset(int offset); /** Sets the limit for the query. */ Builder setLimit(Integer limit); Builder setFilter(Filter filter); /** Clears any previously specified order by settings. */ Builder clearOrderBy(); /** Sets the query's order by clause (clearing any previously specified order by settings). */ Builder setOrderBy(OrderBy orderBy, OrderBy... others); /** Adds settings to the existing order by clause. */ Builder addOrderBy(OrderBy orderBy, OrderBy... others); StructuredQuery build(); } /** * Base class for StructuredQuery builders. * * @param the type of result the query returns. * @param the query builder. */ abstract static class BuilderImpl> implements Builder { private final ResultType resultType; private String namespace; private String kind; private final List projection = new LinkedList<>(); private Filter filter; private final List distinctOn = new LinkedList<>(); private final List orderBy = new LinkedList<>(); private Cursor startCursor; private Cursor endCursor; private int offset; private Integer limit; BuilderImpl(ResultType resultType) { this.resultType = resultType; } BuilderImpl(StructuredQuery query) { this(query.getType()); namespace = query.getNamespace(); kind = query.kind; projection.addAll(query.projection); filter = query.filter; distinctOn.addAll(query.distinctOn); orderBy.addAll(query.orderBy); startCursor = query.startCursor; endCursor = query.endCursor; offset = query.offset; limit = query.limit; } @SuppressWarnings("unchecked") B self() { return (B) this; } @Override public B setNamespace(String namespace) { this.namespace = namespace; return self(); } @Override public B setKind(String kind) { this.kind = kind; return self(); } @Override public B setStartCursor(Cursor startCursor) { this.startCursor = startCursor; return self(); } @Override public B setEndCursor(Cursor endCursor) { this.endCursor = endCursor; return self(); } @Override public B setOffset(int offset) { Preconditions.checkArgument(offset >= 0, "offset must not be negative"); this.offset = offset; return self(); } @Override public B setLimit(Integer limit) { Preconditions.checkArgument(limit == null || limit >= 0, "limit must not be negative"); this.limit = limit; return self(); } @Override public B setFilter(Filter filter) { this.filter = filter; return self(); } @Override public B clearOrderBy() { orderBy.clear(); return self(); } @Override public B setOrderBy(OrderBy orderBy, OrderBy... others) { clearOrderBy(); addOrderBy(orderBy, others); return self(); } @Override public B addOrderBy(OrderBy orderBy, OrderBy... others) { this.orderBy.add(orderBy); Collections.addAll(this.orderBy, others); return self(); } B clearProjection() { projection.clear(); return self(); } B setProjection(String projection, String... others) { clearProjection(); addProjection(projection, others); return self(); } B addProjection(String projection, String... others) { this.projection.add(projection); Collections.addAll(this.projection, others); return self(); } B clearDistinctOn() { distinctOn.clear(); return self(); } B setDistinctOn(String property, String... others) { clearDistinctOn(); addDistinctOn(property, others); return self(); } B addDistinctOn(String property, String... others) { this.distinctOn.add(property); Collections.addAll(this.distinctOn, others); return self(); } B mergeFrom(com.google.datastore.v1.Query queryPb) { if (queryPb.getKindCount() > 0) { setKind(queryPb.getKind(0).getName()); } if (!queryPb.getStartCursor().isEmpty()) { setStartCursor(new Cursor(queryPb.getStartCursor())); } if (!queryPb.getEndCursor().isEmpty()) { setEndCursor(new Cursor(queryPb.getEndCursor())); } setOffset(queryPb.getOffset()); if (queryPb.hasLimit()) { setLimit(queryPb.getLimit().getValue()); } if (queryPb.hasFilter()) { Filter currFilter = Filter.fromPb(queryPb.getFilter()); if (currFilter != null) { setFilter(currFilter); } } for (com.google.datastore.v1.PropertyOrder orderByPb : queryPb.getOrderList()) { addOrderBy(OrderBy.fromPb(orderByPb)); } for (com.google.datastore.v1.Projection projectionPb : queryPb.getProjectionList()) { addProjection(projectionPb.getProperty().getName()); } for (com.google.datastore.v1.PropertyReference distinctOnPb : queryPb.getDistinctOnList()) { addDistinctOn(distinctOnPb.getName()); } return self(); } } StructuredQuery(BuilderImpl builder) { super(builder.namespace); resultType = checkNotNull(builder.resultType); kind = builder.kind; projection = ImmutableList.copyOf(builder.projection); filter = builder.filter; distinctOn = ImmutableList.copyOf(builder.distinctOn); orderBy = ImmutableList.copyOf(builder.orderBy); startCursor = builder.startCursor; endCursor = builder.endCursor; offset = builder.offset; limit = builder.limit; } @Override public String toString() { return toStringHelper() .add("type", getType()) .add("kind", kind) .add("startCursor", startCursor) .add("endCursor", endCursor) .add("offset", offset) .add("limit", limit) .add("filter", filter) .add("orderBy", orderBy) .add("projection", projection) .add("distinctOn", distinctOn) .toString(); } @Override public int hashCode() { return Objects.hash( getNamespace(), kind, startCursor, endCursor, offset, limit, filter, orderBy, projection, distinctOn); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StructuredQuery)) { return false; } StructuredQuery other = (StructuredQuery) obj; return Objects.equals(getNamespace(), other.getNamespace()) && Objects.equals(kind, other.kind) && Objects.equals(startCursor, other.startCursor) && Objects.equals(endCursor, other.endCursor) && Objects.equals(offset, other.offset) && Objects.equals(limit, other.limit) && Objects.equals(filter, other.filter) && Objects.equals(orderBy, other.orderBy) && Objects.equals(projection, other.projection) && Objects.equals(distinctOn, other.distinctOn); } /** Returns the kind for this query. */ public String getKind() { return kind; } boolean isKeyOnly() { return projection.size() == 1 && KEY_PROPERTY_NAME.equals(projection.get(0)); } /** Returns the projection for this query. */ public List getProjection() { return projection; } /** Returns the filter for this query. */ public Filter getFilter() { return filter; } /** Returns the distinct on clause for this query. */ public List getDistinctOn() { return distinctOn; } /** Returns the order by clause for this query. */ public List getOrderBy() { return orderBy; } /** Returns the start cursor for this query. */ public Cursor getStartCursor() { return startCursor; } /** Returns the end cursor for this query. */ public Cursor getEndCursor() { return endCursor; } /** Returns the offset for this query. */ public int getOffset() { return offset; } /** Returns the limit for this query. */ public Integer getLimit() { return limit; } public abstract Builder toBuilder(); @InternalApi @Override public ResultType getType() { return resultType; } @InternalApi @Override public void populatePb(com.google.datastore.v1.RunQueryRequest.Builder requestPb) { requestPb.setQuery(toPb()); } @InternalApi @Override public StructuredQuery nextQuery(com.google.datastore.v1.RunQueryResponse responsePb) { Builder builder = toBuilder(); builder.setStartCursor(new Cursor(responsePb.getBatch().getEndCursor())); if (offset > 0 && responsePb.getBatch().getSkippedResults() < offset) { builder.setOffset(offset - responsePb.getBatch().getSkippedResults()); } else { builder.setOffset(0); if (limit != null) { builder.setLimit(limit - responsePb.getBatch().getEntityResultsCount()); } } return builder.build(); } com.google.datastore.v1.Query toPb() { StructuredQueryProtoPreparer protoPreparer = new StructuredQueryProtoPreparer(); return protoPreparer.prepare(this); } @SuppressWarnings("unchecked") static StructuredQuery fromPb( ResultType resultType, String namespace, com.google.datastore.v1.Query queryPb) { BuilderImpl builder; if (resultType.equals(ResultType.ENTITY)) { builder = new EntityQuery.Builder(); } else if (resultType.equals(ResultType.KEY)) { builder = new KeyQuery.Builder(); } else { builder = new ProjectionEntityQuery.Builder(); } return (StructuredQuery) builder.setNamespace(namespace).mergeFrom(queryPb).build(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy