1 Star 0 Fork 0

jiangplus / tidb-parser

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
functions.go 22.58 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
// 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 ast
import (
"fmt"
"io"
"strings"
"github.com/pingcap/errors"
. "github.com/pingcap/parser/format"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/types"
)
var (
_ FuncNode = &AggregateFuncExpr{}
_ FuncNode = &FuncCallExpr{}
_ FuncNode = &FuncCastExpr{}
_ FuncNode = &WindowFuncExpr{}
)
// List scalar function names.
const (
LogicAnd = "and"
Cast = "cast"
LeftShift = "leftshift"
RightShift = "rightshift"
LogicOr = "or"
GE = "ge"
LE = "le"
EQ = "eq"
NE = "ne"
LT = "lt"
GT = "gt"
Plus = "plus"
Minus = "minus"
And = "bitand"
Or = "bitor"
Mod = "mod"
Xor = "bitxor"
Div = "div"
Mul = "mul"
UnaryNot = "not" // Avoid name conflict with Not in github/pingcap/check.
BitNeg = "bitneg"
IntDiv = "intdiv"
LogicXor = "xor"
NullEQ = "nulleq"
UnaryPlus = "unaryplus"
UnaryMinus = "unaryminus"
In = "in"
Like = "like"
Case = "case"
Regexp = "regexp"
IsNull = "isnull"
IsTruth = "istrue" // Avoid name conflict with IsTrue in github/pingcap/check.
IsFalsity = "isfalse" // Avoid name conflict with IsFalse in github/pingcap/check.
RowFunc = "row"
SetVar = "setvar"
GetVar = "getvar"
Values = "values"
BitCount = "bit_count"
GetParam = "getparam"
// common functions
Coalesce = "coalesce"
Greatest = "greatest"
Least = "least"
Interval = "interval"
// math functions
Abs = "abs"
Acos = "acos"
Asin = "asin"
Atan = "atan"
Atan2 = "atan2"
Ceil = "ceil"
Ceiling = "ceiling"
Conv = "conv"
Cos = "cos"
Cot = "cot"
CRC32 = "crc32"
Degrees = "degrees"
Exp = "exp"
Floor = "floor"
Ln = "ln"
Log = "log"
Log2 = "log2"
Log10 = "log10"
PI = "pi"
Pow = "pow"
Power = "power"
Radians = "radians"
Rand = "rand"
Round = "round"
Sign = "sign"
Sin = "sin"
Sqrt = "sqrt"
Tan = "tan"
Truncate = "truncate"
// time functions
AddDate = "adddate"
AddTime = "addtime"
ConvertTz = "convert_tz"
Curdate = "curdate"
CurrentDate = "current_date"
CurrentTime = "current_time"
CurrentTimestamp = "current_timestamp"
Curtime = "curtime"
Date = "date"
DateLiteral = "dateliteral"
DateAdd = "date_add"
DateFormat = "date_format"
DateSub = "date_sub"
DateDiff = "datediff"
Day = "day"
DayName = "dayname"
DayOfMonth = "dayofmonth"
DayOfWeek = "dayofweek"
DayOfYear = "dayofyear"
Extract = "extract"
FromDays = "from_days"
FromUnixTime = "from_unixtime"
GetFormat = "get_format"
Hour = "hour"
LocalTime = "localtime"
LocalTimestamp = "localtimestamp"
MakeDate = "makedate"
MakeTime = "maketime"
MicroSecond = "microsecond"
Minute = "minute"
Month = "month"
MonthName = "monthname"
Now = "now"
PeriodAdd = "period_add"
PeriodDiff = "period_diff"
Quarter = "quarter"
SecToTime = "sec_to_time"
Second = "second"
StrToDate = "str_to_date"
SubDate = "subdate"
SubTime = "subtime"
Sysdate = "sysdate"
Time = "time"
TimeLiteral = "timeliteral"
TimeFormat = "time_format"
TimeToSec = "time_to_sec"
TimeDiff = "timediff"
Timestamp = "timestamp"
TimestampLiteral = "timestampliteral"
TimestampAdd = "timestampadd"
TimestampDiff = "timestampdiff"
ToDays = "to_days"
ToSeconds = "to_seconds"
UnixTimestamp = "unix_timestamp"
UTCDate = "utc_date"
UTCTime = "utc_time"
UTCTimestamp = "utc_timestamp"
Week = "week"
Weekday = "weekday"
WeekOfYear = "weekofyear"
Year = "year"
YearWeek = "yearweek"
LastDay = "last_day"
TiDBParseTso = "tidb_parse_tso"
// string functions
ASCII = "ascii"
Bin = "bin"
Concat = "concat"
ConcatWS = "concat_ws"
Convert = "convert"
Elt = "elt"
ExportSet = "export_set"
Field = "field"
Format = "format"
FromBase64 = "from_base64"
InsertFunc = "insert_func"
Instr = "instr"
Lcase = "lcase"
Left = "left"
Length = "length"
LoadFile = "load_file"
Locate = "locate"
Lower = "lower"
Lpad = "lpad"
LTrim = "ltrim"
MakeSet = "make_set"
Mid = "mid"
Oct = "oct"
Ord = "ord"
Position = "position"
Quote = "quote"
Repeat = "repeat"
Replace = "replace"
Reverse = "reverse"
Right = "right"
RTrim = "rtrim"
Space = "space"
Strcmp = "strcmp"
Substring = "substring"
Substr = "substr"
SubstringIndex = "substring_index"
ToBase64 = "to_base64"
Trim = "trim"
Upper = "upper"
Ucase = "ucase"
Hex = "hex"
Unhex = "unhex"
Rpad = "rpad"
BitLength = "bit_length"
CharFunc = "char_func"
CharLength = "char_length"
CharacterLength = "character_length"
FindInSet = "find_in_set"
// information functions
Benchmark = "benchmark"
Charset = "charset"
Coercibility = "coercibility"
Collation = "collation"
ConnectionID = "connection_id"
CurrentUser = "current_user"
CurrentRole = "current_role"
Database = "database"
FoundRows = "found_rows"
LastInsertId = "last_insert_id"
RowCount = "row_count"
Schema = "schema"
SessionUser = "session_user"
SystemUser = "system_user"
User = "user"
Version = "version"
TiDBVersion = "tidb_version"
TiDBIsDDLOwner = "tidb_is_ddl_owner"
TiDBDecodePlan = "tidb_decode_plan"
// control functions
If = "if"
Ifnull = "ifnull"
Nullif = "nullif"
// miscellaneous functions
AnyValue = "any_value"
DefaultFunc = "default_func"
InetAton = "inet_aton"
InetNtoa = "inet_ntoa"
Inet6Aton = "inet6_aton"
Inet6Ntoa = "inet6_ntoa"
IsFreeLock = "is_free_lock"
IsIPv4 = "is_ipv4"
IsIPv4Compat = "is_ipv4_compat"
IsIPv4Mapped = "is_ipv4_mapped"
IsIPv6 = "is_ipv6"
IsUsedLock = "is_used_lock"
MasterPosWait = "master_pos_wait"
NameConst = "name_const"
ReleaseAllLocks = "release_all_locks"
Sleep = "sleep"
UUID = "uuid"
UUIDShort = "uuid_short"
// get_lock() and release_lock() is parsed but do nothing.
// It is used for preventing error in Ruby's activerecord migrations.
GetLock = "get_lock"
ReleaseLock = "release_lock"
// encryption and compression functions
AesDecrypt = "aes_decrypt"
AesEncrypt = "aes_encrypt"
Compress = "compress"
Decode = "decode"
DesDecrypt = "des_decrypt"
DesEncrypt = "des_encrypt"
Encode = "encode"
Encrypt = "encrypt"
MD5 = "md5"
OldPassword = "old_password"
PasswordFunc = "password_func"
RandomBytes = "random_bytes"
SHA1 = "sha1"
SHA = "sha"
SHA2 = "sha2"
Uncompress = "uncompress"
UncompressedLength = "uncompressed_length"
ValidatePasswordStrength = "validate_password_strength"
// json functions
JSONType = "json_type"
JSONExtract = "json_extract"
JSONUnquote = "json_unquote"
JSONArray = "json_array"
JSONObject = "json_object"
JSONMerge = "json_merge"
JSONSet = "json_set"
JSONInsert = "json_insert"
JSONReplace = "json_replace"
JSONRemove = "json_remove"
JSONContains = "json_contains"
JSONContainsPath = "json_contains_path"
JSONValid = "json_valid"
JSONArrayAppend = "json_array_append"
JSONArrayInsert = "json_array_insert"
JSONMergePatch = "json_merge_patch"
JSONMergePreserve = "json_merge_preserve"
JSONPretty = "json_pretty"
JSONQuote = "json_quote"
JSONSearch = "json_search"
JSONStorageSize = "json_storage_size"
JSONDepth = "json_depth"
JSONKeys = "json_keys"
JSONLength = "json_length"
)
// FuncCallExpr is for function expression.
type FuncCallExpr struct {
funcNode
// FnName is the function name.
FnName model.CIStr
// Args is the function args.
Args []ExprNode
}
// Restore implements Node interface.
func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord(n.FnName.O)
ctx.WritePlain("(")
switch n.FnName.L {
case "convert":
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCastExpr.Expr")
}
ctx.WriteKeyWord(" USING ")
ctx.WriteKeyWord(n.Args[1].GetType().Charset)
case "adddate", "subdate", "date_add", "date_sub":
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WritePlain(", ")
ctx.WriteKeyWord("INTERVAL ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WritePlain(" ")
ctx.WriteKeyWord(n.Args[2].(ValueExpr).GetString())
case "extract":
ctx.WriteKeyWord(n.Args[0].(ValueExpr).GetString())
ctx.WriteKeyWord(" FROM ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case "get_format":
ctx.WriteKeyWord(n.Args[0].(ValueExpr).GetString())
ctx.WritePlain(", ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case "position":
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WriteKeyWord(" IN ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case "trim":
switch len(n.Args) {
case 1:
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case 2:
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WriteKeyWord(" FROM ")
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case 3:
switch fmt.Sprint(n.Args[2].(ValueExpr).GetValue()) {
case "3":
ctx.WriteKeyWord("TRAILING ")
case "2":
ctx.WriteKeyWord("LEADING ")
case "0", "1":
ctx.WriteKeyWord("BOTH ")
}
if n.Args[1].(ValueExpr).GetValue() != nil {
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("FROM ")
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
}
case "timestampdiff", "timestampadd":
ctx.WriteKeyWord(n.Args[0].(ValueExpr).GetString())
for i := 1; i < len(n.Args); {
ctx.WritePlain(", ")
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
i++
}
default:
for i, argv := range n.Args {
if i != 0 {
ctx.WritePlain(", ")
}
if err := argv.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr.Args %d", i)
}
}
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *FuncCallExpr) Format(w io.Writer) {
fmt.Fprintf(w, "%s(", n.FnName.L)
if !n.specialFormatArgs(w) {
for i, arg := range n.Args {
arg.Format(w)
if i != len(n.Args)-1 {
fmt.Fprint(w, ", ")
}
}
}
fmt.Fprint(w, ")")
}
// specialFormatArgs formats argument list for some special functions.
func (n *FuncCallExpr) specialFormatArgs(w io.Writer) bool {
switch n.FnName.L {
case DateAdd, DateSub, AddDate, SubDate:
n.Args[0].Format(w)
fmt.Fprint(w, ", INTERVAL ")
n.Args[1].Format(w)
fmt.Fprintf(w, " %s", n.Args[2].(ValueExpr).GetDatumString())
return true
case TimestampAdd, TimestampDiff:
fmt.Fprintf(w, "%s, ", n.Args[0].(ValueExpr).GetDatumString())
n.Args[1].Format(w)
fmt.Fprint(w, ", ")
n.Args[2].Format(w)
return true
}
return false
}
// Accept implements Node interface.
func (n *FuncCallExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*FuncCallExpr)
for i, val := range n.Args {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Args[i] = node.(ExprNode)
}
return v.Leave(n)
}
// CastFunctionType is the type for cast function.
type CastFunctionType int
// CastFunction types
const (
CastFunction CastFunctionType = iota + 1
CastConvertFunction
CastBinaryOperator
)
// FuncCastExpr is the cast function converting value to another type, e.g, cast(expr AS signed).
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html
type FuncCastExpr struct {
funcNode
// Expr is the expression to be converted.
Expr ExprNode
// Tp is the conversion type.
Tp *types.FieldType
// FunctionType is either Cast, Convert or Binary.
FunctionType CastFunctionType
}
// Restore implements Node interface.
func (n *FuncCastExpr) Restore(ctx *RestoreCtx) error {
switch n.FunctionType {
case CastFunction:
ctx.WriteKeyWord("CAST")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCastExpr.Expr")
}
ctx.WriteKeyWord(" AS ")
n.Tp.RestoreAsCastType(ctx)
ctx.WritePlain(")")
case CastConvertFunction:
ctx.WriteKeyWord("CONVERT")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCastExpr.Expr")
}
ctx.WritePlain(", ")
n.Tp.RestoreAsCastType(ctx)
ctx.WritePlain(")")
case CastBinaryOperator:
ctx.WriteKeyWord("BINARY ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCastExpr.Expr")
}
}
return nil
}
// Format the ExprNode into a Writer.
func (n *FuncCastExpr) Format(w io.Writer) {
switch n.FunctionType {
case CastFunction:
fmt.Fprint(w, "CAST(")
n.Expr.Format(w)
fmt.Fprint(w, " AS ")
n.Tp.FormatAsCastType(w)
fmt.Fprint(w, ")")
case CastConvertFunction:
fmt.Fprint(w, "CONVERT(")
n.Expr.Format(w)
fmt.Fprint(w, ", ")
n.Tp.FormatAsCastType(w)
fmt.Fprint(w, ")")
case CastBinaryOperator:
fmt.Fprint(w, "BINARY ")
n.Expr.Format(w)
}
}
// Accept implements Node Accept interface.
func (n *FuncCastExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*FuncCastExpr)
node, ok := n.Expr.Accept(v)
if !ok {
return n, false
}
n.Expr = node.(ExprNode)
return v.Leave(n)
}
// TrimDirectionType is the type for trim direction.
type TrimDirectionType int
const (
// TrimBothDefault trims from both direction by default.
TrimBothDefault TrimDirectionType = iota
// TrimBoth trims from both direction with explicit notation.
TrimBoth
// TrimLeading trims from left.
TrimLeading
// TrimTrailing trims from right.
TrimTrailing
)
// DateArithType is type for DateArith type.
type DateArithType byte
const (
// DateArithAdd is to run adddate or date_add function option.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_adddate
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-add
DateArithAdd DateArithType = iota + 1
// DateArithSub is to run subdate or date_sub function option.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_subdate
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-sub
DateArithSub
)
const (
// AggFuncCount is the name of Count function.
AggFuncCount = "count"
// AggFuncSum is the name of Sum function.
AggFuncSum = "sum"
// AggFuncAvg is the name of Avg function.
AggFuncAvg = "avg"
// AggFuncFirstRow is the name of FirstRowColumn function.
AggFuncFirstRow = "firstrow"
// AggFuncMax is the name of max function.
AggFuncMax = "max"
// AggFuncMin is the name of min function.
AggFuncMin = "min"
// AggFuncGroupConcat is the name of group_concat function.
AggFuncGroupConcat = "group_concat"
// AggFuncBitOr is the name of bit_or function.
AggFuncBitOr = "bit_or"
// AggFuncBitXor is the name of bit_xor function.
AggFuncBitXor = "bit_xor"
// AggFuncBitAnd is the name of bit_and function.
AggFuncBitAnd = "bit_and"
// AggFuncVarPop is the name of var_pop function
AggFuncVarPop = "var_pop"
// AggFuncVarSamp is the name of var_samp function
AggFuncVarSamp = "var_samp"
// AggFuncStddevPop is the name of stddev_pop function
AggFuncStddevPop = "stddev_pop"
// AggFuncStddevSamp is the name of stddev_samp function
AggFuncStddevSamp = "stddev_samp"
)
// AggregateFuncExpr represents aggregate function expression.
type AggregateFuncExpr struct {
funcNode
// F is the function name.
F string
// Args is the function args.
Args []ExprNode
// Distinct is true, function hence only aggregate distinct values.
// For example, column c1 values are "1", "2", "2", "sum(c1)" is "5",
// but "sum(distinct c1)" is "3".
Distinct bool
}
// Restore implements Node interface.
func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord(n.F)
ctx.WritePlain("(")
if n.Distinct {
ctx.WriteKeyWord("DISTINCT ")
}
switch strings.ToLower(n.F) {
case "group_concat":
for i := 0; i < len(n.Args)-1; i++ {
if i != 0 {
ctx.WritePlain(", ")
}
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
}
ctx.WriteKeyWord(" SEPARATOR ")
if err := n.Args[len(n.Args)-1].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AggregateFuncExpr.Args SEPARATOR")
}
default:
for i, argv := range n.Args {
if i != 0 {
ctx.WritePlain(", ")
}
if err := argv.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
}
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
func (n *AggregateFuncExpr) Format(w io.Writer) {
panic("Not implemented")
}
// Accept implements Node Accept interface.
func (n *AggregateFuncExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*AggregateFuncExpr)
for i, val := range n.Args {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Args[i] = node.(ExprNode)
}
return v.Leave(n)
}
const (
// WindowFuncRowNumber is the name of row_number function.
WindowFuncRowNumber = "row_number"
// WindowFuncRank is the name of rank function.
WindowFuncRank = "rank"
// WindowFuncDenseRank is the name of dense_rank function.
WindowFuncDenseRank = "dense_rank"
// WindowFuncCumeDist is the name of cume_dist function.
WindowFuncCumeDist = "cume_dist"
// WindowFuncPercentRank is the name of percent_rank function.
WindowFuncPercentRank = "percent_rank"
// WindowFuncNtile is the name of ntile function.
WindowFuncNtile = "ntile"
// WindowFuncLead is the name of lead function.
WindowFuncLead = "lead"
// WindowFuncLag is the name of lag function.
WindowFuncLag = "lag"
// WindowFuncFirstValue is the name of first_value function.
WindowFuncFirstValue = "first_value"
// WindowFuncLastValue is the name of last_value function.
WindowFuncLastValue = "last_value"
// WindowFuncNthValue is the name of nth_value function.
WindowFuncNthValue = "nth_value"
)
// WindowFuncExpr represents window function expression.
type WindowFuncExpr struct {
funcNode
// F is the function name.
F string
// Args is the function args.
Args []ExprNode
// Distinct cannot be true for most window functions, except `max` and `min`.
// We need to raise error if it is not allowed to be true.
Distinct bool
// IgnoreNull indicates how to handle null value.
// MySQL only supports `RESPECT NULLS`, so we need to raise error if it is true.
IgnoreNull bool
// FromLast indicates the calculation direction of this window function.
// MySQL only supports calculation from first, so we need to raise error if it is true.
FromLast bool
// Spec is the specification of this window.
Spec WindowSpec
}
// Restore implements Node interface.
func (n *WindowFuncExpr) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord(n.F)
ctx.WritePlain("(")
for i, v := range n.Args {
if i != 0 {
ctx.WritePlain(", ")
} else if n.Distinct {
ctx.WriteKeyWord("DISTINCT ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore WindowFuncExpr.Args[%d]", i)
}
}
ctx.WritePlain(")")
if n.FromLast {
ctx.WriteKeyWord(" FROM LAST")
}
if n.IgnoreNull {
ctx.WriteKeyWord(" IGNORE NULLS")
}
ctx.WriteKeyWord(" OVER ")
if err := n.Spec.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore WindowFuncExpr.Spec")
}
return nil
}
// Format formats the window function expression into a Writer.
func (n *WindowFuncExpr) Format(w io.Writer) {
panic("Not implemented")
}
// Accept implements Node Accept interface.
func (n *WindowFuncExpr) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*WindowFuncExpr)
for i, val := range n.Args {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Args[i] = node.(ExprNode)
}
node, ok := n.Spec.Accept(v)
if !ok {
return n, false
}
n.Spec = *node.(*WindowSpec)
return v.Leave(n)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/jiangplus/tidb-parser.git
git@gitee.com:jiangplus/tidb-parser.git
jiangplus
tidb-parser
tidb-parser
v3.1.0-rc

搜索帮助

344bd9b3 5694891 D2dac590 5694891