GreatSQL社区

搜索

[已解决] Cannot convert string '\xE9\x87...' from utf8mb3 to binary

1546 4 2023-2-23 16:22
8.0.32查一个视图中的中文报错,默认字符集utf8mb4和utf8mb4_0900_ai_ci
视图引用的表字段为utf8mb3,未在视图上指定字符集,显示为utf8mb4和utf8mb4_0900_ai_ci
select * from t1 where name ='金'
查询无结果 show warnnings报Cannot convert string '\xE9\x87...' from utf8mb3 to binary,
直接查源表的对应字段无问题。
这个怎么解决?

全部回复(4)
yejr 2023-2-23 17:49:27
请补充几个信息
1、表DDL定义
2、使用何种客户端连接
3、客户端(连接)字符集怎么设置的
nyp30 2023-2-23 19:39:23
复现
CREATE TABLE `test` (
    `ID` varchar(64) NOT NULL COMMENT 'id',
    `NAME` varchar(200)  DEFAULT NULL COMMENT '名称',
    PRIMARY KEY (`ID`) USING BTREE
    ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

insert into test values('1','中国');
select * from (select name from test union all select name from test) b where b.name='中国';

官方8.0.32有关union的修改
8.0.32 修改了union的 一些bug可能和这个有个
A condition pushdown into a UNION of queries having LIKE clauses did not preserve the correct character set, leading to an (erroneous) empty result.
We solve this problem in two parts:
By refactoring resolution of LIKE expressions, in which character set determination and propagation were previously performed in two separate blocks of the code that were not always consistent with one another.
By adding, in the internal parse_expression() function, a character set prefix to any literal character string that is cloned.
(Bug #107787, Bug #34359297, Bug #34589153)

感谢一位大神提供的临时解决方案
set optimizer_switch='derived_condition_pushdown=off';
yejr 2023-2-23 19:40:55
nyp30 发表于 2023-2-23 19:39
复现
CREATE TABLE `test` (
    `ID` varchar(64) NOT NULL COMMENT 'id',

赞,谢谢分享
baguai 2023-2-28 08:54:44
从函数Sql_cmd_select::prepare_inner开始,实际上这个语句包含2个query expression和3个query block,而下推的条件在外层的query block中为Item_func_like

p select                                                       外层的select语句的 query block
p select->slave->slave->m_table_list->first                    第一个内层select 语句的 第一个query block的第一个表
p select->slave->slave->m_table_list->first->next_local        第一个内层select 语句的 第一个query block的第二个表
p select->slave->slave->next->m_table_list->first              第二个内层select 语句的 第二个query block的第一个表
p select->slave->slave->next->m_table_list->first->next_local  第二个内层select 语句的 第二个query block的第二个表

第一个slave代表的是 内层的 query expression,而这个query expression包含2 query block,而每个query block 又是一个join 因此有个相关连的表
那么实际上like语句的item like 语法分析后还在外层的query block上,因此需要确认他是怎么处理的这部分的item如何处理的

当将外层的query block的Item_func_like下推的时候,Condition_pushdown::make_cond_for_derived函数中循环内层union这个expression的两个query block,进行
条件下推,下推的时候会clone一个Item_func_like出来,如下:

  Item *orig_cond_to_push = m_cond_to_push; //原始的 下推条件 也就是这里的 like
  for (Query_block *qb = derived_query_expression->first_query_block();
       qb != nullptr; qb = qb->next_query_block()) { //循环内层的 query block 将条件orig_cond_to_push下推
    // Make a copy that can be pushed to this query block
    if (derived_query_expression->is_set_operation()) {
      m_cond_to_push =
          derived_query_expression->outer_query_block()->clone_expression( //外层 query block 进行clone
              thd, orig_cond_to_push);
      if (m_cond_to_push == nullptr) return true;
      m_cond_to_push->apply_is_true();
    }

而clone的任务在parse_expression 函数中,其中包含一个StringBuffer<1024> str;,这个玩意默认是binary字符集的。
Condition_pushdown::make_cond_for_derived
  ->Query_block::clone_expression
    ->parse_expression   
   
已经提交BUG给官方。
nyp30

2

主题

0

博客

9

贡献

新手上路

Rank: 1

积分
14

合作电话:010-64087828

社区邮箱:greatsql@greatdb.com

社区公众号
社区小助手
QQ群
GMT+8, 2024-11-23 19:29 , Processed in 0.019865 second(s), 15 queries , Redis On.
快速回复 返回顶部 返回列表