coalesceCommonColumns is used by buildUsingClause and buildNaturalJoin. The filter is used by buildUsingClause.
(p *logicalop.LogicalJoin, leftPlan, rightPlan base.LogicalPlan, joinTp ast.JoinType, filter map[string]bool)
| 751 | |
| 752 | // coalesceCommonColumns is used by buildUsingClause and buildNaturalJoin. The filter is used by buildUsingClause. |
| 753 | func (b *PlanBuilder) coalesceCommonColumns(p *logicalop.LogicalJoin, leftPlan, rightPlan base.LogicalPlan, joinTp ast.JoinType, filter map[string]bool) error { |
| 754 | lsc := leftPlan.Schema().Clone() |
| 755 | rsc := rightPlan.Schema().Clone() |
| 756 | if joinTp == ast.LeftJoin { |
| 757 | util.ResetNotNullFlag(rsc, 0, rsc.Len()) |
| 758 | } else if joinTp == ast.RightJoin { |
| 759 | util.ResetNotNullFlag(lsc, 0, lsc.Len()) |
| 760 | } |
| 761 | lColumns, rColumns := lsc.Columns, rsc.Columns |
| 762 | lNames, rNames := leftPlan.OutputNames().Shallow(), rightPlan.OutputNames().Shallow() |
| 763 | if joinTp == ast.RightJoin { |
| 764 | leftPlan, rightPlan = rightPlan, leftPlan |
| 765 | lNames, rNames = rNames, lNames |
| 766 | lColumns, rColumns = rsc.Columns, lsc.Columns |
| 767 | } |
| 768 | |
| 769 | // Check using clause with ambiguous columns. |
| 770 | if filter != nil { |
| 771 | checkAmbiguous := func(names types.NameSlice) error { |
| 772 | columnNameInFilter := set.StringSet{} |
| 773 | for _, name := range names { |
| 774 | if _, ok := filter[name.ColName.L]; !ok { |
| 775 | continue |
| 776 | } |
| 777 | if columnNameInFilter.Exist(name.ColName.L) { |
| 778 | return plannererrors.ErrAmbiguous.GenWithStackByArgs(name.ColName.L, "from clause") |
| 779 | } |
| 780 | columnNameInFilter.Insert(name.ColName.L) |
| 781 | } |
| 782 | return nil |
| 783 | } |
| 784 | err := checkAmbiguous(lNames) |
| 785 | if err != nil { |
| 786 | return err |
| 787 | } |
| 788 | err = checkAmbiguous(rNames) |
| 789 | if err != nil { |
| 790 | return err |
| 791 | } |
| 792 | } else { |
| 793 | // Even with no using filter, we still should check the checkAmbiguous name before we try to find the common column from both side. |
| 794 | // (t3 cross join t4) natural join t1 |
| 795 | // t1 natural join (t3 cross join t4) |
| 796 | // t3 and t4 may generate the same name column from cross join. |
| 797 | // for every common column of natural join, the name from right or left should be exactly one. |
| 798 | commonNames := make([]string, 0, len(lNames)) |
| 799 | lNameMap := make(map[string]int, len(lNames)) |
| 800 | rNameMap := make(map[string]int, len(rNames)) |
| 801 | for i, name := range lNames { |
| 802 | // Natural join should ignore _tidb_rowid |
| 803 | if name.ColName.L == "_tidb_rowid" { |
| 804 | continue |
| 805 | } |
| 806 | if lColumns[i].IsHidden { |
| 807 | continue |
| 808 | } |
| 809 | // record left map |
| 810 | if cnt, ok := lNameMap[name.ColName.L]; ok { |
no test coverage detected