当前位置: 首页 > 科技观察

MySQL客户端显示二进制字符编码转换

时间:2023-03-18 17:28:49 科技观察

一、客户端显示字符背景介绍最新版本的MySQL有一个新的功能。使用客户端时,在末尾添加--skip-binary-as-hex选项,可以直接显示binary值对应的字符串,不添加该选项也可以按原格式显示。让我们看看下面的varbaniry显示示例。#建表:createtablevarb(idint,bbvarbinary(1000));insertintovarbvalues(1,'abcd');#Login:mysql-h127.0.0.1-P3307-uroot--skip-binary-as-hexmysql>select*fromvarb;+------+-----+|编号|bb|+-----+-----+|1|abcd|+------+------+1rowinset(0.00sec)如果不加--skip-binary-as-hex选项,显示如下:mysql-h127.0.0.1-P3307-urootmysql>从varb中选择*;+------+------------+|编号|bb|+------+------------+|1|0x61626364|+------+------------+1rowinset(0.01sec)这个功能可能有些用惯了旧版本的同学会觉得不方便。今天,我将在这里更改它并以字符格式显示,而不是通过--skip-binary-as-hex选项进行设置。2.代码跟踪利用上表查看是哪个代码决定了字符的显示格式。代码分析如下:输入这条命令后,找到相关字符显示的代码:mysql>select*fromvarb;Item_field类的成员函数如下:constCHARSET_INFO*charset_for_protocol(void)override{returnfield->charset_for_protocol();#表格字段的字符显示取决于字段的字符设置。}继续查找类Field的成员函数如下:constCHARSET_INFO*charset_for_protocol()const{returnbinary()?&my_charset_bin:字符集();#字段的字符设置取决于是否为二进制类型。}输入以后命令GDB跟踪一下代码堆栈:Thread47"mysqld"hitBreakpoint3,Item_field::charset_for_protocol(this=0x7fff340bc1f0)at/home/greatdb/sql/item.h:43734373constCHARSET_INFO*charset_for_protocol{void(void(gdb)bt#0Item_field::charset_for_protocol(this=0x7fff340bc1f0)at/home/greatdb/sql/item.h:4373#10x0000555558e60ca8inTHD::send_result_metadata(this=0x7fff34000c00,list=...,flags=5)在/home/greatdb/sql/sql_class.cc:2831#20x0000555558d9fe59在Query_result_send::send_result_set_metadata(this=0x7fff3429cfa0,thd=0x7fff34000c00,list=...,flags=5)在/home/greatdb/sql/query_result.cc:74#30x0000555559093d1binQuery_expression::ExecuteIteratorQuery(this=0x7fff3429ae08,thd=0x7fff34000c00)at/home/greatdb/sql/sql_union.cc:1169#40x0000555559094452inQuery_expression::execute(this=0x7fff3429ae08,thd=0x7fff34000c00)在/home/greatdb/sql/sql_union.cc:1305#50x0000555558fd4b18在Sql_cmd_dml::execute_inner(this=0x7fff3429cf68,thd=0x7fff34000c00)at/home/greatdb/sql/sql_select.cc:810#60x0000555558fd3f24inSql_cmd_dml::execute(this=0x7fff3429cf68,thd=0x7fff34000c00)atselect/sql_select.sql/00cc:578#70x0000555558f4ac03inmysql_execute_command(thd=0x7fff34000c00,first_level=true)at/home/greatdb/sql/sql_parse.cc:4784#80x0000555558f4cd80indispatch_sql_command(thd=0x7fff34000c00,parser_state=0x7fffe82ab990,update_userstat=false)at/home/greatdb/sql/sql_parse.cc:5384#90x0000555558f42257在dispatch_command(thd=0x7fff34000c00,com_data=0x7fffe82acb70,command=COM_QUERY)在/home/greatdb/sql/sql_parse.cc:1992#100x00005555558inf40x7fff34000c00)at/home/greatdb/sql/sql_parse.cc:1440#110x0000555559163f7einhandle_connection(arg=0x55556091c920)at/home/greatdb/sql/conn_handler/connection_handler_per_thread.cc:307#120x000055555ad85edfinpfs_spawn_thread(arg=0x5555607808c0)At/home/greatdb/storage/perfschema/pfs.cc:2899#130x00007ffff77a6609instart_thread(arg=)atpthread_create.c:477#140x00007ffff76cb163inclone()at../sysdeps/unix/sysv/linux/x86_64/clone.S:95非表字段的内容显示格式依赖什么?继续查找:mysql>select'abcd'fromvarb;输入此命令后,找到相关字符显示的代码。对于非表字段,内容取决于结果是否为STRING_RESULT,'abcd'属于Item_string,result_type()=STRING_RESULT,所以显示的字符格式为collat??ion.collat??ionclassItem的成员函数如下:virtualconstCHARSET_INFO*charset_for_protocol(){返回结果类型()==STRING_RESULT?collat??ion.collat??ion:&my_charset_bin;}3.代码修改上述第一种情况的代码修改如下:mysql>select*fromvarb;#classField的成员函数改成如下,其中system_charset_info=my_charset_utf8_general_ci:constCHARSET_INFO*charset_for_protocol()const{returnsystem_charset_info;}登录客户端,可以看到结果已经自动以字符格式显示,而不是刚刚看到的baniry格式。mysql-h127.0.0.1-P3307-urootmysql>从varb中选择*;+------+------+|编号|bb|+-----+-----+|1|abcd|+------+-----+1rowinset(0.00sec)4.总结MySQL客户端字符显示依赖于charset_for_protocol()函数,可以根据需要修改显示功能模式方便自己使用。如果您以后定义了新的Item或Field,请记得相应地修改此函数以正确显示数据。