Openstack数据库管理工具alembic更新Enum类型
admin
2023-05-25 08:21:32
0

        在使用alembic开发管理数据库时,会遇到一个比较麻烦的问题,就是变更某列的枚举类型,事实上使用sql命令变更相当的简单,一条alter的执行即可:

ALTER TYPE status ADD value 'output_limit_exceeded' after 'timed_out';
#删除
DROP TYPE status

但这样并不能满足alembic管理的初衷,也无法实现downgrade。


        使用google搜索关键字“alembic enum type”,第一个出现的是stackflow的一个帖子Altering an Enum field using Alembic。

from alembic import opimport sqlalchemy as sa

old_options = ('nonexistent_executable', 'signal', 'success', 'timed_out')
new_options = sorted(old_options + ('output_limit_exceeded',))old_type = sa.Enum(*old_options, name='status')new_type = sa.Enum(*new_options, name='status')tmp_type = sa.Enum(*new_options, name='_status')tcr = sa.sql.table('testcaseresult',
                   sa.Column('status', new_type, nullable=False))
                   
def upgrade():
    # Create a tempoary "_status" type, convert and drop the "old" type
    tmp_type.create(op.get_bind(), checkfirst=False)
    op.execute('ALTER TABLE testcaseresult ALTER COLUMN status TYPE _status'
               ' USING status::text::_status')
    old_type.drop(op.get_bind(), checkfirst=False)
    # Create and convert to the "new" status type
    new_type.create(op.get_bind(), checkfirst=False)
    op.execute('ALTER TABLE testcaseresult ALTER COLUMN status TYPE status'
               ' USING status::text::status')
    tmp_type.drop(op.get_bind(), checkfirst=False)
    
    
def downgrade():
    # Convert 'output_limit_exceeded' status into 'timed_out'
    op.execute(tcr.update().where(tcr.c.status==u'output_limit_exceeded')
               .values(status='timed_out'))
    # Create a tempoary "_status" type, convert and drop the "new" type
    tmp_type.create(op.get_bind(), checkfirst=False)
    op.execute('ALTER TABLE testcaseresult ALTER COLUMN status TYPE _status'
               ' USING status::text::_status')
    new_type.drop(op.get_bind(), checkfirst=False)
    # Create and convert to the "old" status type
    old_type.create(op.get_bind(), checkfirst=False)
    op.execute('ALTER TABLE testcaseresult ALTER COLUMN status TYPE status'
               ' USING status::text::status')
    tmp_type.drop(op.get_bind(), checkfirst=False)


这个方法提供了解决了问题,但稍显繁琐。我们可以做一下简单的封装,生成一个通用函数:

def upgrade_enum(table, column_name, enum_name, old_options, new_options):
    old_type = sa.Enum(*old_options, name=enum_name)
    new_type = sa.Enum(*new_options, name=enum_name)
    tmp_type = sa.Enum(*new_options, name="_" + enum_name)
    # Create a temporary type, convert and drop the "old" type
    tmp_type.create(op.get_bind(), checkfirst=False)
    op.execute(
        u'ALTER TABLE {0} ALTER COLUMN {1} TYPE _{2}'
        u' USING {1}::text::_{2}'.format(
            table,
            column_name,
            enum_name
        )
    )
    old_type.drop(op.get_bind(), checkfirst=False)
    # Create and convert to the "new" type
    new_type.create(op.get_bind(), checkfirst=False)
    op.execute(
        u'ALTER TABLE {0} ALTER COLUMN {1} TYPE {2}'
        u' USING {1}::text::{2}'.format(
            table,
            column_name,
            enum_name
        )
    )
    tmp_type.drop(op.get_bind(), checkfirst=False)

 这样就可以直接通过传参直接来执行升级或降级操作了。


操作环境:

 alembic-0.8.2
-bash-4.2$ psql --version
psql (PostgreSQL) 9.3.10


相关内容

热门资讯

“普京把半个国家的内阁和经济班... 俄罗斯总统普京开启对中国国事访问行程。此次随同普京访华的俄方代表团有哪些亮点值得关注?凤凰卫视驻北京...
韩国三星电子劳资谈判再破裂,明... 最新消息:韩国三星电子今天(5月20日)的劳资谈判再度宣告破裂,明天起将举行大罢工。这也将是该公司史...
国台办:赖清德上台两年所作所为... 5月20日,国务院台办举行例行新闻发布会。有记者问,赖清德上台满两年,岛内最新民调显示,台湾民众对于...
岛内舆论批评台电力公司砸钱搞“... 【环球网报道】5月20日上午,国台办举行例行新闻发布会,发言人朱凤莲就近期两岸热点问题回答记者提问。...
国安部:网速变慢,元凶竟是它 微信公众号“国家安全部”消息,近期,国家安全机关工作发现,境外间谍情报机关利用我国境内路由器充当“跳...
Vision Pro将支持眼控... 【CNMO科技消息】5月20日,苹果公司发布了多项新辅助功能,包括由Apple Intelligen...
“洪水最高没过2楼楼顶”,女子... 5月17日至18日,湖南常德市石门县普降大暴雨,其中壶瓶山镇、所街乡等地出现极端大暴雨天气过程。暴雨...
暴风雨来临前,百度抛下了锚 AI早已在搜索与推荐完成了对互联网的颠覆,因为搜推是互联网的价值转换器。信息分发、流量匹配、人找信息...
一文看懂谷歌I/O 2026:... 谷歌CEO 桑达尔·皮查伊 出品|搜狐科技 作者|郑松毅 编辑|杨锦 北京时间5月20日凌晨,加州山...
框式交换机为何备受青睐?解读T... 在数据中心与大型企业网络的核心层,框式交换机扮演着至关重要的角色。它不仅是网络流量汇聚与分发的中枢,...