// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.bigquery.v2;

import "google/api/field_behavior.proto";
import "google/protobuf/wrappers.proto";

option go_package = "cloud.google.com/go/bigquery/v2/apiv2/bigquerypb;bigquerypb";
option java_outer_classname = "TableSchemaProto";
option java_package = "com.google.cloud.bigquery.v2";

// Schema of a table
message TableSchema {
  // Describes the fields in a table.
  repeated TableFieldSchema fields = 1;

  // Optional. Specifies metadata of the foreign data type definition in field
  // schema
  // ([TableFieldSchema.foreign_type_definition][google.cloud.bigquery.v2.TableFieldSchema.foreign_type_definition]).
  ForeignTypeInfo foreign_type_info = 3
      [(google.api.field_behavior) = OPTIONAL];
}

// Metadata about the foreign data type definition such as the system
// in which the type is defined.
message ForeignTypeInfo {
  // External systems, such as query engines or table formats, that have their
  // own data types.
  enum TypeSystem {
    // TypeSystem not specified.
    TYPE_SYSTEM_UNSPECIFIED = 0;

    // Represents Hive data types.
    HIVE = 1;
  }

  // Required. Specifies the system which defines the foreign data type.
  TypeSystem type_system = 1 [(google.api.field_behavior) = REQUIRED];
}

// Data policy option. For more information, see
// [Mask data by applying data policies to a
// column](https://docs.cloud.google.com/bigquery/docs/column-data-masking#data-policies-on-column).
message DataPolicyOption {
  // Data policy resource name in the form of
  // projects/project_id/locations/location_id/dataPolicies/data_policy_id.
  optional string name = 1;
}

// A list of data policy options. For more information, see
// [Mask data by applying data policies to a
// column](https://docs.cloud.google.com/bigquery/docs/column-data-masking#data-policies-on-column).
message DataPolicyList {
  // Contains a list of data policy options. At most 9 data policies are
  // allowed per field.
  repeated DataPolicyOption data_policies = 1;
}

// A field in TableSchema
message TableFieldSchema {
  message PolicyTagList {
    // A list of policy tag resource names. For example,
    // "projects/1/locations/eu/taxonomies/2/policyTags/3". At most 1 policy tag
    // is currently allowed.
    repeated string names = 1;
  }

  message DataGovernanceTagsInfo {
    // Optional. The data governance tags added to this field are used for
    // field-level access control. Only one data governance tag is currently
    // supported on a field. Tag keys are globally unique. Tag key is expected
    // to be in the namespaced format, for example "123456789012/pii" where
    // 123456789012 is the ID of the parent organization or project resource for
    // this tag key. Tag value is expected to be the short name, for example
    // "sensitive". See [Tag
    // definitions](https://cloud.google.com/iam/docs/tags-access-control#definitions)
    // for more details. For example:
    //   "123456789012/pii": "sensitive",
    //   "myProject/cost_center": "sales"
    map<string, string> data_governance_tags = 1
        [(google.api.field_behavior) = OPTIONAL];
  }

  // Rounding mode options that can be used when storing NUMERIC
  // or BIGNUMERIC values.
  enum RoundingMode {
    // Unspecified will default to using ROUND_HALF_AWAY_FROM_ZERO.
    ROUNDING_MODE_UNSPECIFIED = 0;

    // ROUND_HALF_AWAY_FROM_ZERO rounds half values away from zero
    // when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
    // values.
    // For Scale: 0
    // 1.1, 1.2, 1.3, 1.4 => 1
    // 1.5, 1.6, 1.7, 1.8, 1.9 => 2
    ROUND_HALF_AWAY_FROM_ZERO = 1;

    // ROUND_HALF_EVEN rounds half values to the nearest even value
    // when applying precision and scale upon writing of NUMERIC and BIGNUMERIC
    // values.
    // For Scale: 0
    // 1.1, 1.2, 1.3, 1.4 => 1
    // 1.5 => 2
    // 1.6, 1.7, 1.8, 1.9 => 2
    // 2.5 => 2
    ROUND_HALF_EVEN = 2;
  }

  // Represents the type of a field element.
  message FieldElementType {
    // Required. The type of a field element. For more information, see
    // [TableFieldSchema.type][google.cloud.bigquery.v2.TableFieldSchema.type].
    string type = 1 [(google.api.field_behavior) = REQUIRED];
  }

  // Definition of the expression used to generate the field.
  message GeneratedExpressionInfo {
    // Optional. The generation expression (e.g. AI.EMBED(...)) used to
    // generated the field.
    optional string generation_expression = 1
        [(google.api.field_behavior) = OPTIONAL];

    // Optional. Whether the column generation is done asynchronously.
    optional bool asynchronous = 2 [(google.api.field_behavior) = OPTIONAL];

    // Optional. Whether the generated column is stored in the table.
    optional bool stored = 3 [(google.api.field_behavior) = OPTIONAL];
  }

  // Optional. Definition of how values are generated for the field.
  // Only valid for top-level schema fields (not nested fields).
  message GeneratedColumn {
    // Dictates when system generated values are used to populate the field.
    enum GeneratedMode {
      // Unspecified GeneratedMode will default to GENERATED_ALWAYS.
      GENERATED_MODE_UNSPECIFIED = 0;

      // Field can only have system generated values. Users cannot manually
      // insert values into the field.
      GENERATED_ALWAYS = 1;

      // Use system generated values only if the user does not explicitly
      // provide a value.
      GENERATED_BY_DEFAULT = 2;
    }

    // Optional. Dictates when system generated values are used to populate the
    // field.
    optional GeneratedMode generated_mode = 1
        [(google.api.field_behavior) = OPTIONAL];

    // Captures the metadata for the generated column. Could be either an
    // identity column or a generated column.
    oneof definition {
      // Definition of the expression used to generate the field.
      GeneratedExpressionInfo generated_expression_info = 3;
    }
  }

  // Required. The field name. The name must contain only letters (a-z, A-Z),
  // numbers (0-9), or underscores (_), and must start with a letter or
  // underscore. The maximum length is 300 characters.
  string name = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The field data type. Possible values include:
  //
  // * STRING
  // * BYTES
  // * INTEGER (or INT64)
  // * FLOAT (or FLOAT64)
  // * BOOLEAN (or BOOL)
  // * TIMESTAMP
  // * DATE
  // * TIME
  // * DATETIME
  // * GEOGRAPHY
  // * NUMERIC
  // * BIGNUMERIC
  // * JSON
  // * RECORD (or STRUCT)
  // * RANGE
  //
  // Use of RECORD/STRUCT indicates that the field contains a nested schema.
  string type = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. The field mode. Possible values include NULLABLE, REQUIRED and
  // REPEATED. The default value is NULLABLE.
  string mode = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Describes the nested schema fields if the type property is set
  // to RECORD.
  repeated TableFieldSchema fields = 4 [(google.api.field_behavior) = OPTIONAL];

  // Optional. The field description. The maximum length is 1,024 characters.
  google.protobuf.StringValue description = 6
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. The policy tags attached to this field, used for field-level
  // access control. If not set, defaults to empty policy_tags.
  PolicyTagList policy_tags = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specifies the data governance tags on this field. This field
  // works with other column-level security fields as follows:
  // - Precedence: If a data governance tag is attached to a column, it takes
  //   precedence over the policy tag attached to the column.
  //   However, if a data policy is attached to a column, it takes precedence
  //   over the data governance tag.
  //
  // - Patching behavior (how this field behaves during a `Table.patch` schema
  // update):
  //   - Unset: If the `data_governance_tags_info` field is omitted
  //     from the update request, the existing tags on the column are preserved.
  //   - Empty Field: To clear data governance tags from a column, send the
  //     `data_governance_tags_info` field as an empty object. This will remove
  //     all tags from the column.
  //   - Updating tags: To replace existing tag, send the field with the
  //   new tag.
  DataGovernanceTagsInfo data_governance_tags_info = 30
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Data policies attached to this field, used for field-level access
  // control.
  repeated DataPolicyOption data_policies = 21
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specifies data policies attached to this field, used for
  // field-level access control. When set, this will be the source of truth for
  // data policy information.
  DataPolicyList data_policy_list = 29 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Maximum length of values of this field for STRINGS or BYTES.
  //
  // If max_length is not specified, no maximum length constraint is imposed
  // on this field.
  //
  // If type = "STRING", then max_length represents the maximum UTF-8
  // length of strings in this field.
  //
  // If type = "BYTES", then max_length represents the maximum number of
  // bytes in this field.
  //
  // It is invalid to set this field if type &ne; "STRING" and &ne; "BYTES".
  int64 max_length = 10 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Precision (maximum number of total digits in base 10) and scale
  // (maximum number of digits in the fractional part in base 10) constraints
  // for values of this field for NUMERIC or BIGNUMERIC.
  //
  // It is invalid to set precision or scale if type &ne; "NUMERIC" and &ne;
  // "BIGNUMERIC".
  //
  // If precision and scale are not specified, no value range constraint is
  // imposed on this field insofar as values are permitted by the type.
  //
  // Values of this NUMERIC or BIGNUMERIC field must be in this range when:
  //
  // * Precision (<var>P</var>) and scale (<var>S</var>) are specified:
  //   [-10<sup><var>P</var>-<var>S</var></sup> + 10<sup>-<var>S</var></sup>,
  //    10<sup><var>P</var>-<var>S</var></sup> - 10<sup>-<var>S</var></sup>]
  // * Precision (<var>P</var>) is specified but not scale (and thus scale is
  //   interpreted to be equal to zero):
  //   [-10<sup><var>P</var></sup> + 1, 10<sup><var>P</var></sup> - 1].
  //
  // Acceptable values for precision and scale if both are specified:
  //
  // * If type = "NUMERIC":
  //   1 &le; precision - scale &le; 29 and 0 &le; scale &le; 9.
  // * If type = "BIGNUMERIC":
  //   1 &le; precision - scale &le; 38 and 0 &le; scale &le; 38.
  //
  // Acceptable values for precision if only precision is specified but not
  // scale (and thus scale is interpreted to be equal to zero):
  //
  // * If type = "NUMERIC": 1 &le; precision &le; 29.
  // * If type = "BIGNUMERIC": 1 &le; precision &le; 38.
  //
  // If scale is specified but not precision, then it is invalid.
  int64 precision = 11 [(google.api.field_behavior) = OPTIONAL];

  // Optional. See documentation for precision.
  int64 scale = 12 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Precision (maximum number of total digits in base 10) for seconds
  // of TIMESTAMP type.
  //
  // Possible values include:
  // * 6 (Default, for TIMESTAMP type with microsecond precision)
  // * 12 (For TIMESTAMP type with picosecond precision)
  google.protobuf.Int64Value timestamp_precision = 27
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Specifies the rounding mode to be used when storing values of
  // NUMERIC and BIGNUMERIC type.
  RoundingMode rounding_mode = 15 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Field collation can be set only when the type of field is STRING.
  // The following values are supported:
  //
  // * 'und:ci': undetermined locale, case insensitive.
  // * '': empty string. Default to case-sensitive behavior.
  google.protobuf.StringValue collation = 13
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. A SQL expression to specify the [default value]
  // (https://cloud.google.com/bigquery/docs/default-values) for this field.
  google.protobuf.StringValue default_value_expression = 14
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. The subtype of the RANGE, if the type of this field is RANGE. If
  // the type is RANGE, this field is required. Values for the field element
  // type can be the following:
  //
  // * DATE
  // * DATETIME
  // * TIMESTAMP
  FieldElementType range_element_type = 18
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. Definition of the foreign data type.
  // Only valid for top-level schema fields (not nested fields).
  // If the type is FOREIGN, this field is required.
  string foreign_type_definition = 23 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Definition of how values are generated for the field.
  // Only valid for top-level schema fields (not nested fields).
  GeneratedColumn generated_column = 28
      [(google.api.field_behavior) = OPTIONAL];
}
