増强alembic

alembic是sqlalchemy的作者Mike Bayer开发的数据库迁移工具。在uliweb中已经有集成,比如你安装了uliweb.contrib.orm后,即可以使用uliweb alembic [init][diff][upgrade] 来进行数据库的迁移。具体这个模块我不在这里细说,感兴趣可以访问 http://alembic.readthedocs.org/en/latest/ 这是它的文档,功能还是很强大的。

在我的使用过程中我发现两个问题:

1. Pickle类型生成的迁移代码不正确,总有一些象<PickleType...>之类的东西,在升级数据库时会报错。

2. 对于某些类型的修改识别上不完美,所以缺省都是关闭的。这个体现在:同样的varchar类型,但是自动探测一般是和某个数据库引擎有关系,但是程序Model却是使用的通用类型,这样得到的有可能还带有象unicodeconvert=True之类的参数信息,但是另一个却不带,结果造成两个类型不一致。还有象使用mysql引擎,boolean类型会使用TinyInt来代替,这样Boolean和TinyInt就会认为是不同的类型,但是处理后其实还是这样。

所以针对上面的问题我对原来的alembic进行了一些hack的工作。我直接修改了alembic的源码,作了些特殊的处理。比如修改了Pickle的错误。同时对类型的比较我进行了一些限制,比如代码为:

def _get_type(t):
    
    name = t.__class__.__name__
    r = repr(t)
    if name.upper() == 'VARCHAR':
        r = '%s(length=%d)' % (name, t.length)
    elif name.upper() == 'CHAR':
        r = '%s(length=%d)' % (name, t.length)
    elif name.upper() == 'DECIMAL':
        r = '%s(precision=%d, scale=%d)' % ('Numeric', t.precision, t.scale)
    elif name.upper() == 'PICKLETYPE':
        r = '%s()' % 'BLOB'
    elif name.upper() == 'INTEGER':
        r = '%s()' % 'INTEGER'
    return r
    
def _compare(c1, c2):
    r1 = _get_type(c1)
    r2 = _get_type(c2)
    if r1.upper() == 'BOOLEAN()' or r2.upper() == 'BOOLEAN()':
        return False
    else:
        return r1.upper() != r2.upper()
目前只对我感兴趣的几种类型进行了重新生成类型字符串的工作,将不必要的参数过滤掉,并且对某些类型,如Decimal进行了转換,使用Numeric。这样就统一了。在比较时,对于Boolean直接忽略。

因为原来的代码放在bitbucket,我不太习惯使用。于是我在github上的某个人的clone创建作了一个fork,首先将其升级到0.4.0(看文档是0.4.1了,不过pypi上没有变化),然后加上了我的补丁。所以感兴趣的可以从 https://github.com/limodou/alembic/archive/0.4.1.zip 下载0.4.1tag的代码试用一下。

你可能感兴趣的:(増强alembic)