Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: support window function #8630

Merged
merged 29 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1aaf513
planner: support window function
alivxxx Dec 7, 2018
d8ebf09
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 10, 2018
52d7513
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 10, 2018
db59bed
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 10, 2018
aaa2adf
Merge branch 'master' into window
zz-jason Dec 10, 2018
6244626
address comments
alivxxx Dec 11, 2018
1f077b8
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 11, 2018
f120ab9
Merge branch 'window' of github.com:lamxTyler/tidb into window
alivxxx Dec 11, 2018
2b8d890
use latest parser
alivxxx Dec 11, 2018
3095b2d
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 18, 2018
aa59c92
address comments
alivxxx Dec 19, 2018
eddbb79
Merge branch 'master' of github.com:pingcap/tidb into window
alivxxx Dec 26, 2018
33e76f9
fix gofmt
alivxxx Dec 26, 2018
db13052
address comment
alivxxx Dec 26, 2018
ecf4ef8
address comments
alivxxx Dec 26, 2018
b3ad3d9
address comments
alivxxx Dec 27, 2018
7e3e545
fix unit test
alivxxx Dec 27, 2018
aec7a2c
address comments
alivxxx Dec 29, 2018
71bdea1
Merge branch 'master' into window
zz-jason Dec 29, 2018
b9b3366
add comment for build projection
alivxxx Jan 2, 2019
d047eb2
Merge branch 'window' of github.com:lamxTyler/tidb into window
alivxxx Jan 2, 2019
dcf8981
add more comments
alivxxx Jan 2, 2019
b2d293f
address comments
alivxxx Jan 3, 2019
87e50ab
remove dot
alivxxx Jan 3, 2019
2fd62ba
address comments
alivxxx Jan 3, 2019
58de4fc
address comment
alivxxx Jan 3, 2019
36c5993
update parser
alivxxx Jan 3, 2019
ccc13a4
Merge branch 'master' into window
alivxxx Jan 3, 2019
5eb3e5b
Merge branch 'master' into window
eurekaka Jan 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it belong to aggregation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the package name to udf or something else?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to, window function is also a kind of aggregate function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But its behavior is quite different with normal aggregate function since it won't make the rows grouped into one though there's OVER clause.
I think they should be in the same level not superior-subordinate.

//
// 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.
zz-jason marked this conversation as resolved.
Show resolved Hide resolved
return p.WindowFuncDesc.String()
zz-jason marked this conversation as resolved.
Show resolved Hide resolved
}
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)
zz-jason marked this conversation as resolved.
Show resolved Hide resolved
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