HashSemiJoin is only used in Apply, it exists only because NestedLoopJoin doesn't support SemiJoin type. This PR support SemiJoin type in NestedLoopJoin executor, so HashSemiJoin can be removed.
216 lines
6.1 KiB
Go
216 lines
6.1 KiB
Go
// Copyright 2015 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package plan
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ToString explains a Plan, returns description string.
|
|
func ToString(p Plan) string {
|
|
strs, _ := toString(p, []string{}, []int{})
|
|
return strings.Join(strs, "->")
|
|
}
|
|
|
|
func toString(in Plan, strs []string, idxs []int) ([]string, []int) {
|
|
if len(in.Children()) > 1 {
|
|
idxs = append(idxs, len(strs))
|
|
}
|
|
|
|
for _, c := range in.Children() {
|
|
strs, idxs = toString(c, strs, idxs)
|
|
}
|
|
|
|
var str string
|
|
switch x := in.(type) {
|
|
case *CheckTable:
|
|
str = "CheckTable"
|
|
case *PhysicalIndexScan:
|
|
str = fmt.Sprintf("Index(%s.%s)%v", x.Table.Name.L, x.Index.Name.L, x.Ranges)
|
|
case *PhysicalTableScan:
|
|
str = fmt.Sprintf("Table(%s)", x.Table.Name.L)
|
|
case *PhysicalHashJoin:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
idxs = idxs[:last]
|
|
if x.SmallChildIdx == 0 {
|
|
str = "RightHashJoin{" + strings.Join(children, "->") + "}"
|
|
} else {
|
|
str = "LeftHashJoin{" + strings.Join(children, "->") + "}"
|
|
}
|
|
for _, eq := range x.EqualConditions {
|
|
l := eq.GetArgs()[0].String()
|
|
r := eq.GetArgs()[1].String()
|
|
str += fmt.Sprintf("(%s,%s)", l, r)
|
|
}
|
|
case *PhysicalMergeJoin:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
idxs = idxs[:last]
|
|
id := "MergeJoin"
|
|
switch x.JoinType {
|
|
case SemiJoin:
|
|
id = "MergeSemiJoin"
|
|
case AntiSemiJoin:
|
|
id = "MergeAntiSemiJoin"
|
|
case LeftOuterSemiJoin:
|
|
id = "MergeLeftOuterSemiJoin"
|
|
case AntiLeftOuterSemiJoin:
|
|
id = "MergeAntiLeftOuterSemiJoin"
|
|
case LeftOuterJoin:
|
|
id = "MergeLeftOuterJoin"
|
|
case RightOuterJoin:
|
|
id = "MergeRightOuterJoin"
|
|
case InnerJoin:
|
|
id = "MergeInnerJoin"
|
|
}
|
|
str = id + "{" + strings.Join(children, "->") + "}"
|
|
for _, eq := range x.EqualConditions {
|
|
l := eq.GetArgs()[0].String()
|
|
r := eq.GetArgs()[1].String()
|
|
str += fmt.Sprintf("(%s,%s)", l, r)
|
|
}
|
|
case *LogicalApply, *PhysicalApply:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
idxs = idxs[:last]
|
|
str = "Apply{" + strings.Join(children, "->") + "}"
|
|
case *LogicalExists, *PhysicalExists:
|
|
str = "Exists"
|
|
case *LogicalMaxOneRow, *PhysicalMaxOneRow:
|
|
str = "MaxOneRow"
|
|
case *LogicalLimit, *PhysicalLimit:
|
|
str = "Limit"
|
|
case *PhysicalLock, *LogicalLock:
|
|
str = "Lock"
|
|
case *ShowDDL:
|
|
str = "ShowDDL"
|
|
case *Show:
|
|
if len(x.Conditions) == 0 {
|
|
str = "Show"
|
|
} else {
|
|
str = fmt.Sprintf("Show(%s)", x.Conditions)
|
|
}
|
|
case *LogicalSort, *PhysicalSort:
|
|
str = "Sort"
|
|
case *LogicalJoin:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
str = "Join{" + strings.Join(children, "->") + "}"
|
|
idxs = idxs[:last]
|
|
for _, eq := range x.EqualConditions {
|
|
l := eq.GetArgs()[0].String()
|
|
r := eq.GetArgs()[1].String()
|
|
str += fmt.Sprintf("(%s,%s)", l, r)
|
|
}
|
|
case *LogicalUnionAll, *PhysicalUnionAll:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
str = "UnionAll{" + strings.Join(children, "->") + "}"
|
|
idxs = idxs[:last]
|
|
case *DataSource:
|
|
if x.TableAsName != nil && x.TableAsName.L != "" {
|
|
str = fmt.Sprintf("DataScan(%s)", x.TableAsName)
|
|
} else {
|
|
str = fmt.Sprintf("DataScan(%s)", x.tableInfo.Name)
|
|
}
|
|
case *LogicalSelection:
|
|
str = fmt.Sprintf("Sel(%s)", x.Conditions)
|
|
case *PhysicalSelection:
|
|
str = fmt.Sprintf("Sel(%s)", x.Conditions)
|
|
case *LogicalProjection, *PhysicalProjection:
|
|
str = "Projection"
|
|
case *LogicalTopN:
|
|
str = fmt.Sprintf("TopN(%s,%d,%d)", x.ByItems, x.Offset, x.Count)
|
|
case *PhysicalTopN:
|
|
str = fmt.Sprintf("TopN(%s,%d,%d)", x.ByItems, x.Offset, x.Count)
|
|
case *LogicalTableDual, *PhysicalTableDual:
|
|
str = "Dual"
|
|
case *PhysicalHashAgg:
|
|
str = "HashAgg"
|
|
case *PhysicalStreamAgg:
|
|
str = "StreamAgg"
|
|
case *LogicalAggregation:
|
|
str = "Aggr("
|
|
for i, aggFunc := range x.AggFuncs {
|
|
str += aggFunc.String()
|
|
if i != len(x.AggFuncs)-1 {
|
|
str += ","
|
|
}
|
|
}
|
|
str += ")"
|
|
case *PhysicalTableReader:
|
|
str = fmt.Sprintf("TableReader(%s)", ToString(x.tablePlan))
|
|
case *PhysicalIndexReader:
|
|
str = fmt.Sprintf("IndexReader(%s)", ToString(x.indexPlan))
|
|
case *PhysicalIndexLookUpReader:
|
|
str = fmt.Sprintf("IndexLookUp(%s, %s)", ToString(x.indexPlan), ToString(x.tablePlan))
|
|
case *PhysicalUnionScan:
|
|
str = fmt.Sprintf("UnionScan(%s)", x.Conditions)
|
|
case *PhysicalIndexJoin:
|
|
last := len(idxs) - 1
|
|
idx := idxs[last]
|
|
children := strs[idx:]
|
|
strs = strs[:idx]
|
|
idxs = idxs[:last]
|
|
str = "IndexJoin{" + strings.Join(children, "->") + "}"
|
|
for i := range x.OuterJoinKeys {
|
|
l := x.OuterJoinKeys[i]
|
|
r := x.InnerJoinKeys[i]
|
|
str += fmt.Sprintf("(%s,%s)", l, r)
|
|
}
|
|
case *Analyze:
|
|
str = "Analyze{"
|
|
var children []string
|
|
for _, idx := range x.IdxTasks {
|
|
children = append(children, fmt.Sprintf("Index(%s.%s)", idx.TableInfo.Name.O, idx.IndexInfo.Name.O))
|
|
}
|
|
for _, col := range x.ColTasks {
|
|
var colNames []string
|
|
if col.PKInfo != nil {
|
|
colNames = append(colNames, fmt.Sprintf("%s.%s", col.TableInfo.Name.O, col.PKInfo.Name.O))
|
|
}
|
|
for _, c := range col.ColsInfo {
|
|
colNames = append(colNames, fmt.Sprintf("%s.%s", col.TableInfo.Name.O, c.Name.O))
|
|
}
|
|
children = append(children, fmt.Sprintf("Table(%s)", strings.Join(colNames, ", ")))
|
|
}
|
|
str = str + strings.Join(children, ",") + "}"
|
|
case *Update:
|
|
str = fmt.Sprintf("%s->Update", ToString(x.SelectPlan))
|
|
case *Delete:
|
|
str = fmt.Sprintf("%s->Delete", ToString(x.SelectPlan))
|
|
case *Insert:
|
|
str = "Insert"
|
|
if x.SelectPlan != nil {
|
|
str = fmt.Sprintf("%s->Insert", ToString(x.SelectPlan))
|
|
}
|
|
default:
|
|
str = fmt.Sprintf("%T", in)
|
|
}
|
|
strs = append(strs, str)
|
|
return strs, idxs
|
|
}
|