0

I am using alembic to generate database migration scripts for a mysql database. I've noticed that the syntax of the generated upgrade and downgrade scripts differ slightly, whereas I thought they would basically be the same.

models.py- before

class Message_User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(20), nullable=True)

models.py-after table modification

class Message_User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    tag = db.Column(db.String(15), nullable=True)

migration file - original - shows table creation

def upgrade():
    op.create_table('message_user',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=20), nullable=True)
    sa.PrimaryKeyConstraint('id', name=op.f('pk_message_user'))
    )

def downgrade():
    op.drop_table('message_user')

migration file - after - shows table modification

def upgrade():
    op.add_column('message_user', sa.Column('tag', sa.String(length=15), nullable=True))
    op.drop_column('message_user', 'name')

def downgrade():
    op.add_column('message_user', sa.Column('name', mysql.VARCHAR(collation='utf8_bin', 
    length=20), nullable=True))
    op.drop_column('message_user', 'tag')

The upgrade scripts describe the changes purely in sqlalchemy terms, whereas the downgrade scripts add mysql dialect specific changes. Specifically, the upgrade script defines the type as sa.String(length=15) whereas the downgrade defines it as mysql.VARCHAR(collation='utf8_bin', length=20). In create table statements in the downgrade scripts, the autogenerated script also includes mysql_collate, mysql_default_charset and mysql_engine whereas these aren't in create table statements for upgrade scripts. I didn't see any mention of this in the alembic documentation. Does anyone know why this differs?

  • You are not providing any details about this column, but consider the Alembic is trying to put the column back the way it was before the migration. How was this column created? If it wasn't created as a standard SQLAlchemy column it could be needing those special MySQL attributes. – Miguel Grinberg Apr 04 '20 at 09:41
  • updated post to include sqlalchemy column definiton. let me know if you need anything else. thanks. – Douglas Leister Apr 05 '20 at 12:27
  • Did you look for the creation of this column in a previous migration as I suggested? – Miguel Grinberg Apr 06 '20 at 09:22
  • sorry, misunderstood your original ask. post is updated showing original script for table creation. – Douglas Leister Apr 06 '20 at 16:30
  • Okay, thanks. As far as I can see you haven't done anything wrong. It seems this is because Alembic does not really have access to your definition of the `name` column because you deleted it from the model, so it needs to come up with its own to put in the `downgrade()` function. Could be an Alembic bug, I guess. If the MySQL'isms bother you, feel free to edit the script to use the generic column definition. – Miguel Grinberg Apr 07 '20 at 14:57
  • Thanks. Will let be as its working fine. Just wanted to know why the difference exists. BTW, thanks a lot for putting together the Flask mega-tutorial. Its been very helpful. – Douglas Leister Apr 08 '20 at 14:53

0 Answers0