S | M | T | W | T | F | S |
|
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | |
|
2007.02.07 Zhou JingYu
昨天在升级 cnpack.db 数据库时遇到附件表 blob 字段不能导入的问题,今天想到个变通的法子。
首先用 sqlite cnpack.db .dump > cnpack.sql 将数据库导出为 sql 文件,
再执行 echo .read %1.sql | sqlite3 %1.db 让 sqlite3 直接从 sql 中创建数据库。
实践证明,该方法终于可以把 blob 字段转成 3.x 格式了。然而好景不长,转换了 blob 字段的新数据库在 CVSTracNT 下无法工作,浏览页面无法打开,并且数据库目录下出了个 cvstrac_chs.exe.stackdump 文件。
在网上找了找资料,查到 cygwin 下编译的 exe 程序可以用 nm 查看其内部函数地址。果然,堆栈调用显示,AV异常出在 blob 转换函数中。
sqlite3 已经内置对 blob 二进制数据的支持,而 sqlite2 下 blob 是用 string 来保存的。cvstrac 1.x 为了保存附件,使用了简单的算法把二进制数据转为字符串保存。
cvstrac 2.0 在第一次打开 1.x 的数据库时,自动对数据库表进行升级,附件表中的 blob 自动 decode 为普通的二进制格式再替换回去,decode 的代码为:
int blob_decode(const unsigned char *in, unsigned char *out){
int i, c, e;
e = *(in++);
i = 0;
while( (c = *(in++))!=0 ){
if( c==1 ){
c = *(in++);
if( c==1 ){
c = 0;
}else if( c==2 ){
c = 1;
}else if( c==3 ){
c = '\'';
}else{
return -1;
}
}
out[i++] = (c + e)&0xff;
}
return i;
}
因为这里的代码没有对长度进行判断,我简单修改了这个函数,加上对输出缓冲区长度的判断。再次编译运行,总算可以正确显示 cnpack.db 的内容了。附件文件也还在,但是下载了一个 rar 文件发现文件格式错了。
于是,我安装 1.2.1 版本从老数据库中下载同一个 rar 文件,与新版本下载来的进行二进制比较。结果发现在新的文件中,所有的 0x4A 前面都多了一个 0x4D。仔细一想,估计是导出 sql 文件时,本来是换行一个字符结果变成了回车加换行两个字符,blob 解码后就出来多余的字符了。
看来使用现成的 sqlite 命令行工具来升级数据库是比较麻烦的了,还是自己动手写个升级工具来转换吧。
sqlite3 支持 utf-8 格式,官网上也提到本地化处理时可以有 utf-8 和本地代码页两种方式,各有优缺点。而去年就发现日本有个程序员为 CVSTracNT 做了个日文版补丁,使用 gettext 来进行代码多语言处理,似乎比我直接修改代码来本地化的办法好,而且支持动态语言切换。看来 2.x 中多语的支持也可以考虑改改,有空再研究。
补了昨天的手记,加上今天的内容,真累。
明天继续。。。 |
This blog was closed or you do not have permission to post comment.
|
|