alembic 这个升级/降级的工具,看上去挺好的,编写好一系列版本脚本之后,能够自动地把数据库给升级或者降级到指定版本。它也使用类似 git 的一串十六进制数来表示各个版本,也支持分支,不过呢,比 git 的易用性差太远了。
我今天有个需求,给一些列添加外键。因为懒得单独新写一些脚本,所以我直接改了相关脚本,手动去数据库执行了 SQL。本以为这样子就好了,后来发现新添加外键所引用的表的创建顺序不对,应该在所有引用到它的表之前创建才对。
可是 alembic 没有 git rebase -i 命令啊,不能简单地调整各种版本的顺序。我尝试着手工编辑了一下,结果弄出来两个 head,一个 branchpoint,但是我就是没能看出来是哪里分叉了……于是想到把各个版本的关系给画出来。这种图 GraphViz 最适合了,而简单地解析 alembic history 的输出,用 awk 就好了:
#!/usr/bin/awk -f BEGIN { print "digraph alembic {"; shape = "box"; } /^Rev:/ { switch($3) { case "(branchpoint)": shape = "hexagon"; break; case "(head)": shape = "ellipse"; break; default: shape = "box"; } } /^Path:/ { finding_title = 1; } /^ \S/ && finding_title { sub(/^\s+|\s+$/, ""); title = $0; finding_title = 0; } /^ Revision ID:/ { rev = $NF; } /^ Revises:/ { printf(" r%s -> { r%s };\n", rev, $NF); printf(" r%s[label=\"%s: %s\",shape=%s];\n", rev, rev, title, shape); } END { print "}"; }
head(以及第一个之前的 None 版本)会使用椭圆,分叉点(alembic 说的)会使用六边形,而其它版本是矩形的。这样就可以很方便地看出来是哪里分叉啦:
alembic history | alembic_graph | dot -Txlib
结果发现,我的数据库版本们根本就没有分叉嘛……没办法 revert 回去,把关系图导出 SVG 然后放 Inkscape 里边画边改,总算是把顺序给调整对了=w=