From a8711d9cf9baed19c68e66467a4a5935918830ff Mon Sep 17 00:00:00 2001 From: Arenatlx <314806019@qq.com> Date: Fri, 25 Mar 2022 11:32:34 +0800 Subject: [PATCH] cherry pick #33311 to release-6.0 Signed-off-by: ti-srebot --- parser/ast/dml.go | 4 +++- parser/ast/dml_test.go | 6 +++--- planner/core/integration_test.go | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/parser/ast/dml.go b/parser/ast/dml.go index 5a8041fb3e939..1da250553bac0 100644 --- a/parser/ast/dml.go +++ b/parser/ast/dml.go @@ -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} } diff --git a/parser/ast/dml_test.go b/parser/ast/dml_test.go index f569543f701ea..f7bfd78e25901 100644 --- a/parser/ast/dml_test.go +++ b/parser/ast/dml_test.go @@ -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 diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index f66e3bf5a0817..48bd7fb3f9c03 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -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()