absl::Status ColumnValidator::Validate()

in backend/schema/validators/column_validator.cc [212:300]


absl::Status ColumnValidator::Validate(const Column* column,
                                       SchemaValidationContext* context) {
  ZETASQL_RET_CHECK_NE(column->table_, nullptr);
  ZETASQL_RET_CHECK(!column->name_.empty());
  ZETASQL_RET_CHECK(!column->id_.empty());
  ZETASQL_RET_CHECK(column->type_ != nullptr && IsSupportedColumnType(column->type_));
  const zetasql::Type* base_type = BaseType(column->type_);
  ZETASQL_RET_CHECK(!column->declared_max_length_.has_value() ||
            base_type->IsString() || base_type->IsBytes());

  if (column->name_.length() > limits::kMaxSchemaIdentifierLength) {
    return error::InvalidSchemaName("Column", column->Name());
  }

  if (column->source_column_) {
    ZETASQL_RET_CHECK(column->type_->Equals(column->source_column_->type_));
    ZETASQL_RET_CHECK(column->declared_max_length_ ==
              column->source_column_->declared_max_length_);
  }

  if (column->declared_max_length_.has_value()) {
    if (base_type->IsString() && (column->declared_max_length_.value() == 0 ||
                                  column->declared_max_length_.value() >
                                      limits::kMaxStringColumnLength)) {
      return error::InvalidColumnLength(column->FullName(),
                                        column->declared_max_length_.value(), 1,
                                        limits::kMaxStringColumnLength);
    }
    if (base_type->IsBytes() && (column->declared_max_length_.value() == 0 ||
                                 column->declared_max_length_.value() >
                                     limits::kMaxBytesColumnLength)) {
      return error::InvalidColumnLength(column->FullName(),
                                        column->declared_max_length_.value(), 1,
                                        limits::kMaxBytesColumnLength);
    }
  }

  if (column->has_vector_length()) {
    if (!column->type_->IsArray() ||
        (column->type_->IsArray() && !base_type->IsFloat() &&
         !base_type->IsDouble())) {
      return error::InvalidTypeForVectorLength(column->FullName());
    } else if (column->is_generated() || column->has_default_value()) {
      return error::VectorLengthOnGeneratedOrDefaultColumn(column->FullName());
    }
  }

  if (base_type->IsProto() || base_type->IsEnum()) {
    ZETASQL_RETURN_IF_ERROR(ValidateTypeExistsInProtoBundle(
        base_type, context->proto_bundle(), column->FullName()));
  }

  if (column->has_allows_commit_timestamp() && !column->type_->IsTimestamp()) {
    return error::UnallowedCommitTimestampOption(column->FullName());
  }

  if (column->has_default_value()) {
    if (column->allows_commit_timestamp()) {
      return error::CannotUseCommitTimestampWithColumnDefaultValue(
          column->Name());
    }
    if (context->is_postgresql_dialect()) {
      ZETASQL_RET_CHECK(column->postgresql_oid().has_value());
    } else {
      ZETASQL_RET_CHECK(!column->postgresql_oid().has_value());
    }
  }

  if (column->is_generated()) {
    if (context->is_postgresql_dialect()) {
      ZETASQL_RET_CHECK(column->postgresql_oid().has_value());
    } else {
      ZETASQL_RET_CHECK(!column->postgresql_oid().has_value());
    }
    if (!EmulatorFeatureFlags::instance().flags().enable_generated_pk &&
        column->table()->FindKeyColumn(column->Name())) {
      return error::CannotUseGeneratedColumnInPrimaryKey(
          column->table()->Name(), column->Name());
    }
    for (const Column* dep : column->dependent_columns()) {
      if (dep->allows_commit_timestamp()) {
        return error::CannotUseCommitTimestampOnGeneratedColumnDependency(
            dep->Name());
      }
    }
  }

  return absl::OkStatus();
}