//
// Copyright 2019 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.
//

syntax = "proto2";

package zetasql.local_service;

import "google/protobuf/empty.proto";
import "google/protobuf/descriptor.proto";
import "zetasql/parser/parse_tree.proto";
import "zetasql/proto/function.proto";
import "zetasql/proto/options.proto";
import "zetasql/proto/simple_catalog.proto";
import "zetasql/public/formatter_options.proto";
import "zetasql/public/options.proto";
import "zetasql/public/parse_resume_location.proto";
import "zetasql/public/simple_table.proto";
import "zetasql/public/type.proto";
import "zetasql/public/value.proto";
import "zetasql/resolved_ast/resolved_ast.proto";

option java_package = "com.google.zetasql";
option java_outer_classname = "LocalService";

// Note that *all* service RPCs are locked down to only be authorized by
// the user that started the ZetaSql service.  This disallows random users
// from sending requests to this service to be executed on behalf of the
// user that started the service.  Given that this service does not currently
// provide access to external data, this lockdown is precautionary and
// conservative.  But the lockdown will be necessary once the reference
// implementation is extended to execute full queries over external data,
// since we cannot allow random users to run queries over data accessible by
// the (different) user that started the ZetaSql service.
service ZetaSqlLocalService {

  // Prepare the sql expression in PrepareRequest with given columns and
  // parameters with zetasql::PreparedExpression and return the result
  // type as PrepareResponse. The prepared expression will be kept at server
  // side which can be referred to with the returned id.
  rpc Prepare(PrepareRequest) returns (PrepareResponse) {
  }
  // Evaluate the prepared expression in EvaluateRequest with given columns and
  // parameters with zetasql::PreparedExpression and return the result
  // and value as EvaluateResponse.
  rpc Evaluate(EvaluateRequest) returns (EvaluateResponse) {
  }
  // Evaluate a Stream of prepared expression batches and return a stream of
  // result batches. Requests will be evaluated and returned in the same order
  // as received, but batches may be packed differently.
  rpc EvaluateStream(stream EvaluateRequestBatch)
      returns (stream EvaluateResponseBatch) {
  }
  // Cleanup the prepared expression kept at server side with given id.
  rpc Unprepare(UnprepareRequest) returns (google.protobuf.Empty) {
  }
  // Prepare the sql query in PrepareQueryRequest with given parameters
  // with zetasql::PreparedQuery and return the result type
  // as PrepareQueryResponse. The prepared query will be kept at server
  // side which can be referred to with the returned id.
  rpc PrepareQuery(PrepareQueryRequest) returns (PrepareQueryResponse) {
  }
  // Cleanup the prepared query kept at server side with given id.
  rpc UnprepareQuery(UnprepareQueryRequest) returns (google.protobuf.Empty) {
  }
  // Evaluate the prepared query in EvaluateQueryRequest with given parameters
  // with zetasql::PreparedQuery and return the result and value
  // as EvaluateQueryResponse.
  rpc EvaluateQuery(EvaluateQueryRequest) returns (EvaluateQueryResponse) {
  }
  // Evaluate a Stream of prepared query batches and return a stream of
  // result batches. Requests will be evaluated and returned in the same order
  // as received, but batches may be packed differently.
  rpc EvaluateQueryStream(stream EvaluateQueryBatchRequest)
      returns (stream EvaluateQueryBatchResponse) {
  }
  // Prepare the sql modify statement in PrepareModifyRequest
  // with given parameters with zetasql::PreparedModify and return
  // the result type as PrepareModifyResponse. The prepared modify will be kept
  // at server side which can be referred to with the returned id.
  rpc PrepareModify(PrepareModifyRequest) returns (PrepareModifyResponse) {
  }
  // Cleanup the prepared modify kept at server side with given id.
  rpc UnprepareModify(UnprepareModifyRequest) returns (google.protobuf.Empty) {
  }
  // Evaluate the prepared modify statement in EvaluateModifyRequest
  // with given parameters with zetasql::PreparedModify and return
  // the result and value as EvaluateModifyResponse.
  // Note: This API does not actually modify the contents of any of the  tables
  // being accessed
  rpc EvaluateModify(EvaluateModifyRequest) returns (EvaluateModifyResponse) {
  }
  // Evaluate a Stream of prepared modify batches and return a stream of
  // result batches. Requests will be evaluated and returned in the same order
  // as received, but batches may be packed differently.
  rpc EvaluateModifyStream(stream EvaluateModifyBatchRequest)
      returns (stream EvaluateModifyBatchResponse) {
  }
  // Get a table schema from a proto.
  rpc GetTableFromProto(TableFromProtoRequest) returns (SimpleTableProto) {
  }
  // Register a catalog at server side so that it can be reused.
  rpc RegisterCatalog(RegisterCatalogRequest) returns (RegisterResponse) {
  }
  // Analyze a SQL statement, return the resolved AST and an optional byte
  // position if end of input is not yet reached.
  rpc Analyze(AnalyzeRequest) returns (AnalyzeResponse) {
  }
  // Build a SQL statement or expression from a resolved AST.
  rpc BuildSql(BuildSqlRequest) returns (BuildSqlResponse) {
  }
  // Validate statement and extract table names.
  rpc ExtractTableNamesFromStatement(ExtractTableNamesFromStatementRequest)
      returns (ExtractTableNamesFromStatementResponse) {
  }

  // Validate statement, return table names and a byte offset of the next
  // statement.
  //
  // Statements are separated by semicolons. A final semicolon is not required
  // on the last statement. Whitespace between statements is ignored. Whitespace
  // after that last semicolon is treated as a separate empty statement and
  // would cause a parse error.
  //
  // Full text passed to this method does not need to be syntactically valid;
  // only the current statement pointed by parse_resume_location should be
  // parseable.
  //
  // Passing incorrect parse_resume_position (negative or pointing outside
  // input data) would result in a generic::internal error.
  //
  // If language options are not provided, the parser would use a default
  // LanguageOptions object. Refer to the LanguageOptions class definition
  // for the exact implementation details.
  //
  // Client can detect that there's no more SQL statements to parse
  // by comparing this byte offset to the overall input length
  // (similar to Analyze method)
  //
  // After a parse error, parse_resume_location is not available; it's up
  // to client to try and recover from parse errors.
  //
  // Unsupported statements (e.g. SET statements from F1 dialect) are treated
  // as parse errors.
  //
  // Note: statements are handled by ParseNextStatement function.
  // Documentation on that function is the source of truth on the behavior.
  //
  rpc ExtractTableNamesFromNextStatement(
      ExtractTableNamesFromNextStatementRequest)
      returns (ExtractTableNamesFromNextStatementResponse) {
  }
  // Format a SQL statement (see also (broken link))
  rpc FormatSql(FormatSqlRequest) returns (FormatSqlResponse) {
  }
  // Format a SQL statement using the new lenient_formatter.h
  rpc LenientFormatSql(FormatSqlRequest) returns (FormatSqlResponse) {
  }
  // Cleanup a registered catalog.
  rpc UnregisterCatalog(UnregisterRequest) returns (google.protobuf.Empty) {
  }
  // Get ZetaSQL builtin functions specified by given options.
  rpc GetBuiltinFunctions(ZetaSQLBuiltinFunctionOptionsProto)
      returns (GetBuiltinFunctionsResponse) {
  }
  // Gets ZetaSQL lanauge options.
  rpc GetLanguageOptions(LanguageOptionsRequest)
      returns (LanguageOptionsProto) {
  }
  // Gets ZetaSQL analyzer options.
  rpc GetAnalyzerOptions(AnalyzerOptionsRequest)
      returns (AnalyzerOptionsProto) {
  }
  // Return the parsed SQL statement.
  rpc Parse(ParseRequest) returns (ParseResponse) {
  }
}

// Defines how to construct DescriptorPool objects in the local service.

// A DescriptorPool conceptually provides a mapping from a protobuf
// message or enum full name (e.g. "zetasql.ValueProto") to an in memory
// descriptor api appropriate to each language.
//
// ZetaSQL as an API generally allows multiple DescriptorPools. The main use
// of DescriptorPools is when performing type lookups in Catalog objects.
// For serialization, each object that must encode a proto type
// (zetasql.ProtoTypeProto) object lists both the full name and an index
// into a list of DescriptorPools.
//
// DescriptorPools themselves are usually encoded as google.protobuf.FileDescriptorSet
// messages. Historically, a simple `repeated google.protobuf.FileDescriptorSet` was
// used.
//
// However, this lead to strange issues when dealing with reentrant calls,
// such as when using registered catalogs or PreparedExpressions.
//
// A DescriptorPoolListProto helps work around these issues.
//
// When using a DescriptorPoolListProto, the _client_ is responsible for
// providing all DescriptorPools that may be needed to decode the request
// _and_ response. Here is a list of all inputs and outputs that may require
// proto encoding.
//
// ResolvedAST - The ResolvedAST may include some nodes that directly encode
//               protos, such as the types used in function default values.
//               Everything that zetasql uses _by_default_  is encoded in
//               in the "Builtin" DescriptorPool.  Because some operations
//               require "same-instance" equality, it is important to always
//               provide the builtin descriptor pool for all calls.
// Catalog:Tables - Tables may include protos (such as a column with a proto)
//                  while it isn't necessary for the _catalog_ to provide
//                  lookups on these types, they must still be serialized.
// SimpleCatalog:DescriporPool - a simple catalog _may_ have a DescriptorPool
//                               provided to add all of Message types in that
//                               pool to the catalog. I.e. if you want to allow
//                               `select new zetasql_test__.KitchenSinkPB(...)`
//                               the simple catalog must have a DescriptorPool
//                               set to perform the lookup.
// QueryParameters - these can, in theory, have proto types, and those types
//                   might not exist in any of the above.
// AnalyzerOptions - lots of weird things can be typed, such as system variables
//                   hints, options (also again, QueryParameters).
//
// It is also worth noting that having an entry in this list, does not make a
// given set of protos automatically available within the language generally
// i.e. if you have some protos in QueryParameters, that does not mean you
// can use that proto type in catalog lookups.
//
// Response protos will _never_ include a list of protos, the client must
// provide all possible DescriptorPools, and must remember their order in this
// list, as the returned responses will use index offsets from this list, in the
// same order.
message DescriptorPoolListProto {
  message Builtin {}
  message Definition {
    oneof definition {
      // A literal FileDescriptorSet proto which will be used to construct
      // a DescriptorPool. This must include the full set of transitive
      // dependencies _in_dependency_order_.
      google.protobuf.FileDescriptorSet file_descriptor_set = 1;

      // References an already registered descriptor pool. Note, this may
      // be used to reference the builtin descriptor pool, if the registered_id
      // is known. Registered DescriptorPools are always owned by some other
      // object (which isn't defined here), and will become unregistered
      // automatically when that owning object is unregistered - future
      // references will be an error.
      int64 registered_id = 2;

      // The 'builtin' descriptor set. This is defined by an explicit set of
      // protos used for encoding and decoding local service rpcs. Example:
      //
      //   zetasql.functions.DateTimestampPart
      //
      // The builtin DescriptorPool may be assigned a registered_id, in which
      // case it is allowable to use `registered_id` instead of this object.
      // It is strongly not recommended that catalogs use the builtin catalog.
      // since its exact composition is not defined.
      Builtin builtin = 3;
    }
  }
  // A list of definitions that describe how to construct or find DescriptorPool
  // to be used in encoding. The order is relevant, as encoding of other
  // ProtoTypeProto (and a few other objects) will reference DescriptorPools
  // by index in this list.
  repeated Definition definitions = 1;
}

// Ids associated with each entry in DescriptorPoolListProto
message DescriptorPoolIdList {
  repeated int64 registered_ids = 1 [packed = true];
}

message PrepareRequest {
  optional string sql = 1;
  optional AnalyzerOptionsProto options = 2;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 6;

  optional SimpleCatalogProto simple_catalog = 4;
  optional int64 registered_catalog_id = 5;

  reserved 3;
}

message PreparedState {
  optional int64 prepared_expression_id = 1;
  optional TypeProto output_type = 2;
  // No file_descriptor_set returned. Use the same descriptor pools as sent in
  // the request deserialize the type.

  repeated string referenced_columns = 3;
  repeated string referenced_parameters = 4;
  optional int64 positional_parameter_count = 5;

  // An ordered list of descriptor_pool_ids that match (in length and order)
  // the descriptor_pool_list sent in RegisterCatalogRequest.
  // This may be necessary in the case of a PreparedExpression.
  optional DescriptorPoolIdList descriptor_pool_id_list = 6;
}

message PrepareResponse {
  // Never add fields to this proto, add them to PreparedState instead.
  optional PreparedState prepared = 3;
  reserved 1, 2;
}

message EvaluateRequest {
  optional string sql = 1;

  message Parameter {
    optional string name = 1;
    optional ValueProto value = 2;
    reserved 3;
  }

  repeated Parameter columns = 2;
  repeated Parameter params = 3;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 7;

  // Set if the expression is already prepared, in which case sql and
  // file_descriptor_set will be ignored.
  optional int64 prepared_expression_id = 5;
  optional AnalyzerOptionsProto options = 6;

  reserved 4;
}

message EvaluateResponse {
  optional ValueProto value = 1;
  optional PreparedState prepared = 4;
  reserved 2, 3;
}

message EvaluateRequestBatch {
  repeated EvaluateRequest request = 1;
}

message EvaluateResponseBatch {
  repeated EvaluateResponse response = 1;
}

message UnprepareRequest {
  optional int64 prepared_expression_id = 1;
}

message PrepareQueryRequest {
  optional string sql = 1;
  optional AnalyzerOptionsProto options = 2;
  optional DescriptorPoolListProto descriptor_pool_list = 3;
  oneof catalog {
    SimpleCatalogProto simple_catalog = 4;
    // If using the registered_catalog_id, the service will return an error
    // if the table_content is provide as well.
    int64 registered_catalog_id = 5;
  }

  // A map between a table name and its content which enable
  // users to set the content for their tables.
  // This is needed because the SimpleTableProto does not provide such a field.
  // When using a registered catalog, if the table_content is provided
  // then an error will be returned.
  // At the moment, because we don't have a concrete use case
  // where the user needs to update the content of any of the tables
  // after the catalog has been registered, we did not implement the required
  // logic within the service. This could change once such an use case occurs.
  map<string, TableContent> table_content = 6;
}

message PreparedQueryState {
  optional int64 prepared_query_id = 1;

  repeated string referenced_parameters = 2;
  optional int64 positional_parameter_count = 3;

  // The list of columns representing the resulting table
  repeated SimpleColumnProto columns = 4;

  // An ordered list of descriptor_pool_ids that match (in length and order)
  // the descriptor_pool_list sent in PrepareQueryRequest.
  // This may be necessary in the case of a PreparedQuery.
  optional DescriptorPoolIdList descriptor_pool_id_list = 5;
}

message PrepareQueryResponse {
  optional PreparedQueryState prepared = 1;
}

message Parameter {
  optional string name = 1;
  optional ValueProto value = 2;
  reserved 3;
}

message UnprepareQueryRequest {
  optional int64 prepared_query_id = 1;
}

message EvaluateQueryRequest {
  optional string sql = 1;
  optional AnalyzerOptionsProto options = 2;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 3;

  oneof catalog {
    SimpleCatalogProto simple_catalog = 4;
    // If using the registered_catalog_id, the service will return an error
    // if the table_content is provide as well.
    int64 registered_catalog_id = 5;
    // Set if the query statement is already prepared, in which case
    // sql, options and descriptor_pool_list will be ignored.
    // An error is being return if a prepared query is being used and
    // the table_content is provided as well.
    int64 prepared_query_id = 6;
  }

  // A map between a table name and its content which enable
  // users to set the content for their tables.
  // This is needed because the SimpleTableProto does not provide such a field.
  // When using a registered catalog or a prepared query statement,
  // if the table_content is provided then an error will be returned.
  // At the moment, because we don't have a concrete use case
  // where the user needs to update the content of any of the tables
  // after the catalog has been registered, we did not implement the required
  // logic within the service. This could change once such an use case occurs.
  map<string, TableContent> table_content = 7;

  repeated Parameter params = 8;
}

message EvaluateQueryResponse {
  // The content
  optional TableContent content = 1;
  // This contains the schema for the results table
  optional PreparedQueryState prepared = 2;
}

message EvaluateQueryBatchRequest {
  repeated EvaluateQueryRequest request = 1;
}

message EvaluateQueryBatchResponse {
  repeated EvaluateQueryResponse response = 1;
}

message PrepareModifyRequest {
  // This contains a single SQL statement of type INSERT, UPDATE or DELETE
  optional string sql = 1;
  optional AnalyzerOptionsProto options = 2;
  optional DescriptorPoolListProto descriptor_pool_list = 3;
  oneof catalog {
    SimpleCatalogProto simple_catalog = 4;
    // If using the registered_catalog_id, the service will return an error
    // if the table_content is provide as well.
    int64 registered_catalog_id = 5;
  }

  // A map between a table name and its content which enable
  // users to set the content for their tables.
  // This is needed because the SimpleTableProto does not provide such a field.
  // When using a registered catalog, if the table_content is provided
  // then an error will be returned.
  // At the moment, because we don't have a concrete use case
  // where the user needs to update the content of any of the tables
  // after the catalog has been registered, we did not implement the required
  // logic within the service. This could change once such an use case occurs.
  map<string, TableContent> table_content = 6;
}

message PreparedModifyState {
  optional int64 prepared_modify_id = 1;

  repeated string referenced_parameters = 2;
  optional int64 positional_parameter_count = 3;

  // An ordered list of descriptor_pool_ids that match (in length and order)
  // the descriptor_pool_list sent in PrepareModifyRequest.
  // This may be necessary in the case of a PreparedModify.
  optional DescriptorPoolIdList descriptor_pool_id_list = 5;
}

message PrepareModifyResponse {
  optional PreparedModifyState prepared = 1;
}

message UnprepareModifyRequest {
  optional int64 prepared_modify_id = 1;
}

message EvaluateModifyRequest {
  // This contains a single SQL statement of type INSERT, UPDATE or DELETE
  optional string sql = 1;
  optional AnalyzerOptionsProto options = 2;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 3;

  oneof catalog {
    SimpleCatalogProto simple_catalog = 4;
    // If using the registered_catalog_id, the service will return an error
    // if the table_content is provide as well.
    int64 registered_catalog_id = 5;
    // Set if the modify statement is already prepared, in which case
    // sql, options and descriptor_pool_list will be ignored.
    // An error is being return if a prepared modify is being used and
    // the table_content is provided as well.
    int64 prepared_modify_id = 6;
  }

  // A map between a table name and its content which enable
  // users to set the content for their tables.
  // This is needed because the SimpleTableProto does not provide such a field.
  // When using a registered catalog or a prepared modify statement,
  // if the table_content is provided then an error will be returned.
  // At the moment, because we don't have a concrete use case
  // where the user needs to update the content of any of the tables
  // after the catalog has been registered, we did not implement the required
  // logic within the service. This could change once such an use case occurs.
  map<string, TableContent> table_content = 7;

  repeated Parameter params = 8;
}

message EvaluateModifyResponse {
  // The name of the table that has been modified
  optional string table_name = 1;

  // This represents a row that was modified by the sql statement
  message Row {
    enum Operation {
      UNKNOWN = 0;
      INSERT = 1;
      DELETE = 2;
      UPDATE = 3;
    }

    // The DML operation performed on the current row
    optional Operation operation = 1;
    // The new values for all cells inside the row after executing
    // the sql statement
    repeated ValueProto cell = 2;
    // The old values of the primary keys before executing the sql statement
    repeated ValueProto old_primary_key = 3;
  }

  // This will contain the list of rows being touched
  repeated Row content = 2;

  optional PreparedModifyState prepared = 3;
}

message EvaluateModifyBatchRequest {
  repeated EvaluateModifyRequest request = 1;
}

message EvaluateModifyBatchResponse {
  repeated EvaluateModifyResponse response = 1;
}

message TableFromProtoRequest {
  optional ProtoTypeProto proto = 1;
  optional google.protobuf.FileDescriptorSet file_descriptor_set = 2;
}

message AnalyzeRequest {
  optional AnalyzerOptionsProto options = 1;
  optional SimpleCatalogProto simple_catalog = 2;

  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 9;

  // Set if using a registered catalog, in which case simple_catalog and
  // file_descriptor_set will be ignored.
  optional int64 registered_catalog_id = 4;

  oneof target {
    // Single statement.
    string sql_statement = 5;
    // Multiple statement.
    ParseResumeLocationProto parse_resume_location = 6;
    // Expression.
    string sql_expression = 8;
  }

  reserved 3, 7;
}

message AnalyzeResponse {
  oneof result {
    AnyResolvedStatementProto resolved_statement = 1;
    AnyResolvedExprProto resolved_expression = 3;
  }
  // Set only if the request had parse_resume_location.
  optional int32 resume_byte_position = 2;
}

message BuildSqlRequest {
  optional SimpleCatalogProto simple_catalog = 1;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 6;

  // Set if using a registered catalog, in which case simple_catalog and
  // file_descriptor_set will be ignored.
  optional int64 registered_catalog_id = 3;

  oneof target {
    AnyResolvedStatementProto resolved_statement = 4;
    AnyResolvedExprProto resolved_expression = 5;
  }
  reserved 2;
}

message BuildSqlResponse {
  optional string sql = 1;
}

message ExtractTableNamesFromStatementRequest {
  optional string sql_statement = 1;

  // If language options are not provided, the parser would use a default
  // LanguageOptions object. See ExtractTableNamesFromNextStatementRequest
  // for further details.
  optional LanguageOptionsProto options = 2;

  // sql_statement is interpreted as a script rather than a single statement.
  optional bool allow_script = 3;
}

message ExtractTableNamesFromStatementResponse {
  repeated TableName table_name = 1;

  message TableName {
    repeated string table_name_segment = 1;
  }
}

message ExtractTableNamesFromNextStatementRequest {
  required ParseResumeLocationProto parse_resume_location = 1;

  // If language options are not provided, the parser would use a default
  // LanguageOptions object. Refer to the LanguageOptions class definition
  // for the exact implementation details.
  //
  // Note that There may be untrivial differences between providing an empty
  // options/ field and not providing one which depending on the
  // LanguageOptions implementation details.
  //
  // The current implementation of the LanguageOptions class has default value
  // of supported_statement_kinds set to {RESOLVED_QUERY_STMT}. This means that
  // if you don't provide any options, then you're limited to this one
  // kind of statement. If you provide an empty options proto, you're
  // explicitly setting supported_statement_kinds to an empty set,
  // allowing all types of statements.
  //
  // See LanguageOptions::SupportsStatementKind and
  // LanguageOptions::supported_statement_kinds_ definitions for the source of
  // truth on this example.
  optional LanguageOptionsProto options = 2;
}

message ExtractTableNamesFromNextStatementResponse {
  message TableName {
    repeated string table_name_segment = 1;
  }

  repeated TableName table_name = 1;
  optional int32 resume_byte_position = 2;
}

message FormatSqlRequest {
  optional string sql = 1;
  // TODO: Options are supported only by LenientFormatSql.
  optional FormatterOptionsProto options = 2;

  // Specific ranges to format, in bytes. If empty, the entire input is
  // formatted.
  repeated FormatterRangeProto byte_ranges = 3;
}

message FormatSqlResponse {
  optional string sql = 1;
}

message RegisterCatalogRequest {
  optional SimpleCatalogProto simple_catalog = 1;
  // This list defines how to construct the list of DescriptorPools for
  // use during deserialization.
  optional DescriptorPoolListProto descriptor_pool_list = 3;

  // A map between a table name and its content which enable
  // users to set the content for their tables
  // This is needed because the SimpleTableProto does not provide such a field
  map<string, TableContent> table_content = 4;

  reserved 2;
}

message TableContent {
  optional TableData table_data = 1;
}

message TableData {
  // A list of Values representing one single row in the table
  message Row {
    repeated ValueProto cell = 1;
  }
  repeated Row row = 1;
}

message RegisterResponse {
  optional int64 registered_id = 1;
  // An ordered list of descriptor_pool_ids that match (in length and order)
  // the descriptor_pool_list sent in RegisterCatalogRequest.
  optional DescriptorPoolIdList descriptor_pool_id_list = 2;
}

message UnregisterRequest {
  optional int64 registered_id = 1;
}

message GetBuiltinFunctionsResponse {
  repeated FunctionProto function = 1;
  map<string, TypeProto> types = 2;
  // This implicitly requires the builtin descriptor pool for deserialization.
}

message LanguageOptionsRequest {
  optional bool maximum_features = 1;
  optional LanguageVersion language_version = 2;
}

message AnalyzerOptionsRequest {}

message ParseRequest {
  oneof target {
    // Single statement.
    string sql_statement = 1;
    // Multiple statements.
    ParseResumeLocationProto parse_resume_location = 3;
  }

  optional LanguageOptionsProto options = 2;

  // sql_statement is interpreted as a script rather than a single statement.
  // parse_resume_location is allowed to contain script statements.
  optional bool allow_script = 4;
}

message ParseResponse {
  oneof result {
    AnyASTStatementProto parsed_statement = 1;
    ASTScriptProto parsed_script = 3;
  }
  // Set only if the request had parse_resume_location.
  optional int32 resume_byte_position = 2;
}
