Skip to content

Commit

Permalink
planner: support window function (#8630)
Browse files Browse the repository at this point in the history
  • Loading branch information
alivxxx authored Jan 3, 2019
1 parent 41ad626 commit 91cdbf2
Show file tree
Hide file tree
Showing 18 changed files with 470 additions and 21 deletions.
29 changes: 29 additions & 0 deletions expression/aggregation/window_func.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2018 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 aggregation

import (
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/sessionctx"
)

// WindowFuncDesc describes a window function signature, only used in planner.
type WindowFuncDesc struct {
baseFuncDesc
}

// NewWindowFuncDesc creates a window function signature descriptor.
func NewWindowFuncDesc(ctx sessionctx.Context, name string, args []expression.Expression) *WindowFuncDesc {
return &WindowFuncDesc{newBaseFuncDesc(ctx, name, args)}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
github.com/pingcap/gofail v0.0.0-20181217135706-6a951c1e42c3
github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c
github.com/pingcap/parser v0.0.0-20181225032741-ff56f7f11ed6
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641
github.com/pingcap/pd v2.1.0-rc.4+incompatible
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e h1:P73/4dPCL96rG
github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c h1:Qf5St5XGwKgKQLar9lEXoeO0hJMVaFBj3JqvFguWtVg=
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot9q4/3JyCZodnWDGNXt4pKemhIYCvVJM7P24=
github.com/pingcap/parser v0.0.0-20181225032741-ff56f7f11ed6 h1:ooapyJxH6uSHNvpYjPOggHtd2dzLKwSvYLVzs3OjoM0=
github.com/pingcap/parser v0.0.0-20181225032741-ff56f7f11ed6/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641 h1:KTGU8kr2wY+FRiHHs8I5lp385b+OzYnbOr3/tPVw7mU=
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE=
github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible h1:Bsd+NHosPVowEGB3BCx+2d8wUQGDTXSSC5ljeNS6cXo=
Expand Down
9 changes: 9 additions & 0 deletions planner/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ const (
codeWrongNumberOfColumnsInSelect = mysql.ErrWrongNumberOfColumnsInSelect
codeWrongValueCountOnRow = mysql.ErrWrongValueCountOnRow
codeTablenameNotAllowedHere = mysql.ErrTablenameNotAllowedHere

codeWindowInvalidWindowFuncUse = mysql.ErrWindowInvalidWindowFuncUse
codeWindowInvalidWindowFuncAliasUse = mysql.ErrWindowInvalidWindowFuncAliasUse
)

// error definitions.
Expand Down Expand Up @@ -88,6 +91,9 @@ var (
ErrNonUniqTable = terror.ClassOptimizer.New(codeNonUniqTable, mysql.MySQLErrName[mysql.ErrNonuniqTable])
ErrWrongValueCountOnRow = terror.ClassOptimizer.New(mysql.ErrWrongValueCountOnRow, mysql.MySQLErrName[mysql.ErrWrongValueCountOnRow])
ErrViewInvalid = terror.ClassOptimizer.New(mysql.ErrViewInvalid, mysql.MySQLErrName[mysql.ErrViewInvalid])

ErrWindowInvalidWindowFuncUse = terror.ClassOptimizer.New(codeWindowInvalidWindowFuncUse, mysql.MySQLErrName[mysql.ErrWindowInvalidWindowFuncUse])
ErrWindowInvalidWindowFuncAliasUse = terror.ClassOptimizer.New(codeWindowInvalidWindowFuncAliasUse, mysql.MySQLErrName[mysql.ErrWindowInvalidWindowFuncAliasUse])
)

func init() {
Expand Down Expand Up @@ -115,6 +121,9 @@ func init() {
codeNonUniqTable: mysql.ErrNonuniqTable,
codeWrongNumberOfColumnsInSelect: mysql.ErrWrongNumberOfColumnsInSelect,
codeWrongValueCountOnRow: mysql.ErrWrongValueCountOnRow,

codeWindowInvalidWindowFuncUse: mysql.ErrWindowInvalidWindowFuncUse,
codeWindowInvalidWindowFuncAliasUse: mysql.ErrWindowInvalidWindowFuncAliasUse,
}
terror.ErrClassToMySQLCodes[terror.ClassOptimizer] = mysqlErrCodeMap
}
12 changes: 12 additions & 0 deletions planner/core/exhaust_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,18 @@ func (la *LogicalApply) exhaustPhysicalPlans(prop *property.PhysicalProperty) []
return []PhysicalPlan{apply}
}

func (p *LogicalWindow) exhaustPhysicalPlans(prop *property.PhysicalProperty) []PhysicalPlan {
childProperty := &property.PhysicalProperty{ExpectedCnt: math.MaxFloat64, Items: p.ByItems, Enforced: true}
if !prop.IsPrefix(childProperty) {
return nil
}
window := PhysicalWindow{
WindowFuncDesc: p.WindowFuncDesc,
}.Init(p.ctx, p.stats.ScaleByExpectCnt(prop.ExpectedCnt), childProperty)
window.SetSchema(p.Schema())
return []PhysicalPlan{window}
}

// exhaustPhysicalPlans is only for implementing interface. DataSource and Dual generate task in `findBestTask` directly.
func (p *baseLogicalPlan) exhaustPhysicalPlans(_ *property.PhysicalProperty) []PhysicalPlan {
panic("baseLogicalPlan.exhaustPhysicalPlans() should never be called.")
Expand Down
6 changes: 6 additions & 0 deletions planner/core/explain.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,9 @@ func (p *PhysicalTopN) ExplainInfo() string {
fmt.Fprintf(buffer, ", offset:%v, count:%v", p.Offset, p.Count)
return buffer.String()
}

// ExplainInfo implements PhysicalPlan interface.
func (p *PhysicalWindow) ExplainInfo() string {
// TODO: Add explain info for partition by, order by and frame.
return p.WindowFuncDesc.String()
}
15 changes: 14 additions & 1 deletion planner/core/expression_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,25 @@ func (er *expressionRewriter) Enter(inNode ast.Node) (ast.Node, bool) {
}
er.ctxStack = append(er.ctxStack, expression.NewValuesFunc(er.ctx, col.Index, col.RetType))
return inNode, true
case *ast.WindowFuncExpr:
return er.handleWindowFunction(v)
default:
er.asScalar = true
}
return inNode, false
}

func (er *expressionRewriter) handleWindowFunction(v *ast.WindowFuncExpr) (ast.Node, bool) {
windowPlan, err := er.b.buildWindowFunction(er.p, v, er.aggrMap)
if err != nil {
er.err = err
return v, false
}
er.ctxStack = append(er.ctxStack, windowPlan.GetWindowResultColumn())
er.p = windowPlan
return v, true
}

func (er *expressionRewriter) handleCompareSubquery(v *ast.CompareSubqueryExpr) (ast.Node, bool) {
v.L.Accept(er)
if er.err != nil {
Expand Down Expand Up @@ -753,7 +766,7 @@ func (er *expressionRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok
}
switch v := inNode.(type) {
case *ast.AggregateFuncExpr, *ast.ColumnNameExpr, *ast.ParenthesesExpr, *ast.WhenClause,
*ast.SubqueryExpr, *ast.ExistsSubqueryExpr, *ast.CompareSubqueryExpr, *ast.ValuesExpr:
*ast.SubqueryExpr, *ast.ExistsSubqueryExpr, *ast.CompareSubqueryExpr, *ast.ValuesExpr, *ast.WindowFuncExpr:
case *driver.ValueExpr:
value := &expression.Constant{Value: v.Datum, RetType: &v.Type}
er.ctxStack = append(er.ctxStack, value)
Expand Down
16 changes: 16 additions & 0 deletions planner/core/initialize.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ const (
TypeTableReader = "TableReader"
// TypeIndexReader is the type of IndexReader.
TypeIndexReader = "IndexReader"
// TypeWindow is the type of Window.
TypeWindow = "Window"
)

// Init initializes LogicalAggregation.
Expand Down Expand Up @@ -231,6 +233,20 @@ func (p PhysicalMaxOneRow) Init(ctx sessionctx.Context, stats *property.StatsInf
return &p
}

// Init initializes LogicalWindow.
func (p LogicalWindow) Init(ctx sessionctx.Context) *LogicalWindow {
p.baseLogicalPlan = newBaseLogicalPlan(ctx, TypeWindow, &p)
return &p
}

// Init initializes PhysicalWindow.
func (p PhysicalWindow) Init(ctx sessionctx.Context, stats *property.StatsInfo, props ...*property.PhysicalProperty) *PhysicalWindow {
p.basePhysicalPlan = newBasePhysicalPlan(ctx, TypeWindow, &p)
p.childrenReqProps = props
p.stats = stats
return &p
}

// Init initializes Update.
func (p Update) Init(ctx sessionctx.Context) *Update {
p.basePlan = newBasePlan(ctx, TypeUpdate)
Expand Down
Loading

0 comments on commit 91cdbf2

Please sign in to comment.