You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
2.3 KiB
77 lines
2.3 KiB
// 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 (
|
|
"strings"
|
|
|
|
"github.com/pingcap/parser/ast"
|
|
"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, error) {
|
|
switch strings.ToLower(name) {
|
|
case ast.WindowFuncNthValue:
|
|
val, isNull, ok := expression.GetUint64FromConstant(args[1])
|
|
// nth_value does not allow `0`, but allows `null`.
|
|
if !ok || (val == 0 && !isNull) {
|
|
return nil, nil
|
|
}
|
|
case ast.WindowFuncNtile:
|
|
val, isNull, ok := expression.GetUint64FromConstant(args[0])
|
|
// ntile does not allow `0`, but allows `null`.
|
|
if !ok || (val == 0 && !isNull) {
|
|
return nil, nil
|
|
}
|
|
case ast.WindowFuncLead, ast.WindowFuncLag:
|
|
if len(args) < 2 {
|
|
break
|
|
}
|
|
_, isNull, ok := expression.GetUint64FromConstant(args[1])
|
|
if !ok || isNull {
|
|
return nil, nil
|
|
}
|
|
}
|
|
base, err := newBaseFuncDesc(ctx, name, args)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &WindowFuncDesc{base}, nil
|
|
}
|
|
|
|
// noFrameWindowFuncs is the functions that operate on the entire partition,
|
|
// they should not have frame specifications.
|
|
var noFrameWindowFuncs = map[string]struct{}{
|
|
ast.WindowFuncCumeDist: {},
|
|
ast.WindowFuncDenseRank: {},
|
|
ast.WindowFuncLag: {},
|
|
ast.WindowFuncLead: {},
|
|
ast.WindowFuncNtile: {},
|
|
ast.WindowFuncPercentRank: {},
|
|
ast.WindowFuncRank: {},
|
|
ast.WindowFuncRowNumber: {},
|
|
}
|
|
|
|
// NeedFrame checks if the function need frame specification.
|
|
func NeedFrame(name string) bool {
|
|
_, ok := noFrameWindowFuncs[strings.ToLower(name)]
|
|
return !ok
|
|
}
|
|
|