// Copyright 2013 Google Inc. All Rights Reserved.
//
// 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.
//
// The datastore v1 service proto definitions

syntax = "proto2";

package datastore;
option java_package = "com.google.api.services.datastore";


// An identifier for a particular subset of entities.
//
// Entities are partitioned into various subsets, each used by different
// datasets and different namespaces within a dataset and so forth.
//
// All input partition IDs are normalized before use.
// A partition ID is normalized as follows:
//   If the partition ID is unset or is set to an empty partition ID, replace it
//       with the context partition ID.
//   Otherwise, if the partition ID has no dataset ID, assign it the context
//       partition ID's dataset ID.
// Unless otherwise documented, the context partition ID has the dataset ID set
// to the context dataset ID and no other partition dimension set.
//
// A partition ID is empty if all of its fields are unset.
//
// Partition dimension:
// A dimension may be unset.
// A dimension's value must never be "".
// A dimension's value must match [A-Za-z\d\.\-_]{1,100}
// If the value of any dimension matches regex "__.*__",
// the partition is reserved/read-only.
// A reserved/read-only partition ID is forbidden in certain documented contexts.
//
// Dataset ID:
// A dataset id's value must never be "".
// A dataset id's value must match
// ([a-z\d\-]{1,100}~)?([a-z\d][a-z\d\-\.]{0,99}:)?([a-z\d][a-z\d\-]{0,99}
message PartitionId {
  // The dataset ID.
  optional string dataset_id = 3;
  // The namespace.
  optional string namespace = 4;
}

// A unique identifier for an entity.
// If a key's partition id or any of its path kinds or names are
// reserved/read-only, the key is reserved/read-only.
// A reserved/read-only key is forbidden in certain documented contexts.
message Key {
  // Entities are partitioned into subsets, currently identified by a dataset
  // (usually implicitly specified by the project) and namespace ID.
  // Queries are scoped to a single partition.
  optional PartitionId partition_id = 1;

  // A (kind, ID/name) pair used to construct a key path.
  //
  // At most one of name or ID may be set.
  // If either is set, the element is complete.
  // If neither is set, the element is incomplete.
  message PathElement {
    // The kind of the entity.
    // A kind matching regex "__.*__" is reserved/read-only.
    // A kind must not contain more than 500 characters.
    // Cannot be "".
    required string kind = 1;
    // The ID of the entity.
    // Never equal to zero. Values less than zero are discouraged and will not
    // be supported in the future.
    optional int64 id = 2;
    // The name of the entity.
    // A name matching regex "__.*__" is reserved/read-only.
    // A name must not be more than 500 characters.
    // Cannot be "".
    optional string name = 3;
  }

  // The entity path.
  // An entity path consists of one or more elements composed of a kind and a
  // string or numerical identifier, which identify entities. The first
  // element identifies a <em>root entity</em>, the second element identifies
  // a <em>child</em> of the root entity, the third element a child of the
  // second entity, and so forth. The entities identified by all prefixes of
  // the path are called the element's <em>ancestors</em>.
  // An entity path is always fully complete: ALL of the entity's ancestors
  // are required to be in the path along with the entity identifier itself.
  // The only exception is that in some documented cases, the identifier in the
  // last path element (for the entity) itself may be omitted. A path can never
  // be empty.
  repeated PathElement path_element = 2;
}

// A message that can hold any of the supported value types and associated
// metadata.
//
// At most one of the <type>Value fields may be set.
// If none are set the value is "null".
//
message Value {
  // A boolean value.
  optional bool boolean_value = 1;
  // An integer value.
  optional int64 integer_value = 2;
  // A double value.
  optional double double_value = 3;
  // A timestamp value.
  optional int64 timestamp_microseconds_value = 4;
  // A key value.
  optional Key key_value  = 5;
  // A blob key value.
  optional string blob_key_value = 16;
  // A UTF-8 encoded string value.
  optional string string_value = 17;
  // A blob value.
  optional bytes blob_value = 18;
  // An entity value.
  // May have no key.
  // May have a key with an incomplete key path.
  // May have a reserved/read-only key.
  optional Entity entity_value = 6;
  // A list value.
  // Cannot contain another list value.
  // Cannot also have a meaning and indexing set.
  repeated Value list_value = 7;

  // The <code>meaning</code> field is reserved and should not be used.
  optional int32 meaning = 14;

  // If the value should be indexed.
  //
  // The <code>indexed</code> property may be set for a
  // <code>null</code> value.
  // When <code>indexed</code> is <code>true</code>, <code>stringValue</code>
  // is limited to 500 characters and the blob value is limited to 500 bytes.
  // Exception: If meaning is set to 2, string_value is limited to 2038
  // characters regardless of indexed.
  // When indexed is true, meaning 15 and 22 are not allowed, and meaning 16
  // will be ignored on input (and will never be set on output).
  // Input values by default have <code>indexed</code> set to
  // <code>true</code>; however, you can explicitly set <code>indexed</code> to
  // <code>true</code> if you want. (An output value never has
  // <code>indexed</code> explicitly set to <code>true</code>.) If a value is
  // itself an entity, it cannot have <code>indexed</code> set to
  // <code>true</code>.
  // Exception: An entity value with meaning 9, 20 or 21 may be indexed.
  optional bool indexed = 15 [default = true];
}

// An entity property.
message Property {
  // The name of the property.
  // A property name matching regex "__.*__" is reserved.
  // A reserved property name is forbidden in certain documented contexts.
  // The name must not contain more than 500 characters.
  // Cannot be "".
  required string name = 1;

  // The value(s) of the property.
  // Each value can have only one value property populated. For example,
  // you cannot have a values list of <code>{ value: { integerValue: 22,
  // stringValue: "a" } }</code>, but you can have <code>{ value: { listValue:
  // [ { integerValue: 22 }, { stringValue: "a" } ] }</code>.
  required Value value = 4;
}

// An entity.
//
// An entity is limited to 1 megabyte when stored. That <em>roughly</em>
// corresponds to a limit of 1 megabyte for the serialized form of this
// message.
message Entity {
  // The entity's key.
  //
  // An entity must have a key, unless otherwise documented (for example,
  // an entity in <code>Value.entityValue</code> may have no key).
  // An entity's kind is its key's path's last element's kind,
  // or null if it has no key.
  optional Key key = 1;
  // The entity's properties.
  // Each property's name must be unique for its entity.
  repeated Property property = 2;
}

// The result of fetching an entity from the datastore.
message EntityResult {
  // Specifies what data the 'entity' field contains.
  // A ResultType is either implied (for example, in LookupResponse.found it
  // is always FULL) or specified by context (for example, in message
  // QueryResultBatch, field 'entity_result_type' specifies a ResultType
  // for all the values in field 'entity_result').
  enum ResultType {
    FULL = 1;  // The entire entity.
    PROJECTION = 2;  // A projected subset of properties.
                     // The entity may have no key.
                     // A property value may have meaning 18.
    KEY_ONLY = 3;  // Only the key.
  }

  // The resulting entity.
  required Entity entity = 1;
}

// A query.
message Query {
  // The projection to return. If not set the entire entity is returned.
  repeated PropertyExpression projection = 2;

  // The kinds to query (if empty, returns entities from all kinds).
  repeated KindExpression kind = 3;

  // The filter to apply (optional).
  optional Filter filter = 4;

  // The order to apply to the query results (if empty, order is unspecified).
  repeated PropertyOrder order = 5;

  // The properties to group by (if empty, no grouping is applied to the
  // result set).
  repeated PropertyReference group_by = 6;

  // A starting point for the query results. Optional. Query cursors are
  // returned in query result batches.
  optional bytes /* serialized QueryCursor */ start_cursor = 7;

  // An ending point for the query results. Optional. Query cursors are
  // returned in query result batches.
  optional bytes /* serialized QueryCursor */ end_cursor = 8;

  // The number of results to skip. Applies before limit, but after all other
  // constraints (optional, defaults to 0).
  optional int32 offset = 10 [default=0];

  // The maximum number of results to return. Applies after all other
  // constraints. Optional.
  optional int32 limit = 11;
}

// A representation of a kind.
message KindExpression {
  // The name of the kind.
  required string name = 1;
}

// A reference to a property relative to the kind expressions.
// exactly.
message PropertyReference {
  // The name of the property.
  required string name = 2;
}

// A representation of a property in a projection.
message PropertyExpression {
  enum AggregationFunction {
    FIRST = 1;
  }
  // The property to project.
  required PropertyReference property = 1;
  // The aggregation function to apply to the property. Optional.
  // Can only be used when grouping by at least one property. Must
  // then be set on all properties in the projection that are not
  // being grouped by.
  optional AggregationFunction aggregation_function = 2;
}

// The desired order for a specific property.
message PropertyOrder {
  enum Direction {
    ASCENDING = 1;
    DESCENDING = 2;
  }
  // The property to order by.
  required PropertyReference property = 1;
  // The direction to order by.
  optional Direction direction = 2 [default=ASCENDING];
}

// A holder for any type of filter. Exactly one field should be specified.
message Filter {
  // A composite filter.
  optional CompositeFilter composite_filter = 1;
  // A filter on a property.
  optional PropertyFilter property_filter = 2;
}

// A filter that merges the multiple other filters using the given operation.
message CompositeFilter {
  enum Operator {
    AND = 1;
  }

  // The operator for combining multiple filters.
  required Operator operator = 1;
  // The list of filters to combine.
  // Must contain at least one filter.
  repeated Filter filter = 2;
}

// A filter on a specific property.
message PropertyFilter {
  enum Operator {
    LESS_THAN = 1;
    LESS_THAN_OR_EQUAL = 2;
    GREATER_THAN = 3;
    GREATER_THAN_OR_EQUAL = 4;
    EQUAL = 5;

    HAS_ANCESTOR = 11;
  }

  // The property to filter by.
  required PropertyReference property = 1;
  // The operator to filter by.
  required Operator operator = 2;
  // The value to compare the property to.
  required Value value = 3;
}

// A GQL query.
message GqlQuery {
  required string query_string = 1;
  // When false, the query string must not contain a literal.
  optional bool allow_literal = 2 [default = false];
  // A named argument must set field GqlQueryArg.name.
  // No two named arguments may have the same name.
  // For each non-reserved named binding site in the query string,
  // there must be a named argument with that name,
  // but not necessarily the inverse.
  repeated GqlQueryArg name_arg = 3;
  // Numbered binding site @1 references the first numbered argument,
  // effectively using 1-based indexing, rather than the usual 0.
  // A numbered argument must NOT set field GqlQueryArg.name.
  // For each binding site numbered i in query_string,
  // there must be an ith numbered argument.
  // The inverse must also be true.
  repeated GqlQueryArg number_arg = 4;
}

// A binding argument for a GQL query.
// Exactly one of fields value and cursor must be set.
message GqlQueryArg {
  // Must match regex "[A-Za-z_$][A-Za-z_$0-9]*".
  // Must not match regex "__.*__".
  // Must not be "".
  optional string name = 1;
  optional Value value = 2;
  optional bytes cursor = 3;
}

// A batch of results produced by a query.
message QueryResultBatch {
  // The possible values for the 'more_results' field.
  enum MoreResultsType {
    NOT_FINISHED = 1;  // There are additional batches to fetch from this query.
    MORE_RESULTS_AFTER_LIMIT = 2;  // The query is finished, but there are more
                                   // results after the limit.
    NO_MORE_RESULTS = 3;  // The query has been exhausted.
  }

  // The result type for every entity in entityResults.
  required EntityResult.ResultType entity_result_type = 1;
  // The results for this batch.
  repeated EntityResult entity_result = 2;

  // A cursor that points to the position after the last result in the batch.
  // May be absent.
  optional bytes /* serialized QueryCursor */ end_cursor = 4;

  // The state of the query after the current batch.
  required MoreResultsType more_results = 5;

  // The number of results skipped because of <code>Query.offset</code>.
  optional int32 skipped_results = 6;
}

// A set of changes to apply.
//
// No entity in this message may have a reserved property name,
// not even a property in an entity in a value.
// No value in this message may have meaning 18,
// not even a value in an entity in another value.
//
// If entities with duplicate keys are present, an arbitrary choice will
// be made as to which is written.
message Mutation {
  // Entities to upsert.
  // Each upserted entity's key must have a complete path and
  // must not be reserved/read-only.
  repeated Entity upsert = 1;
  // Entities to update.
  // Each updated entity's key must have a complete path and
  // must not be reserved/read-only.
  repeated Entity update = 2;
  // Entities to insert.
  // Each inserted entity's key must have a complete path and
  // must not be reserved/read-only.
  repeated Entity insert = 3;
  // Insert entities with a newly allocated ID.
  // Each inserted entity's key must omit the final identifier in its path and
  // must not be reserved/read-only.
  repeated Entity insert_auto_id = 4;
  // Keys of entities to delete.
  // Each key must have a complete key path and must not be reserved/read-only.
  repeated Key delete = 5;
  // Ignore a user specified read-only period. Optional.
  optional bool force = 6;
}

// The result of applying a mutation.
message MutationResult {
  // Number of index writes.
  required int32 index_updates = 1;
  // Keys for <code>insertAutoId</code> entities. One per entity from the
  // request, in the same order.
  repeated Key insert_auto_id_key = 2;
}

// Options shared by read requests.
message ReadOptions {
  enum ReadConsistency {
    DEFAULT = 0;
    STRONG = 1;
    EVENTUAL = 2;
  }

  // The read consistency to use.
  // Cannot be set when transaction is set.
  // Lookup and ancestor queries default to STRONG, global queries default to
  // EVENTUAL and cannot be set to STRONG.
  optional ReadConsistency read_consistency = 1 [default=DEFAULT];

  // The transaction to use. Optional.
  optional bytes /* serialized Transaction */ transaction = 2;
}

// The request for Lookup.
message LookupRequest {

  // Options for this lookup request. Optional.
  optional ReadOptions read_options = 1;
  // Keys of entities to look up from the datastore.
  repeated Key key = 3;
}

// The response for Lookup.
message LookupResponse {

  // The order of results in these fields is undefined and has no relation to
  // the order of the keys in the input.

  // Entities found as ResultType.FULL entities.
  repeated EntityResult found = 1;

  // Entities not found as ResultType.KEY_ONLY entities.
  repeated EntityResult missing = 2;

  // A list of keys that were not looked up due to resource constraints.
  repeated Key deferred = 3;
}


// The request for RunQuery.
message RunQueryRequest {

  // The options for this query.
  optional ReadOptions read_options = 1;

  // Entities are partitioned into subsets, identified by a dataset (usually
  // implicitly specified by the project) and namespace ID. Queries are scoped
  // to a single partition.
  // This partition ID is normalized with the standard default context
  // partition ID, but all other partition IDs in RunQueryRequest are
  // normalized with this partition ID as the context partition ID.
  optional PartitionId partition_id = 2;

  // The query to run.
  // Either this field or field gql_query must be set, but not both.
  optional Query query = 3;
  // The GQL query to run.
  // Either this field or field query must be set, but not both.
  optional GqlQuery gql_query = 7;
}

// The response for RunQuery.
message RunQueryResponse {

  // A batch of query results (always present).
  optional QueryResultBatch batch = 1;

}

// The request for BeginTransaction.
message BeginTransactionRequest {

  enum IsolationLevel {
    SNAPSHOT = 0;  // Read from a consistent snapshot. Concurrent transactions
                   // conflict if their mutations conflict. For example:
                   // Read(A),Write(B) may not conflict with Read(B),Write(A),
                   // but Read(B),Write(B) does conflict with Read(B),Write(B).
    SERIALIZABLE = 1; // Read from a consistent snapshot. Concurrent
                      // transactions conflict if they cannot be serialized.
                      // For example Read(A),Write(B) does conflict with
                      // Read(B),Write(A) but Read(A) may not conflict with
                      // Write(A).
  }

  // The transaction isolation level.
  optional IsolationLevel isolation_level = 1 [default=SNAPSHOT];
}

// The response for BeginTransaction.
message BeginTransactionResponse {

  // The transaction identifier (always present).
  optional bytes /* serialized Transaction */ transaction = 1;
}

// The request for Rollback.
message RollbackRequest {

  // The transaction identifier, returned by a call to
  // <code>beginTransaction</code>.
  required bytes /* serialized Transaction */ transaction = 1;
}

// The response for Rollback.
message RollbackResponse {
// Empty
}

// The request for Commit.
message CommitRequest {

  enum Mode {
    TRANSACTIONAL = 1;
    NON_TRANSACTIONAL = 2;
  }

  // The transaction identifier, returned by a call to
  // <code>beginTransaction</code>. Must be set when mode is TRANSACTIONAL.
  optional bytes /* serialized Transaction */ transaction = 1;
  // The mutation to perform. Optional.
  optional Mutation mutation = 2;
  // The type of commit to perform. Either TRANSACTIONAL or NON_TRANSACTIONAL.
  optional Mode mode = 5 [default=TRANSACTIONAL];
}

// The response for Commit.
message CommitResponse {

  // The result of performing the mutation (if any).
  optional MutationResult mutation_result = 1;
}

// The request for AllocateIds.
message AllocateIdsRequest {

  // A list of keys with incomplete key paths to allocate IDs for.
  // No key may be reserved/read-only.
  repeated Key key = 1;
}

// The response for AllocateIds.
message AllocateIdsResponse {

  // The keys specified in the request (in the same order), each with
  // its key path completed with a newly allocated ID.
  repeated Key key = 1;
}

// Each rpc normalizes the partition IDs of the keys in its input entities,
// and always returns entities with keys with normalized partition IDs.
// (Note that applies to all entities, including entities in values.)
service DatastoreService {
  // Look up some entities by key.
  rpc Lookup(LookupRequest) returns (LookupResponse) {
  };
  // Query for entities.
  rpc RunQuery(RunQueryRequest) returns (RunQueryResponse) {
  };
  // Begin a new transaction.
  rpc BeginTransaction(BeginTransactionRequest) returns (BeginTransactionResponse) {
  };
  // Commit a transaction, optionally creating, deleting or modifying some
  // entities.
  rpc Commit(CommitRequest) returns (CommitResponse) {
  };
  // Roll back a transaction.
  rpc Rollback(RollbackRequest) returns (RollbackResponse) {
  };
  // Allocate IDs for incomplete keys (useful for referencing an entity before
  // it is inserted).
  rpc AllocateIds(AllocateIdsRequest) returns (AllocateIdsResponse) {
  };
}
