代码拉取完成,页面将自动刷新
topn_push_down
rule. (#6899) (#6923)
// Copyright 2017 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 (
"github.com/pingcap/tidb/expression"
)
// pushDownTopNOptimizer pushes down the topN or limit. In the future we will remove the limit from `requiredProperty` in CBO phase.
type pushDownTopNOptimizer struct {
}
func (s *pushDownTopNOptimizer) optimize(p LogicalPlan) (LogicalPlan, error) {
return p.pushDownTopN(nil), nil
}
func (s *baseLogicalPlan) pushDownTopN(topN *LogicalTopN) LogicalPlan {
p := s.self
for i, child := range p.Children() {
p.Children()[i] = child.pushDownTopN(nil)
}
if topN != nil {
return topN.setChild(p)
}
return p
}
// setChild set p as topn's child.
func (lt *LogicalTopN) setChild(p LogicalPlan) LogicalPlan {
if lt.isLimit() {
limit := LogicalLimit{
Count: lt.Count,
Offset: lt.Offset,
}.init(lt.ctx)
limit.SetChildren(p)
return limit
}
// Then lt must be topN.
lt.SetChildren(p)
return lt
}
func (ls *LogicalSort) pushDownTopN(topN *LogicalTopN) LogicalPlan {
if topN == nil {
return ls.baseLogicalPlan.pushDownTopN(nil)
} else if topN.isLimit() {
topN.ByItems = ls.ByItems
return ls.children[0].pushDownTopN(topN)
}
// If a TopN is pushed down, this sort is useless.
return ls.children[0].pushDownTopN(topN)
}
func (p *LogicalLimit) convertToTopN() *LogicalTopN {
return LogicalTopN{Offset: p.Offset, Count: p.Count}.init(p.ctx)
}
func (p *LogicalLimit) pushDownTopN(topN *LogicalTopN) LogicalPlan {
child := p.children[0].pushDownTopN(p.convertToTopN())
if topN != nil {
return topN.setChild(child)
}
return child
}
func (p *LogicalUnionAll) pushDownTopN(topN *LogicalTopN) LogicalPlan {
for i, child := range p.children {
var newTopN *LogicalTopN
if topN != nil {
newTopN = LogicalTopN{Count: topN.Count + topN.Offset}.init(p.ctx)
for _, by := range topN.ByItems {
newTopN.ByItems = append(newTopN.ByItems, &ByItems{by.Expr.Clone(), by.Desc})
}
}
p.children[i] = child.pushDownTopN(newTopN)
}
if topN != nil {
return topN.setChild(p)
}
return p
}
func (p *LogicalProjection) pushDownTopN(topN *LogicalTopN) LogicalPlan {
if topN != nil {
for _, by := range topN.ByItems {
by.Expr = expression.ColumnSubstitute(by.Expr, p.schema, p.Exprs)
}
}
p.children[0] = p.children[0].pushDownTopN(topN)
return p
}
// pushDownTopNToChild will push a topN to one child of join. The idx stands for join child index. 0 is for left child.
func (p *LogicalJoin) pushDownTopNToChild(topN *LogicalTopN, idx int) LogicalPlan {
if topN == nil {
return p.children[idx].pushDownTopN(nil)
}
for _, by := range topN.ByItems {
cols := expression.ExtractColumns(by.Expr)
for _, col := range cols {
if p.children[1-idx].Schema().Contains(col) {
return p.children[idx].pushDownTopN(nil)
}
}
}
newTopN := LogicalTopN{
Count: topN.Count + topN.Offset,
ByItems: make([]*ByItems, len(topN.ByItems)),
}.init(topN.ctx)
for i := range topN.ByItems {
newTopN.ByItems[i] = topN.ByItems[i].Clone()
}
return p.children[idx].pushDownTopN(newTopN)
}
func (p *LogicalJoin) pushDownTopN(topN *LogicalTopN) LogicalPlan {
switch p.JoinType {
case LeftOuterJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin:
p.children[0] = p.pushDownTopNToChild(topN, 0)
p.children[1] = p.children[1].pushDownTopN(nil)
case RightOuterJoin:
p.children[1] = p.pushDownTopNToChild(topN, 1)
p.children[0] = p.children[0].pushDownTopN(nil)
default:
return p.baseLogicalPlan.pushDownTopN(topN)
}
// The LogicalJoin may be also a LogicalApply. So we must use self to set parents.
if topN != nil {
return topN.setChild(p.self)
}
return p.self
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。