absl::Status UdfValidator::ValidateUpdate()

in backend/schema/validators/udf_validator.cc [97:181]


absl::Status UdfValidator::ValidateUpdate(const Udf* udf, const Udf* old_udf,
                                          SchemaValidationContext* context) {
  // During a REPLACE, the udf name's case can change.
  if (context->IsModifiedNode(udf)) {
    ZETASQL_RET_CHECK(absl::EqualsIgnoreCase(udf->Name(), old_udf->Name()));
  } else {
    ZETASQL_RET_CHECK_EQ(udf->Name(), old_udf->Name());
  }
  if (udf->is_deleted()) {
    context->global_names()->RemoveName(udf->Name());
    return absl::OkStatus();
  }
  if (context->is_postgresql_dialect()) {
    ZETASQL_RET_CHECK(udf->postgresql_oid().has_value());
    ZETASQL_RET_CHECK(old_udf->postgresql_oid().has_value());
    ZETASQL_RET_CHECK_EQ(udf->postgresql_oid().value(),
                 old_udf->postgresql_oid().value());
  } else {
    ZETASQL_RET_CHECK(!udf->postgresql_oid().has_value());
    ZETASQL_RET_CHECK(!old_udf->postgresql_oid().has_value());
  }

  for (const SchemaNode* dependency : udf->dependencies()) {
    // Cannot drop dependencies of the udf.
    if (dependency->is_deleted()) {
      // If the deleted dependency is a column that was marked as deleted
      // as a result of a table drop, then we use the table to report the error
      // message.
      if (auto dep_column = dependency->As<const Column>();
          dep_column != nullptr) {
        const Table* dep_table = dep_column->table();
        if (dep_table->is_deleted()) {
          dependency = dep_table;
        }
      }
      const auto& dep_info = dependency->GetSchemaNameInfo();
      std::string dependency_type =
          (dep_info->global ? absl::AsciiStrToUpper(dep_info->kind)
                            : absl::AsciiStrToLower(dep_info->kind));
      return error::InvalidDropDependentFunction(dependency_type,
                                                 dep_info->name, udf->Name());
    }

    // If a dependency was updated during the schema change then we need to
    // re-analyze *this.
    if (context->IsModifiedNode(dependency)) {
      const auto& dep_info = dependency->GetSchemaNameInfo();
      std::string dependency_type =
          (dep_info->global ? absl::AsciiStrToUpper(dep_info->kind)
                            : absl::AsciiStrToLower(dep_info->kind));
      std::string modify_action = absl::StrCat("alter ", dependency_type);
      std::string dependency_name;
      if (auto dep_view = dependency->As<const View>(); dep_view != nullptr) {
        dependency_name = dep_view->Name();
      }
      if (auto dep_table = dependency->As<const Table>();
          dep_table != nullptr) {
        dependency_name = dep_table->Name();
      }
      if (auto dep_column = dependency->As<const Column>();
          dep_column != nullptr) {
        dependency_name = dep_column->FullName();
      }
      if (auto dep_udf = dependency->As<const Udf>(); dep_udf != nullptr) {
        dependency_name = dep_udf->Name();
      }
      // No need to check modifications on index dependencies as indexes
      // cannot currently be altered.
      std::string param_list = "";
      auto args = udf->signature()->arguments();
      for (int i = 0; i < args.size(); i++) {
        const auto& param = args[i];
        param_list += param.argument_name() + " " +
                      param.type()->TypeName(zetasql::PRODUCT_EXTERNAL);
        if (i < args.size() - 1) {
          param_list += ", ";
        }
      }
      ZETASQL_RETURN_IF_ERROR(ValidateUdfSignatureChange(
          modify_action, dependency_name, param_list, udf,
          context->tmp_new_schema(), context->type_factory()));
    }
  }
  return absl::OkStatus();
}