// Copyright 2024 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/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 proto, it currently supports name only, will support
// precedence later.
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 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;
  }

  // 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];
  }

  // 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. Data policy options, will replace the data_policies.
  repeated DataPolicyOption data_policies = 21
      [(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. 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];
}
