code: def downgrade():
      bind = op.get_bind()
      insp = sa.engine.reflection.Inspector.from_engine(bind)
  
      # Add the new more restrictive uniqueness constraint which is required by
      # the foreign key constraints. Note this operation will fail if the
      # datasources.datasource_name column is no longer unique.
      with op.batch_alter_table(
          "datasources", naming_convention=conv
      ) as batch_op:
          batch_op.create_unique_constraint(
              "uq_datasources_datasource_name", ["datasource_name"]
          )
  
      # Augment the tables which have a foreign key constraint related to the
      # datasources.datasource_id column.
      for foreign in ["columns", "metrics"]:
          with op.batch_alter_table(
              foreign, naming_convention=conv
          ) as batch_op:
              # Add the datasource_name column with the relevant constraints.
              batch_op.add_column(
                  sa.Column("datasource_name", sa.String(255))
              )
  
              batch_op.create_foreign_key(
                  f"fk_{foreign}_datasource_name_datasources",
                  "datasources",
                  ["datasource_name"],
                  ["datasource_name"],
              )
  
          # Helper table for database migration using minimal schema.
          table = sa.Table(
              foreign,
              sa.MetaData(),
              sa.Column("id", sa.Integer, primary_key=True),
              sa.Column("datasource_name", sa.String(255)),
              sa.Column("datasource_id", sa.Integer),
          )
  
          # Migrate the existing data.
          for datasource in bind.execute(datasources.select()):
              bind.execute(
                  table.update()
                  .where(table.c.datasource_id == datasource.id)
                  .values(datasource_name=datasource.datasource_name)
              )
  
          with op.batch_alter_table(
              foreign, naming_convention=conv
          ) as batch_op:
              # Drop the datasource_id column and associated constraint.
              batch_op.drop_constraint(
                  f"fk_{foreign}_datasource_id_datasources",
                  type_="foreignkey",
              )
  
              batch_op.drop_column("datasource_id")
  
      with op.batch_alter_table(
          "datasources", naming_convention=conv
      ) as batch_op:
          # Prior to dropping the uniqueness constraint, the foreign key
          # associated with the cluster_name column needs to be dropped.
          batch_op.drop_constraint(
              generic_find_fk_constraint_name(
                  "datasources", {"cluster_name"}, "clusters", insp
              )
              or "fk_datasources_cluster_name_clusters",
              type_="foreignkey",
          )
  
          # Drop the old less restrictive uniqueness constraint.
          batch_op.drop_constraint(
              generic_find_uq_constraint_name(
                  "datasources",
                  {"cluster_name", "datasource_name"},
                  insp,
              )
              or "uq_datasources_cluster_name",
              type_="unique",
          )
  
          # Re-create the foreign key associated with the cluster_name column.
          batch_op.create_foreign_key(
              f"fk_{foreign}_datasource_id_datasources",
              "clusters",
              ["cluster_name"],
              ["cluster_name"],
          )
  
imports: import logging
  import sqlalchemy
  from alembic import op
  from superset.utils.core import generic_find_fk_constraint_name, generic_find_fk_constraint_names, generic_find_uq_constraint_name
label_desc: Use image node_id 2 for calling a global function with example usage: downgrade() without return types