Repository: pingcap/tidb (Go)

Issue:
join get the incorrect result
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)
```sql

CREATE TABLE t0 (a int, b int, c int);
CREATE TABLE t1 (a int, b int, c int);
CREATE TABLE t2 (a int, b int, c int);
CREATE TABLE t3 (a int, b int, c int);
CREATE TABLE t4 (a int, b int, c int);
CREATE TABLE t5 (a int, b int, c int);
CREATE TABLE t6 (a int, b int, c int);
CREATE TABLE t7 (a int, b int, c int);
CREATE TABLE t8 (a int, b int, c int);
CREATE TABLE t9 (a int, b int, c int);

INSERT INTO t0 VALUES (1,1,0), (1,2,0), (2,2,0);
INSERT INTO t1 VALUES (1,3,0), (2,2,0), (3,2,0);
INSERT INTO t2 VALUES (3,3,0), (4,2,0), (5,3,0);
INSERT INTO t3 VALUES (1,2,0), (2,2,0);
INSERT INTO t4 VALUES (3,2,0), (4,2,0);
INSERT INTO t5 VALUES (3,1,0), (2,2,0), (3,3,0);
INSERT INTO t6 VALUES (3,2,0), (6,2,0), (6,1,0);
INSERT INTO t7 VALUES (1,1,0), (2,2,0);
INSERT INTO t8 VALUES (0,2,0), (1,2,0);
INSERT INTO t9 VALUES (1,1,0), (1,2,0), (3,3,0);

SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
  FROM (t3,t4)
       LEFT JOIN
       (t1,t2)
       ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;

explain SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
  FROM (t3,t4)
       LEFT JOIN
       (t1,t2)
       ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
```
<!-- a step by step guide for reproducing the bug. -->

### 2. What did you expect to see? (Required)
```sql
MySQL root@127.0.0.1:test>  SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
                       ->    FROM (t3,t4)
                       ->         LEFT JOIN
                       ->         (t1,t2)
                       ->         ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
+--------+--------+---+---+---+---+
| a      | b      | a | b | a | b |
+--------+--------+---+---+---+---+
| <null> | <null> | 2 | 2 | 3 | 2 |
| <null> | <null> | 2 | 2 | 4 | 2 |
| 4      | 2      | 1 | 2 | 3 | 2 |
| 4      | 2      | 1 | 2 | 3 | 2 |
| 4      | 2      | 1 | 2 | 3 | 2 |
| 4      | 2      | 1 | 2 | 4 | 2 |
| 4      | 2      | 1 | 2 | 4 | 2 |
| 4      | 2      | 1 | 2 | 4 | 2 |
+--------+--------+---+---+---+---+
MySQL root@127.0.0.1:test>  explain SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
                       ->    FROM (t3,t4)
                       ->         LEFT JOIN
                       ->         (t1,t2)
                       ->         ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
+-------------------------------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------+
| id                            | estRows | task      | access object | operator info                                                                                            |
+-------------------------------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------+
| Sort_13                       | 15.00   | root      |               | test.t2.a, test.t2.b, test.t3.a, test.t3.b, test.t4.a                                                    |
| └─Projection_15               | 15.00   | root      |               | test.t2.a, test.t2.b, test.t3.a, test.t3.b, test.t4.a, test.t4.b                                         |
|   └─HashJoin_17               | 15.00   | root      |               | left outer join, equal:[eq(test.t3.b, test.t2.b) eq(test.t4.b, test.t2.b)], left cond:[eq(test.t3.a, 1)] |
|     ├─HashJoin_18(Build)      | 4.00    | root      |               | CARTESIAN inner join                                                                                     |
|     │ ├─TableReader_23(Build) | 2.00    | root      |               | data:TableFullScan_22                                                                                    |
|     │ │ └─TableFullScan_22    | 2.00    | cop[tikv] | table:t4      | keep order:false, stats:pseudo                                                                           |
|     │ └─TableReader_21(Probe) | 2.00    | root      |               | data:TableFullScan_20                                                                                    |
|     │   └─TableFullScan_20    | 2.00    | cop[tikv] | table:t3      | keep order:false, stats:pseudo                                                                           |
|     └─HashJoin_26(Probe)      | 8.99    | root      |               | CARTESIAN inner join                                                                                     |
|       ├─TableReader_29(Build) | 3.00    | root      |               | data:Selection_28                                                                                        |
|       │ └─Selection_28        | 3.00    | cop[tikv] |               | not(isnull(test.t2.b))                                                                                   |
|       │   └─TableFullScan_27  | 3.00    | cop[tikv] | table:t2      | keep order:false, stats:pseudo                                                                           |
|       └─TableReader_31(Probe) | 3.00    | root      |               | data:TableFullScan_30                                                                                    |
|         └─TableFullScan_30    | 3.00    | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                                                           |
+-------------------------------+---------+-----------+---------------+----------------------------------------------------------------------------------------------------------+


```

### 3. What did you see instead (Required)
```sql
MySQL root@127.0.0.1:test>  SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
                       ->    FROM (t3,t4)
                       ->         LEFT JOIN
                       ->         (t1,t2)
                       ->         ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
+---+---+---+---+---+---+
| a | b | a | b | a | b |
+---+---+---+---+---+---+
| 4 | 2 | 1 | 2 | 3 | 2 |
| 4 | 2 | 1 | 2 | 3 | 2 |
| 4 | 2 | 1 | 2 | 3 | 2 |
| 4 | 2 | 1 | 2 | 4 | 2 |
| 4 | 2 | 1 | 2 | 4 | 2 |
| 4 | 2 | 1 | 2 | 4 | 2 |
+---+---+---+---+---+---+

MySQL root@127.0.0.1:test>  explain SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b
                       ->    FROM (t3,t4)
                       ->         LEFT JOIN
                       ->         (t1,t2)
                       ->         ON t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;
+-----------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------+
| id                                | estRows | task      | access object | operator info                                                                   |
+-----------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------+
| Sort_15                           | 6.26    | root      |               | test.t2.a, test.t2.b, test.t3.a, test.t3.b, test.t4.a                           |
| └─Projection_17                   | 6.26    | root      |               | test.t2.a, test.t2.b, test.t3.a, test.t3.b, test.t4.a, test.t4.b                |
|   └─Projection_18                 | 6.26    | root      |               | test.t3.a, test.t3.b, test.t4.a, test.t4.b, test.t2.a, test.t2.b                |
|     └─HashJoin_20                 | 6.26    | root      |               | left outer join, equal:[eq(test.t4.b, test.t2.b)]                               |
|       ├─TableReader_22(Build)     | 2.00    | root      |               | data:TableFullScan_21                                                           |
|       │ └─TableFullScan_21        | 2.00    | cop[tikv] | table:t4      | keep order:false, stats:pseudo                                                  |
|       └─HashJoin_24(Probe)        | 7.50    | root      |               | left outer join, equal:[eq(test.t3.b, test.t2.b)], left cond:[eq(test.t3.a, 1)] |
|         ├─TableReader_26(Build)   | 2.00    | root      |               | data:TableFullScan_25                                                           |
|         │ └─TableFullScan_25      | 2.00    | cop[tikv] | table:t3      | keep order:false, stats:pseudo                                                  |
|         └─HashJoin_29(Probe)      | 8.99    | root      |               | CARTESIAN inner join                                                            |
|           ├─TableReader_32(Build) | 3.00    | root      |               | data:Selection_31                                                               |
|           │ └─Selection_31        | 3.00    | cop[tikv] |               | not(isnull(test.t2.b))                                                          |
|           │   └─TableFullScan_30  | 3.00    | cop[tikv] | table:t2      | keep order:false, stats:pseudo                                                  |
|           └─TableReader_34(Probe) | 3.00    | root      |               | data:TableFullScan_33                                                           |
|             └─TableFullScan_33    | 3.00    | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                                  |
+-----------------------------------+---------+-----------+---------------+---------------------------------------------------------------------------------+

```
### 4. What is your TiDB version? (Required)
```sql
MySQL root@127.0.0.1:test> select tidb_version()\G
***************************[ 1. row ]***************************
tidb_version() | Release Version: v6.1.0-alpha-390-g98c31070d
Edition: Community
Git Commit Hash: 98c31070d95858ecf5f9ffb9d5e0dab3aca13d9c
Git Branch: master
UTC Build Time: 2022-05-12 01:58:56
GoVersion: go1.18
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
```
<!-- Paste the output of SELECT tidb_version() -->


join's inner condition should be empty:  Failed to build executor
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)
```sql
drop table if exists t1,t2,t3;
create table t1 (a1 int, a2 int);
create table t2 (b1 int not null, b2 int);
create table t3 (c1 int, c2 int);

insert into t1 values (1,2), (2,2), (3,2);
insert into t2 values (1,3), (2,3);
insert into t3 values (2,4),        (3,4);

select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null;
```
<!-- a step by step guide for reproducing the bug. -->

### 2. What did you expect to see? (Required)
```sql
MySQL root@127.0.0.1:test> explain select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null;
                       ->  select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null;
Reconnecting...
+---------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+
| id                        | estRows | task      | access object | operator info                                                                       |
+---------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+
| HashJoin_8                | 3.00    | root      |               | left outer join, equal:[eq(test.t1.a1, test.t3.c1)], left cond:[isnull(test.t2.b1)] |
| ├─TableReader_18(Build)   | 2.00    | root      |               | data:Selection_17                                                                   |
| │ └─Selection_17          | 2.00    | cop[tikv] |               | not(isnull(test.t3.c1))                                                             |
| │   └─TableFullScan_16    | 2.00    | cop[tikv] | table:t3      | keep order:false, stats:pseudo                                                      |
| └─HashJoin_10(Probe)      | 3.00    | root      |               | left outer join, equal:[eq(test.t1.a1, test.t2.b1)]                                 |
|   ├─TableReader_15(Build) | 2.00    | root      |               | data:TableFullScan_14                                                               |
|   │ └─TableFullScan_14    | 2.00    | cop[tikv] | table:t2      | keep order:false, stats:pseudo                                                      |
|   └─TableReader_13(Probe) | 3.00    | root      |               | data:TableFullScan_12                                                               |
|     └─TableFullScan_12    | 3.00    | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                                      |
+---------------------------+---------+-----------+---------------+-------------------------------------------------------------------------------------+

9 rows in set
Time: 0.014s

+----+----+--------+--------+--------+--------+
| a1 | a2 | b1     | b2     | c1     | c2     |
+----+----+--------+--------+--------+--------+
| 1  | 2  | 1      | 3      | <null> | <null> |
| 2  | 2  | 2      | 3      | <null> | <null> |
| 3  | 2  | <null> | <null> | 3      | 4      |
+----+----+--------+--------+--------+--------+
```
### 3. What did you see instead (Required)
```sql
MySQL root@127.0.0.1:test> explain select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null;
                       ->  select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null;
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------+
| id                          | estRows | task      | access object | operator info                                                                      |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------+
| Projection_11               | 3.00    | root      |               | test.t1.a1, test.t1.a2, test.t2.b1, test.t2.b2, test.t3.c1, test.t3.c2             |
| └─HashJoin_12               | 3.00    | root      |               | left outer join, equal:[eq(test.t1.a1, test.t2.b1)], right cond:isnull(test.t2.b1) |
|   ├─TableReader_22(Build)   | 2.00    | root      |               | data:TableFullScan_21                                                              |
|   │ └─TableFullScan_21      | 2.00    | cop[tikv] | table:t2      | keep order:false, stats:pseudo                                                     |
|   └─HashJoin_14(Probe)      | 3.00    | root      |               | left outer join, equal:[eq(test.t1.a1, test.t3.c1)]                                |
|     ├─TableReader_20(Build) | 2.00    | root      |               | data:Selection_19                                                                  |
|     │ └─Selection_19        | 2.00    | cop[tikv] |               | not(isnull(test.t3.c1))                                                            |
|     │   └─TableFullScan_18  | 2.00    | cop[tikv] | table:t3      | keep order:false, stats:pseudo                                                     |
|     └─TableReader_17(Probe) | 3.00    | root      |               | data:TableFullScan_16                                                              |
|       └─TableFullScan_16    | 3.00    | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                                     |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------+

10 rows in set
Time: 0.011s
(8118, 'Failed to build executor')
```
tidb.log
```log
[2022/05/12 11:01:57.253 +08:00] [WARN] [session.go:1938] ["run statement failed"] [conn=403] [schemaVersion=140] [error="join's inner condition should be empty: [executor:8118]Failed to build executor"] [session="{\n  \"currDBName\": \"test\",\n  \"id\": 403,\n  \"status\": 2,\n  \"strictMode\": true,\n  \"user\": {\n    \"Username\": \"root\",\n    \"Hostname\": \"127.0.0.1\",\n    \"CurrentUser\": false,\n    \"AuthUsername\": \"root\",\n    \"AuthHostname\": \"%\"\n  }\n}"]
[2022/05/12 11:01:57.254 +08:00] [INFO] [conn.go:1144] ["command dispatched failed"] [conn=403] [connInfo="id:403, addr:127.0.0.1:50122 status:10, collation:utf8_general_ci, user:root"] [command=Query] [status="inTxn:0, autocommit:1"] [sql="select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null"] [txn_mode=OPTIMISTIC] [timestamp=433146958250508288] [err="[executor:8118]Failed to build executor\njoin's inner condition should be empty\ngithub.com/pingcap/tidb/executor.(*executorBuilder).buildHashJoin\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/builder.go:1321\ngithub.com/pingcap/tidb/executor.(*executorBuilder).build\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/builder.go:258\ngithub.com/pingcap/tidb/executor.(*executorBuilder).buildProjection\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/builder.go:1525\ngithub.com/pingcap/tidb/executor.(*executorBuilder).build\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/builder.go:274\ngithub.com/pingcap/tidb/executor.(*ExecStmt).buildExecutor\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/adapter.go:881\ngithub.com/pingcap/tidb/executor.(*ExecStmt).Exec\n\t/Users/aytrack/gitproject/pingcap/tidb/executor/adapter.go:413\ngithub.com/pingcap/tidb/session.runStmt\n\t/Users/aytrack/gitproject/pingcap/tidb/session/session.go:2059\ngithub.com/pingcap/tidb/session.(*session).ExecuteStmt\n\t/Users/aytrack/gitproject/pingcap/tidb/session/session.go:1935\ngithub.com/pingcap/tidb/server.(*TiDBContext).ExecuteStmt\n\t/Users/aytrack/gitproject/pingcap/tidb/server/driver_tidb.go:230\ngithub.com/pingcap/tidb/server.(*clientConn).handleStmt\n\t/Users/aytrack/gitproject/pingcap/tidb/server/conn.go:2013\ngithub.com/pingcap/tidb/server.(*clientConn).handleQuery\n\t/Users/aytrack/gitproject/pingcap/tidb/server/conn.go:1871\ngithub.com/pingcap/tidb/server.(*clientConn).dispatch\n\t/Users/aytrack/gitproject/pingcap/tidb/server/conn.go:1366\ngithub.com/pingcap/tidb/server.(*clientConn).Run\n\t/Users/aytrack/gitproject/pingcap/tidb/server/conn.go:1116\ngithub.com/pingcap/tidb/server.(*Server).onConn\n\t/Users/aytrack/gitproject/pingcap/tidb/server/server.go:556\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1571"]
```
### 4. What is your TiDB version? (Required)
```sql
MySQL root@127.0.0.1:test> select tidb_version()\G
***************************[ 1. row ]***************************
tidb_version() | Release Version: v6.1.0-alpha-390-g98c31070d
Edition: Community
Git Commit Hash: 98c31070d95858ecf5f9ffb9d5e0dab3aca13d9c
Git Branch: master
UTC Build Time: 2022-05-12 01:58:56
GoVersion: go1.18
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
```
<!-- Paste the output of SELECT tidb_version() -->




Discussion:
/assign @winoros 





Patch:
diff --git a/planner/core/rule_join_reorder.go b/planner/core/rule_join_reorder.go
index b08bd76bb7fd0..605ab38daf42b 100644
--- a/planner/core/rule_join_reorder.go
+++ b/planner/core/rule_join_reorder.go
@@ -43,6 +43,30 @@ func extractJoinGroup(p LogicalPlan) (group []LogicalPlan, eqEdges []*expression
 	}
 	if join.JoinType != RightOuterJoin {
 		lhsGroup, lhsEqualConds, lhsOtherConds, lhsJoinTypes := extractJoinGroup(join.children[0])
+		noExpand := false
+		// If the filters of the outer join is related with multiple leaves of the outer join side. We don't reorder it for now.
+		if join.JoinType == LeftOuterJoin {
+			extractedCols := make([]*expression.Column, 0, 8)
+			extractedCols = expression.ExtractColumnsFromExpressions(extractedCols, join.OtherConditions, nil)
+			extractedCols = expression.ExtractColumnsFromExpressions(extractedCols, join.LeftConditions, nil)
+			extractedCols = expression.ExtractColumnsFromExpressions(extractedCols, expression.ScalarFuncs2Exprs(join.EqualConditions), nil)
+			affectedGroups := 0
+			for i := range lhsGroup {
+				for _, col := range extractedCols {
+					if lhsGroup[i].Schema().Contains(col) {
+						affectedGroups++
+						break
+					}
+				}
+				if affectedGroups > 1 {
+					noExpand = true
+					break
+				}
+			}
+		}
+		if noExpand {
+			return []LogicalPlan{p}, nil, nil, nil
+		}
 		group = append(group, lhsGroup...)
 		eqEdges = append(eqEdges, lhsEqualConds...)
 		otherConds = append(otherConds, lhsOtherConds...)
@@ -53,6 +77,30 @@ func extractJoinGroup(p LogicalPlan) (group []LogicalPlan, eqEdges []*expression
 
 	if join.JoinType != LeftOuterJoin {
 		rhsGroup, rhsEqualConds, rhsOtherConds, rhsJoinTypes := extractJoinGroup(join.children[1])
+		noExpand := false
+		// If the filters of the outer join is related with multiple leaves of the outer join side. We don't reorder it for now.
+		if join.JoinType == RightOuterJoin {
+			extractedCols := make([]*expression.Column, 0, 8)
+			expression.ExtractColumnsFromExpressions(extractedCols, join.OtherConditions, nil)
+			expression.ExtractColumnsFromExpressions(extractedCols, join.RightConditions, nil)
+			expression.ExtractColumnsFromExpressions(extractedCols, expression.ScalarFuncs2Exprs(join.EqualConditions), nil)
+			affectedGroups := 0
+			for i := range rhsGroup {
+				for _, col := range extractedCols {
+					if rhsGroup[i].Schema().Contains(col) {
+						affectedGroups++
+						break
+					}
+				}
+				if affectedGroups > 1 {
+					noExpand = true
+					break
+				}
+			}
+		}
+		if noExpand {
+			return []LogicalPlan{p}, nil, nil, nil
+		}
 		group = append(group, rhsGroup...)
 		eqEdges = append(eqEdges, rhsEqualConds...)
 		otherConds = append(otherConds, rhsOtherConds...)


Test patch:
diff --git a/executor/join_test.go b/executor/join_test.go
index 81c2f52596094..672bd63bc72e2 100644
--- a/executor/join_test.go
+++ b/executor/join_test.go
@@ -2834,3 +2834,46 @@ func TestIssue31129(t *testing.T) {
 	require.NoError(t, failpoint.Disable(fpName1))
 	require.NoError(t, failpoint.Disable(fpName2))
 }
+
+func TestOuterJoin(t *testing.T) {
+	store, clean := testkit.CreateMockStore(t)
+	defer clean()
+	tk := testkit.NewTestKit(t, store)
+	tk.MustExec("use test")
+	tk.MustExec("drop table if exists t1, t2, t3, t4")
+	tk.MustExec("create table t1(a int, b int, c int)")
+	tk.MustExec("create table t2(a int, b int, c int)")
+	tk.MustExec("create table t3(a int, b int, c int)")
+	tk.MustExec("create table t4(a int, b int, c int)")
+	tk.MustExec("INSERT INTO t1 VALUES (1,3,0), (2,2,0), (3,2,0);")
+	tk.MustExec("INSERT INTO t2 VALUES (3,3,0), (4,2,0), (5,3,0);")
+	tk.MustExec("INSERT INTO t3 VALUES (1,2,0), (2,2,0);")
+	tk.MustExec("INSERT INTO t4 VALUES (3,2,0), (4,2,0);")
+	tk.MustQuery("SELECT t2.a,t2.b,t3.a,t3.b,t4.a,t4.b from (t3, t4) left join (t1, t2) on t3.a=1 AND t3.b=t2.b AND t2.b=t4.b order by 1, 2, 3, 4, 5;").Check(
+		testkit.Rows(
+			"<nil> <nil> 2 2 3 2",
+			"<nil> <nil> 2 2 4 2",
+			"4 2 1 2 3 2",
+			"4 2 1 2 3 2",
+			"4 2 1 2 3 2",
+			"4 2 1 2 4 2",
+			"4 2 1 2 4 2",
+			"4 2 1 2 4 2",
+		),
+	)
+
+	tk.MustExec("drop table if exists t1, t2, t3")
+	tk.MustExec("create table t1 (a1 int, a2 int);")
+	tk.MustExec("create table t2 (b1 int not null, b2 int);")
+	tk.MustExec("create table t3 (c1 int, c2 int);")
+	tk.MustExec("insert into t1 values (1,2), (2,2), (3,2);")
+	tk.MustExec("insert into t2 values (1,3), (2,3);")
+	tk.MustExec("insert into t3 values (2,4),        (3,4);")
+	tk.MustQuery("select * from t1 left join t2  on  b1 = a1 left join t3  on  c1 = a1  and  b1 is null order by 1, 2, 3, 4, 5, 6").Check(
+		testkit.Rows(
+			"1 2 1 3 <nil> <nil>",
+			"2 2 2 3 <nil> <nil>",
+			"3 2 <nil> <nil> 3 4",
+		),
+	)
+}