MySQL源码学习: concat + outfile的bug 原因分析
项目中碰到一个bug,需要将MySQL表中的数据导出,字段中间用逗号隔开。
?
CREATE TABLE `test` (
?? `id` int(11) DEFAULT NULL,
???? `data` char(10) DEFAULT NULL
???? ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
insert into tad2 values (1,'丁\\奇');
?
b) select concat(id, data) from test into outfile ‘/tmp/a’;
现象:
在生成的/tmp/a中,发现”丁”字乱码了,实际上是”丁”的第二个字节前面多了个 ‘\’。?
?
? ??????for (start=pos=(char*) res->ptr(),end=pos+used_length ;
???????????? pos != end ;
???????????? pos++)
??????? {
if (use_mb(res_charset))
????????? {???
??????????? int l;
??????????? if ((l=my_ismbchar(res_charset, pos, end)))
??????????? {???
??? ??????????pos += l-1;
????????????? continue;
??????????? }???
????????? }?
?
????????? ??if ((NEED_ESCAPING(*pos) ||
?????????????? (check_second_byte &&
??????????????? my_mbcharlen(character_set_client, (uchar) *pos) == 2 &&
??????????????? pos + 1 < end &&
??????????????? NEED_ESCAPING(pos[1]))) &&
????????????? (enclosed || !is_ambiguous_field_term ||
?????????????? (int) (uchar) *pos != field_term_char))
??????????? {当前字符前加入 ‘\’}
??????? }
?
说明:
?
?
CREATE TABLE `test` (
?? `name`blob,
???? `data` char(10) DEFAULT NULL
???? ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
insert into tad2 values ('盶','丁\\奇');
?????? 还是那个需求,把表数据输出,中间用逗号隔开,此时客户端要使用什么字符集呢。实际上不论使用binary还是gbk,都会造成乱码。??
?
? enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
? uint repertoire(void) const { return MY_REPERTOIRE_ASCII; }
? CHARSET_INFO *charset(void) const { return &my_charset_latin1; }
virtual uint repertoire(void) const {? }
?
?
7、小结
??????对于支持多字符集的软件,字符串处理还是很复杂的。当然我们知道5.5还是有问题的,反馈一下,期待官方的方案吧。
???? 目前碰到有这个需求的,还是先直接导出,在生成文件中自己作文本处理吧。