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

// resolved_ast.proto GENERATED FROM resolved_ast.proto.template
syntax = "proto2";

package zetasql;

option java_package = "com.google.zetasql";
option java_multiple_files = true;
option java_outer_classname = "ZetaSQLResolvedAST";

option optimize_for = CODE_SIZE;

import "zetasql/public/annotation.proto";
import "zetasql/public/proto/type_annotation.proto";
import "zetasql/public/type.proto";
import "zetasql/public/type_modifiers.proto";
import "zetasql/public/type_parameters.proto";
import "zetasql/proto/function.proto";
import "zetasql/resolved_ast/serialization.proto";
import "zetasql/resolved_ast/resolved_ast_enums.proto";

// AnyResolvedNodeProto is a container that can hold at most one proto
// representation of a ResolvedNode
message AnyResolvedNodeProto {
  oneof node {
    AnyResolvedArgumentProto resolved_argument_node = 1;
    AnyResolvedExprProto resolved_expr_node = 2;
    AnyResolvedScanProto resolved_scan_node = 18;
    AnyResolvedStatementProto resolved_statement_node = 36;
  }
}

// Argument nodes are not self-contained nodes in the tree.  They exist
// only to describe parameters to another node (e.g. columns in an OrderBy).
// This node is here for organizational purposes only, to cluster these
// argument nodes.
message AnyResolvedArgumentProto {
  oneof node {
    ResolvedMakeProtoFieldProto resolved_make_proto_field_node = 14;
    ResolvedColumnHolderProto resolved_column_holder_node = 23;
    ResolvedComputedColumnProto resolved_computed_column_node = 32;
    ResolvedOrderByItemProto resolved_order_by_item_node = 33;
    ResolvedOutputColumnProto resolved_output_column_node = 34;
    ResolvedWithEntryProto resolved_with_entry_node = 52;
    ResolvedOptionProto resolved_option_node = 53;
    ResolvedWindowPartitioningProto resolved_window_partitioning_node = 54;
    ResolvedWindowOrderingProto resolved_window_ordering_node = 55;
    ResolvedWindowFrameProto resolved_window_frame_node = 56;
    ResolvedAnalyticFunctionGroupProto resolved_analytic_function_group_node = 57;
    ResolvedWindowFrameExprProto resolved_window_frame_expr_node = 58;
    ResolvedDMLValueProto resolved_dmlvalue_node = 59;
    ResolvedAssertRowsModifiedProto resolved_assert_rows_modified_node = 61;
    ResolvedInsertRowProto resolved_insert_row_node = 62;
    ResolvedUpdateItemProto resolved_update_item_node = 65;
    ResolvedPrivilegeProto resolved_privilege_node = 67;
    ResolvedArgumentDefProto resolved_argument_def_node = 77;
    ResolvedArgumentListProto resolved_argument_list_node = 79;
    ResolvedFunctionArgumentProto resolved_function_argument_node = 82;
    ResolvedFunctionSignatureHolderProto resolved_function_signature_holder_node = 84;
    ResolvedAggregateHavingModifierProto resolved_aggregate_having_modifier_node = 85;
    ResolvedColumnDefinitionProto resolved_column_definition_node = 91;
    ResolvedSetOperationItemProto resolved_set_operation_item_node = 94;
    ResolvedIndexItemProto resolved_index_item_node = 96;
    ResolvedMergeWhenProto resolved_merge_when_node = 100;
    ResolvedUpdateArrayItemProto resolved_update_array_item_node = 102;
    ResolvedColumnAnnotationsProto resolved_column_annotations_node = 104;
    ResolvedGeneratedColumnInfoProto resolved_generated_column_info_node = 105;
    ResolvedModelProto resolved_model_node = 109;
    AnyResolvedAlterActionProto resolved_alter_action_node = 116;
    ResolvedUnnestItemProto resolved_unnest_item_node = 126;
    ResolvedReplaceFieldItemProto resolved_replace_field_item_node = 128;
    ResolvedConnectionProto resolved_connection_node = 141;
    ResolvedExecuteImmediateArgumentProto resolved_execute_immediate_argument_node = 143;
    ResolvedDescriptorProto resolved_descriptor_node = 144;
    ResolvedExtendedCastElementProto resolved_extended_cast_element_node = 151;
    ResolvedWithPartitionColumnsProto resolved_with_partition_columns_node = 153;
    ResolvedExtendedCastProto resolved_extended_cast_node = 158;
    ResolvedInlineLambdaProto resolved_inline_lambda_node = 159;
    AnyResolvedConstraintProto resolved_constraint_node = 162;
    ResolvedPivotColumnProto resolved_pivot_column_node = 166;
    ResolvedReturningClauseProto resolved_returning_clause_node = 170;
    ResolvedUnpivotArgProto resolved_unpivot_arg_node = 171;
    ResolvedFilterFieldArgProto resolved_filter_field_arg_node = 173;
    ResolvedTableAndColumnInfoProto resolved_table_and_column_info_node = 179;
    ResolvedColumnDefaultValueProto resolved_column_default_value_node = 188;
    ResolvedObjectUnitProto resolved_object_unit_node = 200;
    ResolvedAuxLoadDataPartitionFilterProto resolved_aux_load_data_partition_filter_node = 222;
    ResolvedCreateModelAliasedQueryProto resolved_create_model_aliased_query_node = 226;
    ResolvedSequenceProto resolved_sequence_node = 233;
    ResolvedGroupingSetMultiColumnProto resolved_grouping_set_multi_column_node = 237;
    AnyResolvedGroupingSetBaseProto resolved_grouping_set_base_node = 238;
    ResolvedGroupingCallProto resolved_grouping_call_node = 241;
  }
}

message ResolvedArgumentProto {
  optional ResolvedNodeProto parent = 1;

}

message AnyResolvedExprProto {
  oneof node {
    ResolvedLiteralProto resolved_literal_node = 3;
    ResolvedParameterProto resolved_parameter_node = 4;
    ResolvedExpressionColumnProto resolved_expression_column_node = 5;
    ResolvedColumnRefProto resolved_column_ref_node = 6;
    AnyResolvedFunctionCallBaseProto resolved_function_call_base_node = 7;
    ResolvedCastProto resolved_cast_node = 11;
    ResolvedMakeStructProto resolved_make_struct_node = 12;
    ResolvedMakeProtoProto resolved_make_proto_node = 13;
    ResolvedGetStructFieldProto resolved_get_struct_field_node = 15;
    ResolvedGetProtoFieldProto resolved_get_proto_field_node = 16;
    ResolvedSubqueryExprProto resolved_subquery_expr_node = 17;
    ResolvedDMLDefaultProto resolved_dmldefault_node = 60;
    ResolvedArgumentRefProto resolved_argument_ref_node = 78;
    ResolvedConstantProto resolved_constant_node = 103;
    ResolvedReplaceFieldProto resolved_replace_field_node = 129;
    ResolvedSystemVariableProto resolved_system_variable_node = 139;
    ResolvedFlattenProto resolved_flatten_node = 149;
    ResolvedFlattenedArgProto resolved_flattened_arg_node = 150;
    ResolvedGetJsonFieldProto resolved_get_json_field_node = 165;
    ResolvedFilterFieldProto resolved_filter_field_node = 174;
    ResolvedWithExprProto resolved_with_expr_node = 197;
    ResolvedCatalogColumnRefProto resolved_catalog_column_ref_node = 206;
  }
}

message ResolvedExprProto {
  optional ResolvedNodeProto parent = 1;

  optional TypeProto type = 2;
  optional AnnotationMapProto type_annotation_map = 3;
}

// Any literal value, including NULL literals.
// There is a special-cased constructor here that gets the type from the
// Value.
message ResolvedLiteralProto {
  optional ResolvedExprProto parent = 1;

  optional ValueWithTypeProto value = 2;
  // If true, then the literal is explicitly typed and cannot be used
  // for literal coercions.
  //
  // This exists mainly for resolver bookkeeping and should be ignored
  // by engines.
  optional bool has_explicit_type = 3;
  // Distinct ID of the literal, if it is a floating point value,
  // within the resolved AST. When coercing from floating point
  // to NUMERIC, the resolver uses the float_literal_id to find the
  // original image of the literal to avoid precision loss. An ID of 0
  // represents a literal without a cached image.
  optional int64 float_literal_id = 4;
  // Indicates whether ReplaceLiteralsByParameters() should leave
  // this literal value in place, rather than replace it with a query
  // parameter.
  optional bool preserve_in_literal_remover = 5;
}

message ResolvedParameterProto {
  optional ResolvedExprProto parent = 1;

  // If non-empty, the name of the parameter.
  //
  // A ResolvedParameter will have either a name or a position but not
  // both.
  optional string name = 2;
  // If non-zero, the 1-based position of the positional parameter.
  //
  // A ResolvedParameter will have either a name or a position but not
  // both.
  optional int64 position = 5;
  // If true, then the parameter has no specified type.
  //
  // This exists mainly for resolver bookkeeping and should be ignored
  // by engines.
  optional bool is_untyped = 3;
}

// This represents a column when analyzing a standalone expression.
// This is only used when the analyzer was called using AnalyzeExpression.
// Expression column names and types come from
// AnalyzerOptions::AddExpressionColumn.
// <name> will always be in lowercase.
message ResolvedExpressionColumnProto {
  optional ResolvedExprProto parent = 1;

  optional string name = 2;
}

// An expression referencing a Column from the Catalog. This is used to
// represent a column reference in an expression inside a DDL statement.
// The DDL statement will normally define the Table context, and the
// referenced Column should be a Column of that Table.
message ResolvedCatalogColumnRefProto {
  optional ResolvedExprProto parent = 1;

  optional ColumnRefProto column = 2;
}

// An expression referencing the value of some column visible in the
// current Scan node.
//
// If <is_correlated> is false, this must be a column visible in the Scan
// containing this expression, either because it was produced inside that
// Scan or it is on the <column_list> of some child of this Scan.
//
// If <is_correlated> is true, this references a column from outside a
// subquery that is visible as a correlated column inside.
// The column referenced here must show up on the parameters list for the
// subquery.  See ResolvedSubqueryExpr.
message ResolvedColumnRefProto {
  optional ResolvedExprProto parent = 1;

  optional ResolvedColumnProto column = 2;
  optional bool is_correlated = 3;
}

// A list of ResolvedColumnRef expression references that will be batched
// together in rollup/cube when being expanded to grouping sets. For
// example, ROLLUP((a, b), c) will be expanded to 3 grouping sets [(a, b, c),
// (a, b), ()], (a, b) is a multi-column.
//
// Duplicated columns are not allowed in the ResolvedGroupingSetMultiColumn
// as they are equivalent to deduplicated columns. column_list must have
// at least one element inside.
message ResolvedGroupingSetMultiColumnProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedColumnRefProto column_list = 2;
}

// A reference to a named constant.
message ResolvedConstantProto {
  optional ResolvedExprProto parent = 1;

  // The matching Constant from the Catalog.
  optional ConstantRefProto constant = 2;
}

// A reference to a system variable.
message ResolvedSystemVariableProto {
  optional ResolvedExprProto parent = 1;

  // Path to system variable.
  repeated string name_path = 2;
}

// A lambda expression, used inline as a function argument.
// This represents both the definition of the lambda and the resolution of
// its templated signature and body for this function call.
// Currently can only be used as an argument of a function.
//
// <argument_list> defines the argument types and names for the lambda, and
// creates new ResolvedColumns which can be used to reference the arguments
// inside <body>.
//
// The return type of the lambda function is the type of <body>.
//
// In addition to the <argument_list>, the body of a lambda expression can
// reference columns visible to the scope of the function call for which this
// lambda is provided as an argument. Columns in this scope accessed by the
// body are stored in <parameter_list>.
//
// For example, the following query
//   SELECT ARRAY_FILTER([1,2,3], e -> e = key) FROM KeyValue;
// would have a lambda with <parameter_list> ['key'] and <argument_list>
// ['e'].
//
// <body> is the body expression of the lambda. The expression can only
// reference columns in <parameter_list> and <argument_list>.
message ResolvedInlineLambdaProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedColumnProto argument_list = 2;
  repeated ResolvedColumnRefProto parameter_list = 3;
  optional AnyResolvedExprProto body = 4;
}

// Represents a sequence as a function argument
message ResolvedSequenceProto {
  optional ResolvedArgumentProto parent = 1;

  optional SequenceRefProto sequence = 2;
}

// An argument to the FILTER_FIELDS() function which specifies a sign to show
// inclusion/exclusion status and a field path to include or exclude.
message ResolvedFilterFieldArgProto {
  optional ResolvedArgumentProto parent = 1;

  // True if we want to include this proto path in the resulting proto
  // (though we may still remove paths below it).
  // If False, we will remove this path (but may still include paths
  // below it).
  optional bool include = 2;
  // A vector of FieldDescriptors that denotes the path to a proto
  // field that will be include or exclude.
  repeated FieldDescriptorRefProto field_descriptor_path = 3;
}

// Represents a call to the FILTER_FIELDS() function. This function can be
// used to modify a proto, prune fields and output the resulting proto. The
// SQL syntax for this function is
//   FILTER_FIELDS(<expr>, <filter_field_arg_list>).
//
// <expr> must have proto type. <filter_field_arg> contains a sign ('+' or
// '-') and a field path starting from the proto.
//
// For example:
//   FILTER_FIELDS(proto, +field1, -field1.field2)
// means the resulting proto only contains field1.* except field1.field2.*.
//
// Field paths are evaluated and processed in order,
// ```
//   IF filter_field_arg_list[0].include:
//     CLEAR all fields
//   FOR filter_field_arg IN filter_field_arg_list:
//     IF filter_field_arg.include:
//       UNCLEAR filter_field_arg.field_descriptor_path (and all children)
//     ELSE:
//       CLEAR filter_field_arg.field_descriptor_path (and all children)
// ```
//
// The order of field_field args have following constraints:
// 1. There must be at least one filter_field arg.
// 2. Args for ancestor fields must precede descendants.
// 3. Each arg must have opposite `include` compared to the last preceding
//    ancestor field.
//
// See (broken link) for more detail.
message ResolvedFilterFieldProto {
  optional ResolvedExprProto parent = 1;

  // The proto to modify.
  optional AnyResolvedExprProto expr = 2;
  // The list of field paths to include or exclude. The path starts
  // from the proto type of <expr>.
  repeated ResolvedFilterFieldArgProto filter_field_arg_list = 3;
  // If true, will reset cleared required fields into a
  // default value.
  optional bool reset_cleared_required_fields = 4;
}

// Common base class for scalar and aggregate function calls.
//
// <argument_list> contains a list of arguments of type ResolvedExpr.
//
// <generic_argument_list> contains an alternative list of generic arguments.
// This is used for function calls that accept non-expression arguments (i.e.
// arguments that aren't part of the type system, like lambdas).
//
// If all arguments of this function call are ResolvedExprs, <argument_list>
// is used. If any of the argument is not a ResolvedExpr,
// <generic_argument_list> will be used. Only one of <argument_list> or
// <generic_argument_list> can be non-empty.
//
// <collation_list> (only set when FEATURE_V_1_3_COLLATION_SUPPORT is
// enabled) is the operation collation to use.
// (broken link) lists the functions affected by
// collation, where this can show up.
// <collation_list> is a vector for future extension. For now, functions
// could have at most one element in the <collation_list>.
message AnyResolvedFunctionCallBaseProto {
  oneof node {
    ResolvedFunctionCallProto resolved_function_call_node = 8;
    AnyResolvedNonScalarFunctionCallBaseProto resolved_non_scalar_function_call_base_node = 86;
  }
}

message ResolvedFunctionCallBaseProto {
  optional ResolvedExprProto parent = 1;

  // The matching Function from the Catalog.
  optional FunctionRefProto function = 2;
  // The concrete FunctionSignature reflecting the matching Function
  // signature and the function's resolved input <argument_list>.
  // The function has the mode AGGREGATE iff it is an aggregate
  // function, in which case this node must be either
  // ResolvedAggregateFunctionCall or ResolvedAnalyticFunctionCall.
  optional FunctionSignatureProto signature = 3;
  repeated AnyResolvedExprProto argument_list = 4;
  repeated ResolvedFunctionArgumentProto generic_argument_list = 6;
  // If error_mode=SAFE_ERROR_MODE, and if this function call returns a
  // semantic error (based on input data, not transient server
  // problems), return NULL instead of an error. This is used for
  // functions called using SAFE, as in SAFE.FUNCTION(...).
  optional ResolvedFunctionCallBaseEnums.ErrorMode error_mode = 5;
  // Function call hints.
  repeated ResolvedOptionProto hint_list = 7;
  repeated ResolvedCollationProto collation_list = 8;
}

// A regular function call.  The signature will always have mode SCALAR.
// Most scalar expressions show up as FunctionCalls using builtin signatures.
message ResolvedFunctionCallProto {
  optional ResolvedFunctionCallBaseProto parent = 1;

  // This contains optional custom information about a particular
  // function call.
  //
  // If some Function subclass requires computing additional
  // information at resolving time, that extra information can be
  // stored as a subclass of ResolvedFunctionCallInfo here.
  // For example, TemplatedSQLFunction stores the resolved template
  // body here as a TemplatedSQLFunctionCall.
  //
  // This field is ignorable because for most types of function calls,
  // there is no extra information to consider besides the arguments
  // and other fields from ResolvedFunctionCallBase.
  optional ResolvedFunctionCallInfoProto function_call_info = 2;
}

// Common base class for analytic and aggregate function calls.
message AnyResolvedNonScalarFunctionCallBaseProto {
  oneof node {
    ResolvedAggregateFunctionCallProto resolved_aggregate_function_call_node = 9;
    ResolvedAnalyticFunctionCallProto resolved_analytic_function_call_node = 10;
  }
}

message ResolvedNonScalarFunctionCallBaseProto {
  optional ResolvedFunctionCallBaseProto parent = 1;

  // Apply DISTINCT to the stream of input values before calling
  // function.
  optional bool distinct = 2;
  // Apply IGNORE/RESPECT NULLS filtering to the stream of input
  // values.
  optional ResolvedNonScalarFunctionCallBaseEnums.NullHandlingModifier null_handling_modifier = 3;
  // Holds a table subquery defined in WITH GROUP_ROWS(...) that is
  // evaluated over the input rows of a ResolvedAggregateScan
  // corresponding to the current group. The function itself is
  // evaluated over the rows returned from the subquery.
  //
  // The subquery should refer to a special TVF GROUP_ROWS(), which
  // resolves as ResolvedGroupRowsScan. The subquery will be run for
  // each group produced by ResolvedAggregateScan.
  //
  // GROUP_ROWS() produces a row for each source row in the
  // ResolvedAggregateScan's input that matches current group.
  //
  // The subquery cannot reference any ResolvedColumns from the outer
  // query except what comes in via <with_group_rows_parameter_list>,
  // and GROUP_ROWS().
  //
  // The subquery can return more than one column, and these columns
  // can be referenced by the function.
  //
  // The subquery can be correlated. In this case the
  // <with_group_rows_parameter_list> gives the set of ResolvedColumns
  // from outside the subquery that are used inside. The subuery cannot
  // refer to correlated columns that are used as aggregation input in
  // the immediate outer query. The same rules apply to
  // <with_group_rows_parameter_list> as in ResolvedSubqueryExpr.
  optional AnyResolvedScanProto with_group_rows_subquery = 4;
  // Correlated parameters to <with_group_rows_subquery>
  repeated ResolvedColumnRefProto with_group_rows_parameter_list = 5;
}

// An aggregate function call.  The signature always has mode AGGREGATE.
// This node only ever shows up as the outer function call in a
// ResolvedAggregateScan::aggregate_list.
message ResolvedAggregateFunctionCallProto {
  optional ResolvedNonScalarFunctionCallBaseProto parent = 1;

  // Apply HAVING MAX/MIN filtering to the stream of input values.
  optional ResolvedAggregateHavingModifierProto having_modifier = 5;
  // Apply ordering to the stream of input values before calling
  // function.
  repeated ResolvedOrderByItemProto order_by_item_list = 3;
  optional AnyResolvedExprProto limit = 4;
  // This contains optional custom information about a particular
  // function call. Functions may introduce subclasses of this class to
  // add custom information as needed on a per-function basis.
  //
  // This field is ignorable because for most types of function calls,
  // there is no extra information to consider besides the arguments
  // and other fields from ResolvedFunctionCallBase. However, for
  // example, the TemplateSQLFunction in
  // zetasql/public/templated_sql_function.h defines the
  // TemplatedSQLFunctionCall subclass which includes the
  // fully-resolved function body in context of the actual concrete
  // types of the arguments provided to the function call.
  optional ResolvedFunctionCallInfoProto function_call_info = 6;
}

// An analytic function call. The mode of the function is either AGGREGATE
// or ANALYTIC. This node only ever shows up as a function call in a
// ResolvedAnalyticFunctionGroup::analytic_function_list. Its associated
// window is not under this node but as a sibling of its parent node.
//
// <window_frame> can be NULL.
message ResolvedAnalyticFunctionCallProto {
  optional ResolvedNonScalarFunctionCallBaseProto parent = 1;

  optional ResolvedWindowFrameProto window_frame = 2;
}

// Describes a leaf extended cast of ResolvedExtendedCast. See the comment
// for element_list field of ResolvedExtendedCast for more details.
message ResolvedExtendedCastElementProto {
  optional ResolvedArgumentProto parent = 1;

  optional TypeProto from_type = 2;
  optional TypeProto to_type = 3;
  optional FunctionRefProto function = 4;
}

// Describes overall cast operation between two values where at least one
// value's type is or contains an extended type (e.g. on a struct field).
message ResolvedExtendedCastProto {
  optional ResolvedArgumentProto parent = 1;

  // Stores the list of leaf extended casts required as elements of
  // this cast.  Each element is a cast where at least one of the input
  // or output is an extended type. For structs or arrays, the elements
  // will be casts for the field or element types. For structs, there
  // can be multiple cast elements (one for each distinct pair of field
  // types). For non-struct types, there will be just a single element.
  repeated ResolvedExtendedCastElementProto element_list = 2;
}

// A cast expression, casting the result of an input expression to the
// target Type.
//
// Valid casts are defined in the CastHashMap (see cast.cc), which identifies
// valid from-Type, to-Type pairs.  Consumers can access it through
// GetZetaSQLCasts().
message ResolvedCastProto {
  optional ResolvedExprProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  // Whether to return NULL if the cast fails. This is set to true for
  // TRY_CAST.
  optional bool return_null_on_error = 3;
  // If at least one of types involved in this cast is or contains an
  // extended (TYPE_EXTENDED) type, this field contains information
  // necessary to execute this cast.
  optional ResolvedExtendedCastProto extended_cast = 4;
  // The format string specified by the optional FORMAT clause. It is
  // nullptr when the clause does not exist.
  optional AnyResolvedExprProto format = 5;
  // The time zone expression by the optional AT TIME ZONE clause. It
  // is nullptr when the clause does not exist.
  optional AnyResolvedExprProto time_zone = 6;
  // Contains the TypeModifiers object which wraps all modifiers
  // following the type name in a type string (e.g. type parameters,
  // collation) in a cast. If there are no type modifiers specified,
  // this object will be empty.
  //
  // Type parameters can be specified inside parentheses following the
  // type name (e.g. STRING(2)). If specified, the result of the cast
  // should conform to the type parameters. Engines are expected to
  // enforce type parameter constraints by erroring out or truncating
  // the cast result, depending on the output type. See
  // (broken link) for more details.
  //
  // For example:
  //   CAST("ABC" as STRING(2)) should error out
  //   CAST(1234 as NUMERIC(2)) should error out
  //   CAST(1.234 as NUMERIC(2,1)) should return a NumericValue of 1.2
  //
  // Collation can be specified with the COLLATE keyword on a string
  // type, e.g. STRING COLLATE 'und:ci'. If specified, the
  // <type_annotation_map> of the ResolvedCast node will have equal
  // collation annotations. See
  // (broken link) for more details.
  //
  // For example:
  //   CAST("abc" AS STRING COLLATE "und:ci") should return value "abc"
  //     in STRING type with collation "und:ci".
  //   CAST(["abc"] AS ARRAY<STRING COLLATE "und:ci">) should return
  //     the array ["abc"] with collation "und:ci" at the element type.
  optional TypeModifiersProto type_modifiers = 8;
}

// Construct a struct value.  <type> is always a StructType.
// <field_list> matches 1:1 with the fields in <type> position-wise.
// Each field's type will match the corresponding field in <type>.
message ResolvedMakeStructProto {
  optional ResolvedExprProto parent = 1;

  repeated AnyResolvedExprProto field_list = 2;
}

// Construct a proto value.  <type> is always a ProtoType.
// <field_list> is a vector of (FieldDescriptor, expr) pairs to write.
// <field_list> will contain all required fields, and no duplicate fields.
message ResolvedMakeProtoProto {
  optional ResolvedExprProto parent = 1;

  repeated ResolvedMakeProtoFieldProto field_list = 2;
}

// One field assignment in a ResolvedMakeProto expression.
// The type of expr will match with the zetasql type of the proto field.
// The type will be an array iff the field is repeated.
//
// For NULL values of <expr>, the proto field should be cleared.
//
// If any value of <expr> cannot be written into the field, this query
// should fail.
message ResolvedMakeProtoFieldProto {
  optional ResolvedArgumentProto parent = 1;

  optional FieldDescriptorRefProto field_descriptor = 2;
  // Provides the Format annotation that should be used when building
  // this field.  The annotation specifies both the ZetaSQL type and
  // the encoding format for this field.
  optional FieldFormat.Format format = 3;
  optional AnyResolvedExprProto expr = 4;
}

// Get the field in position <field_idx> (0-based) from <expr>, which has a
// STRUCT type.
message ResolvedGetStructFieldProto {
  optional ResolvedExprProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  optional int64 field_idx = 3;
  // True if using s[OFFSET(0)] syntax rather than
  // specifying field name, Only for preserving user intent; no
  // semantic consequences
  optional bool field_expr_is_positional = 4;
}

message ResolvedGetProtoFieldProto {
  optional ResolvedExprProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  // The proto2 FieldDescriptor to extract.  This provides the tag
  // number and wire type.  Additional decoding may be necessary if any
  // of the other modifiers below are set.  Consumers should use those
  // ZetaSQL-computed modifiers rather than examining field
  // annotations directly.
  //
  // The field is an extension field iff
  // field_descriptor->is_extension() is true.  NOTE: The extended
  // descriptor's full_name must match the <expr>'s type's full_name,
  // but may not be the same Descriptor. Extension FieldDescriptors may
  // come from a different DescriptorPool.
  //
  // The field is required if field_descriptor->is_required().  If the
  // field is required and not present, an error should result.
  optional FieldDescriptorRefProto field_descriptor = 3;
  // Default value to use when the proto field is not set. The default
  // may be NULL (e.g. for proto2 fields with a use_defaults=false
  // annotation).
  //
  // This will not be filled in (the Value will be uninitialized) if
  // get_has_bit is true, or the field is required.
  //
  // If field_descriptor->is_required() and the field is not present,
  // the engine should return an error.
  //
  // If the <expr> itself returns NULL, then extracting a field should
  // also return NULL, unless <return_default_value_when_unset> is
  // true. In that case, the default value is returned.
  //
  // TODO Make un-ignorable after clients migrate to start
  // using it.
  optional ValueWithTypeProto default_value = 4;
  // Indicates whether to return a bool indicating if a value was
  // present, rather than return the value (or NULL). Never set for
  // repeated fields. This field cannot be set if
  // <return_default_value_when_unset> is true, and vice versa.
  // Expression type will be BOOL.
  optional bool get_has_bit = 5;
  // Provides the Format annotation that should be used when reading
  // this field.  The annotation specifies both the ZetaSQL type and
  // the encoding format for this field. This cannot be set when
  // get_has_bit is true.
  optional FieldFormat.Format format = 6;
  // Indicates that the default value should be returned if <expr>
  // (the parent message) is NULL.  Note that this does *not* affect
  // the return value when the extracted field itself is unset, in
  // which case the return value depends on the extracted field's
  // annotations (e.g., use_field_defaults).
  //
  // This can only be set for non-message fields. If the field is a
  // proto2 field, then it must be annotated with
  // zetasql.use_defaults=true. This cannot be set when <get_has_bit>
  // is true or the field is required.
  optional bool return_default_value_when_unset = 7;
}

// Get the field <field_name> from <expr>, which has a JSON type.
message ResolvedGetJsonFieldProto {
  optional ResolvedExprProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  optional string field_name = 3;
}

// Constructs an initial input ARRAY<T> from expr. For each get_field_list
// expr, we evaluate the expression once with each array input element and
// use the output as a new array of inputs for the next get_field_list expr.
// If the result of a single expr is an array, we add each element from that
// array as input to the next step instead of adding the array itself.
//
// The array elements are evaluated and kept in order. For example, if only
// expr is an array, the result will be equivalent to that array having the
// get_field_list evaluated on each array element retaining order.
message ResolvedFlattenProto {
  optional ResolvedExprProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  // List of 'get' fields to evaluate in order (0 or more struct get
  // fields followed by 0 or more proto or json get fields) starting
  // from expr. Each get is evaluated N times where N is the number of
  // array elements from the previous get (or expr for the first
  // expression) generated.
  //
  // The 'get' fields may either be a ResolvedGet*Field or an array
  // offset function around a ResolvedGet*Field.
  repeated AnyResolvedExprProto get_field_list = 3;
}

// Argument for a child of ResolvedFlatten. This is a placeholder to indicate
// that it will be invoked once for each array element from ResolvedFlatten's
// expr or previous get_field_list entry.
message ResolvedFlattenedArgProto {
  optional ResolvedExprProto parent = 1;

}

// An argument to the REPLACE_FIELDS() function which specifies a field path
// and a value that this field will be set to. The field path to be modified
// can be constructed through the <struct_index_path> and <proto_field_path>
// fields. These vectors correspond to field paths in a STRUCT and PROTO,
// respectively. At least one of these vectors must be non-empty.
//
// If only <struct_index_path> is non-empty, then the field path only
// references top-level and nested struct fields.
//
// If only <proto_field_path> is non-empty, then the field path only
// references top-level and nested message fields.
//
// If both <struct_index_path> and <proto_field_path> are non-empty, then the
// field path should be expanded starting with <struct_index_path>. The last
// field in <struct_index_path> will be the proto from which the first field
// in <proto_field_path> is extracted.
//
// <expr> and the field to be modified must be the same type.
message ResolvedReplaceFieldItemProto {
  optional ResolvedArgumentProto parent = 1;

  // The value that the final field in <proto_field_path> will be set
  // to.
  //
  // If <expr> is NULL, the field will be unset. If <proto_field_path>
  // is a required field, the engine must return an error if it is set
  // to NULL.
  optional AnyResolvedExprProto expr = 2;
  // A vector of integers that denotes the path to a struct field that
  // will be modified. The integer values in this vector correspond to
  // field positions (0-based) in a STRUCT. If <proto_field_path>
  // is also non-empty, then the field corresponding to the last index
  // in this vector should be of proto type.
  repeated int64 struct_index_path = 3;
  // A vector of FieldDescriptors that denotes the path to a proto
  // field that will be modified. If <struct_index_path> is also
  // non-empty, then the first element in this vector should be a
  // subfield of the proto corresponding to the last element in
  // <struct_index_path>.
  repeated FieldDescriptorRefProto proto_field_path = 4;
}

// Represents a call to the REPLACE_FIELDS() function. This function
// can be used to copy a proto or struct, modify a few fields and
// output the resulting proto or struct. The SQL syntax for this
// function is REPLACE_FIELDS(<expr>, <replace_field_item_list>).
//
// See (broken link) for more detail.
message ResolvedReplaceFieldProto {
  optional ResolvedExprProto parent = 1;

  // The proto/struct to modify.
  optional AnyResolvedExprProto expr = 2;
  // The list of field paths to be modified along with their new
  // values.
  //
  // Engines must check at evaluation time that the modifications in
  // <replace_field_item_list> obey the following rules
  // regarding updating protos in ZetaSQL:
  // - Modifying a subfield of a NULL-valued proto-valued field is an
  //   error.
  // - Clearing a required field or subfield is an error.
  repeated ResolvedReplaceFieldItemProto replace_field_item_list = 3;
}

// A subquery in an expression (not a FROM clause).  The subquery runs
// in the context of a single input row and produces a single output value.
//
// Correlated subqueries can be thought of like functions, with a parameter
// list.  The <parameter_list> gives the set of ResolvedColumns from outside
// the subquery that are used inside.
//
// Inside the subquery, the only allowed references to values outside the
// subquery are to the named ColumnRefs listed in <parameter_list>.
// Any reference to one of these parameters will be represented as a
// ResolvedColumnRef with <is_correlated> set to true.
//
// These parameters are only visible through one level of expression
// subquery.  An expression subquery inside an expression has to list
// parameters again if parameters from the outer query are passed down
// further.  (This does not apply for table subqueries inside an expression
// subquery.  Table subqueries are never indicated in the resolved AST, so
// Scan nodes inside an expression query may have come from a nested table
// subquery, and they can still reference the expression subquery's
// parameters.)
//
// An empty <parameter_list> means that the subquery is uncorrelated.  It is
// permissable to run an uncorrelated subquery only once and reuse the result.
// TODO Do we want to specify semantics more firmly here?
//
// The semantics vary based on SubqueryType:
//   SCALAR
//     Usage: ( <subquery> )
//     If the subquery produces zero rows, the output value is NULL.
//     If the subquery produces exactly one row, that row is the output value.
//     If the subquery produces more than one row, raise a runtime error.
//
//   ARRAY
//     Usage: ARRAY( <subquery> )
//     The subquery produces an array value with zero or more rows, with
//     one array element per subquery row produced.
//
//   EXISTS
//     Usage: EXISTS( <subquery> )
//     The output type is always bool.  The result is true if the subquery
//     produces at least one row, and false otherwise.
//
//   IN
//     Usage: <in_expr> [NOT] IN ( <subquery> )
//     The output type is always bool.  The result is true when <in_expr> is
//     equal to at least one row, and false otherwise.  The <subquery> row
//     contains only one column, and the types of <in_expr> and the
//     subquery column must exactly match a built-in signature for the
//     '$equals' comparison function (they must be the same type or one
//     must be INT64 and the other UINT64).  NOT will be expressed as a $not
//     FunctionCall wrapping this SubqueryExpr.
//
//  LIKE
//     Usage: <in_expr> [NOT] LIKE ANY|SOME|ALL ( <subquery> )
//     The output type is always bool. The result is true when <in_expr>
//     matches at least one row for LIKE ANY|SOME or matches all rows for
//     LIKE ALL, and false otherwise.  The <subquery> row contains only one
//     column, and the types of <in_expr> and the subquery column must
//     exactly match a built-in signature for the relevant '$like_any' or
//     '$like_all' comparison function (both must be the same type of either
//     STRING or BYTES).  NOT will be expressed as a $not FunctionCall
//     wrapping this SubqueryExpr.
//
// The subquery for a SCALAR, ARRAY, IN or LIKE subquery must have exactly
// one output column.
// The output type for a SCALAR or ARRAY subquery is that column's type or
// an array of that column's type.  (The subquery scan may include a Project
// with a MakeStruct or MakeProto expression to construct a single value
// from multiple columns.)
message ResolvedSubqueryExprProto {
  optional ResolvedExprProto parent = 1;

  optional ResolvedSubqueryExprEnums.SubqueryType subquery_type = 2;
  repeated ResolvedColumnRefProto parameter_list = 3;
  // Field is only populated for subqueries of type IN or LIKE
  // ANY|SOME|ALL.
  optional AnyResolvedExprProto in_expr = 4;
  // Field is only populated for subqueries of type IN to specify the
  // operation collation to use to compare <in_expr> with the rows from
  // <subquery>.
  optional ResolvedCollationProto in_collation = 7;
  optional AnyResolvedScanProto subquery = 5;
  // Note: Hints currently happen only for EXISTS, IN, or a LIKE
  // expression subquery but not for ARRAY or SCALAR subquery.
  repeated ResolvedOptionProto hint_list = 6;
}

// ResolvedWithExpr introduces one or more columns in <assignment_list> that
// can then be referenced inside <expr>. Each assigned expression is
// evaluated once, and each reference to that column in <expr> sees the same
// value even if the assigned expression is volatile. Multiple assignment
// expressions are independent and cannot reference other columns in the
// <assignment_list>.
//
// <assignment_list> One or more columns that are computed before evaluating
//                   <expr>, and which may be referenced by <expr>.
// <expr> Computes the result of the ResolvedWithExpr. May reference columns
//        from <assignment_list>.
message ResolvedWithExprProto {
  optional ResolvedExprProto parent = 1;

  repeated ResolvedComputedColumnProto assignment_list = 2;
  optional AnyResolvedExprProto expr = 3;
}

// Common superclass for all Scans, which are nodes that produce rows
// (e.g. scans, joins, table subqueries).  A query's FROM clause is
// represented as a single Scan that composes all input sources into
// a single row stream.
//
// Each Scan has a `column_list` that says what columns are produced.
// The Scan logically produces a stream of output rows, where each row
// has exactly these columns.
//
// Each Scan may have an attached `hint_list`, storing each hint as
// a ResolvedOption.
//
// If `is_ordered` is true, this Scan produces an ordered output, either
// by generating order itself (OrderByScan) or by preserving the order
// of its single input scan (LimitOffsetScan, ProjectScan, or WithScan).
//
// Each Scan has a `node_source` field that, if populated, represents where
// the scan was from or why it was added. This is used in some cases by the
// resolver, rewriters or the random query generator to record why a node was
// added. The SQLBuilder may also use `node_source` to influence which query
// patterns to generate.
message AnyResolvedScanProto {
  oneof node {
    ResolvedSingleRowScanProto resolved_single_row_scan_node = 19;
    ResolvedTableScanProto resolved_table_scan_node = 20;
    ResolvedJoinScanProto resolved_join_scan_node = 21;
    ResolvedArrayScanProto resolved_array_scan_node = 22;
    ResolvedFilterScanProto resolved_filter_scan_node = 24;
    ResolvedSetOperationScanProto resolved_set_operation_scan_node = 26;
    ResolvedOrderByScanProto resolved_order_by_scan_node = 27;
    ResolvedLimitOffsetScanProto resolved_limit_offset_scan_node = 28;
    ResolvedWithRefScanProto resolved_with_ref_scan_node = 29;
    ResolvedAnalyticScanProto resolved_analytic_scan_node = 30;
    ResolvedSampleScanProto resolved_sample_scan_node = 31;
    ResolvedProjectScanProto resolved_project_scan_node = 35;
    ResolvedWithScanProto resolved_with_scan_node = 51;
    ResolvedTVFScanProto resolved_tvfscan_node = 81;
    ResolvedRelationArgumentScanProto resolved_relation_argument_scan_node = 89;
    AnyResolvedAggregateScanBaseProto resolved_aggregate_scan_base_node = 111;
    ResolvedRecursiveRefScanProto resolved_recursive_ref_scan_node = 147;
    ResolvedRecursiveScanProto resolved_recursive_scan_node = 148;
    ResolvedPivotScanProto resolved_pivot_scan_node = 161;
    ResolvedUnpivotScanProto resolved_unpivot_scan_node = 172;
    ResolvedGroupRowsScanProto resolved_group_rows_scan_node = 176;
    ResolvedExecuteAsRoleScanProto resolved_execute_as_role_scan_node = 207;
    ResolvedTopScanProto resolved_top_scan_node = 100000;
    ResolvedOffsetFetchScanProto resolved_offset_fetch_scan_node = 100001;
  }
}

message ResolvedScanProto {
  optional ResolvedNodeProto parent = 1;

  repeated ResolvedColumnProto column_list = 2;
  repeated ResolvedOptionProto hint_list = 3;
  optional bool is_ordered = 4;
  optional string node_source = 5;
}

// This node provides the role context for its subtree. Currently, it only
// handles subtrees from inlined TVFs and VIEWs created with DEFINER rights.
// Due to the lack of a ROLE catalog object, we are using the original
// catalog object (VIEW or TVF) as a proxy. The engine is expected to extract
// the target role of these objects.
//
// In the future, when we have catalog objects for roles, this node should
// be updated to attach role object, rather than the original inlined object.
//
// The node's role context covers the whole subtree underneath it, except
// subtrees under other nested ResolvedExecuteAsRoleScan nodes.
//
// Always creates new output columns in <column_list>, which map 1:1 with
// the <input_scan>'s output columns. Most rewriters trace their columns all
// the way back to the scan that defined them so this makes this node a
// boundary, as desired.
message ResolvedExecuteAsRoleScanProto {
  optional ResolvedScanProto parent = 1;

  // The input scan whose subtree is to be encompassed by the current
  // role context.
  optional AnyResolvedScanProto input_scan = 2;
  // The original view that was inlined. If set, then
  // 'original_inlined_tvf' is null. The validator checks that this
  // table is indeed a SqlView, not some other subclass of Table.
  optional TableRefProto original_inlined_view = 3;
  // The original TVF that was inlined. If set, then
  // 'original_inlined_view' is null.
  optional TableValuedFunctionRefProto original_inlined_tvf = 4;
}

// Represents a machine learning model as a TVF argument.
// <model> is the machine learning model object known to the resolver
// (usually through the catalog).
message ResolvedModelProto {
  optional ResolvedArgumentProto parent = 1;

  optional ModelRefProto model = 2;
}

// Represents a connection object as a TVF argument.
// <connection> is the connection object encapsulated metadata to connect to
// an external data source.
message ResolvedConnectionProto {
  optional ResolvedArgumentProto parent = 1;

  optional ConnectionRefProto connection = 2;
}

// Represents a descriptor object as a TVF argument.
// A descriptor is basically a list of unresolved column names, written
//   DESCRIPTOR(column1, column2)
//
// <descriptor_column_name_list> contains the column names.
//
// If FunctionArgumentTypeOptions.get_resolve_descriptor_names_table_offset()
// is true, then <descriptor_column_list> contains resolved columns from
// the sibling ResolvedFunctionArgument of scan type, and will match
// positionally with <descriptor_column_name_list>.
message ResolvedDescriptorProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedColumnProto descriptor_column_list = 2;
  repeated string descriptor_column_name_list = 3;
}

// Scan that produces a single row with no columns.  Used for queries without
// a FROM clause, where all output comes from the select list.
message ResolvedSingleRowScanProto {
  optional ResolvedScanProto parent = 1;

}

// Scan a Table.
// The <column_list>[i] should be matched to a Table column by
// <table>.GetColumn(<column_index_list>[i]).
//
// If AnalyzerOptions::prune_unused_columns is true, the <column_list> and
// <column_index_list> will include only columns that were referenced
// in the user query. (SELECT * counts as referencing all columns.)
// This column_list can then be used for column-level ACL checking on tables.
// Pruning has no effect on value tables (the value is never pruned).
//
// for_system_time_expr when non NULL resolves to TIMESTAMP used in
// FOR SYSTEM_TIME AS OF clause. The expression is expected to be constant
// and no columns are visible to it.
//
// <column_index_list> This list matches 1-1 with the <column_list>, and
// identifies the ordinal of the corresponding column in the <table>'s
// column list.
//
// If provided, <alias> refers to an explicit alias which was used to
// reference a Table in the user query. If the Table was given an implicitly
// generated alias, then defaults to "".
//
// TODO: Enforce <column_index_list> in the constructor arg list. For
// historical reasons, some clients match <column_list> to Table columns by
// ResolvedColumn name. This violates the ResolvedColumn contract, which
// explicitly states that the ResolvedColumn name has no semantic meaning.
// All code building a ResolvedTableScan should always
// set_column_index_list() immediately after construction.
message ResolvedTableScanProto {
  optional ResolvedScanProto parent = 1;

  optional TableRefProto table = 2;
  optional AnyResolvedExprProto for_system_time_expr = 3;
  repeated int64 column_index_list = 4;
  optional string alias = 5;
}

// A Scan that joins two input scans.
// The <column_list> will contain columns selected from the union
// of the input scan's <column_lists>.
// When the join is a LEFT/RIGHT/FULL join, ResolvedColumns that came from
// the non-joined side get NULL values.
message ResolvedJoinScanProto {
  optional ResolvedScanProto parent = 1;

  optional ResolvedJoinScanEnums.JoinType join_type = 2;
  optional AnyResolvedScanProto left_scan = 3;
  optional AnyResolvedScanProto right_scan = 4;
  optional AnyResolvedExprProto join_expr = 5;
  optional bool lateral = 6;
}

// Scan an array value, produced from some expression.
//
// If input_scan is NULL, this scans the given array value and produces
// one row per array element.  This can occur when using UNNEST(expression).
//
// If <input_scan> is non-NULL, for each row in the stream produced by
// input_scan, this evaluates the expression <array_expr> (which must return
// an array type) and then produces a stream with one row per array element.
//
// If <join_expr> is non-NULL, then this condition is evaluated as an ON
// clause for the array join.  The named column produced in <array_expr>
// may be used inside <join_expr>.
//
// If the array is empty (after evaluating <join_expr>), then
// 1. If <is_outer> is false, the scan produces zero rows.
// 2. If <is_outer> is true, the scan produces one row with a NULL value for
//    the <element_column>.
//
// <element_column> is the new column produced by this scan that stores the
// array element value for each row.
//
// If present, <array_offset_column> defines the column produced by this
// scan that stores the array offset (0-based) for the corresponding
// <element_column>.
//
// This node's column_list can have columns from input_scan, <element_column>
// and <array_offset_column>.
message ResolvedArrayScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional AnyResolvedExprProto array_expr = 3;
  optional ResolvedColumnProto element_column = 4;
  optional ResolvedColumnHolderProto array_offset_column = 5;
  optional AnyResolvedExprProto join_expr = 6;
  optional bool is_outer = 7;
}

// This wrapper is used for an optional ResolvedColumn inside another node.
message ResolvedColumnHolderProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedColumnProto column = 2;
}

// Scan rows from input_scan, and emit all rows where filter_expr
// evaluates to true.  filter_expr is always of type bool.
// This node's column_list will be a subset of input_scan's column_list.
message ResolvedFilterScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional AnyResolvedExprProto filter_expr = 3;
}

// A GROUPING function call. `group_by_column` must be a column from
// the `group_by_list` in `ResolvedAggregateScan`.
// `output_column` is a new column of type int64.
// Its output value is 0 if `group_by_column` is included in the current
// grouping set, or 1 if not.
message ResolvedGroupingCallProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedColumnRefProto group_by_column = 2;
  optional ResolvedColumnProto output_column = 3;
}

// The parent node for grouping set, rollup and cube nodes.
//
// This node exists for organizational purposes only, to cluster
// grouping set, rollup and cube nodes. It doesn't have any actual fields.
message AnyResolvedGroupingSetBaseProto {
  oneof node {
    ResolvedGroupingSetProto resolved_grouping_set_node = 93;
    ResolvedRollupProto resolved_rollup_node = 239;
    ResolvedCubeProto resolved_cube_node = 240;
  }
}

message ResolvedGroupingSetBaseProto {
  optional ResolvedArgumentProto parent = 1;

}

// List of group by columns that form a grouping set.
//
// Columns must come from group_by_list in ResolvedAggregateScan.
// group_by_column_list will not contain any duplicates. There may be more
// than one ResolvedGroupingSet in the ResolvedAggregateScan with the same
// columns, however.
message ResolvedGroupingSetProto {
  optional ResolvedGroupingSetBaseProto parent = 1;

  repeated ResolvedColumnRefProto group_by_column_list = 2;
}

// List of ResolvedGroupingSetMultiColumn that forms a rollup.
//
// Each ResolvedGroupingSetMultiColumn is a list of column references that
// will be batched together when expanding to grouping sets. E.g.
// ROLLUP((a, b), c) is expanded to grouping sets [(a, b, c), (a, b), ()].
// Both (a, b) and c are store in ResolvedGroupingSetMultiColumn for
// convenience.
//
// Column references in each ResolvedGroupingSetMultiColumn must come from
// group_by_list in ResolvedAggregateScan. It is allowed to have
// duplicated ResolvedGroupingSetMultiColumn in rollup_column_list.
message ResolvedRollupProto {
  optional ResolvedGroupingSetBaseProto parent = 1;

  repeated ResolvedGroupingSetMultiColumnProto rollup_column_list = 2;
}

// List of ResolvedGroupingSetMultiColumn that forms a cube in grouping sets.
//
// See comments in ResolvdRollup for explanation about
// ResolvedGroupingSetMultiColumn.
message ResolvedCubeProto {
  optional ResolvedGroupingSetBaseProto parent = 1;

  repeated ResolvedGroupingSetMultiColumnProto cube_column_list = 2;
}

// Base class for aggregation scans. Apply aggregation to rows produced from
// input_scan, and output aggregated rows.
//
// Group by keys in <group_by_list>.  If <group_by_list> is empty,
// aggregate all input rows into one output row.
//
// <collation_list> is either empty to indicate that all the elements in
// <group_by_list> have the default collation, or <collation_list> has the
// same number of elements as <group_by_list>.  Each element is the collation
// for the element in <group_by_list> with the same index, or can be empty to
// indicate default collation or when the type is not collatable.
// <collation_list> is only set when FEATURE_V_1_3_COLLATION_SUPPORT is
// enabled.
// See (broken link).
//
// Compute all aggregations in <aggregate_list>.  All expressions in
// <aggregate_list> have a ResolvedAggregateFunctionCall with mode
// Function::AGGREGATE as their outermost node.
//
// The output <column_list> contains only columns produced from
// <group_by_list> and <aggregate_list>.  No other columns are visible after
// aggregation.
//
// If <grouping_set_list> is empty, output rows grouped by the full
// <group_by_list>.
//
// If <grouping_set_list> is non-empty, then
// for each item in <grouping_set_list>, output rows computing the
// same <aggregate_list> over the input rows using a particular grouping set.
// Each item in <grouping_set_list> is either a ResolvedGroupingSet,
// ResolvedRollup, or ResolvedCube before the grouping set rewriter expands
// the grouping set list. After rewriting, it will only contain
// ResolvedGroupingSet that are expanded from grouping set, rollup and cube.
//
// The aggregation input values, including <input_scan>, computed columns in
// <group_by_list>, and aggregate function arguments in <aggregate_list>,
// should be computed just once and then reused as aggregation input for each
// grouping set. (This ensures that ROLLUP rows have correct totals, even
// with non-stable functions in the input.) For each grouping set, the
// <group_by_list> elements not included in the <group_by_column_list> are
// replaced with NULL.
//
// <rollup_column_list> is the original list of columns from
// GROUP BY ROLLUP(...), if there was a ROLLUP clause, and is used only for
// rebuilding equivalent SQL for the resolved AST. Engines should refer to
// <grouping_set_list> rather than <rollup_column_list>.
//
// <grouping_call_list> is the list of resolved group-by columns referenced
// in GROUPING aggregate function calls. Each item in the grouping_call_list
// is associated with a unique GROUPING function call in the SELECT list.
message AnyResolvedAggregateScanBaseProto {
  oneof node {
    ResolvedAggregateScanProto resolved_aggregate_scan_node = 25;
    ResolvedAnonymizedAggregateScanProto resolved_anonymized_aggregate_scan_node = 112;
    ResolvedDifferentialPrivacyAggregateScanProto resolved_differential_privacy_aggregate_scan_node = 221;
    ResolvedAggregationThresholdAggregateScanProto resolved_aggregation_threshold_aggregate_scan_node = 228;
  }
}

message ResolvedAggregateScanBaseProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  repeated ResolvedComputedColumnProto group_by_list = 3;
  repeated ResolvedCollationProto collation_list = 5;
  repeated ResolvedComputedColumnProto aggregate_list = 4;
  repeated AnyResolvedGroupingSetBaseProto grouping_set_list = 6;
  repeated ResolvedColumnRefProto rollup_column_list = 7;
  repeated ResolvedGroupingCallProto grouping_call_list = 8;
}

// Apply aggregation to rows produced from input_scan, and output aggregated
// rows.
message ResolvedAggregateScanProto {
  optional ResolvedAggregateScanBaseProto parent = 1;

}

// Apply differentially private aggregation (anonymization) to rows produced
// from input_scan, and output anonymized rows.
// Spec: (broken link)
//
// <k_threshold_expr> when non-null, points to a function call in
// the <aggregate_list> and adds a filter that acts like:
//   HAVING <k_threshold_expr> >= <implementation-defined k-threshold>
// omitting any rows that would not pass this condition.
// TODO: Update this comment after splitting the rewriter out
// into a separate stage.
//
// <anonymization_option_list> provides user-specified options, and
// requires that option names are one of: delta, epsilon, kappa,
// max_groups_contributed, max_rows_contributed, or k_threshold.
message ResolvedAnonymizedAggregateScanProto {
  optional ResolvedAggregateScanBaseProto parent = 1;

  optional AnyResolvedExprProto k_threshold_expr = 5;
  repeated ResolvedOptionProto anonymization_option_list = 6;
}

// Apply differentially private aggregation (anonymization) to rows produced
// from input_scan, and output anonymized rows.
// Spec: (broken link)
//
// <group_selection_threshold_expr> when non-null, points to a function call
// in the <aggregate_list> and adds a filter that acts like:
//   HAVING <group_selection_threshold_expr> >=
//   <implementation-defined group_selection_threshold>
// omitting any rows that would not pass this condition.
// TODO: Update this comment after splitting the rewriter out
// into a separate stage.
//
// <option_list> provides user-specified options, and
// requires that option names are one of: delta, epsilon,
// max_groups_contributed or max_rows_contributed.
message ResolvedDifferentialPrivacyAggregateScanProto {
  optional ResolvedAggregateScanBaseProto parent = 1;

  optional AnyResolvedExprProto group_selection_threshold_expr = 5;
  repeated ResolvedOptionProto option_list = 6;
}

// Apply aggregation to rows produced from input_scan and output rows to
// that pass aggregation thresholds. It adds:
// HAVING COUNT(DISTINCT `privacy_unit_column`) >= `threshold`.
// Spec: (broken link)
//
// <option_list> provides user-specified options. Allowed options are defined
// in GetAllowedAggregationThresholdOptions function.
message ResolvedAggregationThresholdAggregateScanProto {
  optional ResolvedAggregateScanBaseProto parent = 1;

  repeated ResolvedOptionProto option_list = 5;
}

// This is one input item in a ResolvedSetOperation.
// The <output_column_list> matches 1:1 with the ResolvedSetOperation's
// <column_list> and specifies how columns from <scan> map to output columns.
// Each column from <scan> can map to zero or more output columns.
message ResolvedSetOperationItemProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedScanProto scan = 2;
  repeated ResolvedColumnProto output_column_list = 3;
}

// Apply a set operation (specified by <op_type>) on two or more input scans.
//
// <scan_list> will have at least two elements.
//
// <column_list> is a set of new ResolvedColumns created by this scan.
// Each input ResolvedSetOperationItem has an <output_column_list> which
// matches 1:1 with <column_list> and specifies how the input <scan>'s
// columns map into the final <column_list>.
//
// - Results of {UNION, INTERSECT, EXCEPT} ALL can include duplicate rows.
//   More precisely, with two input scans, if a given row R appears exactly
//   m times in first input and n times in second input (m >= 0, n >= 0):
//   For UNION ALL, R will appear exactly m + n times in the result.
//   For INTERSECT ALL, R will appear exactly min(m, n) in the result.
//   For EXCEPT ALL, R will appear exactly max(m - n, 0) in the result.
//
// - Results of {UNION, INTERSECT, EXCEPT} DISTINCT cannot contain any
//   duplicate rows. For UNION and INTERSECT, the DISTINCT is computed
//   after the result above is computed.  For EXCEPT DISTINCT, row R will
//   appear once in the output if m > 0 and n = 0.
//
// - For n (>2) input scans, the above operations generalize so the output is
//   the same as if the inputs were combined incrementally from left to
//   right.
//
// <column_match_mode> represents how columns from different queries were
// matched, for example BY_POSITION or CORRESPONDING (by name). Engines can
// ignore this field; it is included for informational purposes.
//
// <column_propagation_mode> represents how non-matching columns were
// treated, for example INNER (non-matching columns are dropped) or STRICT
// (non-matching columns are not allowed). Engines can ignore this field;
// it is included for informational purposes.
message ResolvedSetOperationScanProto {
  optional ResolvedScanProto parent = 1;

  optional ResolvedSetOperationScanEnums.SetOperationType op_type = 2;
  repeated ResolvedSetOperationItemProto input_item_list = 4;
  optional ResolvedSetOperationScanEnums.SetOperationColumnMatchMode column_match_mode = 5;
  optional ResolvedSetOperationScanEnums.SetOperationColumnPropagationMode column_propagation_mode = 6;
}

// Apply ordering to rows produced from input_scan, and output ordered
// rows.
//
// The <order_by_item_list> must not be empty.  Each element identifies
// a sort column and indicates direction (ascending or descending).
//
// Order Preservation:
//   A ResolvedScan produces an ordered output if it has <is_ordered>=true.
//   If <is_ordered>=false, the scan may discard order.  This can happen
//   even for a ResolvedOrderByScan, if it is the top-level scan in a
//   subquery (which discards order).
//
// The following Scan nodes may have <is_ordered>=true, producing or
// propagating an ordering:
//   * ResolvedOrderByScan
//   * ResolvedLimitOffsetScan
//   * ResolvedProjectScan
//   * ResolvedWithScan
// Other Scan nodes will always discard ordering.
message ResolvedOrderByScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  repeated ResolvedOrderByItemProto order_by_item_list = 3;
}

// Apply a LIMIT and optional OFFSET to the rows from input_scan. Emit all
// rows after OFFSET rows have been scanned and up to LIMIT total rows
// emitted. The offset is the number of rows to skip.
// E.g., OFFSET 1 means to skip one row, so the first row emitted will be the
// second ROW, provided the LIMIT is greater than zero.
//
// The arguments to LIMIT <int64> OFFSET <int64> must be non-negative
// integer literals or (possibly casted) query parameters.  Query
// parameter values must be checked at run-time by ZetaSQL compliant
// backend systems.
//
// OFFSET is optional and the absence of OFFSET implies OFFSET 0.
message ResolvedLimitOffsetScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional AnyResolvedExprProto limit = 3;
  optional AnyResolvedExprProto offset = 4;
}

// Scan the subquery defined in a WITH statement.
// See ResolvedWithScan for more detail.
// The column_list produced here will match 1:1 with the column_list produced
// by the referenced subquery and will given a new unique id to each column
// produced for this scan.
message ResolvedWithRefScanProto {
  optional ResolvedScanProto parent = 1;

  optional string with_query_name = 2;
}

// Apply analytic functions to rows produced from input_scan.
//
// The set of analytic functions are partitioned into a list of analytic
// function groups <function_group_list> by the window PARTITION BY and the
// window ORDER BY.
//
// The output <column_list> contains all columns from <input_scan>,
// one column per analytic function. It may also conain partitioning/ordering
// expression columns if they reference to select columns.
message ResolvedAnalyticScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  repeated ResolvedAnalyticFunctionGroupProto function_group_list = 3;
}

// Samples rows from <input_scan>.
// Specs: (broken link)
// Specs for WITH WEIGHT and PARTITION BY: (broken link)
//
// <method> is the identifier for the sampling algorithm and will always be
// in lowercase.
// For example BERNOULLI, RESERVOIR, SYSTEM. Engines can also support their
// own implementation-specific set of sampling algorithms.
//
// <size> and <unit> specifies the sample size.
// If <unit> is "ROWS", <size> must be an <int64> and non-negative.
// If <unit> is "PERCENT", <size> must either be a <double> or an <int64> and
// in the range [0, 100].
// <size> can only be a literal value or a (possibly casted) parameter.
//
// <repeatable_argument> is present if we had a REPEATABLE(<argument>) in the
// TABLESAMPLE clause and can only be a literal value or a (possibly
// casted) parameter.
//
// If present, <weight_column> defines the column produced by this scan that
// stores the scaling weight for the corresponding sampled row.
//
// <partition_by_list> can be empty. If <partition_by_list> is not empty,
// <unit> must be ROWS and <method> must be RESERVOIR.
message ResolvedSampleScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional string method = 3;
  optional AnyResolvedExprProto size = 4;
  optional ResolvedSampleScanEnums.SampleUnit unit = 5;
  optional AnyResolvedExprProto repeatable_argument = 6;
  optional ResolvedColumnHolderProto weight_column = 7;
  repeated AnyResolvedExprProto partition_by_list = 8;
}

// This is used when an expression is computed and given a name (a new
// ResolvedColumn) that can be referenced elsewhere.  The new ResolvedColumn
// can appear in a column_list or in ResolvedColumnRefs in other expressions,
// when appropriate.  This node is not an expression itself - it is a
// container that holds an expression.
message ResolvedComputedColumnProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedColumnProto column = 2;
  optional AnyResolvedExprProto expr = 3;
}

// This represents one column of an ORDER BY clause, with the requested
// ordering direction.
//
// <collation_name> is the ORDER BY COLLATE expression, and could be a string
// literal or query parameter.  <collation_name> can only be set when the
// FEATURE_V_1_1_ORDER_BY_COLLATE is enabled.
// See (broken link) for COLLATE clause.
// <collation> (only set when FEATURE_V_1_3_COLLATION_SUPPORT is enabled) is
// the derived collation to use.  It comes from the <column_ref> and COLLATE
// clause.  It is unset if COLLATE is present and set to a parameter.
// See (broken link) for general Collation Support.
// When both features are enabled, if <collation_name> is present and is
// - a parameter, then <collation> is empty
// - a non-parameter, then <collation> is set to the same collation
// An engine which supports both features could read the fields as:
//   If <collation> is set then use it, otherwise use <collation_name>, which
//   must be a query parameter if set.
//
// <null_order> indicates the ordering of NULL values relative to non-NULL
// values. NULLS_FIRST indicates that NULLS sort prior to non-NULL values,
// and NULLS_LAST indicates that NULLS sort after non-NULL values.
message ResolvedOrderByItemProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedColumnRefProto column_ref = 2;
  optional AnyResolvedExprProto collation_name = 3;
  optional bool is_descending = 4;
  optional ResolvedOrderByItemEnums.NullOrderMode null_order = 5;
  optional ResolvedCollationProto collation = 6;
}

// This is used in CREATE TABLE statements to provide column annotations
// such as collation, NOT NULL, type parameters, and OPTIONS().
//
// This class is recursive. It mirrors the structure of the column type
// except that child_list might be truncated.
//
// For ARRAY:
//   If the element or its subfield has annotations, then child_list.size()
//   is 1, and child_list(0) stores the element annotations.
//   Otherwise child_list is empty.
// For STRUCT:
//   If the i-th field has annotations then child_list(i) stores the
//   field annotations.
//   Otherwise either child_list.size() <= i or child_list(i) is trivial.
//   If none of the fields and none of their subfields has annotations, then
//   child_list is empty.
// For other types, child_list is empty.
message ResolvedColumnAnnotationsProto {
  optional ResolvedArgumentProto parent = 1;

  // <collation_name> can only be a string literal, and is only set
  // when FEATURE_V_1_3_COLLATION_SUPPORT is enabled. See
  // (broken link).
  optional AnyResolvedExprProto collation_name = 6;
  optional bool not_null = 2;
  repeated ResolvedOptionProto option_list = 3;
  repeated ResolvedColumnAnnotationsProto child_list = 4;
  // child_list in <type_parameters> is not used in here.
  // Instead we use child_list of this node (ResolvedColumnAnnotations)
  // to store type parameters of subfields of STRUCT or ARRAY. Users
  // can access the full type parameters with child_list by calling
  // ResolvedColumnDefinition.getFullTypeParameters() function.
  optional TypeParametersProto type_parameters = 5;
}

// <expression> indicates the expression that defines the column. The type of
// the expression will always match the type of the column.
//   - The <expression> can contain ResolvedColumnRefs corresponding to
//   ResolvedColumnDefinition.<column> for any of the
//   ResolvedColumnDefinitions in the enclosing statement.
//   - The expression can never include a subquery.
//
// <stored_mode> is the mode of a generated column: Values are:
//   - 'NON_STORED': The <expression> must always be evaluated at read time.
//   - 'STORED': The <expression> should be pre-emptively computed at write
//        time (to save work at read time) and must not call any volatle
//        function (e.g. RAND).
//   - 'STORED_VOLATILE': The <expression> must be computed at write time and
//        may call volatile functions (e.g. RAND).
// See (broken link) and
// (broken link).
message ResolvedGeneratedColumnInfoProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto expression = 2;
  optional ResolvedGeneratedColumnInfoEnums.StoredMode stored_mode = 5;
}

// <expression> is the default value expression of the column. The type of
// the expression must be coercible to the column type.
//   - <default_value> cannot contain any references to another column.
//   - <default_value> cannot include a subquery, aggregation, or window
//     function.
//
// <sql> is the original SQL string for the default value expression.
//
// Since we can't enforce engines to access at least one of the fields, we
// leave both fields NOT_IGNORABLE to ensure engines access at least one of
// them.
message ResolvedColumnDefaultValueProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto expression = 2;
  optional string sql = 3;
}

// This is used in CREATE TABLE statements to provide an explicit column
// definition.
//
// if <is_hidden> is TRUE, then the column won't show up in SELECT * queries.
//
// if <generated_column_info> is non-NULL, then this column is a generated
// column.
//
// if <default_value> is non-NULL, then this column has default value.
//
// <generated_column_info> and <default_value> cannot both be set at the
// same time.
//
// <column> defines an ID for the column, which may appear in expressions in
// the PARTITION BY, CLUSTER BY clause or <generated_column_info> if either
// is present.
message ResolvedColumnDefinitionProto {
  optional ResolvedArgumentProto parent = 1;

  optional string name = 2;
  optional TypeProto type = 3;
  optional ResolvedColumnAnnotationsProto annotations = 4;
  optional bool is_hidden = 5;
  optional ResolvedColumnProto column = 6;
  optional ResolvedGeneratedColumnInfoProto generated_column_info = 7;
  optional ResolvedColumnDefaultValueProto default_value = 9;
}

// Intermediate class for resolved constraints.
message AnyResolvedConstraintProto {
  oneof node {
    ResolvedPrimaryKeyProto resolved_primary_key_node = 92;
    ResolvedForeignKeyProto resolved_foreign_key_node = 110;
    ResolvedCheckConstraintProto resolved_check_constraint_node = 113;
  }
}

message ResolvedConstraintProto {
  optional ResolvedArgumentProto parent = 1;

}

// This represents the PRIMARY KEY constraint on a table.
// <column_offset_list> provides the offsets of the column definitions that
//                      comprise the primary key. This is empty when a
//                      0-element primary key is defined or when the altered
//                      table does not exist.
// <unenforced> specifies whether the constraint is unenforced.
// <constraint_name> specifies the constraint name, if present
// <column_name_list> provides the column names used in column definitions
//                    that comprise the primary key.
message ResolvedPrimaryKeyProto {
  optional ResolvedConstraintProto parent = 1;

  repeated int64 column_offset_list = 2;
  repeated ResolvedOptionProto option_list = 3;
  optional bool unenforced = 4;
  optional string constraint_name = 5;
  repeated string column_name_list = 6;
}

// This represents the FOREIGN KEY constraint on a table. It is of the form:
//
//   CONSTRAINT <constraint_name>
//   FOREIGN KEY <referencing_column_offset_list>
//   REFERENCES <referenced_table> <referenced_column_offset_list>
//   <match_mode>
//   <update_action>
//   <delete_action>
//   <enforced>
//   <option_list>
//
// <constraint_name> uniquely identifies the constraint.
//
// <referencing_column_offset_list> provides the offsets of the column
// definitions for the table defining the foreign key.
//
// <referenced_table> identifies the table this constraint references.
//
// <referenced_column_offset_list> provides the offsets of the column
// definitions for the table referenced by the foreign key.
//
// <match_mode> specifies how referencing keys with null values are handled.
//
// <update_action> specifies what action to take, if any, when a referenced
// value is updated.
//
// <delete_action> specifies what action to take, if any, when a row with a
// referenced values is deleted.
//
// <enforced> specifies whether or not the constraint is enforced.
//
// <option_list> for foreign key table constraints. Empty for foreign key
// column attributes (see instead ResolvedColumnAnnotations).
//
// <referencing_column_list> provides the names for the foreign key's
// referencing columns.
message ResolvedForeignKeyProto {
  optional ResolvedConstraintProto parent = 1;

  optional string constraint_name = 2;
  repeated int64 referencing_column_offset_list = 3;
  optional TableRefProto referenced_table = 4;
  repeated int64 referenced_column_offset_list = 5;
  optional ResolvedForeignKeyEnums.MatchMode match_mode = 6;
  optional ResolvedForeignKeyEnums.ActionOperation update_action = 7;
  optional ResolvedForeignKeyEnums.ActionOperation delete_action = 8;
  optional bool enforced = 9;
  repeated ResolvedOptionProto option_list = 10;
  repeated string referencing_column_list = 11;
}

// This represents the ABSL_CHECK constraint on a table. It is of the form:
//
//   CONSTRAINT <constraint_name>
//   ABSL_CHECK <expression>
//   <enforced>
//   <option_list>
//
// <constraint_name> uniquely identifies the constraint.
//
// <expression> defines a boolean expression to be evaluated when the row is
// updated. If the result is FALSE, update to the row is not allowed.
//
// <enforced> specifies whether or not the constraint is enforced.
//
// <option_list> list of options for check constraint.
//
// See (broken link).
message ResolvedCheckConstraintProto {
  optional ResolvedConstraintProto parent = 1;

  optional string constraint_name = 2;
  optional AnyResolvedExprProto expression = 3;
  optional bool enforced = 4;
  repeated ResolvedOptionProto option_list = 5;
}

// This is used in ResolvedQueryStmt to provide a user-visible name
// for each output column.
message ResolvedOutputColumnProto {
  optional ResolvedArgumentProto parent = 1;

  optional string name = 2;
  optional ResolvedColumnProto column = 3;
}

// A Project node computes new expression values, and possibly drops
// columns from the input Scan's column_list.
//
// Each entry in <expr_list> is a new column computed from an expression.
//
// The column_list can include any columns from input_scan, plus these
// newly computed columns.
//
// NOTE: This scan will propagate the is_ordered property of <input_scan>
// by default.  To make this scan unordered, call set_is_ordered(false).
message ResolvedProjectScanProto {
  optional ResolvedScanProto parent = 1;

  repeated ResolvedComputedColumnProto expr_list = 2;
  optional AnyResolvedScanProto input_scan = 3;
}

// This scan represents a call to a table-valued function (TVF). Each TVF
// returns an entire output relation instead of a single scalar value. The
// enclosing query may refer to the TVF as if it were a table subquery. The
// TVF may accept scalar arguments and/or other input relations.
//
// Scalar arguments work the same way as arguments for non-table-valued
// functions: in the resolved AST, their types are equal to the required
// argument types specified in the function signature.
//
// The function signature may also include relation arguments, and any such
// relation argument may specify a required schema. If such a required schema
// is present, then in the resolved AST, the ResolvedScan for each relational
// ResolvedFunctionArgument is guaranteed to have the same number of columns
// as the required schema, and the provided columns match position-wise with
// the required columns. Each provided column has the same name and type as
// the corresponding required column.
//
// If AnalyzerOptions::prune_unused_columns is true, the <column_list> and
// <column_index_list> will include only columns that were referenced
// in the user query. (SELECT * counts as referencing all columns.)
// Pruning has no effect on value tables (the value is never pruned).
//
// <column_list> is a set of new ResolvedColumns created by this scan.
// The <column_list>[i] should be matched to the related TVFScan's output
// relation column by
// <signature>.result_schema().column(<column_index_list>[i]).
//
// <tvf> The TableValuedFunction entry that the catalog returned for this TVF
//       scan. Contains non-concrete function signatures which may include
//       arguments with templated types.
// <signature> The concrete table function signature for this TVF call,
//             including the types of all scalar arguments and the
//             number and types of columns of all table-valued
//             arguments. An engine may also subclass this object to
//             provide extra custom information and return an instance
//             of the subclass from the TableValuedFunction::Resolve
//             method.
// <argument_list> The vector of resolved concrete arguments for this TVF
//                 call, including the default values or NULLs injected for
//                 the omitted arguments (Note the NULL injection is a
//                 temporary solution to handle omitted named arguments. This
//                 is subject to change by upcoming CLs).
//
// <column_index_list> This list matches 1-1 with the <column_list>, and
// identifies the index of the corresponding column in the <signature>'s
// result relation column list.
//
// <alias> The AS alias for the scan, or empty if none.
// <function_call_signature> The FunctionSignature object from the
//                           <tvf->signatures()> list that matched the
//                           current call. The TVFScan's
//                           <FunctionSignature::ConcreteArgument> list
//                           matches 1:1 to <argument_list>, while its
//                           <FunctionSignature::arguments> list still has
//                           the full argument list.
//                           The analyzer only sets this field when
//                           it could be ambiguous for an engine to figure
//                           out the actual arguments provided, e.g., when
//                           there are arguments omitted from the call. When
//                           it is provided, engines may use this object to
//                           check for the argument names and omitted
//                           arguments. SQLBuilder may also need this object
//                           in cases when the named argument notation is
//                           required for this call.
message ResolvedTVFScanProto {
  optional ResolvedScanProto parent = 1;

  optional TableValuedFunctionRefProto tvf = 2;
  optional TVFSignatureProto signature = 3;
  repeated ResolvedFunctionArgumentProto argument_list = 5;
  repeated int64 column_index_list = 8;
  optional string alias = 6;
  optional FunctionSignatureProto function_call_signature = 7;
}

// ResolvedGroupRowsScan represents a call to a special TVF GROUP_ROWS().
// It can only show up inside WITH GROUP_ROWS clause, which is resolved as
// the field with_group_rows_subquery in ResolvedNonScalarFunctionCallBase
// ResolvedGroupRowsScan. This scan produces rows corresponding to the input
// of ResolvedAggregateScan that belong to the current group.
//
// <input_column_list> is a list of new columns created to store values
// coming from the input of the aggregate scan. ResolvedComputedColumn can
// only hold ResolvedColumnRef's and can reference anything from the
// pre-aggregation scan.
//
// <alias> is the alias of the scan or empty if none.
message ResolvedGroupRowsScanProto {
  optional ResolvedScanProto parent = 1;

  repeated ResolvedComputedColumnProto input_column_list = 2;
  optional string alias = 3;
}

// This represents a generic argument to a function. The argument can be
// semantically an expression, relation, model, connection descriptor, or
// sequence.
// Only one of the six fields will be set.
//
// <expr> represents a scalar function argument.
// <scan> represents a table-typed argument.
// <model> represents a ML model function argument.
// <connection> represents a connection object function argument.
// <descriptor_arg> represents a descriptor object function argument.
// <sequence> represents a sequence object function argument.
//
// This node could be used in multiple places:
// * ResolvedTVFScan supports all of these.
// * ResolvedFunctionCall supports <expr> and <sequence>.
// * ResolvedCallStmt supports only <expr>.
//
// If the argument has type <scan>, <argument_column_list> maps columns from
// <scan> into specific columns of the argument's input schema, matching
// those columns positionally. i.e. <scan>'s column_list may have fewer
// columns or out-of-order columns, and this vector maps those columns into
// specific input columns.
message ResolvedFunctionArgumentProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
  optional AnyResolvedScanProto scan = 3;
  optional ResolvedModelProto model = 5;
  optional ResolvedConnectionProto connection = 6;
  optional ResolvedDescriptorProto descriptor_arg = 7;
  repeated ResolvedColumnProto argument_column_list = 4;
  optional ResolvedInlineLambdaProto inline_lambda = 8;
  optional ResolvedSequenceProto sequence = 9;
}

// The superclass of all ZetaSQL statements.
message AnyResolvedStatementProto {
  oneof node {
    ResolvedExplainStmtProto resolved_explain_stmt_node = 37;
    ResolvedQueryStmtProto resolved_query_stmt_node = 38;
    AnyResolvedCreateStatementProto resolved_create_statement_node = 39;
    ResolvedExportDataStmtProto resolved_export_data_stmt_node = 43;
    ResolvedDefineTableStmtProto resolved_define_table_stmt_node = 44;
    ResolvedDescribeStmtProto resolved_describe_stmt_node = 45;
    ResolvedShowStmtProto resolved_show_stmt_node = 46;
    ResolvedBeginStmtProto resolved_begin_stmt_node = 47;
    ResolvedCommitStmtProto resolved_commit_stmt_node = 48;
    ResolvedRollbackStmtProto resolved_rollback_stmt_node = 49;
    ResolvedDropStmtProto resolved_drop_stmt_node = 50;
    ResolvedInsertStmtProto resolved_insert_stmt_node = 63;
    ResolvedDeleteStmtProto resolved_delete_stmt_node = 64;
    ResolvedUpdateStmtProto resolved_update_stmt_node = 66;
    AnyResolvedGrantOrRevokeStmtProto resolved_grant_or_revoke_stmt_node = 68;
    ResolvedAlterTableSetOptionsStmtProto resolved_alter_table_set_options_stmt_node = 71;
    ResolvedRenameStmtProto resolved_rename_stmt_node = 72;
    ResolvedCreateRowAccessPolicyStmtProto resolved_create_row_access_policy_stmt_node = 73;
    ResolvedDropRowAccessPolicyStmtProto resolved_drop_row_access_policy_stmt_node = 74;
    ResolvedDropFunctionStmtProto resolved_drop_function_stmt_node = 80;
    ResolvedCallStmtProto resolved_call_stmt_node = 83;
    ResolvedImportStmtProto resolved_import_stmt_node = 86;
    ResolvedModuleStmtProto resolved_module_stmt_node = 87;
    ResolvedCreateDatabaseStmtProto resolved_create_database_stmt_node = 95;
    ResolvedAssertStmtProto resolved_assert_stmt_node = 98;
    ResolvedMergeStmtProto resolved_merge_stmt_node = 101;
    AnyResolvedAlterObjectStmtProto resolved_alter_object_stmt_node = 114;
    ResolvedSetTransactionStmtProto resolved_set_transaction_stmt_node = 120;
    ResolvedDropMaterializedViewStmtProto resolved_drop_materialized_view_stmt_node = 121;
    ResolvedStartBatchStmtProto resolved_start_batch_stmt_node = 122;
    ResolvedRunBatchStmtProto resolved_run_batch_stmt_node = 123;
    ResolvedAbortBatchStmtProto resolved_abort_batch_stmt_node = 124;
    ResolvedTruncateStmtProto resolved_truncate_stmt_node = 133;
    ResolvedExecuteImmediateStmtProto resolved_execute_immediate_stmt_node = 140;
    ResolvedAssignmentStmtProto resolved_assignment_stmt_node = 142;
    ResolvedExportModelStmtProto resolved_export_model_stmt_node = 152;
    ResolvedDropTableFunctionStmtProto resolved_drop_table_function_stmt_node = 175;
    ResolvedCloneDataStmtProto resolved_clone_data_stmt_node = 177;
    ResolvedAnalyzeStmtProto resolved_analyze_stmt_node = 180;
    ResolvedDropSnapshotTableStmtProto resolved_drop_snapshot_table_stmt_node = 183;
    ResolvedAuxLoadDataStmtProto resolved_aux_load_data_stmt_node = 186;
    ResolvedDropPrivilegeRestrictionStmtProto resolved_drop_privilege_restriction_stmt_node = 192;
    ResolvedUndropStmtProto resolved_undrop_stmt_node = 227;
    ResolvedExportMetadataStmtProto resolved_export_metadata_stmt_node = 234;
    ResolvedDropIndexStmtProto resolved_drop_index_stmt_node = 242;
  }
}

message ResolvedStatementProto {
  optional ResolvedNodeProto parent = 1;

  repeated ResolvedOptionProto hint_list = 2;
}

// An Explain statement. This is always the root of a statement hierarchy.
// Its child may be any statement type except another ResolvedExplainStmt.
//
// It is implementation dependent what action a back end system takes for an
// ExplainStatement.
message ResolvedExplainStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional AnyResolvedStatementProto statement = 2;
}

// A SQL query statement.  This is the outermost query statement that runs
// and produces rows of output, like a SELECT.  (The contained query may be
// a Scan corresponding to a non-Select top-level operation like UNION ALL
// or WITH.)
//
// <output_column_list> gives the user-visible column names that should be
// returned in the API or query tools.  There may be duplicate names, and
// multiple output columns may reference the same column from <query>.
message ResolvedQueryStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated ResolvedOutputColumnProto output_column_list = 2;
  // If true, the result of this query is a value table. Rather than
  // producing rows with named columns, it produces rows with a single
  // unnamed value type.  output_column_list will have exactly one
  // column, with an empty name. See (broken link).
  optional bool is_value_table = 3;
  optional AnyResolvedScanProto query = 4;
}

// This statement:
//   CREATE DATABASE <name> [OPTIONS (...)]
// <name_path> is a vector giving the identifier path in the database name.
// <option_list> specifies the options of the database.
message ResolvedCreateDatabaseStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  repeated ResolvedOptionProto option_list = 3;
}

// Common superclass for CREATE statements with standard modifiers like
//         CREATE [OR REPLACE] [TEMP|TEMPORARY|PUBLIC|PRIVATE] <object type>
//         [IF NOT EXISTS] <name> ...
//
// <name_path> is a vector giving the identifier path in the table name.
// <create_scope> is the relevant scope, i.e., DEFAULT, TEMP, PUBLIC,
//                or PRIVATE.  PUBLIC/PRIVATE are only valid in module
//                resolution context, see (broken link)
//                for details.
// <create_mode> indicates if this was CREATE, CREATE OR REPLACE, or
//               CREATE IF NOT EXISTS.
message AnyResolvedCreateStatementProto {
  oneof node {
    ResolvedCreateFunctionStmtProto resolved_create_function_stmt_node = 76;
    ResolvedCreateTableFunctionStmtProto resolved_create_table_function_stmt_node = 88;
    ResolvedCreateIndexStmtProto resolved_create_index_stmt_node = 97;
    ResolvedCreateConstantStmtProto resolved_create_constant_stmt_node = 99;
    AnyResolvedCreateTableStmtBaseProto resolved_create_table_stmt_base_node = 106;
    ResolvedCreateModelStmtProto resolved_create_model_stmt_node = 107;
    AnyResolvedCreateViewBaseProto resolved_create_view_base_node = 108;
    ResolvedCreateProcedureStmtProto resolved_create_procedure_stmt_node = 125;
    ResolvedCreateEntityStmtProto resolved_create_entity_stmt_node = 154;
    ResolvedCreateSchemaStmtProto resolved_create_schema_stmt_node = 157;
    ResolvedCreateSnapshotTableStmtProto resolved_create_snapshot_table_stmt_node = 182;
    ResolvedCreatePrivilegeRestrictionStmtProto resolved_create_privilege_restriction_stmt_node = 191;
  }
}

message ResolvedCreateStatementProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  optional ResolvedCreateStatementEnums.CreateScope create_scope = 5;
  optional ResolvedCreateStatementEnums.CreateMode create_mode = 4;
}

// Represents one of indexed items in CREATE INDEX statement, with the
// ordering direction specified.
message ResolvedIndexItemProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedColumnRefProto column_ref = 2;
  optional bool descending = 3;
}

// This is used in CREATE INDEX STMT to represent the unnest operation
// performed on the base table. The produced element columns or array offset
// columns (optional) can appear in other ResolvedUnnestItem or index keys.
//
// <array_expr> is the expression of the array field, e.g., t.array_field.
// <element_column> is the new column produced by this unnest item that
//                  stores the array element value for each row.
// <array_offset_column> is optional. If present, it defines the column
//                       produced by this unnest item that stores the array
//                       offset (0-based) for the corresponding
//                       <element_column>.
message ResolvedUnnestItemProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto array_expr = 2;
  optional ResolvedColumnProto element_column = 3;
  optional ResolvedColumnHolderProto array_offset_column = 4;
}

// This statement:
// CREATE [OR REPLACE] [UNIQUE] [SEARCH | VECTOR] INDEX [IF NOT EXISTS]
//  <index_name_path> ON <table_name_path>
// [STORING (Expression, ...)]
// [UNNEST(path_expression) [[AS] alias] [WITH OFFSET [[AS] alias]], ...]
// (path_expression [ASC|DESC], ...) [OPTIONS (name=value, ...)];
//
// <table_name_path> is the name of table being indexed.
// <table_scan> is a TableScan on the table being indexed.
// <is_unique> specifies if the index has unique entries.
// <is_search> specifies if the index is for search. It is mutually exclusive
//             with is_vector.
// <is_vector> specifies if the index is for vector search. It is mutually
//             exclusive with is_search.
// <index_all_columns> specifies if indexing all the columns of the table.
//                     When this field is true, index_item_list must be
//                     empty and is_search must be true.
// <index_item_list> has the columns being indexed, specified as references
//                   to 'computed_columns_list' entries or the columns of
//                   'table_scan'.
// <storing_expression_list> has the expressions in the storing clause.
// <option_list> has engine-specific directives for how and where to
//               materialize this index.
// <computed_columns_list> has computed columns derived from the columns of
//                         'table_scan' or 'unnest_expressions_list'. For
//                         example, the extracted field (e.g., x.y.z).
// <unnest_expressions_list> has unnest expressions derived from
//                           'table_scan' or previous unnest expressions in
//                           the list. So the list order is significant.
message ResolvedCreateIndexStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated string table_name_path = 2;
  optional ResolvedTableScanProto table_scan = 3;
  optional bool is_unique = 4;
  optional bool is_search = 10;
  optional bool is_vector = 12;
  optional bool index_all_columns = 11;
  repeated ResolvedIndexItemProto index_item_list = 5;
  repeated AnyResolvedExprProto storing_expression_list = 9;
  repeated ResolvedOptionProto option_list = 6;
  repeated ResolvedComputedColumnProto computed_columns_list = 7;
  repeated ResolvedUnnestItemProto unnest_expressions_list = 8;
}

// This statement:
//   CREATE [OR REPLACE] SCHEMA [IF NOT EXISTS] <name>
//   [DEFAULT COLLATE <collation>]
//   [OPTIONS (name=value, ...)]
//
// <option_list> engine-specific options.
// <collation_name> specifies the default collation specification for future
//   tables created in the dataset. If a table is created in this dataset
//   without specifying table-level default collation, it inherits the
//   dataset default collation. A change to this field affects only tables
//   created afterwards, not the existing tables. Only string literals
//   are allowed for this field.
//
//   Note: If a table being created in this schema does not specify table
//   default collation, the engine should copy the dataset default collation
//   to the table as the table default collation.
message ResolvedCreateSchemaStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  optional AnyResolvedExprProto collation_name = 3;
  repeated ResolvedOptionProto option_list = 2;
}

// This statement:
//   CREATE [TEMP] TABLE <name> [(column type, ...) | LIKE <name_path>]
//   [DEFAULT COLLATE <collation>] [PARTITION BY expr, ...]
//   [CLUSTER BY expr, ...] [OPTIONS (...)]
//
// <option_list> has engine-specific directives for how and where to
//               materialize this table.
// <column_definition_list> has the names and types of the columns in the
//                          created table. If <is_value_table> is true, it
//                          must contain exactly one column, with a generated
//                          name such as "$struct".
// <pseudo_column_list> is a list of some pseudo-columns expected to be
//                      present on the created table (provided by
//                      AnalyzerOptions::SetDdlPseudoColumns*).  These can be
//                      referenced in expressions in <partition_by_list> and
//                      <cluster_by_list>.
// <primary_key> specifies the PRIMARY KEY constraint on the table, it is
//               nullptr when no PRIMARY KEY is specified.
// <foreign_key_list> specifies the FOREIGN KEY constraints on the table.
// <check_constraint_list> specifies the ABSL_CHECK constraints on the table.
// <partition_by_list> specifies the partitioning expressions for the table.
// <cluster_by_list> specifies the clustering expressions for the table.
// TODO: Return error when the PARTITION BY / CLUSTER BY
// expression resolves to have collation specified.
// <is_value_table> specifies whether the table is a value table.
//                  See (broken link).
// <like_table> identifies the table in the LIKE <name_path>.
//              By default, all fields (column names, types, constraints,
//              keys, clustering etc.) will be inherited from the source
//              table. But if explicitly set, the explicit settings will
//              take precedence.
// <collation_name> specifies the default collation specification to apply to
//   newly added STRING fields in this table. A change of this field affects
//   only the STRING columns and the STRING fields in STRUCTs added
//   afterwards, not existing columns. Only string literals are allowed for
//   this field.
//
//   Note: During table creation or alteration, if a STRING field is added to
//   this table without explicit collation specified, the engine should copy
//   the table default collation to the STRING field.
message AnyResolvedCreateTableStmtBaseProto {
  oneof node {
    ResolvedCreateTableAsSelectStmtProto resolved_create_table_as_select_stmt_node = 40;
    ResolvedCreateExternalTableStmtProto resolved_create_external_table_stmt_node = 42;
    ResolvedCreateTableStmtProto resolved_create_table_stmt_node = 90;
  }
}

message ResolvedCreateTableStmtBaseProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
  repeated ResolvedColumnDefinitionProto column_definition_list = 3;
  repeated ResolvedColumnProto pseudo_column_list = 7;
  optional ResolvedPrimaryKeyProto primary_key = 4;
  repeated ResolvedForeignKeyProto foreign_key_list = 9;
  repeated ResolvedCheckConstraintProto check_constraint_list = 10;
  optional bool is_value_table = 8;
  optional TableRefProto like_table = 11;
  optional AnyResolvedExprProto collation_name = 12;
  optional ResolvedConnectionProto connection = 13;
}

// This statement:
//   CREATE [TEMP] TABLE <name>
//   [(column schema, ...) | LIKE <name_path> |
//       {CLONE|COPY} <name_path>
//           [FOR SYSTEM_TIME AS OF <time_expr>]
//           [WHERE <where_clause>]]
//   [DEFAULT COLLATE <collation_name>]
//   [PARTITION BY expr, ...] [CLUSTER BY expr, ...]
//   [WITH CONNECTION connection_name]
//   [OPTIONS (...)]
//
// One of <clone_from> or <copy_from> can be present for CLONE or COPY.
//   <clone_from> specifes the data source to clone from (cheap, typically
//   O(1) operation); while <copy_from> is intended for a full copy.
//
//   ResolvedTableScan will represent the source table, with an optional
//   for_system_time_expr.
//
//   The ResolvedTableScan may be wrapped inside a ResolvedFilterScan if the
//   source table has a where clause. No other Scan types are allowed here.
//
//   If the OPTIONS clause is explicitly specified, the option values are
//   intended to be used for the created or replaced table.
//   If any OPTION is unspecified, the corresponding option from the source
//   table will be used instead.
//
//   The 'clone_from.column_list' field may be set, but should be ignored.
//
//   clone_from and copy_from cannot be value tables.
message ResolvedCreateTableStmtProto {
  optional ResolvedCreateTableStmtBaseProto parent = 1;

  optional AnyResolvedScanProto clone_from = 7;
  optional AnyResolvedScanProto copy_from = 8;
  repeated AnyResolvedExprProto partition_by_list = 5;
  repeated AnyResolvedExprProto cluster_by_list = 6;
}

// This statement:
//   CREATE [TEMP] TABLE <name> [(column schema, ...) | LIKE <name_path>]
//   [DEFAULT COLLATE <collation_name>] [PARTITION BY expr, ...]
//   [CLUSTER BY expr, ...]
//   [WITH CONNECTION connection_name]
//   [OPTIONS (...)]
//   AS SELECT ...
//
// The <output_column_list> matches 1:1 with the <column_definition_list> in
// ResolvedCreateTableStmtBase, and maps ResolvedColumns produced by <query>
// into specific columns of the created table.  The output column names and
// types must match the column definition names and types.  If the table is
// a value table, <output_column_list> must have exactly one column, with a
// generated name such as "$struct".
//
// <output_column_list> does not contain all table schema information that
// <column_definition_list> does. For example, NOT NULL annotations, column
// OPTIONS, and primary keys are only available in <column_definition_list>.
// Consumers are encouraged to read from <column_definition_list> rather
// than than <output_column_list> to determine the table schema, if possible.
//
// <query> is the query to run.
message ResolvedCreateTableAsSelectStmtProto {
  optional ResolvedCreateTableStmtBaseProto parent = 1;

  repeated AnyResolvedExprProto partition_by_list = 5;
  repeated AnyResolvedExprProto cluster_by_list = 6;
  repeated ResolvedOutputColumnProto output_column_list = 2;
  optional AnyResolvedScanProto query = 3;
}

// Resolves a create model aliased query:
// identifier AS <query>
//
// <alias> is the string representation of identifier.
// <query> is the ResolvedScan of the subquery.
// <output_column_list> matches 1:1 with the <query>'s column_list and
// identifies the names and types of the columns output from the query.
message ResolvedCreateModelAliasedQueryProto {
  optional ResolvedArgumentProto parent = 1;

  optional string alias = 2;
  optional AnyResolvedScanProto query = 3;
  repeated ResolvedOutputColumnProto output_column_list = 4;
}

// This statement:
//   CREATE [TEMP] MODEL <name> [INPUT(...) OUTPUT(...)] [TRANSFORM(...)]
//   [REMOTE [WITH CONNECTION ...]] [OPTIONS (...)]
//   [AS <query> | (<identifier> AS (<query>) [, ...])]
//
// At most one of <query> and <aliased_query_list> can be set. <query> is
// used when there is a single query as input. <aliased_query_list> is used
// for the syntax with multiple queries with identifiers. For below, let
// <has_query> be true if either of these are present.
//
// Models can be evaluated either locally or remotely. Orthogonally, they can
// be either trained using SQL or come from external source. Depending on
// these properties, different clauses are expected to be present.
//
// * Local models <is_remote> = FALSE
//   * Trained: <has_query>
//   * External: !<has_query>
// * Remote models <is_remote> = TRUE
//   * Trained: <has_query> [Not supported yet]
//   * External: !<has_query>
//
// <option_list> has engine-specific directives for how to train this model.
// <query> is the AS SELECT statement. It can be only set when <is_remote> is
//   false and all of <input_column_definition_list>,
//   <output_column_definition_list> and <aliased_query_list> are empty.
// TODO: consider rename to <query_output_column_list>.
// <output_column_list> matches 1:1 with the <query>'s column_list and
//   identifies the names and types of the columns output from the select
//   statement. Set only when <query> is present.
// <input_column_definition_list> contains names and types of model's input
//   columns. Cannot be set if <has_query> is true. Might be absent when
//   <is_remote> is true, meaning schema is read from the remote model
//   itself.
// <output_column_definition_list> contains names and types of model's output
//   columns. Cannot be set if <has_query> is true. Might be absent when
//   <is_remote> is true, meaning schema is read from the remote model
//   itself.
// <is_remote> is true if this is a remote model. Cannot be set when
//   <has_query> is true.
// <connection> is the identifier path of the connection object. It can be
//   only set when <is_remote> is true.
// <transform_list> is the list of ResolvedComputedColumn in TRANSFORM
//   clause. It can be only set when <query> is present.
// <transform_input_column_list> introduces new ResolvedColumns that have the
//   same names and types of the columns in the <output_column_list>. The
//   transform expressions resolve against these ResolvedColumns. It's only
//   set when <transform_list> is non-empty.
// <transform_output_column_list> matches 1:1 with <transform_list> output.
//   It records the names of the output columns from TRANSFORM clause.
// <transform_analytic_function_group_list> is the list of
//   AnalyticFunctionGroup for analytic functions inside TRANSFORM clause.
//   It records the input expression of the analytic functions. It can
//   see all the columns from <transform_input_column_list>. The only valid
//   group is for the full, unbounded window generated from empty OVER()
//   clause.
//   For example, CREATE MODEL statement
//   "create model Z
//     transform (max(c) over() as d)
//     options ()
//     as select 1 c, 2 b;"
//   will generate transform_analytic_function_group_list:
//   +-transform_analytic_function_group_list=
//     +-AnalyticFunctionGroup
//       +-analytic_function_list=
//         +-d#5 :=
//           +-AnalyticFunctionCall(ZetaSQL:max(INT64) -> INT64)
//             +-ColumnRef(type=INT64, column=Z.c#3)
//             +-window_frame=
//               +-WindowFrame(frame_unit=ROWS)
//                 +-start_expr=
//                 | +-WindowFrameExpr(boundary_type=UNBOUNDED PRECEDING)
//                 +-end_expr=
//                   +-WindowFrameExpr(boundary_type=UNBOUNDED FOLLOWING)
// <aliased_query_list> is the aliased query list. It can only be set when
//   <is_remote> is false and <query> is null. It cannot coexist with any
//   transform related resolved nodes.
message ResolvedCreateModelStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
  repeated ResolvedOutputColumnProto output_column_list = 3;
  optional AnyResolvedScanProto query = 4;
  repeated ResolvedCreateModelAliasedQueryProto aliased_query_list = 13;
  repeated ResolvedColumnDefinitionProto transform_input_column_list = 8;
  repeated ResolvedComputedColumnProto transform_list = 5;
  repeated ResolvedOutputColumnProto transform_output_column_list = 6;
  repeated ResolvedAnalyticFunctionGroupProto transform_analytic_function_group_list = 7;
  repeated ResolvedColumnDefinitionProto input_column_definition_list = 9;
  repeated ResolvedColumnDefinitionProto output_column_definition_list = 10;
  optional bool is_remote = 11;
  optional ResolvedConnectionProto connection = 12;
}

// Common superclass for CREATE view/materialized view:
//   CREATE [TEMP|MATERIALIZED] [RECURSIVE] VIEW <name> [(...)]
//     [OPTIONS (...)]
//     AS SELECT ...
//
// <option_list> has engine-specific directives for options attached to
//               this view.
// <output_column_list> has the names and types of the columns in the
//                      created view, and maps from <query>'s column_list
//                      to these output columns. If <has_explicit_columns> is
//                      true, names will be explicitly provided.
// <has_explicit_columns> If this is set, the statement includes an explicit
//   column name list. These column names should still be applied even if the
//   query changes or is re-resolved in the future. The view becomes invalid
//   if the query produces a different number of columns.
// <query> is the query to run.
// <sql> is the view query text.
// <sql_security> is the declared security mode for the function. Values
//    include 'INVOKER', 'DEFINER'.
// <recursive> specifies whether or not the view is created with the
//   RECURSIVE keyword.
// <column_definition_list> matches 1:1 with the <output_column_list> and
//   provides explicit definition for each output column. Output column names
//   and types must match column definition names and types. If the table is
//   a value table, <column_definition_list> must have exactly one column,
//   with a generated name such as "$struct".
//
// Currently <column_definition_list> contains the same schema information
// (column names and types) as <output_column_list>, but also contains the
// column OPTIONS. Therefore, consumers are encouraged to read from
// <column_definition_list> rather than from <output_column_list> to
// determine the schema, if possible.
//
// Note that <query> and <sql> are both marked as IGNORABLE because
// an engine could look at either one (but might not look at both).
// An engine must look at one (and cannot ignore both) to be
// semantically valid, but there is currently no way to enforce that.
//
// The view must produce named columns with unique names.
message AnyResolvedCreateViewBaseProto {
  oneof node {
    ResolvedCreateViewStmtProto resolved_create_view_stmt_node = 41;
    ResolvedCreateMaterializedViewStmtProto resolved_create_materialized_view_stmt_node = 119;
    ResolvedCreateApproxViewStmtProto resolved_create_approx_view_stmt_node = 235;
  }
}

message ResolvedCreateViewBaseProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
  repeated ResolvedOutputColumnProto output_column_list = 3;
  optional bool has_explicit_columns = 9;
  optional AnyResolvedScanProto query = 5;
  optional string sql = 6;
  optional ResolvedCreateStatementEnums.SqlSecurity sql_security = 7;
  // If true, this view produces a value table. Rather than producing
  // rows with named columns, it produces rows with a single unnamed
  // value type.  output_column_list will have exactly one column, with
  // an empty name. See (broken link).
  optional bool is_value_table = 4;
  // True if the view uses the RECURSIVE keyword. <query>
  // can be a ResolvedRecursiveScan only if this is true.
  optional bool recursive = 8;
  repeated ResolvedColumnDefinitionProto column_definition_list = 10;
}

// This statement:
// CREATE [TEMP] VIEW <name> [(...)] [OPTIONS (...)] AS SELECT ...
message ResolvedCreateViewStmtProto {
  optional ResolvedCreateViewBaseProto parent = 1;

}

// This statement:
// WITH PARTITION COLUMNS [(column schema, ...)]
message ResolvedWithPartitionColumnsProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedColumnDefinitionProto column_definition_list = 2;
}

// This statement:
//   CREATE SNAPSHOT TABLE [IF NOT EXISTS] <name> [OPTIONS (...)]
//   CLONE <name>
//           [FOR SYSTEM_TIME AS OF <time_expr>]
//
// <clone_from> the source data to clone data from.
//              ResolvedTableScan will represent the source table, with an
//              optional for_system_time_expr.
//              The ResolvedTableScan may be wrapped inside a
//              ResolvedFilterScan if the source table has a where clause.
//              No other Scan types are allowed here.
//              By default, all fields (column names, types, constraints,
//              partition, clustering, options etc.) will be inherited from
//              the source table. If table options are explicitly set, the
//              explicit options will take precedence.
//              The 'clone_from.column_list' field may be set, but should be
//              ignored.
message ResolvedCreateSnapshotTableStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  optional AnyResolvedScanProto clone_from = 2;
  repeated ResolvedOptionProto option_list = 3;
}

// This statement:
// CREATE [TEMP] EXTERNAL TABLE <name> [(column type, ...)]
// [DEFAULT COLLATE <collation_name>]
// [WITH PARTITION COLUMN [(column type, ...)]]
// [WITH CONNECTION connection_name]
// OPTIONS (...)
message ResolvedCreateExternalTableStmtProto {
  optional ResolvedCreateTableStmtBaseProto parent = 1;

  optional ResolvedWithPartitionColumnsProto with_partition_columns = 2;
}

// This statement:
//   EXPORT MODEL <model_name_path> [WITH CONNECTION <connection>]
//   <option_list>
// which is used to export a model to a specific location.
// <connection> is the connection that the model is written to.
// <option_list> identifies user specified options to use when exporting the
//   model.
message ResolvedExportModelStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string model_name_path = 2;
  optional ResolvedConnectionProto connection = 3;
  repeated ResolvedOptionProto option_list = 4;
}

// This statement:
//   EXPORT DATA [WITH CONNECTION] <connection> (<option_list>) AS SELECT ...
// which is used to run a query and export its result somewhere
// without giving the result a table name.
// <connection> connection reference for accessing destination source.
// <option_list> has engine-specific directives for how and where to
//               materialize the query result.
// <output_column_list> has the names and types of the columns produced by
//                      the query, and maps from <query>'s column_list
//                      to these output columns.  The engine may ignore
//                      the column names depending on the output format.
// <query> is the query to run.
//
// The query must produce named columns with unique names.
message ResolvedExportDataStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedConnectionProto connection = 6;
  repeated ResolvedOptionProto option_list = 2;
  repeated ResolvedOutputColumnProto output_column_list = 3;
  // If true, the result of this query is a value table. Rather than
  // producing rows with named columns, it produces rows with a single
  // unnamed value type.  output_column_list will have exactly one
  // column, with an empty name. See (broken link).
  optional bool is_value_table = 4;
  optional AnyResolvedScanProto query = 5;
}

// This statement:
//   EXPORT <schema_object_kind> METADATA FROM <name_path>
//   [WITH CONNECTION <connection>] [OPTIONS(<option_list>)]
//
// <schema_object_kind> is a string identifier for the object for which the
// metadata should be exported. Currently, only 'TABLE' object is supported.
// <name_path> is a vector giving the identifier path for the object for
// which the metadata should be exported.
// <connection> connection reference for accessing destination source.
// <option_list> identifies user specified options to use when exporting
// object's metadata.
message ResolvedExportMetadataStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string schema_object_kind = 2;
  repeated string name_path = 3;
  optional ResolvedConnectionProto connection = 4;
  repeated ResolvedOptionProto option_list = 5;
}

// This statement: DEFINE TABLE name (...);
//
// <name_path> is a vector giving the identifier path in the table name.
// <option_list> has engine-specific options of how the table is defined.
//
// DEFINE TABLE normally has the same effect as CREATE TEMP EXTERNAL TABLE.
message ResolvedDefineTableStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  repeated ResolvedOptionProto option_list = 3;
}

// This statement: DESCRIBE [<object_type>] <name> [FROM <from_name_path>];
//
// <object_type> is an optional string identifier,
//               e.g., "INDEX", "FUNCTION", "TYPE", etc.
// <name_path> is a vector giving the identifier path for the object to be
//             described.
// <from_name_path> is an optional vector giving the identifier path of a
//                    containing object, e.g. a table.
message ResolvedDescribeStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string object_type = 2;
  repeated string name_path = 3;
  repeated string from_name_path = 4;
}

// This statement: SHOW <identifier> [FROM <name_path>] [LIKE <like_expr>];
//
// <identifier> is a string that determines the type of objects to be shown,
//              e.g., TABLES, COLUMNS, INDEXES, STATUS,
// <name_path> is an optional path to an object from which <identifier>
//             objects will be shown, e.g., if <identifier> = INDEXES and
//             <name> = table_name, the indexes of "table_name" will be
//             shown,
// <like_expr> is an optional ResolvedLiteral of type string that if present
//             restricts the objects shown to have a name like this string.
message ResolvedShowStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string identifier = 2;
  repeated string name_path = 3;
  optional ResolvedLiteralProto like_expr = 4;
}

// This statement: BEGIN [TRANSACTION] [ <transaction_mode> [, ...] ]
//
// Where transaction_mode is one of:
//      READ ONLY
//      READ WRITE
//      <isolation_level>
//
// <isolation_level> is a string vector storing the identifiers after
//       ISOLATION LEVEL. The strings inside vector could be one of the
//       SQL standard isolation levels:
//
//                   READ UNCOMMITTED
//                   READ COMMITTED
//                   READ REPEATABLE
//                   SERIALIZABLE
//
//       or could be arbitrary strings. ZetaSQL does not validate that
//       the string is valid.
message ResolvedBeginStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedBeginStmtEnums.ReadWriteMode read_write_mode = 3;
  repeated string isolation_level_list = 2;
}

// This statement: SET TRANSACTION <transaction_mode> [, ...]
//
// Where transaction_mode is one of:
//      READ ONLY
//      READ WRITE
//      <isolation_level>
//
// <isolation_level> is a string vector storing the identifiers after
//       ISOLATION LEVEL. The strings inside vector could be one of the
//       SQL standard isolation levels:
//
//                   READ UNCOMMITTED
//                   READ COMMITTED
//                   READ REPEATABLE
//                   SERIALIZABLE
//
//       or could be arbitrary strings. ZetaSQL does not validate that
//       the string is valid.
message ResolvedSetTransactionStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedBeginStmtEnums.ReadWriteMode read_write_mode = 3;
  repeated string isolation_level_list = 2;
}

// This statement: COMMIT [TRANSACTION];
message ResolvedCommitStmtProto {
  optional ResolvedStatementProto parent = 1;

}

// This statement: ROLLBACK [TRANSACTION];
message ResolvedRollbackStmtProto {
  optional ResolvedStatementProto parent = 1;

}

// This statement: START BATCH [<batch_type>];
//
// <batch_type> is an optional string identifier that identifies the type of
//              the batch. (e.g. "DML" or "DDL)
message ResolvedStartBatchStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string batch_type = 2;
}

// This statement: RUN BATCH;
message ResolvedRunBatchStmtProto {
  optional ResolvedStatementProto parent = 1;

}

// This statement: ABORT BATCH;
message ResolvedAbortBatchStmtProto {
  optional ResolvedStatementProto parent = 1;

}

// This statement: DROP <object_type> [IF EXISTS] <name_path> [<drop_mode>];
//
// <object_type> is an string identifier,
//               e.g., "TABLE", "VIEW", "INDEX", "FUNCTION", "TYPE", etc.
// <name_path> is a vector giving the identifier path for the object to be
//             dropped.
// <is_if_exists> silently ignore the "name_path does not exist" error.
// <drop_mode> specifies drop mode RESTRICT/CASCASE, if any.
message ResolvedDropStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string object_type = 2;
  optional bool is_if_exists = 3;
  repeated string name_path = 4;
  optional ResolvedDropStmtEnums.DropMode drop_mode = 5;
}

// This statement: DROP MATERIALIZED VIEW [IF EXISTS] <name_path>;
//
// <name_path> is a vector giving the identifier path for the object to be
//             dropped.
// <is_if_exists> silently ignore the "name_path does not exist" error.
message ResolvedDropMaterializedViewStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_if_exists = 3;
  repeated string name_path = 4;
}

// This statement: DROP SNAPSHOT TABLE [IF EXISTS] <name_path>;
//
// <name_path> is a vector giving the identifier path for the object to be
//             dropped.
// <is_if_exists> silently ignore the "name_path does not exist" error.
message ResolvedDropSnapshotTableStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_if_exists = 3;
  repeated string name_path = 4;
}

// Scan the previous iteration of the recursive alias currently being
// defined, from inside the recursive subquery which defines it. Such nodes
// can exist only in the recursive term of a ResolvedRecursiveScan node.
// The column_list produced here will match 1:1 with the column_list produced
// by the referenced subquery and will be given a new unique name to each
// column produced for this scan.
message ResolvedRecursiveRefScanProto {
  optional ResolvedScanProto parent = 1;

}

// A recursive query inside a WITH RECURSIVE or RECURSIVE VIEW. A
// ResolvedRecursiveScan may appear in a resolved tree only as a top-level
// input scan of a ResolvedWithEntry or ResolvedCreateViewBase.
//
// Recursive queries must satisfy the form:
//     <non-recursive-query> UNION [ALL|DISTINCT] <recursive-query>
//
// where self-references to table being defined are allowed only in the
// <recursive-query> section.
//
// <column_list> is a set of new ResolvedColumns created by this scan.
// Each input ResolvedSetOperationItem has an <output_column_list> which
// matches 1:1 with <column_list> and specifies how the input <scan>'s
// columns map into the final <column_list>.
//
// At runtime, a recursive scan is evaluated using an iterative process:
//
// Step 1: Evaluate the non-recursive term. If UNION DISTINCT
//   is specified, discard duplicates.
//
// Step 2:
//   Repeat until step 2 produces an empty result:
//     Evaluate the recursive term, binding the recursive table to the
//     new rows produced by previous step. If UNION DISTINCT is specified,
//     discard duplicate rows, as well as any rows which match any
//     previously-produced result.
//
// Step 3:
//   The final content of the recursive table is the UNION ALL of all results
//   produced (step 1, plus all iterations of step 2).
//
// ResolvedRecursiveScan only supports a recursive WITH entry which
//   directly references itself; ZetaSQL does not support mutual recursion
//   between multiple with-clause elements.
//
// See (broken link) for details.
message ResolvedRecursiveScanProto {
  optional ResolvedScanProto parent = 1;

  optional ResolvedRecursiveScanEnums.RecursiveSetOperationType op_type = 2;
  optional ResolvedSetOperationItemProto non_recursive_term = 3;
  optional ResolvedSetOperationItemProto recursive_term = 4;
}

// This represents a SQL WITH query (or subquery) like
//   WITH [RECURSIVE] <with_query_name1> AS (<with_subquery1>),
//        <with_query_name2> AS (<with_subquery2>)
//   <query>;
//
// WITH entries are sorted in dependency order so that an entry can only
// reference entries earlier in <with_entry_list>, plus itself if the
// RECURSIVE keyword is used. If the RECURSIVE keyword is not used, this will
// be the same order as in the original query, since an entry which
// references itself or any entry later in the list is not allowed.
//
// If a WITH subquery is referenced multiple times, the full query should
// behave as if the subquery runs only once and its result is reused.
//
// There will be one ResolvedWithEntry here for each subquery in the SQL
// WITH statement, in the same order as in the query.
//
// Inside the resolved <query>, or any <with_entry_list> occurring after
// its definition, a <with_query_name> used as a table scan will be
// represented using a ResolvedWithRefScan.
//
// The <with_query_name> aliases are always unique within a query, and should
// be used to connect the ResolvedWithRefScan to the original query
// definition.  The subqueries are not inlined and duplicated into the tree.
//
// In ZetaSQL 1.0, WITH is allowed only on the outermost query and not in
// subqueries, so the ResolvedWithScan node can only occur as the outermost
// scan in a statement (e.g. a QueryStmt or CreateTableAsSelectStmt).
//
// In ZetaSQL 1.1 (language option FEATURE_V_1_1_WITH_ON_SUBQUERY), WITH
// is allowed on subqueries.  Then, ResolvedWithScan can occur anywhere in
// the tree.  The alias introduced by a ResolvedWithEntry is visible only
// in subsequent ResolvedWithEntry queries and in <query>.  The aliases used
// must be globally unique in the resolved AST however, so consumers do not
// need to implement any scoping for these names.  Because the aliases are
// unique, it is legal to collect all ResolvedWithEntries in the tree and
// treat them as if they were a single WITH clause at the outermost level.
//
// In ZetaSQL 1.3 (language option FEATURE_V_1_3_WITH_RECURSIVE), WITH
// RECURSIVE is supported, which allows any <with_subquery> to reference
// any <with_query_name>, regardless of order, including WITH entries which
// reference themself. Circular dependency chains of WITH entries are allowed
// only for direct self-references, and only when the corresponding
// <with_subquery> takes the form "<non-recursive-term> UNION [ALL|DISTINCT]
// <recursive-term>", with all references to the current <with_query_name>
// confined to the recursive term.
//
// The subqueries inside ResolvedWithEntries cannot be correlated.
//
// If a WITH subquery is defined but never referenced, it will still be
// resolved and still show up here.  Query engines may choose not to run it.
message ResolvedWithScanProto {
  optional ResolvedScanProto parent = 1;

  repeated ResolvedWithEntryProto with_entry_list = 2;
  optional AnyResolvedScanProto query = 3;
  // True if the WITH clause uses the recursive keyword.
  optional bool recursive = 4;
}

// This represents one aliased subquery introduced in a WITH clause.
//
// The <with_query_name>s must be globally unique in the full resolved AST.
// The <with_subquery> cannot be correlated and cannot reference any
// columns from outside.  It may reference other WITH subqueries.
//
// See ResolvedWithScan for full details.
message ResolvedWithEntryProto {
  optional ResolvedArgumentProto parent = 1;

  optional string with_query_name = 2;
  optional AnyResolvedScanProto with_subquery = 3;
}

// This represents one SQL hint key/value pair.
// The SQL syntax @{ key1=value1, key2=value2, some_db.key3=value3 }
// will expand to three ResolvedOptions.  Keyword hints (e.g. LOOKUP JOIN)
// are interpreted as shorthand, and will be expanded to a ResolvedOption
// attached to the appropriate node before any explicit long-form hints.
//
// ResolvedOptions are attached to the ResolvedScan corresponding to the
// operator that the SQL hint was associated with.
// See (broken link) for more detail.
// Hint semantics are implementation defined.
//
// Each hint is resolved as a [<qualifier>.]<name>:=<value> pair.
//   <qualifier> will be empty if no qualifier was present.
//   <name> is always non-empty.
//   <value> can be a ResolvedLiteral or a ResolvedParameter,
//           a cast of a ResolvedParameter (for typed hints only),
//           or a general expression (on constant inputs).
//
// If AllowedHintsAndOptions was set in AnalyzerOptions, and this hint or
// option was included there and had an expected type, the type of <value>
// will match that expected type.  Unknown hints (not listed in
// AllowedHintsAndOptions) are not stripped and will still show up here.
//
// If non-empty, <qualifier> should be interpreted as a target system name,
// and a database system should ignore any hints targeted to different
// systems.
//
// <qualifier> is set only for hints, and will always be empty in options
// lists.
//
// The SQL syntax allows using an identifier as a hint value.
// Such values are stored here as ResolvedLiterals with string type.
message ResolvedOptionProto {
  optional ResolvedArgumentProto parent = 1;

  optional string qualifier = 2;
  optional string name = 3;
  optional AnyResolvedExprProto value = 4;
}

// Window partitioning specification for an analytic function call.
//
// PARTITION BY keys in <partition_by_list>.
//
// <collation_list> is either empty to indicate that all the elements in
// <partition_by_list> have the default collation, or <collation_list> has
// the same number of elements as <partition_by_list>.  Each element is the
// collation for the element in <partition_by_list> with the same index, or
// can be empty to indicate default collation or when the type is not
// collatable. <collation_list> is only set when
// FEATURE_V_1_3_COLLATION_SUPPORT is enabled.
// See (broken link).
message ResolvedWindowPartitioningProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedColumnRefProto partition_by_list = 2;
  repeated ResolvedOptionProto hint_list = 3;
  repeated ResolvedCollationProto collation_list = 4;
}

// Window ordering specification for an analytic function call.
//
// ORDER BY items in <order_by_list>. There should be exactly one ORDER
// BY item if this is a window ORDER BY for a RANGE-based window.
message ResolvedWindowOrderingProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedOrderByItemProto order_by_item_list = 2;
  repeated ResolvedOptionProto hint_list = 3;
}

// Window framing specification for an analytic function call.
//
// ROW-based window frames compute the frame based on physical offsets
// from the current row.
// RANGE-based window frames compute the frame based on a logical
// range of rows around the current row based on the current row's
// ORDER BY key value.
//
// <start_expr> and <end_expr> cannot be NULL. If the window frame
// is one-sided in the input query, the resolver will generate an
// implicit ending boundary.
message ResolvedWindowFrameProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedWindowFrameEnums.FrameUnit frame_unit = 2;
  optional ResolvedWindowFrameExprProto start_expr = 3;
  optional ResolvedWindowFrameExprProto end_expr = 4;
}

// This represents a group of analytic function calls that shares PARTITION
// BY and ORDER BY.
//
// <partition_by> can be NULL. <order_by> may be NULL depending on the
// functions in <analytic_function_list> and the window frame unit. See
// (broken link) for more details.
//
// All expressions in <analytic_function_list> have a
// ResolvedAnalyticFunctionCall with a function in mode
// Function::AGGREGATE or Function::ANALYTIC.
message ResolvedAnalyticFunctionGroupProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedWindowPartitioningProto partition_by = 2;
  optional ResolvedWindowOrderingProto order_by = 3;
  repeated ResolvedComputedColumnProto analytic_function_list = 4;
}

// Window frame boundary expression that determines the first/last row of
// the moving window for each tuple.
//
// <expression> cannot be NULL if the type is OFFSET_PRECEDING
// or OFFSET_FOLLOWING. It must be a constant expression. If this is a
// boundary for a ROW-based window, it must be integer type. Otherwise,
// it must be numeric type and must match exactly the type of the window
// ordering expression.  See (broken link) for more
// details.
message ResolvedWindowFrameExprProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedWindowFrameExprEnums.BoundaryType boundary_type = 2;
  optional AnyResolvedExprProto expression = 3;
}

// This represents a value inside an INSERT or UPDATE statement.
//
// The <value> is either an expression or a DMLDefault.
//
// For proto fields, NULL values mean the field should be cleared.
message ResolvedDMLValueProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto value = 2;
}

// This is used to represent the value DEFAULT that shows up (in place of a
// value expression) in INSERT and UPDATE statements.
// For columns, engines should substitute the engine-defined default value
// for that column, or give an error.
// For proto fields, this always means to clear the field.
// This will never show up inside expressions other than ResolvedDMLValue.
message ResolvedDMLDefaultProto {
  optional ResolvedExprProto parent = 1;

}

// This represents the ASSERT statement:
//   ASSERT <expression> [AS <description>];
//
// <expression> is any expression that returns a bool.
// <description> is an optional string literal used to give a more
// descriptive error message in case the ASSERT fails.
message ResolvedAssertStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional AnyResolvedExprProto expression = 2;
  optional string description = 3;
}

// This represents the ASSERT ROWS MODIFIED clause on a DML statement.
// The value must be a literal or (possibly casted) parameter int64.
//
// The statement should fail if the number of rows updated does not
// exactly match this number.
message ResolvedAssertRowsModifiedProto {
  optional ResolvedArgumentProto parent = 1;

  optional AnyResolvedExprProto rows = 2;
}

// This represents one row in the VALUES clause of an INSERT.
message ResolvedInsertRowProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedDMLValueProto value_list = 2;
}

// This represents an INSERT statement, or a nested INSERT inside an
// UPDATE statement.
//
// For top-level INSERT statements, <table_scan> gives the table to
// scan and creates ResolvedColumns for its columns.  Those columns can be
// referenced in <insert_column_list>.
//
// For nested INSERTS, there is no <table_scan> or <insert_column_list>.
// There is implicitly a single column to insert, and its type is the
// element type of the array being updated in the ResolvedUpdateItem
// containing this statement.
//
// For nested INSERTs, alternate modes are not supported and <insert_mode>
// will always be set to OR_ERROR.
//
// The rows to insert come from <row_list> or the result of <query>.
// Exactly one of these must be present.
//
// If <row_list> is present, the columns in the row_list match
// positionally with <insert_column_list>.
//
// If <query> is present, <query_output_column_list> must also be present.
// <query_output_column_list> is the list of output columns produced by
// <query> that correspond positionally with the target <insert_column_list>
// on the output table.  For nested INSERTs with no <insert_column_list>,
// <query_output_column_list> must have exactly one column.
//
// <query_parameter_list> is set for nested INSERTs where <query> is set and
// references non-target values (columns or field values) from the table. It
// is only set when FEATURE_V_1_2_CORRELATED_REFS_IN_NESTED_DML is enabled.
//
// If <returning> is present, the INSERT statement will return newly inserted
// rows. <returning> can only occur on top-level statements.
//
// The returning clause has a <output_column_list> to represent the data
// sent back to clients. It can only access columns from the <table_scan>.
//
// <column_access_list> indicates for each column in <table_scan.column_list>
// whether it was read and/or written. The query engine may also require
// read or write permissions across all columns, including unreferenced
// columns, depending on the operation.
message ResolvedInsertStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto table_scan = 2;
  // Behavior on duplicate rows (normally defined to mean duplicate
  // primary keys).
  optional ResolvedInsertStmtEnums.InsertMode insert_mode = 3;
  optional ResolvedAssertRowsModifiedProto assert_rows_modified = 4;
  optional ResolvedReturningClauseProto returning = 10;
  repeated ResolvedColumnProto insert_column_list = 5;
  repeated ResolvedColumnRefProto query_parameter_list = 9;
  optional AnyResolvedScanProto query = 6;
  repeated ResolvedColumnProto query_output_column_list = 8;
  repeated ResolvedInsertRowProto row_list = 7;
  repeated ResolvedStatementEnums.ObjectAccess column_access_list = 11;
}

// This represents a DELETE statement or a nested DELETE inside an
// UPDATE statement.
//
// For top-level DELETE statements, <table_scan> gives the table to
// scan and creates ResolvedColumns for its columns.  Those columns can
// be referenced inside the <where_expr>.
//
// For nested DELETEs, there is no <table_scan>.  The <where_expr> can
// only reference:
//   (1) the element_column from the ResolvedUpdateItem containing this
//       statement,
//   (2) columns from the outer statements, and
//   (3) (optionally) <array_offset_column>, which represents the 0-based
//       offset of the array element being modified.
//
// <where_expr> is required.
//
// If <returning> is present, the DELETE statement will return deleted rows
// back. It can only occur on top-level statements.
//
// This returning clause has a <output_column_list> to represent the data
// sent back to clients. It can only access columns from the <table_scan>.
//
// <column_access_list> indicates for each column in <table_scan.column_list>
// whether it was read and/or written. The query engine may also require
// read or write permissions across all columns, including unreferenced
// columns, depending on the operation.
message ResolvedDeleteStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto table_scan = 2;
  optional ResolvedAssertRowsModifiedProto assert_rows_modified = 3;
  optional ResolvedReturningClauseProto returning = 6;
  repeated ResolvedStatementEnums.ObjectAccess column_access_list = 7;
  optional ResolvedColumnHolderProto array_offset_column = 5;
  optional AnyResolvedExprProto where_expr = 4;
}

// This represents one item inside the SET clause of an UPDATE.
//
// The entity being updated is specified by <target>.
//
// For a regular
//   SET {target} = {expression} | DEFAULT
// clause (not including an array element update like SET a[OFFSET(0)] = 5),
// <target> and <set_value> will be present, and all other fields will be
// unset.
//
// For an array element update (e.g. SET a.b[<expr>].c = <value>),
//   - <target> is set to the array,
//   - <element_column> is a new ResolvedColumn that can be used inside the
//     update items to refer to the array element.
//   - <array_update_list> will have a node corresponding to the offset into
//     that array and the modification to that array element.
// For example, for SET a.b[<expr>].c = <value>, we have
//    ResolvedUpdateItem
//    +-<target> = a.b
//    +-<element_column> = <x>
//    +-<array_update_list>
//      +-ResolvedUpdateArrayItem
//        +-<offset> = <expr>
//        +-<update_item> = ResolvedUpdateItem
//          +-<target> = <x>.c
//          +-<set_value> = <value>
//
// The engine is required to fail the update if there are two elements of
// <array_update_list> corresponding to offset expressions that evaluate to
// the same value. These are considered to be conflicting updates.
//
// Multiple updates to the same array are always represented as multiple
// elements of <array_update_list> under a single ResolvedUpdateItem
// corresponding to that array. <array_update_list> will only have one
// element for modifications to an array-valued subfield of an array element.
// E.g., for SET a[<expr1>].b[<expr2>] = 5, a[<expr3>].b[<expr4>] = 6, we
// will have:
//     ResolvedUpdateItem
//     +-<target> = a
//     +-<element_column> = x
//     +-<array_update_list>
//       +-ResolvedUpdateArrayItem
//         +-<offset> = <expr1>
//         +-ResolvedUpdateItem for <x>.b[<expr2>] = 5
//       +-ResolvedUpdateArrayItem
//         +-<offset> = <expr3>
//         +-ResolvedUpdateItem for <x>.b[<expr4>] = 6
// The engine must give a runtime error if <expr1> and <expr3> evaluate to
// the same thing. Notably, it does not have to understand that the
// two ResolvedUpdateItems corresponding to "b" refer to the same array iff
// <expr1> and <expr3> evaluate to the same thing.
//
// TODO: Consider allowing the engine to execute an update like
// SET a[<expr1>].b = 1, a[<expr2>].c = 2 even if <expr1> == <expr2> since
// "b" and "c" do not overlap. Also consider allowing a more complex example
// like SET a[<expr1>].b[<expr2>] = ...,
// a[<expr3>].b[<expr4>].c[<expr5>] = ... even if <expr1> == <expr3>, as long
// as <expr2> != <expr4> in that case.
//
// For nested DML, <target> and <element_column> will both be set, and one or
// more of the nested statement lists will be non-empty. <target> must have
// ARRAY type, and <element_column> introduces a ResolvedColumn representing
// elements of that array. The nested statement lists will always be empty in
// a ResolvedUpdateItem child of a ResolvedUpdateArrayItem node.
//
// See (broken link) for more detail.
message ResolvedUpdateItemProto {
  optional ResolvedArgumentProto parent = 1;

  // The target entity to be updated.
  //
  // This is an expression evaluated using the ResolvedColumns visible
  // inside this statement.  This expression can contain only
  // ResolvedColumnRefs, ResolvedGetProtoField and
  // ResolvedGetStructField nodes.
  //
  // In a top-level UPDATE, the expression always starts with a
  // ResolvedColumnRef referencing a column from the statement's
  // TableScan.
  //
  // In a nested UPDATE, the expression always starts with a
  // ResolvedColumnRef referencing the element_column from the
  // ResolvedUpdateItem containing this scan.
  //
  // This node is also used to represent a modification of a single
  // array element (when it occurs as a child of a
  // ResolvedUpdateArrayItem node).  In that case, the expression
  // starts with a ResolvedColumnRef referencing the <element_column>
  // from its grandparent ResolvedUpdateItem. (E.g., for "SET a[<expr>]
  // = 5", the grandparent ResolvedUpdateItem has <target> "a", the
  // parent ResolvedUpdateArrayItem has offset <expr>, and this node
  // has <set_value> 5 and target corresponding to the grandparent's
  // <element_column> field.)
  //
  // For either a nested UPDATE or an array modification, there may be
  // a path of field accesses after the initial ResolvedColumnRef,
  // represented by a chain of GetField nodes.
  //
  // NOTE: We use the same GetField nodes as we do for queries, but
  // they are not treated the same.  Here, they express a path inside
  // an object that is being mutated, so they have reference semantics.
  optional AnyResolvedExprProto target = 2;
  // Set the target entity to this value.  The types must match.
  // This can contain the same columns that can appear in the
  // <where_expr> of the enclosing ResolvedUpdateStmt.
  //
  // This is mutually exclusive with all fields below, which are used
  // for nested updates only.
  optional ResolvedDMLValueProto set_value = 3;
  // The ResolvedColumn introduced to represent the elements of the
  // array being updated.  This works similarly to
  // ArrayScan::element_column.
  //
  // <target> must have array type, and this column has the array's
  // element type.
  //
  // This column can be referenced inside the nested statements below.
  optional ResolvedColumnHolderProto element_column = 4;
  // Array element modifications to apply. Each item runs on the value
  // of <element_column> specified by ResolvedUpdateArrayItem.offset.
  // This field is always empty if the analyzer option
  // FEATURE_V_1_2_ARRAY_ELEMENTS_WITH_SET is disabled.
  //
  // The engine must fail if two elements in this list have offset
  // expressions that evaluate to the same value.
  // TODO: Consider generalizing this to allow
  // SET a[<expr1>].b = ..., a[<expr2>].c = ...
  repeated ResolvedUpdateArrayItemProto array_update_list = 8;
  // Nested DELETE statements to apply.  Each delete runs on one value
  // of <element_column> and may choose to delete that array element.
  //
  // DELETEs are applied before INSERTs or UPDATEs.
  //
  // It is legal for the same input element to match multiple DELETEs.
  repeated ResolvedDeleteStmtProto delete_list = 5;
  // Nested UPDATE statements to apply.  Each update runs on one value
  // of <element_column> and may choose to update that array element.
  //
  // UPDATEs are applied after DELETEs and before INSERTs.
  //
  // It is an error if any element is matched by multiple UPDATEs.
  repeated ResolvedUpdateStmtProto update_list = 6;
  // Nested INSERT statements to apply.  Each insert will produce zero
  // or more values for <element_column>.
  //
  // INSERTs are applied after DELETEs and UPDATEs.
  //
  // For nested UPDATEs, insert_mode will always be the default, and
  // has no effect.
  repeated ResolvedInsertStmtProto insert_list = 7;
}

// For an array element modification, this node represents the offset
// expression and the modification, but not the array. E.g., for
// SET a[<expr>] = 5, this node represents a modification of "= 5" to offset
// <expr> of the array defined by the parent node.
message ResolvedUpdateArrayItemProto {
  optional ResolvedArgumentProto parent = 1;

  // The array offset to be modified.
  optional AnyResolvedExprProto offset = 2;
  // The modification to perform to the array element.
  optional ResolvedUpdateItemProto update_item = 3;
}

// This represents an UPDATE statement, or a nested UPDATE inside an
// UPDATE statement.
//
// For top-level UPDATE statements, <table_scan> gives the table to
// scan and creates ResolvedColumns for its columns.  Those columns can be
// referenced in the <update_item_list>. The top-level UPDATE statement may
// also have <from_scan>, the output of which is joined with
// the <table_scan> using expressions in the <where_expr>. The columns
// exposed in the <from_scan> are visible in the right side of the
// expressions in the <update_item_list> and in the <where_expr>.
// <array_offset_column> is never set for top-level UPDATE statements.
//
// Top-level UPDATE statements will also have <column_access_list> populated.
// For each column, this vector indicates if the column was read and/or
// written. The columns in this vector match those of
// <table_scan.column_list>. If a column was not encountered when producing
// the resolved AST, then the value at that index will be
// ResolvedStatement::NONE.
//
// For nested UPDATEs, there is no <table_scan>.  The <where_expr> can
// only reference:
//   (1) the element_column from the ResolvedUpdateItem containing this
//       statement,
//   (2) columns from the outer statements, and
//   (3) (optionally) <array_offset_column>, which represents the 0-based
//       offset of the array element being modified.
// The left hand sides of the expressions in <update_item_list> can only
// reference (1). The right hand sides of those expressions can reference
// (1), (2), and (3).
//
// The updates in <update_item_list> will be non-overlapping.
// If there are multiple nested statements updating the same entity,
// they will be combined into one ResolvedUpdateItem.
//
// See (broken link) for more detail on nested DML.
//
// If <returning> is present, the UPDATE statement will return updated rows.
// <returning> can only occur on top-level statements.
//
// This returning clause has a <output_column_list> to represent the data
// sent back to clients. It can only access columns from the <table_scan>.
// The columns in <from_scan> are not allowed.
// TODO: allow columns in <from_scan> to be referenced.
message ResolvedUpdateStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto table_scan = 2;
  repeated ResolvedStatementEnums.ObjectAccess column_access_list = 8;
  optional ResolvedAssertRowsModifiedProto assert_rows_modified = 3;
  optional ResolvedReturningClauseProto returning = 9;
  optional ResolvedColumnHolderProto array_offset_column = 7;
  optional AnyResolvedExprProto where_expr = 4;
  repeated ResolvedUpdateItemProto update_item_list = 5;
  optional AnyResolvedScanProto from_scan = 6;
}

// This is used by ResolvedMergeStmt to represent one WHEN ... THEN clause
// within MERGE statement.
//
// There are three types of clauses, which are MATCHED, NOT_MATCHED_BY_SOURCE
// and NOT_MATCHED_BY_TARGET. The <match_type> must have one of these values.
//
// The <match_expr> defines an optional expression to apply to the join
// result of <table_scan> and <from_scan> of the parent ResolvedMergeStmt.
//
// Each ResolvedMergeWhen must define exactly one of three operations,
//   -- INSERT: <action_type> is ResolvedMergeWhen::INSERT.
//              Both <insert_column_list> and <insert_row> are non-empty.
//              The size of <insert_column_list> must be the same with the
//              value_list size of <insert_row>, and, the column data type
//              must match.
//   -- UPDATE: <action_type> is ResolvedMergeWhen::UPDATE.
//              <update_item_list> is non-empty.
//   -- DELETE: <action_type> is ResolvedMergeWhen::DELETE.
// The INSERT, UPDATE and DELETE operations are mutually exclusive.
//
// When <match_type> is MATCHED, <action_type> must be UPDATE or DELETE.
// When <match_type> is NOT_MATCHED_BY_TARGET, <action_type> must be INSERT.
// When <match_type> is NOT_MATCHED_BY_SOURCE, <action_type> must be UPDATE
// or DELETE.
//
// The column visibility within a ResolvedMergeWhen clause is defined as
// following,
//   -- When <match_type> is MATCHED,
//      -- All columns from <table_scan> and <from_scan> are allowed in
//         <match_expr>.
//      -- If <action_type> is UPDATE, only columns from <table_scan> are
//         allowed on left side of expressions in <update_item_list>.
//         All columns from <table_scan> and <from_scan> are allowed on right
//         side of expressions in <update_item_list>.
//   -- When <match_type> is NOT_MATCHED_BY_TARGET,
//      -- Only columns from <from_scan> are allowed in <match_expr>.
//      -- Only columns from <table_scan> are allowed in
//         <insert_column_list>.
//      -- Only columns from <from_scan> are allowed in <insert_row>.
//   -- When <match_type> is NOT_MATCHED_BY_SOURCE,
//      -- Only columns from <table_scan> are allowed in <match_expr>.
//      -- If <action_type> is UPDATE, only columns from <table_scan> are
//         allowed in <update_item_list>.
message ResolvedMergeWhenProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedMergeWhenEnums.MatchType match_type = 2;
  optional AnyResolvedExprProto match_expr = 3;
  optional ResolvedMergeWhenEnums.ActionType action_type = 4;
  repeated ResolvedColumnProto insert_column_list = 5;
  optional ResolvedInsertRowProto insert_row = 6;
  repeated ResolvedUpdateItemProto update_item_list = 7;
}

// This represents a MERGE statement.
//
// <table_scan> gives the target table to scan and creates ResolvedColumns
// for its columns.
//
// <column_access_list> indicates for each column, whether it was read and/or
// written. The columns in this vector match those of
// <table_scan.column_list>. If a column was not encountered when producing
// the resolved AST, then the value at that index will be
// ResolvedStatement::NONE(0).
//
// The output of <from_scan> is joined with <table_scan> using the join
// expression <merge_expr>.
//
// The order of elements in <when_clause_list> matters, as they are executed
// sequentially. At most one of the <when_clause_list> clause will be applied
// to each row from <table_scan>.
//
// <table_scan>, <from_scan>, <merge_expr> and <when_clause_list> are
// required. <when_clause_list> must be non-empty.
//
// See (broken link) for more detail on MERGE statement.
message ResolvedMergeStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto table_scan = 2;
  repeated ResolvedStatementEnums.ObjectAccess column_access_list = 6;
  optional AnyResolvedScanProto from_scan = 3;
  optional AnyResolvedExprProto merge_expr = 4;
  repeated ResolvedMergeWhenProto when_clause_list = 5;
}

// This represents a TRUNCATE TABLE statement.
//
// Statement:
//   TRUNCATE TABLE <table_name> [WHERE <boolean_expression>]
//
// <table_scan> is a TableScan for the target table, which is used during
//              resolving and validation. Consumers can use either the table
//              object inside it or name_path to reference the table.
// <where_expr> boolean expression that can reference columns in
//              ResolvedColumns (which the TableScan creates); the
//              <where_expr> should always correspond to entire partitions,
//              and is optional.
message ResolvedTruncateStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto table_scan = 3;
  optional AnyResolvedExprProto where_expr = 4;
}

// A reference to a unit of an object (e.g. a column or field of a table).
//
// <name_path> is a vector giving the identifier path of the object unit.
message ResolvedObjectUnitProto {
  optional ResolvedArgumentProto parent = 1;

  repeated string name_path = 2;
}

// A grantable privilege.
//
// <action_type> is the type of privilege action, e.g. SELECT, INSERT, UPDATE
// or DELETE.
// <unit_list> is an optional list of units of the object (e.g. columns of a
// table, fields in a value table) that the privilege is scoped to. The
// privilege is on the whole object if the list is empty.
message ResolvedPrivilegeProto {
  optional ResolvedArgumentProto parent = 1;

  optional string action_type = 2;
  repeated ResolvedObjectUnitProto unit_list = 3;
}

// Common superclass of GRANT/REVOKE statements.
//
// <privilege_list> is the list of privileges to be granted/revoked. ALL
// PRIVILEGES should be granted/fromed if it is empty.
// <object_type_list> is an optional list of string identifiers, e.g., TABLE,
// VIEW, MATERIALIZED VIEW.
// <name_path> is a vector of segments of the object identifier's pathname.
// <grantee_list> (DEPRECATED) is the list of grantees (strings).
// <grantee_expr_list> is the list of grantees, and may include parameters.
//
// Only one of <grantee_list> or <grantee_expr_list> will be populated,
// depending on whether or not the FEATURE_PARAMETERS_IN_GRANTEE_LIST
// is enabled.  The <grantee_list> is deprecated, and will be removed
// along with the corresponding FEATURE once all engines have migrated to
// use the <grantee_expr_list>.  Once <grantee_expr_list> is the only
// one, then it should be marked as NOT_IGNORABLE.
message AnyResolvedGrantOrRevokeStmtProto {
  oneof node {
    ResolvedGrantStmtProto resolved_grant_stmt_node = 69;
    ResolvedRevokeStmtProto resolved_revoke_stmt_node = 70;
  }
}

message ResolvedGrantOrRevokeStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated ResolvedPrivilegeProto privilege_list = 2;
  repeated string object_type_list = 3;
  repeated string name_path = 4;
  repeated string grantee_list = 5;
  repeated AnyResolvedExprProto grantee_expr_list = 6;
}

// A GRANT statement. It represents the action to grant a list of privileges
// on a specific object to/from list of grantees.
message ResolvedGrantStmtProto {
  optional ResolvedGrantOrRevokeStmtProto parent = 1;

}

// A REVOKE statement. It represents the action to revoke a list of
// privileges on a specific object to/from list of grantees.
message ResolvedRevokeStmtProto {
  optional ResolvedGrantOrRevokeStmtProto parent = 1;

}

// Common super class for statements:
//   ALTER <object> [IF EXISTS] <name_path> <alter_action_list>
//
// <name_path> is a vector giving the identifier path in the table <name>. It
//             is optional if
//             FEATURE_ALLOW_MISSING_PATH_EXPRESSION_IN_ALTER_DDL is enabled.
// <alter_action_list> is a vector of actions to be done to the object.
// <is_if_exists> silently ignores the "name_path does not exist" error.
message AnyResolvedAlterObjectStmtProto {
  oneof node {
    ResolvedAlterRowAccessPolicyStmtProto resolved_alter_row_access_policy_stmt_node = 75;
    ResolvedAlterTableStmtProto resolved_alter_table_stmt_node = 115;
    ResolvedAlterViewStmtProto resolved_alter_view_stmt_node = 118;
    ResolvedAlterMaterializedViewStmtProto resolved_alter_materialized_view_stmt_node = 127;
    ResolvedAlterDatabaseStmtProto resolved_alter_database_stmt_node = 134;
    ResolvedAlterAllRowAccessPoliciesStmtProto resolved_alter_all_row_access_policies_stmt_node = 145;
    ResolvedAlterEntityStmtProto resolved_alter_entity_stmt_node = 155;
    ResolvedAlterSchemaStmtProto resolved_alter_schema_stmt_node = 160;
    ResolvedAlterPrivilegeRestrictionStmtProto resolved_alter_privilege_restriction_stmt_node = 196;
    ResolvedAlterModelStmtProto resolved_alter_model_stmt_node = 205;
    ResolvedAlterApproxViewStmtProto resolved_alter_approx_view_stmt_node = 236;
  }
}

message ResolvedAlterObjectStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  repeated AnyResolvedAlterActionProto alter_action_list = 3;
  optional bool is_if_exists = 4;
}

// This statement:
//   ALTER DATABASE [IF EXISTS] <name_path> <alter_action_list>
//
// This statement could be used to change the database level options.
message ResolvedAlterDatabaseStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER MATERIALIZED VIEW [IF EXISTS] <name_path> <alter_action_list>
message ResolvedAlterMaterializedViewStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER APPROX VIEW [IF EXISTS] <name_path> <alter_action_list>
message ResolvedAlterApproxViewStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER SCHEMA [IF NOT EXISTS] <name_path> <alter_action_list>;
message ResolvedAlterSchemaStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER MODEL [IF EXISTS] <name_path> <alter_action_list>
message ResolvedAlterModelStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER TABLE [IF EXISTS] <name_path> <alter_action_list>
message ResolvedAlterTableStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// This statement:
// ALTER VIEW [IF EXISTS] <name_path> <alter_action_list>
message ResolvedAlterViewStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

}

// A common super class for all actions in statement ALTER <object>
message AnyResolvedAlterActionProto {
  oneof node {
    ResolvedSetOptionsActionProto resolved_set_options_action_node = 117;
    ResolvedAddColumnActionProto resolved_add_column_action_node = 131;
    ResolvedDropColumnActionProto resolved_drop_column_action_node = 132;
    ResolvedGrantToActionProto resolved_grant_to_action_node = 135;
    ResolvedFilterUsingActionProto resolved_filter_using_action_node = 136;
    ResolvedRevokeFromActionProto resolved_revoke_from_action_node = 137;
    ResolvedRenameToActionProto resolved_rename_to_action_node = 138;
    ResolvedSetAsActionProto resolved_set_as_action_node = 156;
    ResolvedAddConstraintActionProto resolved_add_constraint_action_node = 163;
    ResolvedDropConstraintActionProto resolved_drop_constraint_action_node = 164;
    ResolvedDropPrimaryKeyActionProto resolved_drop_primary_key_action_node = 184;
    ResolvedRenameColumnActionProto resolved_rename_column_action_node = 185;
    ResolvedSetCollateClauseProto resolved_set_collate_clause_node = 187;
    ResolvedRestrictToActionProto resolved_restrict_to_action_node = 193;
    ResolvedAddToRestricteeListActionProto resolved_add_to_restrictee_list_action_node = 194;
    ResolvedRemoveFromRestricteeListActionProto resolved_remove_from_restrictee_list_action_node = 195;
    AnyResolvedAlterColumnActionProto resolved_alter_column_action_node = 201;
    ResolvedAlterSubEntityActionProto resolved_alter_sub_entity_action_node = 202;
    ResolvedAddSubEntityActionProto resolved_add_sub_entity_action_node = 203;
    ResolvedDropSubEntityActionProto resolved_drop_sub_entity_action_node = 204;
  }
}

message ResolvedAlterActionProto {
  optional ResolvedArgumentProto parent = 1;

}

// A super class for all ALTER COLUMN actions in the ALTER TABLE statement:
//   ALTER TABLE <table_name> ALTER COLUMN [IF EXISTS] <column>
//
// <is_if_exists> silently ignores the "column does not exist" error.
// <column> is the name of the column.
message AnyResolvedAlterColumnActionProto {
  oneof node {
    ResolvedAlterColumnOptionsActionProto resolved_alter_column_options_action_node = 169;
    ResolvedAlterColumnDropNotNullActionProto resolved_alter_column_drop_not_null_action_node = 178;
    ResolvedAlterColumnSetDataTypeActionProto resolved_alter_column_set_data_type_action_node = 181;
    ResolvedAlterColumnSetDefaultActionProto resolved_alter_column_set_default_action_node = 198;
    ResolvedAlterColumnDropDefaultActionProto resolved_alter_column_drop_default_action_node = 199;
  }
}

message ResolvedAlterColumnActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 2;
  optional string column = 3;
}

// SET OPTIONS action for ALTER <object> statement
//
// <option_list> has engine-specific directives that specify how to
//               alter the metadata for this object.
message ResolvedSetOptionsActionProto {
  optional ResolvedAlterActionProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
}

// Alter sub-entity action for ALTER <object> statement.
// (broken link)
//
// ALTER <entity_type> [IF EXISTS] <name> <alter_action>
//
// <entity_type> engine-specific sub-entity type to be altered.
// <name> the identifier for the sub-entity resource being altered.
// <alter_action> action for the sub-entity resource, such as
//     SET OPTIONS or a further nested ALTER sub-entity action.
// <is_if_exists> if set, skip the alter action if the resource does
//     not exist.
message ResolvedAlterSubEntityActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional string entity_type = 2;
  optional string name = 3;
  optional AnyResolvedAlterActionProto alter_action = 4;
  optional bool is_if_exists = 5;
}

// Add sub-entity action for ALTER <object> statement.
// (broken link)
//
// ADD <entity_type> [IF NOT EXISTS] <name> [OPTIONS(...)]
//
// <entity_type> engine-specific sub-entity type to be added.
// <name> the identifier for the sub-entity resource being added.
// <options_list> engine specific options_list for the sub-entity resource.
// <is_if_not_exists> if set, skip the add action if the resource
//     already exists.
message ResolvedAddSubEntityActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional string entity_type = 2;
  optional string name = 3;
  repeated ResolvedOptionProto options_list = 4;
  optional bool is_if_not_exists = 5;
}

// Drop sub-entity action for ALTER <object> statement.
// (broken link)
//
// DROP <entity_type> [IF EXISTS] <name>
//
// <entity_type> engine-specific sub-entity type to be dropped.
// <name> the identifier for the sub-entity resource being dropped.
// <is_if_exists> if set, skip the drop action if the resource does
//     not exist.
message ResolvedDropSubEntityActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional string entity_type = 2;
  optional string name = 3;
  optional bool is_if_exists = 4;
}

// ADD COLUMN action for ALTER TABLE statement
message ResolvedAddColumnActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_not_exists = 2;
  optional ResolvedColumnDefinitionProto column_definition = 3;
}

// ADD CONSTRAINT for ALTER TABLE statement
message ResolvedAddConstraintActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_not_exists = 2;
  optional AnyResolvedConstraintProto constraint = 3;
  optional TableRefProto table = 4;
}

// DROP CONSTRAINT for ALTER TABLE statement
message ResolvedDropConstraintActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 2;
  optional string name = 3;
}

// DROP PRIMARY KEY [IF EXISTS] for ALTER TABLE statement
message ResolvedDropPrimaryKeyActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 2;
}

// This ALTER action:
//   ALTER COLUMN [IF EXISTS] <column> SET OPTIONS <options_list>
//
// <options_list> has engine-specific directives that specify how to
//                alter the metadata for a column.
message ResolvedAlterColumnOptionsActionProto {
  optional ResolvedAlterColumnActionProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
}

// This ALTER action:
//   ALTER COLUMN [IF EXISTS] <column> DROP NOT NULL
//
// Removes the NOT NULL constraint from the given column.
message ResolvedAlterColumnDropNotNullActionProto {
  optional ResolvedAlterColumnActionProto parent = 1;

}

// ALTER COLUMN <column> SET DATA TYPE action for ALTER TABLE
// statement. It supports updating the data type of the column as
// well as updating type parameters and collation specifications of
// the column (and on struct fields and array elements).
message ResolvedAlterColumnSetDataTypeActionProto {
  optional ResolvedAlterColumnActionProto parent = 1;

  // The new type for the column.
  optional TypeProto updated_type = 4;
  // The new type parameters for the column, if the new type has
  // parameters. Note that unlike with CREATE TABLE, the child_list is
  // populated for ARRAY and STRUCT types.
  // TODO Use updated_annotations to pass type parameters.
  optional TypeParametersProto updated_type_parameters = 5;
  // The new annotations for the column including the new collation
  // specifications. Changing options using SET DATA TYPE action is not
  // allowed.
  optional ResolvedColumnAnnotationsProto updated_annotations = 6;
}

// Alter column set default action:
//   ALTER COLUMN [IF EXISTS] <column> SET DEFAULT <default_value>
//
// <default_value> sets the new default value expression. It only impacts
// future inserted rows, and has no impact on existing rows with the current
// default value. This is a metadata only operation.
//
// Resolver validates that <default_value> expression can be coerced to the
// column type when <column> exists. If <column> is not found and
// <is_if_exists> is true, Resolver skips type match check.
message ResolvedAlterColumnSetDefaultActionProto {
  optional ResolvedAlterColumnActionProto parent = 1;

  optional ResolvedColumnDefaultValueProto default_value = 4;
}

// This ALTER action:
//   ALTER COLUMN [IF EXISTS] <column> DROP DEFAULT
//
// Removes the DEFAULT constraint from the given column.
message ResolvedAlterColumnDropDefaultActionProto {
  optional ResolvedAlterColumnActionProto parent = 1;

}

// DROP COLUMN action for ALTER TABLE statement
//
// <name> is the name of the column to drop.
message ResolvedDropColumnActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 2;
  optional string name = 3;
}

// RENAME COLUMN action for ALTER TABLE statement.
//
// <name> is the name of the column to rename.
// <new_name> is the new name of the column.
//
// RENAME COLUMN actions cannot be part of the same alter_action_list as any
// other type of action.
// Chains of RENAME COLUMN will be interpreted as a sequence of mutations.
// The order of actions matters. Each <name> refers to a column name that
// exists after all preceding renames have been applied.
message ResolvedRenameColumnActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 4;
  optional string name = 2;
  optional string new_name = 3;
}

// SET AS action for generic ALTER <entity_type> statement.
// Exactly one of <entity_body_json>, <entity_body_text> should be non-empty.
//
// <entity_body_json> is a JSON literal to be interpreted by engine.
// <entity_body_text> is a text literal to be interpreted by engine.
message ResolvedSetAsActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional string entity_body_json = 2;
  optional string entity_body_text = 3;
}

// SET DEFAULT COLLATE clause for generic ALTER <entity_type> statement.
//
// <collation_name> specifies the new default collation specification for a
//   table or schema. Modifying the default collation for a table or schema
//   does not affect any existing columns or tables - the new default
//   collation only affects new tables and/or columns if applicable. Only
//   string literals are allowed for this field.
message ResolvedSetCollateClauseProto {
  optional ResolvedAlterActionProto parent = 1;

  optional AnyResolvedExprProto collation_name = 2;
}

// This statement:
//   ALTER TABLE [IF EXISTS] <name> SET OPTIONS (...)
//
// NOTE: This is deprecated in favor of ResolvedAlterTableStmt.
//
// <name_path> is a vector giving the identifier path in the table <name>.
// <option_list> has engine-specific directives that specify how to
//               alter the metadata for this table.
// <is_if_exists> silently ignore the "name_path does not exist" error.
message ResolvedAlterTableSetOptionsStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  repeated ResolvedOptionProto option_list = 3;
  optional bool is_if_exists = 4;
}

// This statement: RENAME <object_type> <old_name_path> TO <new_name_path>;
//
// <object_type> is an string identifier,
//               e.g., "TABLE", "VIEW", "INDEX", "FUNCTION", "TYPE", etc.
// <old_name_path> is a vector giving the identifier path for the object to
//                 be renamed.
// <new_name_path> is a vector giving the identifier path for the object to
//                 be renamed to.
message ResolvedRenameStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string object_type = 2;
  repeated string old_name_path = 3;
  repeated string new_name_path = 4;
}

// This statement:
//     CREATE [OR REPLACE] PRIVILEGE RESTRICTION [IF NOT EXISTS]
//     ON <column_privilege_list> ON <object_type> <name_path>
//     [RESTRICT TO (<restrictee_list>)]
//
// <column_privilege_list> is the name of the column privileges on which
//                         to apply the restrictions.
// <object_type> is a string identifier, which is currently either TABLE or
//               VIEW, which tells the engine how to look up the name.
// <restrictee_list> is a list of users and groups the privilege restrictions
//                   should apply to. Each restrictee is either a string
//                   literal or a parameter.
message ResolvedCreatePrivilegeRestrictionStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated ResolvedPrivilegeProto column_privilege_list = 2;
  optional string object_type = 3;
  repeated AnyResolvedExprProto restrictee_list = 4;
}

// This statement: CREATE [OR REPLACE] ROW ACCESS POLICY [IF NOT EXISTS]
//                 [<name>] ON <target_name_path>
//                 [GRANT TO (<grantee_list>)]
//                 FILTER USING (<predicate>);
//
// <create_mode> indicates if this was CREATE, CREATE OR REPLACE, or
//               CREATE IF NOT EXISTS.
// <name> is the name of the row access policy to be created or an empty
//        string.
// <target_name_path> is a vector giving the identifier path of the target
//                    table.
// <table_scan> is a TableScan for the target table, which is used during
//              resolving and validation. Consumers can use either the table
//              object inside it or target_name_path to reference the table.
// <grantee_list> (DEPRECATED) is the list of user principals the policy
//                should apply to.
// <grantee_expr_list> is the list of user principals the policy should
//                     apply to, and may include parameters.
// <predicate> is a boolean expression that selects the rows that are being
//             made visible.
// <predicate_str> is the string form of the predicate.
//
// Only one of <grantee_list> or <grantee_expr_list> will be populated,
// depending on whether or not the FEATURE_PARAMETERS_IN_GRANTEE_LIST
// is enabled.  The <grantee_list> is deprecated, and will be removed
// along with the corresponding FEATURE once all engines have migrated to
// use the <grantee_expr_list>.  Once <grantee_expr_list> is the only
// one, then it should be marked as NOT_IGNORABLE.
message ResolvedCreateRowAccessPolicyStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedCreateStatementEnums.CreateMode create_mode = 2;
  optional string name = 3;
  repeated string target_name_path = 4;
  repeated string grantee_list = 5;
  repeated AnyResolvedExprProto grantee_expr_list = 9;
  optional ResolvedTableScanProto table_scan = 6;
  optional AnyResolvedExprProto predicate = 7;
  optional string predicate_str = 8;
}

// This statement:
//     DROP PRIVILEGE RESTRICTION [IF EXISTS]
//     ON <column_privilege_list> ON <object_type> <name_path>
//
// <column_privilege_list> is the name of the column privileges on which
//                         the restrictions have been applied.
// <object_type> is a string identifier, which is currently either TABLE or
//               VIEW, which tells the engine how to look up the name.
// <name_path> is the name of the table the restrictions are scoped to.
message ResolvedDropPrivilegeRestrictionStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string object_type = 2;
  optional bool is_if_exists = 3;
  repeated string name_path = 4;
  repeated ResolvedPrivilegeProto column_privilege_list = 5;
}

// This statement:
//     DROP ROW ACCESS POLICY <name> ON <target_name_path>; or
//     DROP ALL ROW [ACCESS] POLICIES ON <target_name_path>;
//
// <is_drop_all> indicates that all policies should be dropped.
// <is_if_exists> silently ignore the "policy <name> does not exist" error.
//                This is not allowed if is_drop_all is true.
// <name> is the name of the row policy to be dropped or an empty string.
// <target_name_path> is a vector giving the identifier path of the target
//                    table.
message ResolvedDropRowAccessPolicyStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_drop_all = 2;
  optional bool is_if_exists = 3;
  optional string name = 4;
  repeated string target_name_path = 5;
}

// DROP SEARCH|VECTOR INDEX [IF EXISTS] <name> [ON <table_name_path>];
// Note: DROP INDEX without SEARCH or VECTOR is currently resolved to a
// generic ResolvedDropStmt. The index_type currently would never be
// INDEX_DEFAULT.
//
// <name> is the name of the search index to be dropped.
// <table_name_path> is a vector giving the identifier path of the target
//                   table.
message ResolvedDropIndexStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_if_exists = 2;
  optional string name = 3;
  repeated string table_name_path = 4;
  optional ResolvedDropIndexStmtEnums.IndexType index_type = 5;
}

// GRANT TO action for ALTER ROW ACCESS POLICY statement
//
// <grantee_expr_list> is the list of grantees, and may include parameters.
message ResolvedGrantToActionProto {
  optional ResolvedAlterActionProto parent = 1;

  repeated AnyResolvedExprProto grantee_expr_list = 2;
}

// This action for ALTER PRIVILEGE RESTRICTION statement:
//     RESTRICT TO <restrictee_list>
//
// <restrictee_list> is a list of users and groups the privilege restrictions
//                   should apply to. Each restrictee is either a string
//                   literal or a parameter.
message ResolvedRestrictToActionProto {
  optional ResolvedAlterActionProto parent = 1;

  repeated AnyResolvedExprProto restrictee_list = 2;
}

// This action for ALTER PRIVILEGE RESTRICTION statement:
//     ADD [IF NOT EXISTS] <restrictee_list>
//
// <restrictee_list> is a list of users and groups the privilege restrictions
//                   should apply to. Each restrictee is either a string
//                   literal or a parameter.
message ResolvedAddToRestricteeListActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_not_exists = 2;
  repeated AnyResolvedExprProto restrictee_list = 3;
}

// This action for ALTER PRIVILEGE RESTRICTION statement:
//     REMOVE [IF EXISTS] <restrictee_list>
//
// <restrictee_list> is a list of users and groups the privilege restrictions
//                   should apply to. Each restrictee is either a string
//                   literal or a parameter.
message ResolvedRemoveFromRestricteeListActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional bool is_if_exists = 2;
  repeated AnyResolvedExprProto restrictee_list = 3;
}

// FILTER USING action for ALTER ROW ACCESS POLICY statement
//
// <predicate> is a boolean expression that selects the rows that are being
//             made visible.
// <predicate_str> is the string form of the predicate.
message ResolvedFilterUsingActionProto {
  optional ResolvedAlterActionProto parent = 1;

  optional AnyResolvedExprProto predicate = 2;
  optional string predicate_str = 3;
}

// REVOKE FROM action for ALTER ROW ACCESS POLICY statement
//
// <revokee_expr_list> is the list of revokees, and may include parameters.
// <is_revoke_from_all> is a boolean indicating whether it was a REVOKE FROM
//                      ALL statement.
message ResolvedRevokeFromActionProto {
  optional ResolvedAlterActionProto parent = 1;

  repeated AnyResolvedExprProto revokee_expr_list = 2;
  optional bool is_revoke_from_all = 3;
}

// RENAME TO action for ALTER ROW ACCESS POLICY statement
//         and ALTER TABLE statement
//
// <new_path> is the new name of the row access policy,
//         or the new path of the table.
message ResolvedRenameToActionProto {
  optional ResolvedAlterActionProto parent = 1;

  repeated string new_path = 2;
}

// This statement:
//     ALTER PRIVILEGE RESTRICTION [IF EXISTS]
//     ON <column_privilege_list> ON <object_type> <name_path>
//     <alter_action_list>
//
// <column_privilege_list> is the name of the column privileges on which
//                         the restrictions have been applied.
// <object_type> is a string identifier, which is currently either TABLE or
//               VIEW, which tells the engine how to look up the name.
message ResolvedAlterPrivilegeRestrictionStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

  repeated ResolvedPrivilegeProto column_privilege_list = 2;
  optional string object_type = 3;
}

// This statement:
//     ALTER ROW ACCESS POLICY [IF EXISTS]
//     <name> ON <name_path>
//     <alter_action_list>
//
// <name> is the name of the row access policy to be altered, scoped to the
//        table in the base <name_path>.
// <table_scan> is a TableScan for the target table, which is used during
//              resolving and validation. Consumers can use either the table
//              object inside it or base <name_path> to reference the table.
message ResolvedAlterRowAccessPolicyStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

  optional string name = 2;
  optional ResolvedTableScanProto table_scan = 6;
}

// This statement:
//     ALTER ALL ROW ACCESS POLICIES ON <name_path> <alter_action_list>
//
// <name_path> is a vector giving the identifier path in the table name.
// <alter_action_list> is a vector of actions to be done to the object. It
//                     must have exactly one REVOKE FROM action with either
//                     a non-empty grantee list or 'all'.
// <table_scan> is a TableScan for the target table, which is used during
//              resolving and validation. Consumers can use either the table
//              object inside it or base <name_path> to reference the table.
message ResolvedAlterAllRowAccessPoliciesStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

  optional ResolvedTableScanProto table_scan = 6;
}

// This statement creates a user-defined named constant:
// CREATE [OR REPLACE] [TEMP | TEMPORARY | PUBLIC | PRIVATE] CONSTANT
//   [IF NOT EXISTS] <name_path> = <expression>
//
// <name_path> is the identifier path of the named constants.
// <expr> is the expression that determines the type and the value of the
//        named constant. Note that <expr> need not be constant. Its value
//        is bound to the named constant which is then treated as
//        immutable. <expr> can be evaluated at the time this statement is
//        processed or later (lazy evaluation during query execution).
message ResolvedCreateConstantStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  optional AnyResolvedExprProto expr = 2;
}

// This statement creates a user-defined function:
//   CREATE [TEMP] FUNCTION [IF NOT EXISTS] <name_path> (<arg_list>)
//     [RETURNS <return_type>] [SQL SECURITY <sql_security>]
//     [<determinism_level>]
//     [[LANGUAGE <language>] [AS <code> | AS ( <function_expression> )]
//      | REMOTE [WITH CONNECTION <connection>]]
//     [OPTIONS (<option_list>)]
//
//   <name_path> is the identifier path of the function.
//   <has_explicit_return_type> is true iff RETURNS clause is present.
//   <return_type> is the return type for the function, which can be any
//          valid ZetaSQL type, including ARRAY or STRUCT. It is inferred
//          from <function_expression> if not explicitly set.
//          TODO: Deprecate and remove this. The return type is
//          already specified by the <signature>.
//   <argument_name_list> The names of the function arguments.
//   <signature> is the FunctionSignature of the created function, with all
//          options.  This can be used to create a Function to load into a
//          Catalog for future queries.
//   <is_aggregate> is true if this is an aggregate function.  All arguments
//          are assumed to be aggregate input arguments that may vary for
//          every row.
//   <language> is the programming language used by the function. This field
//          is set to 'SQL' for SQL functions and 'REMOTE' for remote
//          functions and otherwise to the language name specified in the
//          LANGUAGE clause. This field is set to 'REMOTE' iff <is_remote> is
//          set to true.
//   <code> is a string literal that contains the function definition.  Some
//          engines may allow this argument to be omitted for certain types
//          of external functions. This will always be set for SQL functions.
//   <aggregate_expression_list> is a list of SQL aggregate functions to
//          compute prior to computing the final <function_expression>.
//          See below.
//   <function_expression> is the resolved SQL expression invoked for the
//          function. This will be unset for external language functions. For
//          non-template SQL functions, this is a resolved representation of
//          the expression in <code>.
//   <option_list> has engine-specific directives for modifying functions.
//   <sql_security> is the declared security mode for the function. Values
//          include 'INVOKER', 'DEFINER'.
//   <determinism_level> is the declared determinism level of the function.
//          Values are 'DETERMINISTIC', 'NOT DETERMINISTIC', 'IMMUTABLE',
//          'STABLE', 'VOLATILE'.
//   <is_remote> is true if this is an remote function. It is true iff its
//          <language> is set to 'REMOTE'.
//   <connection> is the identifier path of the connection object. It can be
//          only set when <is_remote> is true.
//
// Note that <function_expression> and <code> are both marked as IGNORABLE
// because an engine could look at either one (but might not look at both).
// An engine must look at one (and cannot ignore both, unless the function is
// remote) to be semantically valid, but there is currently no way to enforce
// that.
//
// For aggregate functions, <is_aggregate> will be true.
// Aggregate functions will only occur if LanguageOptions has
// FEATURE_CREATE_AGGREGATE_FUNCTION enabled.
//
// Arguments to aggregate functions must have
// <FunctionSignatureArgumentTypeOptions::is_not_aggregate> true or false.
// Non-aggregate arguments must be passed constant values only.
//
// For SQL aggregate functions, there will be both an
// <aggregate_expression_list>, with aggregate expressions to compute first,
// and then a final <function_expression> to compute on the results
// of the aggregates.  Each aggregate expression is a
// ResolvedAggregateFunctionCall, and may reference any input arguments.
// Each ResolvedComputedColumn in <aggregate_expression_list> gives the
// aggregate expression a column id.  The final <function_expression> can
// reference these created aggregate columns, and any input arguments
// with <argument_kind>=NOT_AGGREGATE.
//
// For example, with
//   CREATE TEMP FUNCTION my_avg(x) = (SUM(x) / COUNT(x));
// we would have an <aggregate_expression_list> with
//   agg1#1 := SUM(ResolvedArgumentRef(x))
//   agg2#2 := COUNT(ResolvedArgumentRef(x))
// and a <function_expression>
//   ResolvedColumnRef(agg1#1) / ResolvedColumnRef(agg2#2)
//
// For example, with
//   CREATE FUNCTION scaled_avg(x,y NOT AGGREGATE) = (SUM(x) / COUNT(x) * y);
// we would have an <aggregate_expression_list> with
//   agg1#1 := SUM(ResolvedArgumentRef(x))
//   agg2#2 := COUNT(ResolvedArgumentRef(x))
// and a <function_expression>
//   ResolvedColumnRef(agg1#1) / ResolvedColumnRef(agg2#2) * ResolvedArgumentRef(y)
//
// When resolving a query that calls an aggregate UDF, the query will
// have a ResolvedAggregateScan that invokes the UDF function.  The engine
// should remove the UDF aggregate function from the <aggregate_list>, and
// instead compute the additional aggregates from the
// UDF's <aggregate_expression_list>, and then add an additional Project
// to compute the final <function_expression>, which should produce the
// value for the original ResolvedAggregateScan's computed column for the
// UDF.  Some rewrites of the ResolvedColumn references inside the UDF will
// be required.  TODO If using ResolvedColumns makes this renaming
// too complicated, we could switch to use ResolvedArgumentRefs, or
// something new.
message ResolvedCreateFunctionStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  optional bool has_explicit_return_type = 13;
  optional TypeProto return_type = 3;
  repeated string argument_name_list = 11;
  optional FunctionSignatureProto signature = 10;
  optional bool is_aggregate = 8;
  optional string language = 4;
  optional string code = 5;
  repeated ResolvedComputedColumnProto aggregate_expression_list = 9;
  optional AnyResolvedExprProto function_expression = 6;
  repeated ResolvedOptionProto option_list = 7;
  optional ResolvedCreateStatementEnums.SqlSecurity sql_security = 12;
  optional ResolvedCreateStatementEnums.DeterminismLevel determinism_level = 14;
  optional bool is_remote = 15;
  optional ResolvedConnectionProto connection = 16;
}

// This represents an argument definition, e.g. in a function's argument
// list.
//
// <name> is the name of the argument; optional for DROP FUNCTION statements.
// <type> is the type of the argument.
// <argument_kind> indicates what kind of argument this is, including scalar
//         vs aggregate.  NOT_AGGREGATE means this is a non-aggregate
//         argument in an aggregate function, which can only passed constant
//         values only.
//
// NOTE: Statements that create functions now include a FunctionSignature
// directly, and an argument_name_list if applicable.  These completely
// describe the function signature, so the ResolvedArgumentDef list can
// be considered unnecessary and deprecated.
// TODO We could remove this node in the future.
message ResolvedArgumentDefProto {
  optional ResolvedArgumentProto parent = 1;

  optional string name = 2;
  optional TypeProto type = 3;
  optional ResolvedArgumentDefEnums.ArgumentKind argument_kind = 4;
}

// This represents an argument reference, e.g. in a function's body.
// <name> is the name of the argument.
// <argument_kind> is the ArgumentKind from the ResolvedArgumentDef.
//         For scalar functions, this is always SCALAR.
//         For aggregate functions, it can be AGGREGATE or NOT_AGGREGATE.
//         If NOT_AGGREGATE, then this is a non-aggregate argument
//         to an aggregate function, which has one constant value
//         for the entire function call (over all rows in all groups).
//         (This is copied from the ResolvedArgumentDef for convenience.)
message ResolvedArgumentRefProto {
  optional ResolvedExprProto parent = 1;

  optional string name = 2;
  optional ResolvedArgumentDefEnums.ArgumentKind argument_kind = 3;
}

// This statement creates a user-defined table-valued function:
//   CREATE [TEMP] TABLE FUNCTION [IF NOT EXISTS]
//     <name_path> (<argument_name_list>)
//     [RETURNS <return_type>]
//     [OPTIONS (<option_list>)]
//     [LANGUAGE <language>]
//     [AS <code> | AS ( <query> )]
//
//   <argument_name_list> contains the names of the function arguments.
//   <signature> is the FunctionSignature of the created function, with all
//          options.  This can be used to create a Function to load into a
//          Catalog for future queries.
//   <option_list> has engine-specific directives for modifying functions.
//   <language> is the programming language used by the function. This field
//          is set to 'SQL' for SQL functions, to the language name specified
//          in the LANGUAGE clause if present, and to 'UNDECLARED' if both
//          the LANGUAGE clause and query are not present.
//   <code> is an optional string literal that contains the function
//          definition.  Some engines may allow this argument to be omitted
//          for certain types of external functions.  This will always be set
//          for SQL functions.
//   <query> is the SQL query invoked for the function.  This will be unset
//          for external language functions. For non-templated SQL functions,
//          this is a resolved representation of the query in <code>.
//   <output_column_list> is the list of resolved output
//          columns returned by the table-valued function.
//   <is_value_table> If true, this function returns a value table.
//          Rather than producing rows with named columns, it produces
//          rows with a single unnamed value type. <output_column_list> will
//          have exactly one anonymous column (with no name).
//          See (broken link).
//   <sql_security> is the declared security mode for the function. Values
//          include 'INVOKER', 'DEFINER'.
//   <has_explicit_return_schema> is true iff RETURNS clause is present.
//
// ----------------------
// Table-Valued Functions
// ----------------------
//
// This is a statement to create a new table-valued function. Each
// table-valued function returns an entire table as output instead of a
// single scalar value. Table-valued functions can only be created if
// LanguageOptions has FEATURE_CREATE_TABLE_FUNCTION enabled.
//
// For SQL table-valued functions that include a defined SQL body, the
// <query> is non-NULL and contains the resolved SQL body.
// In this case, <output_column_list> contains a list of the
// output columns of the SQL body. The <query> uses
// ResolvedArgumentRefs to refer to scalar arguments and
// ResolvedRelationArgumentScans to refer to relation arguments.
//
// The table-valued function may include RETURNS TABLE<...> to explicitly
// specify a schema for the output table returned by the function. If the
// function declaration includes a SQL body, then the names and types of the
// output columns of the corresponding <query> will have been
// coerced to exactly match 1:1 with the names and types of the columns
// specified in the RETURNS TABLE<...> section.
//
// When resolving a query that calls a table-valued function, the query will
// have a ResolvedTVFScan that invokes the function.
//
// Value tables: If the function declaration includes a value-table
// parameter, this is written as an argument of type "TABLE" where the table
// contains a single anonymous column with a type but no name. In this case,
// calls to the function may pass a (regular or value) table with a single
// (named or unnamed) column for any of these parameters, and ZetaSQL
// accepts these arguments as long as the column type matches.
//
// Similarly, if the CREATE TABLE FUNCTION statement includes a "RETURNS
// TABLE" section with a single column with no name, then this defines a
// value-table return type. The function then returns a value table as long
// as the SQL body returns a single column whose type matches (independent of
// whether the SQL body result is a value table or not, and whether the
// returned column is named or unnamed).
//
// --------------------------------
// Templated Table-Valued Functions
// --------------------------------
//
// ZetaSQL supports table-valued function declarations with parameters of
// type ANY TABLE. This type indicates that any schema is valid for tables
// passed for this parameter. In this case:
//
// * the IsTemplated() method of the <signature> field returns true,
// * the <output_column_list> field is empty,
// * the <is_value_table> field is set to a default value of false (since
//   ZetaSQL cannot analyze the function body in the presence of templated
//   parameters, it is not possible to detect this property yet),
//
// TODO: Update this description once ZetaSQL supports more types
// of templated function parameters. Currently only ANY TABLE is supported.
message ResolvedCreateTableFunctionStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated string argument_name_list = 2;
  optional FunctionSignatureProto signature = 3;
  optional bool has_explicit_return_schema = 11;
  repeated ResolvedOptionProto option_list = 4;
  optional string language = 5;
  optional string code = 6;
  optional AnyResolvedScanProto query = 7;
  repeated ResolvedOutputColumnProto output_column_list = 8;
  optional bool is_value_table = 9;
  optional ResolvedCreateStatementEnums.SqlSecurity sql_security = 10;
}

// This represents a relation argument reference in a table-valued function's
// body. The 'column_list' of this ResolvedScan includes column names from
// the relation argument in the table-valued function signature.
message ResolvedRelationArgumentScanProto {
  optional ResolvedScanProto parent = 1;

  // This is the name of the relation argument for the table-valued
  // function.  It is used to match this relation argument reference in
  // a TVF SQL function body with one of possibly several relation
  // arguments in the TVF call.
  optional string name = 2;
  // If true, the result of this query is a value table. Rather than
  // producing rows with named columns, it produces rows with a single
  // unnamed value type. See (broken link).
  optional bool is_value_table = 3;
}

// This statement: [ (<arg_list>) ];
//
// <arg_list> is an optional list of parameters.  If given, each parameter
//            may consist of a type, or a name and a type.
//
// NOTE: This can be considered deprecated in favor of the FunctionSignature
//       stored directly in the statement.
//
// NOTE: ResolvedArgumentList is not related to the ResolvedArgument class,
//       which just exists to organize node classes.
message ResolvedArgumentListProto {
  optional ResolvedArgumentProto parent = 1;

  repeated ResolvedArgumentDefProto arg_list = 2;
}

// This wrapper is used for an optional FunctionSignature.
message ResolvedFunctionSignatureHolderProto {
  optional ResolvedArgumentProto parent = 1;

  optional FunctionSignatureProto signature = 2;
}

// This statement: DROP FUNCTION [IF EXISTS] <name_path>
//   [ (<arguments>) ];
//
// <is_if_exists> silently ignore the "name_path does not exist" error.
// <name_path> is the identifier path of the function to be dropped.
// <arguments> is an optional list of parameters.  If given, each parameter
//            may consist of a type, or a name and a type.  The name is
//            disregarded, and is allowed to permit copy-paste from CREATE
//            FUNCTION statements.
// <signature> is the signature of the dropped function.  Argument names and
//            argument options are ignored because only the types matter
//            for matching signatures in DROP FUNCTION.  The return type
//            in this signature will always be <void>, since return type
//            is ignored when matching signatures for DROP.
//            TODO <arguments> could be deprecated in favor of this.
message ResolvedDropFunctionStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_if_exists = 2;
  repeated string name_path = 3;
  // NOTE: arguments for DROP FUNCTION statements are matched only on
  // type; names for any arguments in ResolvedArgumentList will be set
  // to the empty string irrespective of whether or not argument names
  // were given in the DROP FUNCTION statement.
  optional ResolvedArgumentListProto arguments = 4;
  // NOTE: arguments for DROP FUNCTION statements are matched only on
  // type; names are irrelevant, so no argument names are saved to use
  // with this signature.  Additionally, the return type will always be
  // <void>, since return types are ignored for DROP FUNCTION.
  optional ResolvedFunctionSignatureHolderProto signature = 5;
}

// This statement: DROP TABLE FUNCTION [IF EXISTS] <name_path>;
//
// <is_if_exists> silently ignore the "name_path does not exist" error.
// <name_path> is the identifier path of the function to be dropped.
message ResolvedDropTableFunctionStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional bool is_if_exists = 2;
  repeated string name_path = 3;
}

// This statement: CALL <procedure>;
//
// <procedure> Procedure to call.
// <signature> Resolved FunctionSignature for this procedure.
// <argument_list> Procedure arguments.
message ResolvedCallStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ProcedureRefProto procedure = 2;
  optional FunctionSignatureProto signature = 3;
  repeated AnyResolvedExprProto argument_list = 4;
}

// This statement: IMPORT <import_kind>
//                              [<name_path> [AS|INTO <alias_path>]
//                              |<file_path>]
//                        [<option_list>];
//
// <import_kind> The type of the object, currently supports MODULE and PROTO.
// <name_path>   The identifier path of the object to import, e.g., foo.bar,
//               used in IMPORT MODULE statement.
// <file_path>   The file path of the object to import, e.g., "file.proto",
//               used in IMPORT PROTO statement.
// <alias_path>  The AS alias path for the object.
// <into_alias_path>  The INTO alias path for the object.
// <option_list> Engine-specific directives for the import.
//
// Either <name_path> or <file_path> will be populated but not both.
//       <name_path> will be populated for IMPORT MODULE.
//       <file_path> will be populated for IMPORT PROTO.
//
// At most one of <alias_path> or <into_alias_path> will be populated.
//       <alias_path> may be populated for IMPORT MODULE.
//       <into_alias_path> may be populated for IMPORT PROTO.
//
// IMPORT MODULE and IMPORT PROTO both support options.
//
// See (broken link) for more detail on IMPORT MODULE.
// See (broken link) for more detail on IMPORT PROTO.
message ResolvedImportStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedImportStmtEnums.ImportKind import_kind = 2;
  repeated string name_path = 3;
  optional string file_path = 4;
  repeated string alias_path = 5;
  repeated string into_alias_path = 7;
  repeated ResolvedOptionProto option_list = 6;
}

// This statement: MODULE <name_path> [<option_list>];
//
// <name_path> is the identifier path of the module.
// <option_list> Engine-specific directives for the module statement.
//
// See (broken link) for more detail on MODULEs.
message ResolvedModuleStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated string name_path = 2;
  repeated ResolvedOptionProto option_list = 3;
}

// This represents a HAVING MAX or HAVING MIN modifier in an aggregate
// expression. If an aggregate has arguments (x HAVING {MAX/MIN} y),
// the aggregate will be computed over only the x values in the rows with the
// maximal/minimal values of y.
//
// <kind> the MAX/MIN kind of this HAVING
// <having_expr> the HAVING expression (y in the above example)
message ResolvedAggregateHavingModifierProto {
  optional ResolvedArgumentProto parent = 1;

  optional ResolvedAggregateHavingModifierEnums.HavingModifierKind kind = 2;
  optional AnyResolvedExprProto having_expr = 3;
}

// This statement:
//   CREATE MATERIALIZED VIEW <name> [(...)] [PARTITION BY expr, ...]
//   [CLUSTER BY expr, ...] [OPTIONS (...)]
//   {AS SELECT ... | AS REPLICA OF ...}
//
// <partition_by_list> specifies the partitioning expressions for the
//                     materialized view.
// <cluster_by_list> specifies the clustering expressions for the
//                   materialized view.
message ResolvedCreateMaterializedViewStmtProto {
  optional ResolvedCreateViewBaseProto parent = 1;

  repeated AnyResolvedExprProto partition_by_list = 3;
  repeated AnyResolvedExprProto cluster_by_list = 4;
  optional AnyResolvedScanProto replica_source = 5;
}

// This statement creates an APPROX VIEW:
//   CREATE APPROX VIEW <name> [(...)] [OPTIONS (...)] AS SELECT ...
//
// An APPROX VIEW provides approximate results from the view query, as
// opposed to a regular view which returns exact results from its view query.
// APPROX VIEW is a generic operator whose behavior is implementation-defined
// based on the OPTIONS and query engines.
//
// See (broken link) for more details on APPROX VIEW.
message ResolvedCreateApproxViewStmtProto {
  optional ResolvedCreateViewBaseProto parent = 1;

}

// This statement creates a user-defined procedure:
// CREATE [OR REPLACE] [TEMP] PROCEDURE [IF NOT EXISTS] <name_path>
// (<arg_list>) [EXTERNAL SECURITY <external_security>]
// [WITH CONNECTION <connection>] [OPTIONS (<option_list>)]
// [BEGIN <procedure_body> END | LANGUAGE <language> [AS <code>]];
//
// <name_path> is the identifier path of the procedure.
// <argument_name_list> The names of the function arguments.
// <signature> is the FunctionSignature of the created procedure, with all
//        options.  This can be used to create a procedure to load into a
//        Catalog for future queries.
// <external_security> is the external security mode for the created
//        procedure. Values include 'INVOKER', 'DEFINER'.
// <connection> is the identifier path of the connection object.
// <option_list> has engine-specific directives for modifying procedures.
// <procedure_body> is a string literal that contains the SQL procedure
//        body. It includes everything from the BEGIN keyword to the END
//        keyword, inclusive. This will always be set for SQL procedures
//        and unset for external language procedures.
//
//        The resolver will perform some basic validation on the procedure
//        body, for example, verifying that DECLARE statements are in the
//        proper position, and that variables are not declared more than
//        once, but any validation that requires the catalog (including
//        generating resolved tree nodes for individual statements) is
//        deferred until the procedure is actually called.  This deferral
//        makes it possible to define a procedure which references a table
//        or routine that does not yet exist, so long as the entity is
//        created before the procedure is called.
// <language> is the programming language used by the procedure. This field
//        is set to the language name specified in the LANGUAGE clause.
//        Exactly one of <procedure_body> and <language> must be set.
// <code> is a string literal that contains the external language procedure
//        definition. It is allowed only if <language> is set.
message ResolvedCreateProcedureStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  repeated string argument_name_list = 2;
  optional FunctionSignatureProto signature = 3;
  repeated ResolvedOptionProto option_list = 4;
  optional string procedure_body = 5;
  optional ResolvedConnectionProto connection = 6;
  optional string language = 7;
  optional string code = 8;
  optional ResolvedCreateStatementEnums.SqlSecurity external_security = 9;
}

// An argument for an EXECUTE IMMEDIATE's USING clause.
//
// <name> an optional name for this expression
// <expression> the expression's value
message ResolvedExecuteImmediateArgumentProto {
  optional ResolvedArgumentProto parent = 1;

  optional string name = 2;
  optional AnyResolvedExprProto expression = 3;
}

// An EXECUTE IMMEDIATE statement
// EXECUTE IMMEDIATE <sql> [<into_clause>] [<using_clause>]
//
// <sql> a string expression indicating a SQL statement to be dynamically
//   executed
// <into_identifier_list> the identifiers whose values should be set.
//   Identifiers should not be repeated in the list.
// <using_argument_list> a list of arguments to supply for dynamic SQL.
//    The arguments should either be all named or all unnamed, and
//    arguments should not be repeated in the list.
message ResolvedExecuteImmediateStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional AnyResolvedExprProto sql = 2;
  repeated string into_identifier_list = 3;
  repeated ResolvedExecuteImmediateArgumentProto using_argument_list = 4;
}

// An assignment of a value to another value.
message ResolvedAssignmentStmtProto {
  optional ResolvedStatementProto parent = 1;

  // Target of the assignment.  Currently, this will be
  // either ResolvedSystemVariable, or a chain of ResolveGetField
  // operations around it.
  optional AnyResolvedExprProto target = 2;
  // Value to assign into the target.  This will always be
  // the same type as the target.
  optional AnyResolvedExprProto expr = 3;
}

// (broken link)
// This statement:
// CREATE [OR REPLACE] <entity_type> [IF NOT EXISTS] <path_expression>
// [OPTIONS <option_list>]
// [AS <entity_body_json>];
//
// At most one of <entity_body_json>, <entity_body_text> can be non-empty.
//
// <entity_type> engine-specific entity type to be created.
// <entity_body_json> is a JSON literal to be interpreted by engine.
// <entity_body_text> is a text literal to be interpreted by engine.
// <option_list> has engine-specific directives for how to
//               create this entity.
message ResolvedCreateEntityStmtProto {
  optional ResolvedCreateStatementProto parent = 1;

  optional string entity_type = 2;
  optional string entity_body_json = 3;
  optional string entity_body_text = 5;
  repeated ResolvedOptionProto option_list = 4;
}

// (broken link)
// This statement:
// ALTER <entity_type> [IF EXISTS]  <path_expression>
// <generic_alter_action>, ...
//
// <entity_type> engine-specific entity type to be altered.
message ResolvedAlterEntityStmtProto {
  optional ResolvedAlterObjectStmtProto parent = 1;

  optional string entity_type = 2;
}

// Represents a column produced by aggregating a particular pivot
// expression over a subset of the input for which the FOR expression
// matches a particular pivot value. This aggregation is further
// broken up by the enclosing ResolvedPivotScan's groupby columns,
// with each distinct value of the groupby columns producing a
// separate row in the output.
//
// In any pivot column, 'c',
// 'c' is produced by aggregating pivot expression
//   <pivot_expr_list[c.pivot_expr_index]>
// over input rows such that
//   <for_expr> IS NOT DISTINCT FROM
//   <pivot_value_list[c.pivot_value_index]>
message ResolvedPivotColumnProto {
  optional ResolvedArgumentProto parent = 1;

  // The output column used to represent the result of the pivot.
  optional ResolvedColumnProto column = 2;
  // Specifies the index of the pivot expression
  // within the enclosing ResolvedPivotScan's <pivot_expr_list> used to
  // determine the result of the column.
  optional int64 pivot_expr_index = 3;
  // Specifies the index of the pivot value within
  // the enclosing ResolvedPivotScan's <pivot_value_list> used to
  // determine the subset of input rows the pivot expression should be
  // evaluated over.
  optional int64 pivot_value_index = 4;
}

// A scan produced by the following SQL fragment:
//   <input_scan> PIVOT(... FOR ... IN (...))
//
// The column list of this scan consists of a subset of columns from
// <group_by_column_list> and <pivot_column_list>.
//
// Details: (broken link)
message ResolvedPivotScanProto {
  optional ResolvedScanProto parent = 1;

  // Input to the PIVOT clause
  optional AnyResolvedScanProto input_scan = 2;
  // The columns from <input_scan> to group by.
  // The output will have one row for each distinct combination of
  // values for all grouping columns. (There will be one output row if
  // this list is empty.)
  //
  // Each element is a ResolvedComputedColumn. The expression is always
  // a ResolvedColumnRef that references a column from <input_scan>.
  repeated ResolvedComputedColumnProto group_by_list = 3;
  // Pivot expressions which aggregate over the subset of <input_scan>
  // where <for_expr> matches each value in <pivot_value_list>, plus
  // all columns in <group_by_list>.
  repeated AnyResolvedExprProto pivot_expr_list = 4;
  // Expression following the FOR keyword, to be evaluated over each row
  // in <input_scan>. This value is compared with each value in
  // <pivot_value_list> to determine which columns the aggregation
  // results of <pivot_expr_list> should go to.
  optional AnyResolvedExprProto for_expr = 5;
  // A list of pivot values within the IN list, to be compared against
  // the result of <for_expr> for each row in the input table. Each
  // pivot value generates a distinct column in the output for each
  // pivot expression, representing the result of the corresponding
  // pivot expression over the subset of input where <for_expr> matches
  // this pivot value.
  //
  // All pivot values in this list must have the same type as
  // <for_expr> and must be constant.
  repeated AnyResolvedExprProto pivot_value_list = 6;
  // List of columns created to store the output pivot columns.
  // Each is computed using one of pivot_expr_list and one of
  // pivot_value_list.
  repeated ResolvedPivotColumnProto pivot_column_list = 7;
}

// Represents the returning clause on a DML statement.
message ResolvedReturningClauseProto {
  optional ResolvedArgumentProto parent = 1;

  // Specifies the columns in the returned output row with column
  // names. It can reference columns from the target table scan
  // <table_scan> from INSERT/DELETE/UPDATE statements. Also this list
  // can have columns computed in the <expr_list> or an <action_column>
  // as the last column.
  repeated ResolvedOutputColumnProto output_column_list = 2;
  // Represents the WITH ACTION column in <output_column_list> as a
  // string type column. There are four valid values for this action
  // column: "INSERT", "REPLACE", "UPDATE", and "DELETE".
  optional ResolvedColumnHolderProto action_column = 3;
  // Represents the computed expressions so they can be referenced in
  // <output_column_list>. Worth noting, it can't see <action_column>
  // and can only access columns from the DML statement target table.
  repeated ResolvedComputedColumnProto expr_list = 4;
}

// A column group in the UNPIVOT IN clause.
//
// Example:
//   'a' in 'UNPIVOT(x FOR z IN (a , b , c))'
//   or '(a , b)' in 'UNPIVOT((x , y) FOR z IN ((a , b), (c , d))'
message ResolvedUnpivotArgProto {
  optional ResolvedArgumentProto parent = 1;

  // A list of columns referencing an output column of the <input_scan>
  // of ResolvedUnpivotScan. The size of this vector is
  // the same as <value_column_list>.
  repeated ResolvedColumnRefProto column_list = 2;
}

// A scan produced by the following SQL fragment:
// <input_scan> UNPIVOT(<value_column_list>
//   FOR <label_column>
//   IN (<unpivot_arg_list>))
//
// size of (<unpivot_arg_list>[i], i.e. column groups inside
// <unpivot_arg_list>)
//   = size of (<value_column_list>)
//   = Let's say num_value_columns
//
// size of (<unpivot_arg_list>)
//   = size of (<label_list>)
//   = Let's say num_args
//
// Here is how output rows are generated --
// for each input row :
//   for arg_index = 0 .. (num_args - 1) :
//     output a row with the original columns from <input_scan>
//
//       plus
//     arg = <unpivot_arg_list>[arg_index]
//     for value_column_index = 0 .. (num_value_columns - 1) :
//       output_value_column = <value_column_list>[value_column_index]
//       input_arg_column = arg [value_column_index]
//       output_value_column = input_arg_column
//
//       plus
//     <label_column> = <label_list>[arg_index]
//
//
// Hence the total number of rows generated in the output =
//   input rows * size of <unpivot_arg_list>
//
// For all column groups inside <unpivot_arg_list>, datatype of
// columns at the same position in the vector must be equivalent, and
// also equivalent to the datatype of the column at the same position in
// <value_column_list>.
// I.e. in the above pseudocode, datatypes must be equivalent for
// output_value_column and input_arg_column.
// Datatype of <label_column> must be the same as datatype of
// <label_list> and can be string or int64.
//
// Details: (broken link)
message ResolvedUnpivotScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  // This is a list of one or more new columns added by UNPIVOT.
  // These new column(s) store the value of input columns that are in
  // the UNPIVOT IN clause.
  repeated ResolvedColumnProto value_column_list = 3;
  // This is a new column added in the output for storing labels for
  // input columns groups that are present in the IN clause. Its
  // values are taken from <label_list>.
  optional ResolvedColumnProto label_column = 4;
  // String or integer literal for each column group in
  // <unpivot_arg_list>.
  repeated ResolvedLiteralProto label_list = 5;
  // The list of groups of columns in the UNPIVOT IN list. Each group
  // contains references to the output columns of <input_scan> of the
  // ResolvedUnpivotScan. The values of these columns are stored in the
  // new <value_column_list> and the column group labels/names
  // in the <label_column>.
  repeated ResolvedUnpivotArgProto unpivot_arg_list = 6;
  // The columns from <input_scan> that are not unpivoted in UNPIVOT
  // IN clause. Columns in <projected_input_column_list> and
  // <unpivot_arg_list> are mutually exclusive and their union is the
  // complete set of columns in the unpivot input-source.
  //
  // The expression of each ResolvedComputedColumn is a
  // ResolvedColumnRef that references a column from <input_scan>.
  repeated ResolvedComputedColumnProto projected_input_column_list = 7;
  // Whether we need to include the rows from output where ALL columns
  // from <value_column_list> are null.
  optional bool include_nulls = 8;
}

// CLONE DATA INTO <table_name> FROM ...
//
// <target_table> the table to clone data into. Cannot be value table.
// <clone_from> The source table(s) to clone data from.
//              For a single table, the scan is TableScan, with an optional
//                  for_system_time_expr;
//              If WHERE clause is present, the Scan is wrapped inside
//                  ResolvedFilterScan;
//              When multiple sources are present, they are UNION'ed together
//                  in a ResolvedSetOperationScan.
//
//              Constraints:
//                The target_table must not be the same as any source table,
//                and two sources cannot refer to the same table.
//                All source tables and target table must have equal number
//                of columns, with positionally identical column names and
//                types.
//                Cannot be value table.
message ResolvedCloneDataStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedTableScanProto target_table = 2;
  optional AnyResolvedScanProto clone_from = 3;
}

// Identifies the <table> and <column_index_list> (which can be empty) that
// are targets of the ANALYZE statement.
//
// <column_index_list> This list identifies the ordinals of columns to be
// analyzed in the <table>'s column list.
message ResolvedTableAndColumnInfoProto {
  optional ResolvedArgumentProto parent = 1;

  optional TableRefProto table = 2;
  repeated int64 column_index_list = 3;
}

// This represents the ANALYZE statement:
// ANALYZE [OPTIONS (<option_list>)] [<table_and_column_index_list> [, ...]];
//
// <option_list> is a list of options for ANALYZE.
//
// <table_and_column_info_list> identifies a list of tables along with their
// related columns that are the target of ANALYZE.
message ResolvedAnalyzeStmtProto {
  optional ResolvedStatementProto parent = 1;

  repeated ResolvedOptionProto option_list = 2;
  repeated ResolvedTableAndColumnInfoProto table_and_column_index_list = 3;
}

// Indicates that the LOAD DATA statement will load to or overwrite the
// selected partitions:
//   [OVERWRITE] PARTITIONS (<filter>)
message ResolvedAuxLoadDataPartitionFilterProto {
  optional ResolvedArgumentProto parent = 1;

  // Expression to find the partitions to load.
  // Scan rows from source file, and fail the query if filter
  // evaluates some rows to false.
  // <filter> is always of type bool.
  // When this expression produces NULL, the query should fail.
  optional AnyResolvedExprProto filter = 2;
  // Indicates whether the load data will append to or overwrite the
  // selected partition.
  optional bool is_overwrite = 3;
}

// LOAD DATA {OVERWRITE|INTO} [{TEMP|TEMPORARY} TABLE] <table_name>
// [[OVERWRITE] PARTITIONS(...)] ...
// FROM FILES ...
//   This statement loads an external file to a new or existing table.
//   See (broken link).
//
// <insertion_mode> either OVERWRITE or APPEND (INTO) the destination table.
// <is_temp_table> True if the destination table should be a temporary table.
//   Otherwise, the destination table should be a persistent table.
// <name_path> the table to load data into.
// <output_column_list> the list of visible columns of the destination table.
//   If <column_definition_list> is explicitly specified:
//     <output_column_list> =
//         <column_definition_list> + <with_partition_columns>
//   Or if the table already exists:
//     <output_column_list> = <name_path>.columns
//   Last, if the table doesn't exist and <column_definition_list> isn't
//   explicitly specified:
//     <output_column_list> = detected-columns + <with_partition_columns>
// <column_definition_list> If not empty, the explicit columns of the
//     destination table. Must be coerciable from the source file's fields.
//
//     When the destination table doesn't already exist, it will be created
//     with these columns (plus the additional columns from WITH PARTITION
//     COLUMNS subclause); otherwise, the destination table's schema must
//     match the explicit columns by both name and type.
// <pseudo_column_list> is a list of pseudo-columns expected to be present on
//     the created table (provided by AnalyzerOptions::SetDdlPseudoColumns*).
//     These can be referenced in expressions in <partition_by_list> and
//     <cluster_by_list>.
// <primary_key> specifies the PRIMARY KEY constraint on the table. It is
//     nullptr when no PRIMARY KEY is specified.
//     If specified, and the table already exists, the primary_key is
//     required to be the same as that of the existing.
// <foreign_key_list> specifies the FOREIGN KEY constraints on the table.
//     If specified, and the table already exists, the foreign keys are
//     required to be the same as that of the existing.
// <check_constraint_list> specifies the ABSL_CHECK constraints on the table.
//     If specified, and the table already exists, the constraints are
//     required to be the same as that of the existing.
// <partition_by_list> The list of columns to partition the destination
//     table. Similar to <column_definition_list>, it must match the
//     destination table's partitioning spec if it already exists.
// <cluster_by_list> The list of columns to cluster the destination
//     table. Similar to <column_definition_list>, it must match the
//     destination table's partitioning spec if it already exists.
// <partition_filter> specifies the destination partition selections and
//     whether load to or overwrite the selected partitions.
// <option_list> the options list describing the destination table.
//     If the destination doesn't already exist, it will be created with
//     these options; otherwise it must match the existing destination
//     table's options.
// <with_partition_columns> The columns decoded from partitioned source
//     files. If the destination table doesn't already exist, these columns
//     will be implicitly added to the destination table's schema; otherwise
//     the destination table must already have these columns
//     (matching by both names and types).
//
//     The hive partition columns from the source file do not automatically
//     partition the destination table. To apply the partition, the
//     <partition_by_list> must be specified.
// <connection> optional connection reference for accessing files.
// <from_files_option_list> the options list describing the source file(s).
message ResolvedAuxLoadDataStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional ResolvedAuxLoadDataStmtEnums.InsertionMode insertion_mode = 2;
  optional bool is_temp_table = 17;
  repeated string name_path = 3;
  optional ResolvedAuxLoadDataPartitionFilterProto partition_filter = 16;
  repeated ResolvedOutputColumnProto output_column_list = 4;
  repeated ResolvedColumnDefinitionProto column_definition_list = 5;
  repeated ResolvedColumnProto pseudo_column_list = 6;
  optional ResolvedPrimaryKeyProto primary_key = 7;
  repeated ResolvedForeignKeyProto foreign_key_list = 8;
  repeated ResolvedCheckConstraintProto check_constraint_list = 9;
  repeated AnyResolvedExprProto partition_by_list = 10;
  repeated AnyResolvedExprProto cluster_by_list = 11;
  repeated ResolvedOptionProto option_list = 12;
  optional ResolvedWithPartitionColumnsProto with_partition_columns = 13;
  optional ResolvedConnectionProto connection = 14;
  repeated ResolvedOptionProto from_files_option_list = 15;
}

// Constrains the maximum number of rows returned by a statement or subquery.
//
// The argument to TOP <int64> must be non-negative
// integer literal or (possibly casted) query parameter.  Query
// parameter value must be checked at run-time by ZetaSQL compliant
// backend systems.
message ResolvedTopScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional AnyResolvedExprProto top = 3;
}

// Apply a OFFSET and FETCH to the rows from input_scan. Emit all
// rows after OFFSET rows have been scanned and up to FETCH total rows
// emitted. The offset is the number of rows to skip.
// E.g., OFFSET 1 means to skip one row, so the first row emitted will be the
// second ROW, provided the FETCH is greater than zero.
//
// OFFSET is optional and the absence of OFFSET implies OFFSET 0.
//
// The arguments to FETCH <int64> OFFSET <int64> must be non-negative
// integer literals or (possibly casted) query parameters.  Query
// parameter values must be checked at run-time by ZetaSQL compliant
// backend systems.
message ResolvedOffsetFetchScanProto {
  optional ResolvedScanProto parent = 1;

  optional AnyResolvedScanProto input_scan = 2;
  optional AnyResolvedExprProto offset = 3;
  optional AnyResolvedExprProto fetch = 4;
}

// This statement:
//   UNDROP <schema_object_kind> [IF NOT EXISTS] <name_path>
//   FOR SYSTEM_TIME AS OF [<for_system_time_expr>];
//
// <schema_object_kind> is a string identifier for the entity to be
// undroped. Currently, only 'SCHEMA' object is supported.
//
// <name_path> is a vector giving the identifier path for the object to
// be undropped.
//
// <is_if_not_exists> if set, skip the undrop if the resource already
// exists.
//
// <for_system_time_expr> specifies point in time from which entity is to
// be undropped.
message ResolvedUndropStmtProto {
  optional ResolvedStatementProto parent = 1;

  optional string schema_object_kind = 2;
  optional bool is_if_not_exists = 3;
  repeated string name_path = 4;
  optional AnyResolvedExprProto for_system_time_expr = 5;
}

