51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

查看: 626|回复: 0
打印 上一主题 下一主题

MySQL客户端显示binary字符代码改造

[复制链接]
  • TA的每日心情
    无聊
    3 天前
  • 签到天数: 941 天

    连续签到: 3 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-8-3 10:13:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     一、客户端显示字符背景介绍
      MySQL最新版本有一个新功能,在使用客户端的时候,最后加上--skip-binary-as-hex选项可以直接显示二进制值对应的字符串,不加该选项就可以按照原来的设置格式显示。先来看一下以下的varbaniry的显示例子。
    1. #建表:
    2.   create table varb(id int,bb varbinary(1000));
    3.   insert into varb values(1,'abcd');
    4.   #登录:
    5.   mysql -h 127.0.0.1 -P3307 -uroot  --skip-binary-as-hex
    6.   mysql> select * from varb;
    7.   +------+------+
    8.   | id   | bb   |
    9.   +------+------+
    10.   |    1 | abcd |
    11.   +------+------+
    12.   1 row in set (0.00 sec)
    复制代码
    如果不加--skip-binary-as-hex选项的显示如下:

    1.  mysql -h 127.0.0.1 -P3307 -uroot
    2.   mysql> select * from varb;
    3.   +------+------------+
    4.   | id   | bb         |
    5.   +------+------------+
    6.   |    1 | 0x61626364 |
    7.   +------+------------+
    8.   1 row in set (0.01 sec)
    复制代码
    这个功能对于用惯了旧版本的同学们有的会觉得不方便,今天这里动手改造一下都显示成字符格式而不用通过--skip-binary-as-hex选项设置。
      二、代码跟踪
      沿用上面的表查询一下哪段代码决定字符的显示格式,代码解析如下:
      输入该命令后找到相关字符显示的代码:
    1.   mysql> select * from varb;
    复制代码
    class Item_field的成员函数如下:
    1. const CHARSET_INFO *charset_for_protocol(void) override {
    2.       return field->charset_for_protocol();
    3.       #表字段的字符显示取决于field的字符设置。
    4.     }
    复制代码
    继续找到class Field的成员函数如下:
    1. const CHARSET_INFO *charset_for_protocol() const {
    2.       return binary() ? &my_charset_bin : charset();
    3.       #field的字符设置取决于是否binary类型。
    4.     }
    复制代码
    输入以上命令GDB跟踪一下代码堆栈:
    1. Thread 47 "mysqld" hit Breakpoint 3, Item_field::charset_for_protocol (this=0x7fff340bc1f0)
    2.       at /home/greatdb/sql/item.h:4373
    3.   4373   const CHARSET_INFO *charset_for_protocol(void) override {
    4.   (gdb) bt
    5.   #0  Item_field::charset_for_protocol (this=0x7fff340bc1f0)
    6.       at /home/greatdb/sql/item.h:4373#1  0x0000555558e60ca8 in THD::send_result_metadata (this=0x7fff34000c00, list=..., flags=5)
    7.       at /home/greatdb/sql/sql_class.cc:2831
    8.   #2  0x0000555558d9fe59 in Query_result_send::send_result_set_metadata (this=0x7fff3429cfa0,
    9.       thd=0x7fff34000c00, list=..., flags=5)
    10.       at /home/greatdb/sql/query_result.cc:74
    11.   #3  0x0000555559093d1b in Query_expression::ExecuteIteratorQuery (this=0x7fff3429ae08,
    12.       thd=0x7fff34000c00) at /home/greatdb/sql/sql_union.cc:1169
    13.   #4  0x0000555559094452 in Query_expression::execute (this=0x7fff3429ae08, thd=0x7fff34000c00)
    14.       at /home/greatdb/sql/sql_union.cc:1305
    15.   #5  0x0000555558fd4b18 in Sql_cmd_dml::execute_inner (this=0x7fff3429cf68, thd=0x7fff34000c00)
    16.       at /home/greatdb/sql/sql_select.cc:810
    17.   #6  0x0000555558fd3f24 in Sql_cmd_dml::execute (this=0x7fff3429cf68, thd=0x7fff34000c00)
    18.       at /home/greatdb/sql/sql_select.cc:578
    19.   #7  0x0000555558f4ac03 in mysql_execute_command (thd=0x7fff34000c00, first_level=true)
    20.       at /home/greatdb/sql/sql_parse.cc:4784
    21.   #8  0x0000555558f4cd80 in dispatch_sql_command (thd=0x7fff34000c00, parser_state=0x7fffe82ab990,
    22.       update_userstat=false) at /home/greatdb/sql/sql_parse.cc:5384
    23.   #9  0x0000555558f42257 in dispatch_command (thd=0x7fff34000c00, com_data=0x7fffe82acb70,
    24.       command=COM_QUERY) at /home/greatdb/sql/sql_parse.cc:1992
    25.   #10 0x0000555558f405c7 in do_command (thd=0x7fff34000c00)
    26.       at /home/greatdb/sql/sql_parse.cc:1440
    27.   #11 0x0000555559163f7e in handle_connection (arg=0x55556091c920)
    28.       at /home/greatdb/sql/conn_handler/connection_handler_per_thread.cc:307
    29.   #12 0x000055555ad85edf in pfs_spawn_thread (arg=0x5555607808c0)
    30.       at /home/greatdb/storage/perfschema/pfs.cc:2899
    31.   #13 0x00007ffff77a6609 in start_thread (arg=<optimized out>) at pthread_create.c:477
    32.   #14 0x00007ffff76cb163 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
    复制代码
    对于非表字段的内容显示格式取决于什么呢?继续找:
    1.   mysql> select 'abcd' from varb;
    复制代码
    输入该命令后找到相关字符显示的代码,对于非表字段的内容取决于结果是否STRING_RESULT,'abcd'属于Item_string,result_type()=STRING_RESULT,所以显示字符格式是collation.collation。
      class Item的成员函数如下:
    1. virtual const CHARSET_INFO *charset_for_protocol() {
    2.       return result_type() == STRING_RESULT ? collation.collation
    3.                                             : &my_charset_bin;
    4.     }
    复制代码
    三、代码改造
      针对上面介绍的第一种情况改造代码如下:
    1. mysql> select * from varb;
    2.   #class Field的成员函数改成如下,其中system_charset_info=my_charset_utf8_general_ci:
    3.     const CHARSET_INFO *charset_for_protocol() const {
    4.       return system_charset_info;
    5.     }
    复制代码
    登录客户端,可以看到结果已经自动显示成字符格式而不是刚才看到的baniry格式。
    1. mysql -h 127.0.0.1 -P3307 -uroot
    2.   mysql> select * from varb;
    3.   +------+------+
    4.   | id   | bb   |
    5.   +------+------+
    6.   |    1 | abcd |
    7.   +------+------+
    8.   1 row in set (0.00 sec)
    复制代码
    四、总结
      MySQL客户端字符显示依赖charset_for_protocol()函数,可以根据自己的需求修改该函数的显示方式,方便自己的使用。如果未来新定义Item或者Field记得也要相应修改该函数来正确显示数据。





    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-5-3 06:27 , Processed in 0.063593 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表