Skip to content

Commit

Permalink
planner: fix name ambiguous check when building natural join without …
Browse files Browse the repository at this point in the history
…filter (#36012)

close #32044
  • Loading branch information
AilinKid authored Jan 29, 2024
1 parent 729a711 commit 41f56d1
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
46 changes: 46 additions & 0 deletions pkg/planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
13 changes: 13 additions & 0 deletions tests/integrationtest/r/executor/jointest/join.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
15 changes: 15 additions & 0 deletions tests/integrationtest/t/executor/jointest/join.test
Original file line number Diff line number Diff line change
Expand Up @@ -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);

0 comments on commit 41f56d1

Please sign in to comment.