当前使用版本(必填,否则不予处理)

mybatis-plus-extension-3.5.3.1.jar

该问题是如何引起的?(确定最新版也有问题再提!!!)

在自定义插件拦截器 拼写SQL时,交给分页插件时分页插件优化了LEFT(根据优化条件:条件中包含了 LEFT JOIN 表 的别名 不进行移除,而我的SQL条件中是存在的)

SELECT
    su.`user_id`,
    su.`dept_id`,
    su.`username`,
    su.`nick_name`,
    su.`user_type`,
    su.`email`,
    su.`phonenumber`,
    su.`sex`,
    su.`avatar`,
    su.`status`,
    su.`del_flag`,
    su.`login_ip`,
    su.`login_date`,
    su.`create_by`,
    su.`create_time`,
    su.`update_by`,
    su.`update_time`,
    su.`remark`,
    sd.dept_name 
FROM
    sys_user su
    LEFT JOIN sys_dept sd ON su.dept_id = sd.dept_id 
WHERE
    su.del_flag = '0' 
    AND (
        `sd`.dept_id = 105 
        OR `su`.dept_id IN (
        SELECT
            dept_id 
        FROM
            `sys_role_dept` 
        WHERE
        FIND_IN_SET( role_id, '2,100' ))) 
ORDER BY
    su.`create_time`

优化后:

SELECT
    COUNT(*) AS total 
FROM
    sys_user su 
WHERE
    su.del_flag = '0' 
    AND (
        `sd`.dept_id = 105 
        OR `su`.dept_id IN (
        SELECT
            dept_id 
        FROM
            `sys_role_dept` 
    WHERE
    FIND_IN_SET( role_id, '2,100' )))

DEUBG后发现此段代码:

if (rightItem instanceof Table) {
    Table table = (Table) rightItem;
    str = Optional.ofNullable(table.getAlias()).map(Alias::getName).orElse(table.getName()) + StringPool.DOT;
} else if (rightItem instanceof SubSelect) {
    SubSelect subSelect = (SubSelect) rightItem;
    /* 如果 left join 是子查询,并且子查询里包含 ?(代表有入参) 或者 where 条件里包含使用 join 的表的字段作条件,就不移除 join */
    if (subSelect.toString().contains(StringPool.QUESTION_MARK)) {
        canRemoveJoin = false;
        break;
    }
    str = subSelect.getAlias().getName() + StringPool.DOT;
}
// 不区分大小写
str = str.toLowerCase();

if (whereS.contains(str)) {
    /* 如果 where 条件里包含使用 join 的表的字段作条件,就不移除 join */
    canRemoveJoin = false;
    break;
}

str = subSelect.getAlias().getName() + StringPool.DOT; 只是alias + . 而少了 MYSQL 转义字符 `

重现步骤(如果有就写完整)

报错信息

Comment From: miemieYaho

去掉转义字符

Comment From: timnick-snow

是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符

Comment From: miemieYaho

为了你目前这种极端情况添加判断也没必要

Comment From: code-brandon

是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符

我觉得也是,我是用转义字符 是为了避免别名与关键字冲突,也是为了兼容一下框架的CRUD,框架的CRUD似乎没有加入别名,出于此考虑才选择拼接SQL时使用转义字符包裹

Comment From: javaofferss

干脆自己重新写一个. 或者fork自己改改.

是否具有转义字符的两个sql是等价的,mp应该对这两种情况都做好兼容和支持。个人觉得,不应该强制用户不加转义字符

Comment From: missfine

为了你目前这种极端情况添加判断也没必要

这边也遇到了这段代码引发的问题,走的是第一个if分支。

select * from a left join `b` on a.x = b.x where b.y = xxx
if (rightItem instanceof Table) {
    Table table = (Table) rightItem;
    str = Optional.ofNullable(table.getAlias()).map(Alias::getName).orElse(table.getName()) + StringPool.DOT;
} 

虽然修改sql就能规避这个问题,但是给框架使用带来了极大的影响,不清楚的人都需要跟着debug一遍源码才知道问题所在

建议在判断条件是否覆盖left join右侧的表时,把可能的`字符去除掉