code: def upgrade():
      bind = op.get_bind()
      session = db.Session(bind=bind)
  
      slices = (
          session.query(Slice).filter_by(viz_type="cal_heatmap").all()
      )
      slice_len = len(slices)
      for i, slc in enumerate(slices):
          try:
              params = json.loads(slc.params or "{}")
              params["metrics"] = [params.get("metric")]
              del params["metric"]
              slc.params = json.dumps(params, indent=2, sort_keys=True)
              session.commit()
              print(f"Upgraded ({i}/{slice_len}): {slc.slice_name}")
          except Exception as ex:
              print(slc.slice_name + " error: " + str(ex))
  
      session.close()
  
file_path: superset/superset/migrations/versions/2018-04-10_11-19_bf706ae5eb46_cal_heatmap_metric_to_metrics.py
imports: import json
  from alembic import op
  from sqlalchemy import Column, Integer, String, Text
  from sqlalchemy.ext.declarative import declarative_base
  from superset import db
label_desc: Use image node_id 1 for calling a global function with example usage: upgrade() without return types