void VisitColumnNodeAlter()

in backend/schema/parser/ddl_parser.cc [1022:1137]


void VisitColumnNodeAlter(const std::string& table_name,
                          const std::string& column_name,
                          const SimpleNode* node, absl::string_view ddl_text,
                          DDLStatement* statement,
                          std::vector<std::string>* errors) {
  CheckNode(node, JJTCOLUMN_DEF_ALTER);
  const SimpleNode* child = GetChildNode(node, 0);
  AlterTable* alter_table = statement->mutable_alter_table();
  if (child->getId() == JJTOPTIONS_CLAUSE) {
    // "ALTER COLUMN c SET OPTIONS (...)" does not contain the
    // column TYPE or NOT NULL attributes. Translate this into a
    // SetColumnOptions statement which does not take these
    // attributes as input, and the schema change code will keep
    // these attributes unchanged.
    SetColumnOptions* set_options = statement->mutable_set_column_options();
    SetColumnOptions::ColumnPath* path = set_options->add_column_path();
    path->set_table_name(table_name);
    path->set_column_name(column_name);
    VisitColumnOptionListNode(child, 0 /* option_list_offset */,
                              set_options->mutable_options(), errors);
    return;
  }
  if (child->getId() == JJTCOLUMN_DEF_ALTER_ATTRS) {
    // For "ALTER COLUMN c TYPE NOT NULL"
    alter_table->set_table_name(table_name);
    ColumnDefinition* column =
        alter_table->mutable_alter_column()->mutable_column();
    VisitColumnNodeAlterAttrs(child, column_name, column, ddl_text, errors);
    return;
  }

  alter_table->set_table_name(table_name);
  AlterTable::AlterColumn* alter_column = alter_table->mutable_alter_column();
  ColumnDefinition* column = alter_column->mutable_column();
  column->set_column_name(column_name);
  // `type` is required in ColumnDefinition, so set it to NONE here.
  column->set_type(ColumnDefinition::NONE);

  switch (child->getId()) {
    case JJTCOLUMN_DEFAULT_CLAUSE: {
      // "ALTER COLUMN c SET DEFAULT " does not contain the column TYPE or
      // NOT NULL attributes.
      alter_column->set_operation(AlterTable::AlterColumn::SET_DEFAULT);
      VisitColumnDefaultClauseNode(child, column, ddl_text);
      break;
    }
    case JJTDROP_COLUMN_DEFAULT: {
      // "ALTER COLUMN c DROP DEFAULT " does not contain the column TYPE or
      // NOT NULL attributes.
      alter_column->set_operation(AlterTable::AlterColumn::DROP_DEFAULT);
      column->clear_column_default();
      break;
    }
    case JJTSET_NOT_NULL: {
      errors->push_back(
          "ALTER COLUMN SET NOT NULL not supported without a column type");
      break;
    }
    case JJTDROP_NOT_NULL: {
      errors->push_back(
          "ALTER COLUMN DROP NOT NULL not supported without a column type");
      break;
    }
    case JJTRESTART_COUNTER: {
      if (!EmulatorFeatureFlags::instance().flags().enable_identity_columns) {
        errors->push_back("Identity columns are not supported.");
        return;
      }
      // The reason to use two separate fields is because we would like to have
      // the capability to support updating multiple properties in a single
      // statement. Also, if we supported RESTART COUNTER without WITH, we can
      // set this bool to true but not set the start_with_counter field.
      alter_column->set_operation(AlterTable::AlterColumn::ALTER_IDENTITY);
      alter_column->set_identity_alter_start_with_counter(true);
      column->mutable_identity_column()->set_start_with_counter(
          child->image_as_int64());
      break;
    }
    case JJTSKIP_RANGE_MIN: {
      if (!EmulatorFeatureFlags::instance().flags().enable_identity_columns) {
        errors->push_back("Identity columns are not supported.");
        return;
      }
      if (node->jjtGetNumChildren() != 2) {
        // It should theoretically never happen.
        errors->push_back(
            "skip_range_max is missing in ALTER IDENTITY SET SKIP RANGE.");
        return;
      }
      const SimpleNode* next_child = GetChildNode(node, 1);
      CheckNode(next_child, JJTSKIP_RANGE_MAX);

      alter_column->set_operation(AlterTable::AlterColumn::ALTER_IDENTITY);
      alter_column->set_identity_alter_skip_range(true);
      column->mutable_identity_column()->set_skip_range_min(
          child->image_as_int64());
      column->mutable_identity_column()->set_skip_range_max(
          next_child->image_as_int64());
      break;
    }
    case JJTNO_SKIP_RANGE: {
      if (!EmulatorFeatureFlags::instance().flags().enable_identity_columns) {
        errors->push_back("Identity columns are not supported.");
        return;
      }
      alter_column->set_operation(AlterTable::AlterColumn::ALTER_IDENTITY);
      alter_column->set_identity_alter_skip_range(true);
      column->mutable_identity_column()->clear_skip_range_min();
      column->mutable_identity_column()->clear_skip_range_max();
      break;
    }
    default:
      ABSL_LOG(FATAL) << "Unexpected alter column type: "
                 << GetChildNode(node, 1)->toString();
  }
}