absl::Status SchemaUpdaterImpl::AlterColumnSetDropDefault()

in backend/schema/updater/schema_updater.cc [1415:1495]


absl::Status SchemaUpdaterImpl::AlterColumnSetDropDefault(
    const ddl::AlterTable::AlterColumn& alter_column, const Table* table,
    const Column* column, const database_api::DatabaseDialect& dialect,
    Column::Editor* editor) {
  const ddl::AlterTable::AlterColumn::AlterColumnOp type =
      alter_column.operation();
  ZETASQL_RET_CHECK(type == ddl::AlterTable::AlterColumn::SET_DEFAULT ||
            type == ddl::AlterTable::AlterColumn::DROP_DEFAULT);

  const ddl::ColumnDefinition& new_column_def = alter_column.column();
  absl::flat_hash_set<const SchemaNode*> dependent_sequences;
  if (type == ddl::AlterTable::AlterColumn::SET_DEFAULT) {
    if (column->is_generated()) {
      return error::CannotSetDefaultValueOnGeneratedColumn(column->FullName());
    }

    if (column->is_identity_column() &&
        (new_column_def.has_column_default() ||
         new_column_def.has_generated_column())) {
      return error::CannotAlterIdentityColumnToGeneratedOrDefaultColumn(
          table->Name(), new_column_def.column_name());
    }

    std::string expression = new_column_def.column_default().expression();
    if (dialect == database_api::DatabaseDialect::POSTGRESQL) {
      ZETASQL_ASSIGN_OR_RETURN(expression, TranslatePGExpression(
                                       new_column_def.column_default(), table,
                                       /*ddl_create_table=*/nullptr, *editor));
    }
    ZETASQL_RET_CHECK(new_column_def.has_column_default() && !expression.empty());
    absl::flat_hash_set<const SchemaNode*> udf_dependencies;
    absl::Status s = AnalyzeColumnDefaultValue(
        expression, column->Name(), column->GetType(), table,
        /*ddl_create_table=*/nullptr, &dependent_sequences, &udf_dependencies);
    if (!s.ok()) {
      return error::ColumnDefaultValueParseError(table->Name(), column->Name(),
                                                 s.message());
    }
    editor->set_postgresql_oid(pg_oid_assigner_->GetNextPostgresqlOid());
    editor->set_expression(expression);
    editor->set_has_default_value(true);
    editor->set_udf_dependencies(udf_dependencies);
    const Column* existing_column =
        table->FindColumn(alter_column.column().column_name());
    if (existing_column == nullptr) {
      return error::ColumnNotFound(table->Name(),
                                   alter_column.column().column_name());
    }
    absl::flat_hash_set<const SchemaNode*> deps;
    for (const auto& dep : existing_column->udf_dependencies()) {
      deps.insert(dep);
    }

    // Check for a recursive columns by analyzing the transitive set of
    // dependencies, i.e., if the view is a dependency of itself.
    auto transitive_deps = GatherTransitiveDependenciesForSchemaNode(deps);
    if (std::find_if(transitive_deps.begin(), transitive_deps.end(),
                     [existing_column](const SchemaNode* dep) {
                       return (dep->As<const Column>() != nullptr &&
                               dep->As<const Column>()->Name() ==
                                   existing_column->Name());
                     }) != transitive_deps.end()) {
      return error::ViewReplaceRecursive(existing_column->Name());
    }
  } else {
    if (!column->has_default_value() || column->is_identity_column()) {
      return absl::OkStatus();
    }
    editor->clear_expression();
    editor->clear_original_expression();
    editor->set_has_default_value(false);
    if (!column->is_generated()) {
      // Only default and generated columns need an OID. If the default is
      // dropped and the column is not generated then unassign the OID.
      editor->set_postgresql_oid(std::nullopt);
    }
  }
  // Clear all the old sequence dependencies and set the new ones
  editor->set_sequences_used(dependent_sequences);
  return absl::OkStatus();
}