pingcap / tidb

TiDB is an open-source, cloud-native, distributed, MySQL-Compatible database for elastic scale and real-time analytics. Try AI-powered Chat2Query free at : https://www.pingcap.com/tidb-serverless/
https://pingcap.com
Apache License 2.0
36.66k stars 5.77k forks source link

outer join reorder will produce unexpected join sequence. #53387

Closed AilinKid closed 6 days ago

AilinKid commented 2 months ago

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

schema

CREATE TABLE Forp_User (
  id INT PRIMARY KEY,
  userName VARCHAR(255)
);

CREATE TABLE Forp_UserRole (
  FK_UserID INT,
  fk_roleId INT,
  FOREIGN KEY (FK_UserID) REFERENCES Forp_User(id),
  FOREIGN KEY (fk_roleId) REFERENCES forp_role(id)
);

CREATE TABLE forp_role (
  id INT PRIMARY KEY,
  NAME VARCHAR(255),
  CODE VARCHAR(255)
);

data

INSERT INTO `forp_role` VALUES
(1, '小天才俱乐部', 'Administrator role'), 
(2, 'User', 'User role');

INSERT INTO `Forp_User` VALUES
(41398, 'Alice'),
(41399, 'Bob'), 
(41400, 'Carol'),
(41401, 'Dave');

INSERT INTO `Forp_UserRole` VALUES
(198316, 41398, 1),
(198317, 41399, 2),
(198318, 41400, 2),
(198319, 41401, 2);

query

SELECT
    u.id,
    u.userName,
    a.fk_roleId ,
    b.`NAME`
FROM
    Forp_User u
    LEFT JOIN Forp_UserRole a ON a.FK_UserID = u.id
    LEFT JOIN forp_role b ON b.id = a.fk_roleId 
WHERE
    u.state = 1 
    AND   
b.`CODE` = 123456789

2. What did you expect to see? (Required)

empty result

3. What did you see instead (Required)

two rows

4. What is your TiDB version? (Required)

v7.1.3 & even master

AilinKid commented 2 months ago
tidb> select * from (select u.id, u.username, a.fk_roleid from forp_user u LEFT JOIN forp_userrole a ON a.FK_UserID = u.id where u.state=1) x left join forp_role b ON b.id = x.fk_roleId where b.`CODE` = 123456789;
+-------+----------+-----------+------+-------------+-----------+------+-------------+-----------+----------+------------+----------------+----------------+------------------+--------------------+--------+--------------+------+-----------+
| id    | username | fk_roleid | ID   | FK_DOMAINID | FK_USERID | NAME | DESCRIPTION | ROLELEVEL | ISINITED | CREATEDATE | CREATEUSERNAME | LASTMODIFYDATE | LASTMODIFYUSERID | LASTMODIFYUSERNAME | REMARK | FK_SOURCE_ID | CODE | IS_REMIND |
+-------+----------+-----------+------+-------------+-----------+------+-------------+-----------+----------+------------+----------------+----------------+------------------+--------------------+--------+--------------+------+-----------+
| 41398 | Alice    |      NULL | NULL |        NULL |      NULL | NULL | NULL        |      NULL | NULL     | NULL       | NULL           | NULL           |             NULL | NULL               | NULL   |         NULL | NULL | NULL      |
| 41399 | Bob      |      NULL | NULL |        NULL |      NULL | NULL | NULL        |      NULL | NULL     | NULL       | NULL           | NULL           |             NULL | NULL               | NULL   |         NULL | NULL | NULL      |
+-------+----------+-----------+------+-------------+-----------+------+-------------+-----------+----------+------------+----------------+----------------+------------------+--------------------+--------+--------------+------+-----------+
2 rows in set, 2 warnings (0.00 sec)

I change control the left join sequence manually, it should outputs the empty result as well.

AilinKid commented 2 months ago
AilinKid commented 2 months ago

image

seiya-annie commented 1 month ago

/found customer

AilinKid commented 6 days ago

implicitly fixed by https://github.com/pingcap/tidb/pull/52941, this is an enhancement refactoring, which will not be cherry-picked to earlier versions.

AilinKid commented 5 days ago

this one has been implictly fixed by https://github.com/pingcap/tidb/pull/52941, this pull request covers refactoring of the current outer join elimination framework, extracting them out predicate-pushdown as a logic rule, and enhancing more cases of it which is not capable in the old one.