Altering an Enum field using Alembic

后端 未结 10 1128
故里飘歌
故里飘歌 2020-12-12 21:32

How can I add an element to an Enum field in an alembic migration when using a version of PostgreSQL older than 9.1 (which adds the ALTER TYPE for enums)? This SO question e

10条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-12 21:58

    I used a bit simpler approach with less steps than the accepted answer, which I based this on. In this example I will pretend the enum in question is called 'status_enum', because in the accepted answer the use of 'status' for both the column and enum confused me.

    from alembic import op 
    import sqlalchemy as sa
    
    name = 'status_enum'
    tmp_name = 'tmp_' + name
    
    old_options = ('nonexistent_executable', 'signal', 'success', 'timed_out')
    new_options = sorted(old_options + ('output_limit_exceeded',))
    
    new_type = sa.Enum(*new_options, name=name)
    old_type = sa.Enum(*old_options, name=name)
    
    tcr = sa.sql.table('testcaseresult',
                       sa.Column('status', new_type, nullable=False))
    
    def upgrade():
        op.execute('ALTER TYPE ' + name + ' RENAME TO ' + tmp_name)
    
        new_type.create(op.get_bind())
        op.execute('ALTER TABLE testcaseresult ALTER COLUMN status ' +
                   'TYPE ' + name + ' USING status::text::' + name)
        op.execute('DROP TYPE ' + tmp_name)
    
    
    def downgrade():
        # Convert 'output_limit_exceeded' status into 'timed_out'                                                                                                                      
        op.execute(tcr.update().where(tcr.c.status=='output_limit_exceeded')
                   .values(status='timed_out'))
    
        op.execute('ALTER TYPE ' + name + ' RENAME TO ' + tmp_name)
    
        old_type.create(op.get_bind())
        op.execute('ALTER TABLE testcaseresult ALTER COLUMN status ' +
                   'TYPE ' + name + ' USING status::text::' + name)
        op.execute('DROP TYPE ' + tmp_name)
    

提交回复
热议问题