91 Star 502 Fork 154

平凯星辰(北京)科技有限公司/tidb

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
builtin_math.go 49.33 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866
// Copyright 2013 The ql Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSES/QL-LICENSE file.
// 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 expression
import (
"fmt"
"hash/crc32"
"math"
"math/rand"
"strconv"
"strings"
"time"
"github.com/juju/errors"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/types"
tipb "github.com/pingcap/tipb/go-tipb"
)
var (
_ functionClass = &absFunctionClass{}
_ functionClass = &roundFunctionClass{}
_ functionClass = &ceilFunctionClass{}
_ functionClass = &floorFunctionClass{}
_ functionClass = &logFunctionClass{}
_ functionClass = &log2FunctionClass{}
_ functionClass = &log10FunctionClass{}
_ functionClass = &randFunctionClass{}
_ functionClass = &powFunctionClass{}
_ functionClass = &convFunctionClass{}
_ functionClass = &crc32FunctionClass{}
_ functionClass = &signFunctionClass{}
_ functionClass = &sqrtFunctionClass{}
_ functionClass = &acosFunctionClass{}
_ functionClass = &asinFunctionClass{}
_ functionClass = &atanFunctionClass{}
_ functionClass = &cosFunctionClass{}
_ functionClass = &cotFunctionClass{}
_ functionClass = &degreesFunctionClass{}
_ functionClass = &expFunctionClass{}
_ functionClass = &piFunctionClass{}
_ functionClass = &radiansFunctionClass{}
_ functionClass = &sinFunctionClass{}
_ functionClass = &tanFunctionClass{}
_ functionClass = &truncateFunctionClass{}
)
var (
_ builtinFunc = &builtinAbsRealSig{}
_ builtinFunc = &builtinAbsIntSig{}
_ builtinFunc = &builtinAbsUIntSig{}
_ builtinFunc = &builtinAbsDecSig{}
_ builtinFunc = &builtinRoundRealSig{}
_ builtinFunc = &builtinRoundIntSig{}
_ builtinFunc = &builtinRoundDecSig{}
_ builtinFunc = &builtinRoundWithFracRealSig{}
_ builtinFunc = &builtinRoundWithFracIntSig{}
_ builtinFunc = &builtinRoundWithFracDecSig{}
_ builtinFunc = &builtinCeilRealSig{}
_ builtinFunc = &builtinCeilIntToDecSig{}
_ builtinFunc = &builtinCeilIntToIntSig{}
_ builtinFunc = &builtinCeilDecToIntSig{}
_ builtinFunc = &builtinCeilDecToDecSig{}
_ builtinFunc = &builtinFloorRealSig{}
_ builtinFunc = &builtinFloorIntToDecSig{}
_ builtinFunc = &builtinFloorIntToIntSig{}
_ builtinFunc = &builtinFloorDecToIntSig{}
_ builtinFunc = &builtinFloorDecToDecSig{}
_ builtinFunc = &builtinLog1ArgSig{}
_ builtinFunc = &builtinLog2ArgsSig{}
_ builtinFunc = &builtinLog2Sig{}
_ builtinFunc = &builtinLog10Sig{}
_ builtinFunc = &builtinRandSig{}
_ builtinFunc = &builtinRandWithSeedSig{}
_ builtinFunc = &builtinPowSig{}
_ builtinFunc = &builtinConvSig{}
_ builtinFunc = &builtinCRC32Sig{}
_ builtinFunc = &builtinSignSig{}
_ builtinFunc = &builtinSqrtSig{}
_ builtinFunc = &builtinAcosSig{}
_ builtinFunc = &builtinAsinSig{}
_ builtinFunc = &builtinAtan1ArgSig{}
_ builtinFunc = &builtinAtan2ArgsSig{}
_ builtinFunc = &builtinCosSig{}
_ builtinFunc = &builtinCotSig{}
_ builtinFunc = &builtinDegreesSig{}
_ builtinFunc = &builtinExpSig{}
_ builtinFunc = &builtinPISig{}
_ builtinFunc = &builtinRadiansSig{}
_ builtinFunc = &builtinSinSig{}
_ builtinFunc = &builtinTanSig{}
_ builtinFunc = &builtinTruncateIntSig{}
_ builtinFunc = &builtinTruncateRealSig{}
_ builtinFunc = &builtinTruncateDecimalSig{}
_ builtinFunc = &builtinTruncateUintSig{}
)
type absFunctionClass struct {
baseFunctionClass
}
func (c *absFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(c.verifyArgs(args))
}
argFieldTp := args[0].GetType()
argTp := argFieldTp.EvalType()
if argTp != types.ETInt && argTp != types.ETDecimal {
argTp = types.ETReal
}
bf := newBaseBuiltinFuncWithTp(ctx, args, argTp, argTp)
if mysql.HasUnsignedFlag(argFieldTp.Flag) {
bf.tp.Flag |= mysql.UnsignedFlag
}
if argTp == types.ETReal {
bf.tp.Flen, bf.tp.Decimal = mysql.GetDefaultFieldLengthAndDecimal(mysql.TypeDouble)
} else {
bf.tp.Flen = argFieldTp.Flen
bf.tp.Decimal = argFieldTp.Decimal
}
var sig builtinFunc
switch argTp {
case types.ETInt:
if mysql.HasUnsignedFlag(argFieldTp.Flag) {
sig = &builtinAbsUIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_AbsUInt)
} else {
sig = &builtinAbsIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_AbsInt)
}
case types.ETDecimal:
sig = &builtinAbsDecSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_AbsDecimal)
case types.ETReal:
sig = &builtinAbsRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_AbsReal)
default:
panic("unexpected argTp")
}
return sig, nil
}
type builtinAbsRealSig struct {
baseBuiltinFunc
}
func (b *builtinAbsRealSig) Clone() builtinFunc {
newSig := &builtinAbsRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals ABS(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs
func (b *builtinAbsRealSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Abs(val), false, nil
}
type builtinAbsIntSig struct {
baseBuiltinFunc
}
func (b *builtinAbsIntSig) Clone() builtinFunc {
newSig := &builtinAbsIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals ABS(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs
func (b *builtinAbsIntSig) evalInt(row types.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val >= 0 {
return val, false, nil
}
if val == math.MinInt64 {
return 0, false, types.ErrOverflow.GenByArgs("BIGINT", fmt.Sprintf("abs(%d)", val))
}
return -val, false, nil
}
type builtinAbsUIntSig struct {
baseBuiltinFunc
}
func (b *builtinAbsUIntSig) Clone() builtinFunc {
newSig := &builtinAbsUIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals ABS(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs
func (b *builtinAbsUIntSig) evalInt(row types.Row) (int64, bool, error) {
return b.args[0].EvalInt(b.ctx, row)
}
type builtinAbsDecSig struct {
baseBuiltinFunc
}
func (b *builtinAbsDecSig) Clone() builtinFunc {
newSig := &builtinAbsDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDecimal evals ABS(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs
func (b *builtinAbsDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
to := new(types.MyDecimal)
if !val.IsNegative() {
*to = *val
} else {
if err = types.DecimalSub(new(types.MyDecimal), val, to); err != nil {
return nil, true, errors.Trace(err)
}
}
return to, false, nil
}
func (c *roundFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(c.verifyArgs(args))
}
argTp := args[0].GetType().EvalType()
if argTp != types.ETInt && argTp != types.ETDecimal {
argTp = types.ETReal
}
argTps := []types.EvalType{argTp}
if len(args) > 1 {
argTps = append(argTps, types.ETInt)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, argTp, argTps...)
argFieldTp := args[0].GetType()
if mysql.HasUnsignedFlag(argFieldTp.Flag) {
bf.tp.Flag |= mysql.UnsignedFlag
}
bf.tp.Flen = argFieldTp.Flen
bf.tp.Decimal = 0
var sig builtinFunc
if len(args) > 1 {
switch argTp {
case types.ETInt:
sig = &builtinRoundWithFracIntSig{bf}
case types.ETDecimal:
sig = &builtinRoundWithFracDecSig{bf}
case types.ETReal:
sig = &builtinRoundWithFracRealSig{bf}
default:
panic("unexpected argTp")
}
} else {
switch argTp {
case types.ETInt:
sig = &builtinRoundIntSig{bf}
case types.ETDecimal:
sig = &builtinRoundDecSig{bf}
case types.ETReal:
sig = &builtinRoundRealSig{bf}
default:
panic("unexpected argTp")
}
}
return sig, nil
}
type builtinRoundRealSig struct {
baseBuiltinFunc
}
func (b *builtinRoundRealSig) Clone() builtinFunc {
newSig := &builtinRoundRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals ROUND(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundRealSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return types.Round(val, 0), false, nil
}
type builtinRoundIntSig struct {
baseBuiltinFunc
}
func (b *builtinRoundIntSig) Clone() builtinFunc {
newSig := &builtinRoundIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals ROUND(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundIntSig) evalInt(row types.Row) (int64, bool, error) {
return b.args[0].EvalInt(b.ctx, row)
}
type builtinRoundDecSig struct {
baseBuiltinFunc
}
func (b *builtinRoundDecSig) Clone() builtinFunc {
newSig := &builtinRoundDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDecimal evals ROUND(value).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
to := new(types.MyDecimal)
if err = val.Round(to, 0, types.ModeHalfEven); err != nil {
return nil, true, errors.Trace(err)
}
return to, false, nil
}
type builtinRoundWithFracRealSig struct {
baseBuiltinFunc
}
func (b *builtinRoundWithFracRealSig) Clone() builtinFunc {
newSig := &builtinRoundWithFracRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals ROUND(value, frac).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundWithFracRealSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
frac, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return types.Round(val, int(frac)), false, nil
}
type builtinRoundWithFracIntSig struct {
baseBuiltinFunc
}
func (b *builtinRoundWithFracIntSig) Clone() builtinFunc {
newSig := &builtinRoundWithFracIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals ROUND(value, frac).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundWithFracIntSig) evalInt(row types.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
frac, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return int64(types.Round(float64(val), int(frac))), false, nil
}
type builtinRoundWithFracDecSig struct {
baseBuiltinFunc
}
func (b *builtinRoundWithFracDecSig) Clone() builtinFunc {
newSig := &builtinRoundWithFracDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDecimal evals ROUND(value, frac).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
func (b *builtinRoundWithFracDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
frac, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
to := new(types.MyDecimal)
if err = val.Round(to, int(frac), types.ModeHalfEven); err != nil {
return nil, true, errors.Trace(err)
}
return to, false, nil
}
type ceilFunctionClass struct {
baseFunctionClass
}
func (c *ceilFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
if err = c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
retTp, argTp := getEvalTp4FloorAndCeil(args[0])
bf := newBaseBuiltinFuncWithTp(ctx, args, retTp, argTp)
setFlag4FloorAndCeil(bf.tp, args[0])
argFieldTp := args[0].GetType()
bf.tp.Flen, bf.tp.Decimal = argFieldTp.Flen, 0
switch argTp {
case types.ETInt:
if retTp == types.ETInt {
sig = &builtinCeilIntToIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CeilIntToInt)
} else {
sig = &builtinCeilIntToDecSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CeilIntToDec)
}
case types.ETDecimal:
if retTp == types.ETInt {
sig = &builtinCeilDecToIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CeilDecToInt)
} else {
sig = &builtinCeilDecToDecSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CeilDecToDec)
}
default:
sig = &builtinCeilRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CeilReal)
}
return sig, nil
}
type builtinCeilRealSig struct {
baseBuiltinFunc
}
func (b *builtinCeilRealSig) Clone() builtinFunc {
newSig := &builtinCeilRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinCeilRealSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil
func (b *builtinCeilRealSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Ceil(val), false, nil
}
type builtinCeilIntToIntSig struct {
baseBuiltinFunc
}
func (b *builtinCeilIntToIntSig) Clone() builtinFunc {
newSig := &builtinCeilIntToIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a builtinCeilIntToIntSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil
func (b *builtinCeilIntToIntSig) evalInt(row types.Row) (int64, bool, error) {
return b.args[0].EvalInt(b.ctx, row)
}
type builtinCeilIntToDecSig struct {
baseBuiltinFunc
}
func (b *builtinCeilIntToDecSig) Clone() builtinFunc {
newSig := &builtinCeilIntToDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDec evals a builtinCeilIntToDecSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_Ceil
func (b *builtinCeilIntToDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return nil, true, errors.Trace(err)
}
if mysql.HasUnsignedFlag(b.args[0].GetType().Flag) || val >= 0 {
return types.NewDecFromUint(uint64(val)), false, nil
}
return types.NewDecFromInt(val), false, nil
}
type builtinCeilDecToIntSig struct {
baseBuiltinFunc
}
func (b *builtinCeilDecToIntSig) Clone() builtinFunc {
newSig := &builtinCeilDecToIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a builtinCeilDecToIntSig.
// Ceil receives
func (b *builtinCeilDecToIntSig) evalInt(row types.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
// err here will only be ErrOverFlow(will never happen) or ErrTruncate(can be ignored).
res, err := val.ToInt()
if err == types.ErrTruncated {
err = nil
if !val.IsNegative() {
res = res + 1
}
}
return res, false, errors.Trace(err)
}
type builtinCeilDecToDecSig struct {
baseBuiltinFunc
}
func (b *builtinCeilDecToDecSig) Clone() builtinFunc {
newSig := &builtinCeilDecToDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDec evals a builtinCeilDecToDecSig.
func (b *builtinCeilDecToDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
res := new(types.MyDecimal)
if val.IsNegative() {
err = val.Round(res, 0, types.ModeTruncate)
return res, err != nil, errors.Trace(err)
}
err = val.Round(res, 0, types.ModeTruncate)
if err != nil || res.Compare(val) == 0 {
return res, err != nil, errors.Trace(err)
}
err = types.DecimalAdd(res, types.NewDecFromInt(1), res)
return res, err != nil, errors.Trace(err)
}
type floorFunctionClass struct {
baseFunctionClass
}
// getEvalTp4FloorAndCeil gets the types.EvalType of FLOOR and CEIL.
func getEvalTp4FloorAndCeil(arg Expression) (retTp, argTp types.EvalType) {
fieldTp := arg.GetType()
retTp, argTp = types.ETInt, fieldTp.EvalType()
switch argTp {
case types.ETInt:
if fieldTp.Tp == mysql.TypeLonglong {
retTp = types.ETDecimal
}
case types.ETDecimal:
if fieldTp.Flen-fieldTp.Decimal > mysql.MaxIntWidth-2 { // len(math.MaxInt64) - 1
retTp = types.ETDecimal
}
default:
retTp, argTp = types.ETReal, types.ETReal
}
return retTp, argTp
}
// setFlag4FloorAndCeil sets return flag of FLOOR and CEIL.
func setFlag4FloorAndCeil(tp *types.FieldType, arg Expression) {
fieldTp := arg.GetType()
if (fieldTp.Tp == mysql.TypeLong || fieldTp.Tp == mysql.TypeNewDecimal) && mysql.HasUnsignedFlag(fieldTp.Flag) {
tp.Flag |= mysql.UnsignedFlag
}
// TODO: when argument type is timestamp, add not null flag.
}
func (c *floorFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
if err = c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
retTp, argTp := getEvalTp4FloorAndCeil(args[0])
bf := newBaseBuiltinFuncWithTp(ctx, args, retTp, argTp)
setFlag4FloorAndCeil(bf.tp, args[0])
bf.tp.Flen, bf.tp.Decimal = args[0].GetType().Flen, 0
switch argTp {
case types.ETInt:
if retTp == types.ETInt {
sig = &builtinFloorIntToIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_FloorIntToInt)
} else {
sig = &builtinFloorIntToDecSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_FloorIntToDec)
}
case types.ETDecimal:
if retTp == types.ETInt {
sig = &builtinFloorDecToIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_FloorDecToInt)
} else {
sig = &builtinFloorDecToDecSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_FloorDecToDec)
}
default:
sig = &builtinFloorRealSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_FloorReal)
}
return sig, nil
}
type builtinFloorRealSig struct {
baseBuiltinFunc
}
func (b *builtinFloorRealSig) Clone() builtinFunc {
newSig := &builtinFloorRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinFloorRealSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor
func (b *builtinFloorRealSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Floor(val), false, nil
}
type builtinFloorIntToIntSig struct {
baseBuiltinFunc
}
func (b *builtinFloorIntToIntSig) Clone() builtinFunc {
newSig := &builtinFloorIntToIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a builtinFloorIntToIntSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor
func (b *builtinFloorIntToIntSig) evalInt(row types.Row) (int64, bool, error) {
return b.args[0].EvalInt(b.ctx, row)
}
type builtinFloorIntToDecSig struct {
baseBuiltinFunc
}
func (b *builtinFloorIntToDecSig) Clone() builtinFunc {
newSig := &builtinFloorIntToDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDec evals a builtinFloorIntToDecSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor
func (b *builtinFloorIntToDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return nil, true, errors.Trace(err)
}
if mysql.HasUnsignedFlag(b.args[0].GetType().Flag) || val >= 0 {
return types.NewDecFromUint(uint64(val)), false, nil
}
return types.NewDecFromInt(val), false, nil
}
type builtinFloorDecToIntSig struct {
baseBuiltinFunc
}
func (b *builtinFloorDecToIntSig) Clone() builtinFunc {
newSig := &builtinFloorDecToIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a builtinFloorDecToIntSig.
// floor receives
func (b *builtinFloorDecToIntSig) evalInt(row types.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
// err here will only be ErrOverFlow(will never happen) or ErrTruncate(can be ignored).
res, err := val.ToInt()
if err == types.ErrTruncated {
err = nil
if val.IsNegative() {
res--
}
}
return res, false, errors.Trace(err)
}
type builtinFloorDecToDecSig struct {
baseBuiltinFunc
}
func (b *builtinFloorDecToDecSig) Clone() builtinFunc {
newSig := &builtinFloorDecToDecSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDec evals a builtinFloorDecToDecSig.
func (b *builtinFloorDecToDecSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, true, errors.Trace(err)
}
res := new(types.MyDecimal)
if !val.IsNegative() {
err = val.Round(res, 0, types.ModeTruncate)
return res, err != nil, errors.Trace(err)
}
err = val.Round(res, 0, types.ModeTruncate)
if err != nil || res.Compare(val) == 0 {
return res, err != nil, errors.Trace(err)
}
err = types.DecimalSub(res, types.NewDecFromInt(1), res)
return res, err != nil, errors.Trace(err)
}
type logFunctionClass struct {
baseFunctionClass
}
func (c *logFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
var (
sig builtinFunc
bf baseBuiltinFunc
argsLen = len(args)
)
if argsLen == 1 {
bf = newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
} else {
bf = newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal, types.ETReal)
}
if argsLen == 1 {
sig = &builtinLog1ArgSig{bf}
} else {
sig = &builtinLog2ArgsSig{bf}
}
return sig, nil
}
type builtinLog1ArgSig struct {
baseBuiltinFunc
}
func (b *builtinLog1ArgSig) Clone() builtinFunc {
newSig := &builtinLog1ArgSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinLog1ArgSig, corresponding to log(x).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log
func (b *builtinLog1ArgSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val <= 0 {
return 0, true, nil
}
return math.Log(val), false, nil
}
type builtinLog2ArgsSig struct {
baseBuiltinFunc
}
func (b *builtinLog2ArgsSig) Clone() builtinFunc {
newSig := &builtinLog2ArgsSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinLog2ArgsSig, corresponding to log(b, x).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log
func (b *builtinLog2ArgsSig) evalReal(row types.Row) (float64, bool, error) {
val1, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
val2, isNull, err := b.args[1].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val1 <= 0 || val1 == 1 || val2 <= 0 {
return 0, true, nil
}
return math.Log(val2) / math.Log(val1), false, nil
}
type log2FunctionClass struct {
baseFunctionClass
}
func (c *log2FunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinLog2Sig{bf}
return sig, nil
}
type builtinLog2Sig struct {
baseBuiltinFunc
}
func (b *builtinLog2Sig) Clone() builtinFunc {
newSig := &builtinLog2Sig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinLog2Sig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log2
func (b *builtinLog2Sig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val <= 0 {
return 0, true, nil
}
return math.Log2(val), false, nil
}
type log10FunctionClass struct {
baseFunctionClass
}
func (c *log10FunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinLog10Sig{bf}
return sig, nil
}
type builtinLog10Sig struct {
baseBuiltinFunc
}
func (b *builtinLog10Sig) Clone() builtinFunc {
newSig := &builtinLog10Sig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinLog10Sig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log10
func (b *builtinLog10Sig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val <= 0 {
return 0, true, nil
}
return math.Log10(val), false, nil
}
type randFunctionClass struct {
baseFunctionClass
}
func (c *randFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
var sig builtinFunc
var argTps []types.EvalType
if len(args) > 0 {
argTps = []types.EvalType{types.ETInt}
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, argTps...)
bt := bf
if len(args) == 0 {
sig = &builtinRandSig{bt, nil}
} else {
sig = &builtinRandWithSeedSig{bt, nil}
}
return sig, nil
}
type builtinRandSig struct {
baseBuiltinFunc
randGen *rand.Rand
}
func (b *builtinRandSig) Clone() builtinFunc {
newSig := &builtinRandSig{randGen: b.randGen}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals RAND().
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand
func (b *builtinRandSig) evalReal(row types.Row) (float64, bool, error) {
if b.randGen == nil {
b.randGen = rand.New(rand.NewSource(time.Now().UnixNano()))
}
return b.randGen.Float64(), false, nil
}
type builtinRandWithSeedSig struct {
baseBuiltinFunc
randGen *rand.Rand
}
func (b *builtinRandWithSeedSig) Clone() builtinFunc {
newSig := &builtinRandWithSeedSig{randGen: b.randGen}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals RAND(N).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand
func (b *builtinRandWithSeedSig) evalReal(row types.Row) (float64, bool, error) {
seed, isNull, err := b.args[0].EvalInt(b.ctx, row)
if err != nil {
return 0, true, errors.Trace(err)
}
if b.randGen == nil {
if isNull {
// When seed is NULL, it is equal to RAND().
b.randGen = rand.New(rand.NewSource(time.Now().UnixNano()))
} else {
b.randGen = rand.New(rand.NewSource(seed))
}
}
return b.randGen.Float64(), false, nil
}
type powFunctionClass struct {
baseFunctionClass
}
func (c *powFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal, types.ETReal)
sig := &builtinPowSig{bf}
return sig, nil
}
type builtinPowSig struct {
baseBuiltinFunc
}
func (b *builtinPowSig) Clone() builtinFunc {
newSig := &builtinPowSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals POW(x, y).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_pow
func (b *builtinPowSig) evalReal(row types.Row) (float64, bool, error) {
x, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
y, isNull, err := b.args[1].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
power := math.Pow(x, y)
if math.IsInf(power, -1) || math.IsInf(power, 1) || math.IsNaN(power) {
return 0, false, types.ErrOverflow.GenByArgs("DOUBLE", fmt.Sprintf("pow(%s, %s)", strconv.FormatFloat(x, 'f', -1, 64), strconv.FormatFloat(y, 'f', -1, 64)))
}
return power, false, nil
}
type roundFunctionClass struct {
baseFunctionClass
}
type convFunctionClass struct {
baseFunctionClass
}
func (c *convFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETString, types.ETString, types.ETInt, types.ETInt)
bf.tp.Flen = 64
sig := &builtinConvSig{bf}
return sig, nil
}
type builtinConvSig struct {
baseBuiltinFunc
}
func (b *builtinConvSig) Clone() builtinFunc {
newSig := &builtinConvSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalString evals CONV(N,from_base,to_base).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_conv.
func (b *builtinConvSig) evalString(row types.Row) (res string, isNull bool, err error) {
n, isNull, err := b.args[0].EvalString(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
fromBase, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
toBase, isNull, err := b.args[2].EvalInt(b.ctx, row)
if isNull || err != nil {
return res, isNull, errors.Trace(err)
}
var (
signed bool
negative bool
ignoreSign bool
)
if fromBase < 0 {
fromBase = -fromBase
signed = true
}
if toBase < 0 {
toBase = -toBase
ignoreSign = true
}
if fromBase > 36 || fromBase < 2 || toBase > 36 || toBase < 2 {
return res, true, nil
}
n = getValidPrefix(strings.TrimSpace(n), fromBase)
if len(n) == 0 {
return "0", false, nil
}
if n[0] == '-' {
negative = true
n = n[1:]
}
val, err := strconv.ParseUint(n, int(fromBase), 64)
if err != nil {
return res, false, types.ErrOverflow.GenByArgs("BIGINT UNSINGED", n)
}
if signed {
if negative && val > -math.MinInt64 {
val = -math.MinInt64
}
if !negative && val > math.MaxInt64 {
val = math.MaxInt64
}
}
if negative {
val = -val
}
if int64(val) < 0 {
negative = true
} else {
negative = false
}
if ignoreSign && negative {
val = 0 - val
}
s := strconv.FormatUint(val, int(toBase))
if negative && ignoreSign {
s = "-" + s
}
res = strings.ToUpper(s)
return res, false, nil
}
type crc32FunctionClass struct {
baseFunctionClass
}
func (c *crc32FunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETInt, types.ETString)
bf.tp.Flen = 10
bf.tp.Flag |= mysql.UnsignedFlag
sig := &builtinCRC32Sig{bf}
return sig, nil
}
type builtinCRC32Sig struct {
baseBuiltinFunc
}
func (b *builtinCRC32Sig) Clone() builtinFunc {
newSig := &builtinCRC32Sig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a CRC32(expr).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_crc32
func (b *builtinCRC32Sig) evalInt(row types.Row) (int64, bool, error) {
x, isNull, err := b.args[0].EvalString(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
r := crc32.ChecksumIEEE([]byte(x))
return int64(r), false, nil
}
type signFunctionClass struct {
baseFunctionClass
}
func (c *signFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETInt, types.ETReal)
sig := &builtinSignSig{bf}
return sig, nil
}
type builtinSignSig struct {
baseBuiltinFunc
}
func (b *builtinSignSig) Clone() builtinFunc {
newSig := &builtinSignSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals SIGN(v).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sign
func (b *builtinSignSig) evalInt(row types.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val > 0 {
return 1, false, nil
} else if val == 0 {
return 0, false, nil
} else {
return -1, false, nil
}
}
type sqrtFunctionClass struct {
baseFunctionClass
}
func (c *sqrtFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinSqrtSig{bf}
return sig, nil
}
type builtinSqrtSig struct {
baseBuiltinFunc
}
func (b *builtinSqrtSig) Clone() builtinFunc {
newSig := &builtinSqrtSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a SQRT(x).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sqrt
func (b *builtinSqrtSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val < 0 {
return 0, true, nil
}
return math.Sqrt(val), false, nil
}
type acosFunctionClass struct {
baseFunctionClass
}
func (c *acosFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinAcosSig{bf}
return sig, nil
}
type builtinAcosSig struct {
baseBuiltinFunc
}
func (b *builtinAcosSig) Clone() builtinFunc {
newSig := &builtinAcosSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinAcosSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_acos
func (b *builtinAcosSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val < -1 || val > 1 {
return 0, true, nil
}
return math.Acos(val), false, nil
}
type asinFunctionClass struct {
baseFunctionClass
}
func (c *asinFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinAsinSig{bf}
return sig, nil
}
type builtinAsinSig struct {
baseBuiltinFunc
}
func (b *builtinAsinSig) Clone() builtinFunc {
newSig := &builtinAsinSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinAsinSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_asin
func (b *builtinAsinSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if val < -1 || val > 1 {
return 0, true, nil
}
return math.Asin(val), false, nil
}
type atanFunctionClass struct {
baseFunctionClass
}
func (c *atanFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
var (
sig builtinFunc
bf baseBuiltinFunc
argsLen = len(args)
)
if argsLen == 1 {
bf = newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
} else {
bf = newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal, types.ETReal)
}
if argsLen == 1 {
sig = &builtinAtan1ArgSig{bf}
} else {
sig = &builtinAtan2ArgsSig{bf}
}
return sig, nil
}
type builtinAtan1ArgSig struct {
baseBuiltinFunc
}
func (b *builtinAtan1ArgSig) Clone() builtinFunc {
newSig := &builtinAtan1ArgSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinAtan1ArgSig, corresponding to atan(x).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_atan
func (b *builtinAtan1ArgSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Atan(val), false, nil
}
type builtinAtan2ArgsSig struct {
baseBuiltinFunc
}
func (b *builtinAtan2ArgsSig) Clone() builtinFunc {
newSig := &builtinAtan2ArgsSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinAtan1ArgSig, corresponding to atan(y, x).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_atan
func (b *builtinAtan2ArgsSig) evalReal(row types.Row) (float64, bool, error) {
val1, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
val2, isNull, err := b.args[1].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Atan2(val1, val2), false, nil
}
type cosFunctionClass struct {
baseFunctionClass
}
func (c *cosFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinCosSig{bf}
return sig, nil
}
type builtinCosSig struct {
baseBuiltinFunc
}
func (b *builtinCosSig) Clone() builtinFunc {
newSig := &builtinCosSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinCosSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_cos
func (b *builtinCosSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Cos(val), false, nil
}
type cotFunctionClass struct {
baseFunctionClass
}
func (c *cotFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinCotSig{bf}
return sig, nil
}
type builtinCotSig struct {
baseBuiltinFunc
}
func (b *builtinCotSig) Clone() builtinFunc {
newSig := &builtinCotSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinCotSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_cot
func (b *builtinCotSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
tan := math.Tan(val)
if tan != 0 {
cot := 1 / tan
if !math.IsInf(cot, 0) && !math.IsNaN(cot) {
return cot, false, nil
}
}
return 0, false, types.ErrOverflow.GenByArgs("DOUBLE", fmt.Sprintf("cot(%s)", strconv.FormatFloat(val, 'f', -1, 64)))
}
type degreesFunctionClass struct {
baseFunctionClass
}
func (c *degreesFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinDegreesSig{bf}
return sig, nil
}
type builtinDegreesSig struct {
baseBuiltinFunc
}
func (b *builtinDegreesSig) Clone() builtinFunc {
newSig := &builtinDegreesSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinDegreesSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_degrees
func (b *builtinDegreesSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
res := val * 180 / math.Pi
return res, false, nil
}
type expFunctionClass struct {
baseFunctionClass
}
func (c *expFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinExpSig{bf}
return sig, nil
}
type builtinExpSig struct {
baseBuiltinFunc
}
func (b *builtinExpSig) Clone() builtinFunc {
newSig := &builtinExpSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinExpSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_exp
func (b *builtinExpSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
exp := math.Exp(val)
if math.IsInf(exp, 0) || math.IsNaN(exp) {
s := fmt.Sprintf("exp(%s)", strconv.FormatFloat(val, 'f', -1, 64))
return 0, false, types.ErrOverflow.GenByArgs("DOUBLE", s)
}
return exp, false, nil
}
type piFunctionClass struct {
baseFunctionClass
}
func (c *piFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
var (
bf baseBuiltinFunc
sig builtinFunc
)
bf = newBaseBuiltinFuncWithTp(ctx, args, types.ETReal)
bf.tp.Decimal = 6
bf.tp.Flen = 8
sig = &builtinPISig{bf}
return sig, nil
}
type builtinPISig struct {
baseBuiltinFunc
}
func (b *builtinPISig) Clone() builtinFunc {
newSig := &builtinPISig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a builtinPISig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_pi
func (b *builtinPISig) evalReal(_ types.Row) (float64, bool, error) {
return float64(math.Pi), false, nil
}
type radiansFunctionClass struct {
baseFunctionClass
}
func (c *radiansFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinRadiansSig{bf}
return sig, nil
}
type builtinRadiansSig struct {
baseBuiltinFunc
}
func (b *builtinRadiansSig) Clone() builtinFunc {
newSig := &builtinRadiansSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals RADIANS(X).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_radians
func (b *builtinRadiansSig) evalReal(row types.Row) (float64, bool, error) {
x, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return x * math.Pi / 180, false, nil
}
type sinFunctionClass struct {
baseFunctionClass
}
func (c *sinFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinSinSig{bf}
return sig, nil
}
type builtinSinSig struct {
baseBuiltinFunc
}
func (b *builtinSinSig) Clone() builtinFunc {
newSig := &builtinSinSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalreal evals a builtinSinSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sin
func (b *builtinSinSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Sin(val), false, nil
}
type tanFunctionClass struct {
baseFunctionClass
}
func (c *tanFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETReal, types.ETReal)
sig := &builtinTanSig{bf}
return sig, nil
}
type builtinTanSig struct {
baseBuiltinFunc
}
func (b *builtinTanSig) Clone() builtinFunc {
newSig := &builtinTanSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// eval evals a builtinTanSig.
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_tan
func (b *builtinTanSig) evalReal(row types.Row) (float64, bool, error) {
val, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return math.Tan(val), false, nil
}
type truncateFunctionClass struct {
baseFunctionClass
}
// getDecimal returns the `Decimal` value of return type for function `TRUNCATE`.
func (c *truncateFunctionClass) getDecimal(ctx sessionctx.Context, arg Expression) int {
if constant, ok := arg.(*Constant); ok {
decimal, isNull, err := constant.EvalInt(ctx, nil)
if isNull || err != nil {
return 0
} else if decimal > 30 {
return 30
} else if decimal < 0 {
return 0
}
return int(decimal)
}
return 3
}
func (c *truncateFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
argTp := args[0].GetType().EvalType()
if argTp == types.ETTimestamp || argTp == types.ETDatetime || argTp == types.ETDuration || argTp == types.ETString {
argTp = types.ETReal
}
bf := newBaseBuiltinFuncWithTp(ctx, args, argTp, argTp, types.ETInt)
if argTp == types.ETInt {
bf.tp.Decimal = 0
} else {
bf.tp.Decimal = c.getDecimal(bf.ctx, args[1])
}
bf.tp.Flen = args[0].GetType().Flen - args[0].GetType().Decimal + bf.tp.Decimal
bf.tp.Flag |= args[0].GetType().Flag
var sig builtinFunc
switch argTp {
case types.ETInt:
if mysql.HasUnsignedFlag(args[0].GetType().Flag) {
sig = &builtinTruncateUintSig{bf}
} else {
sig = &builtinTruncateIntSig{bf}
}
case types.ETReal:
sig = &builtinTruncateRealSig{bf}
case types.ETDecimal:
sig = &builtinTruncateDecimalSig{bf}
}
return sig, nil
}
type builtinTruncateDecimalSig struct {
baseBuiltinFunc
}
func (b *builtinTruncateDecimalSig) Clone() builtinFunc {
newSig := &builtinTruncateDecimalSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalDecimal evals a TRUNCATE(X,D).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate
func (b *builtinTruncateDecimalSig) evalDecimal(row types.Row) (*types.MyDecimal, bool, error) {
x, isNull, err := b.args[0].EvalDecimal(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
d, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return nil, isNull, errors.Trace(err)
}
result := new(types.MyDecimal)
if err := x.Round(result, int(d), types.ModeTruncate); err != nil {
return nil, true, errors.Trace(err)
}
return result, false, nil
}
type builtinTruncateRealSig struct {
baseBuiltinFunc
}
func (b *builtinTruncateRealSig) Clone() builtinFunc {
newSig := &builtinTruncateRealSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalReal evals a TRUNCATE(X,D).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate
func (b *builtinTruncateRealSig) evalReal(row types.Row) (float64, bool, error) {
x, isNull, err := b.args[0].EvalReal(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
d, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
return types.Truncate(x, int(d)), false, nil
}
type builtinTruncateIntSig struct {
baseBuiltinFunc
}
func (b *builtinTruncateIntSig) Clone() builtinFunc {
newSig := &builtinTruncateIntSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
// evalInt evals a TRUNCATE(X,D).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate
func (b *builtinTruncateIntSig) evalInt(row types.Row) (int64, bool, error) {
x, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
d, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if d >= 0 {
return x, false, nil
}
shift := int64(math.Pow10(int(-d)))
return x / shift * shift, false, nil
}
func (b *builtinTruncateUintSig) Clone() builtinFunc {
newSig := &builtinTruncateUintSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}
type builtinTruncateUintSig struct {
baseBuiltinFunc
}
// evalInt evals a TRUNCATE(X,D).
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate
func (b *builtinTruncateUintSig) evalInt(row types.Row) (int64, bool, error) {
x, isNull, err := b.args[0].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
uintx := uint64(x)
d, isNull, err := b.args[1].EvalInt(b.ctx, row)
if isNull || err != nil {
return 0, isNull, errors.Trace(err)
}
if d >= 0 {
return x, false, nil
}
shift := uint64(math.Pow10(int(-d)))
return int64(uintx / shift * shift), false, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/pingcap/tidb.git
git@gitee.com:pingcap/tidb.git
pingcap
tidb
tidb
v2.0.11

搜索帮助