Skip to content

Commit

Permalink
planner: fix the join scope with explicit parents (#33311)
Browse files Browse the repository at this point in the history
close #31770
  • Loading branch information
AilinKid authored Mar 25, 2022
1 parent ca0ade0 commit 59fac2a
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
4 changes: 3 additions & 1 deletion parser/ast/dml.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ func (*Join) resultSet() {}
// We get (t1 join t3) left join t2, the semantics is correct.
func NewCrossJoin(left, right ResultSetNode) (n *Join) {
rj, ok := right.(*Join)
if !ok || rj.Right == nil {
// don't break the explicit parents name scope constraints.
// this kind of join re-order can be done in logical-phase after the name resolution.
if !ok || rj.Right == nil || rj.ExplicitParens {
return &Join{Left: left, Right: right, Tp: CrossJoin}
}

Expand Down
6 changes: 3 additions & 3 deletions parser/ast/dml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ func TestJoinRestore(t *testing.T) {
//{"(select a from t) t1 join t t2, t3;", "((SELECT `a` FROM `t`) AS `t1` JOIN `t` AS `t2`) JOIN `t3`"},
}
testChangedCases := []NodeRestoreTestCase{
{"(a al left join b bl on al.a1 > bl.b1) join (a ar right join b br on ar.a1 > br.b1)", "((`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN `b` AS `br`) LEFT JOIN `a` AS `ar` ON `ar`.`a1`>`br`.`b1`"},
{"(a al left join b bl on al.a1 > bl.b1) join (a ar right join b br on ar.a1 > br.b1)", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"},
{"a al left join b bl on al.a1 > bl.b1, a ar right join b br on ar.a1 > br.b1", "(`a` AS `al` LEFT JOIN `b` AS `bl` ON `al`.`a1`>`bl`.`b1`) JOIN (`a` AS `ar` RIGHT JOIN `b` AS `br` ON `ar`.`a1`>`br`.`b1`)"},
{"t1 join (t2 right join t3 on t2.a > t3.a join (t4 right join t5 on t4.a > t5.a))", "(((`t1` JOIN `t2`) RIGHT JOIN `t3` ON `t2`.`a`>`t3`.`a`) JOIN `t5`) LEFT JOIN `t4` ON `t4`.`a`>`t5`.`a`"},
{"t1 join (t2 right join t3 on t2.a > t3.a join (t4 right join t5 on t4.a > t5.a))", "`t1` JOIN ((`t2` RIGHT JOIN `t3` ON `t2`.`a`>`t3`.`a`) JOIN (`t4` RIGHT JOIN `t5` ON `t4`.`a`>`t5`.`a`))"},
{"t1 join t2 right join t3 on t2.a=t3.a", "(`t1` JOIN `t2`) RIGHT JOIN `t3` ON `t2`.`a`=`t3`.`a`"},
{"t1 join (t2 right join t3 on t2.a=t3.a)", "(`t1` JOIN `t3`) LEFT JOIN `t2` ON `t2`.`a`=`t3`.`a`"},
{"t1 join (t2 right join t3 on t2.a=t3.a)", "`t1` JOIN (`t2` RIGHT JOIN `t3` ON `t2`.`a`=`t3`.`a`)"},
}
extractNodeFunc := func(node Node) Node {
return node.(*SelectStmt).From.TableRefs
Expand Down
15 changes: 15 additions & 0 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ func TestShowSubquery(t *testing.T) {
))
}

func TestJoinOperatorRightAssociative(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 t")
tk.MustExec("create table t(a int, b int)")
tk.MustExec("insert into t values(1,10),(2,20)")
// make sure this join won't rewrite as left-associative join like (t0 join t1) join t2 when explicit parent existed.
// mysql will detect the t0.a is out of it's join parent scope and errors like ERROR 1054 (42S22): Unknown column 't0.a' in 'on clause'
err := tk.ExecToErr("select t1.* from t t0 cross join (t t1 join t t2 on 100=t0.a);")
require.Error(t, err)
require.EqualError(t, err, "[planner:1054]Unknown column 't0.a' in 'on clause'")
}

func TestPpdWithSetVar(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
Expand Down

0 comments on commit 59fac2a

Please sign in to comment.