自动化环境需要及时从测试环境同步mysql的表结构,选择的技术方案是python的一个第三方库schemasync
,这个库使用起来整体是OK的,但是在某些情况下会生成有语法错误的sql文件,例如:
MODIFY COLUMN `biz_id` varchar(10) NOT NULL DEFAULT AP AFTER `original_trans_id`
ADD COLUMN remark varchar(50) NULL DEFAULT * FIRST
可以看出,这个库在处理表的列的默认值时是有问题的,一些字符串类型的默认值没有加引号,从而引发了语法错误。于是下决心找出这个bug。
首先下载 schemasync 的源码,代码并不多,只有三个python文件,通过走查源码发现其并没有处理表字段的细节。
找到相关代码后,增加打印日志,发现他是在这里生成的语句,这里生成的语句已经有问题了。
def sync_created_columns(from_cols, to_cols, sync_comments=False):
for c in from_cols:
if c not in to_cols:
fprev = get_previous_item(from_cols.keys(), c)
yield (from_cols[c].create(after=fprev, with_comment=sync_comments),
from_cols[c].drop())
向上反查,发现生成sql语句其实是通过另外一个库schemaobject
实现的,于是下载源码继续撸
这份代码也算比较清晰,在可疑代码位置设置断点,终于找到了生成sql语句的代码:
if self.default is not None and isinstance(self.default, str) and self.default is not 'CURRENT_TIMESTAMP':
sql.append("DEFAULT '%s'" % self.default)
elif self.default is not None:
sql.append("DEFAULT %s" % self.default)
这里判断是不是字符串类型,然后决定生成的语句要不要加引号。通过调试,发现 self.default
的类型是 unicode
,不是 str
,所以没走上面的判断分支。
到此差不多解决方案也有了,但是我在考虑这么明显的问题作者没考虑到吗?
python2在字符串处理这里是有坑的,从python3开始就没有这些个区别了。所以,建议感觉入手python3吧,会顺手很多。
Copyright © 2015-2022 BY-NC-ND 4.0