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

v3.5.4.1

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

BaseMultiTableInnerInterceptor 在执行 processPlainSelect(final PlainSelect plainSelect, final String whereSegment) 方法时逻辑有漏洞

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

看官方用例MultiDataPermissionInterceptorTest#test6

    sqlSegmentMap.put(TEST_6, "sys_user", "u.state=1 and u.amount > 1000");
        sqlSegmentMap.put(TEST_6, "sys_user_role", "r.role_id=3 AND r.role_id IN (7,9,11)");

@Test
    void test6() {
        // 显式指定 JOIN 类型时 JOIN 右侧表才能进行拼接条件
        assertSql(TEST_6, "select u.username from sys_user u LEFT join sys_user_role r on u.id=r.user_id",
            "SELECT u.username FROM sys_user u LEFT JOIN sys_user_role r ON u.id = r.user_id AND r.role_id = 3 AND r.role_id IN (7, 9, 11) WHERE u.state = 1 AND u.amount > 1000");
    }

因为left join 只拼接到了on条件下 会导致 主表还是有数据 只是 left join 不到数据 正确sql应该是

SELECT u.username FROM sys_user u LEFT JOIN sys_user_role r ON u.id = r.user_id AND r.role_id = 3 AND r.role_id IN (7, 9, 11) WHERE u.state = 1 AND u.amount > 1000 and r.role_id=3 AND r.role_id IN (7,9,11)

比如说

SELECT * FROM entity e 

left join entity1 e1 on e1.id = e.id 

WHERE e.id = ?

变成

SELECT * FROM entity e 

LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 

WHERE (e.id = ?) AND e1.tenant_id = 1

目前是变成

SELECT * FROM entity e 

LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 

WHERE (e.id = ?) 

原因是BaseMultiTableInnerInterceptor这段代码

   // 处理 join
        List<Join> joins = plainSelect.getJoins();
        if (CollectionUtils.isNotEmpty(joins)) {
            mainTables = processJoins(mainTables, joins, whereSegment);
        }

 // 当有 mainTable 时,进行 where 条件追加
        if (CollectionUtils.isNotEmpty(mainTables)) {
            plainSelect.setWhere(builderExpression(where, mainTables, whereSegment));
        }

改成

// 处理 join
        List<Join> joins = plainSelect.getJoins();
        if (CollectionUtils.isNotEmpty(joins)) {
            mainTables = processJoins(mainTables, joins, whereSegment);
            for (Join join : joins) {
                FromItem rightItem = join.getRightItem();
                if(rightItem instanceof Table){
                    mainTables.add((Table) rightItem);
                }
            }
        }
        // 当有 mainTable 时,进行 where 条件追加
        if (CollectionUtils.isNotEmpty(mainTables)) {
            plainSelect.setWhere(builderExpression(where, mainTables, whereSegment));
        }

就可以避免

Comment From: dandelion2

这个后期会修改吗?LEFT JOIN entity1 e1 ON e1.id = e.id AND e1.tenant_id = 1 这种写法在某些数据库大数据量的表下,如pg,性能影响还是有的。放到where里统一过滤条件反而更好