diff --git a/pkg/planner/core/logical_plan_builder.go b/pkg/planner/core/logical_plan_builder.go index b3f58528f980e..fcc9922e79cb8 100644 --- a/pkg/planner/core/logical_plan_builder.go +++ b/pkg/planner/core/logical_plan_builder.go @@ -1150,6 +1150,52 @@ func (b *PlanBuilder) coalesceCommonColumns(p *LogicalJoin, leftPlan, rightPlan if err != nil { return err } + } else { + // Even with no using filter, we still should check the checkAmbiguous name before we try to find the common column from both side. + // (t3 cross join t4) natural join t1 + // t1 natural join (t3 cross join t4) + // t3 and t4 may generate the same name column from cross join. + // for every common column of natural join, the name from right or left should be exactly one. + commonNames := make([]string, 0, len(lNames)) + lNameMap := make(map[string]int, len(lNames)) + rNameMap := make(map[string]int, len(rNames)) + for _, name := range lNames { + // Natural join should ignore _tidb_rowid + if name.ColName.L == "_tidb_rowid" { + continue + } + // record left map + if cnt, ok := lNameMap[name.ColName.L]; ok { + lNameMap[name.ColName.L] = cnt + 1 + } else { + lNameMap[name.ColName.L] = 1 + } + } + for _, name := range rNames { + // Natural join should ignore _tidb_rowid + if name.ColName.L == "_tidb_rowid" { + continue + } + // record right map + if cnt, ok := rNameMap[name.ColName.L]; ok { + rNameMap[name.ColName.L] = cnt + 1 + } else { + rNameMap[name.ColName.L] = 1 + } + // check left map + if cnt, ok := lNameMap[name.ColName.L]; ok { + if cnt > 1 { + return plannererrors.ErrAmbiguous.GenWithStackByArgs(name.ColName.L, "from clause") + } + commonNames = append(commonNames, name.ColName.L) + } + } + // check right map + for _, commonName := range commonNames { + if rNameMap[commonName] > 1 { + return plannererrors.ErrAmbiguous.GenWithStackByArgs(commonName, "from clause") + } + } } // Find out all the common columns and put them ahead. diff --git a/tests/integrationtest/r/executor/jointest/join.result b/tests/integrationtest/r/executor/jointest/join.result index 0416b61c05ed0..431e45630ccd6 100644 --- a/tests/integrationtest/r/executor/jointest/join.result +++ b/tests/integrationtest/r/executor/jointest/join.result @@ -1590,3 +1590,16 @@ insert into t1 values(2,3),(4,4); select /*+ TIDB_HJ(t, t2) */ * from t, t1 where t.c1 = t1.c1; c1 c2 c1 c2 2 2 2 3 +drop table if exists t1,t2,t3,t4; +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +select * from t1 natural join (t3 cross join t4); +Error 1052 (23000): Column 'c' in from clause is ambiguous +select * from (t3 cross join t4) natural join t1; +Error 1052 (23000): Column 'c' in from clause is ambiguous +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +Error 1052 (23000): Column 'b' in from clause is ambiguous +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); +Error 1052 (23000): Column 'b' in from clause is ambiguous diff --git a/tests/integrationtest/t/executor/jointest/join.test b/tests/integrationtest/t/executor/jointest/join.test index 91cac6282d4da..0649a3fe2b9e8 100644 --- a/tests/integrationtest/t/executor/jointest/join.test +++ b/tests/integrationtest/t/executor/jointest/join.test @@ -1089,3 +1089,18 @@ create table t1(c1 int, c2 int); insert into t values(1,1),(2,2); insert into t1 values(2,3),(4,4); select /*+ TIDB_HJ(t, t2) */ * from t, t1 where t.c1 = t1.c1; + +# TestIssue30244 +drop table if exists t1,t2,t3,t4; +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +--error 1052 +select * from t1 natural join (t3 cross join t4); +--error 1052 +select * from (t3 cross join t4) natural join t1; +--error 1052 +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +--error 1052 +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b);