900 lines
23 KiB
Go
900 lines
23 KiB
Go
// 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 (
|
|
"hash/crc32"
|
|
"math"
|
|
"math/rand"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/juju/errors"
|
|
"github.com/pingcap/tidb/context"
|
|
"github.com/pingcap/tidb/parser/opcode"
|
|
"github.com/pingcap/tidb/util/types"
|
|
)
|
|
|
|
var (
|
|
_ functionClass = &absFunctionClass{}
|
|
_ functionClass = &ceilFunctionClass{}
|
|
_ functionClass = &floorFunctionClass{}
|
|
_ functionClass = &logFunctionClass{}
|
|
_ functionClass = &log2FunctionClass{}
|
|
_ functionClass = &log10FunctionClass{}
|
|
_ functionClass = &randFunctionClass{}
|
|
_ functionClass = &powFunctionClass{}
|
|
_ functionClass = &roundFunctionClass{}
|
|
_ functionClass = &convFunctionClass{}
|
|
_ functionClass = &crc32FunctionClass{}
|
|
_ functionClass = &signFunctionClass{}
|
|
_ functionClass = &sqrtFunctionClass{}
|
|
_ functionClass = &arithmeticFunctionClass{}
|
|
_ functionClass = &acosFunctionClass{}
|
|
_ functionClass = &asinFunctionClass{}
|
|
_ functionClass = &atanFunctionClass{}
|
|
_ functionClass = &cosFunctionClass{}
|
|
_ functionClass = &cotFunctionClass{}
|
|
_ functionClass = °reesFunctionClass{}
|
|
_ functionClass = &expFunctionClass{}
|
|
_ functionClass = &piFunctionClass{}
|
|
_ functionClass = &radiansFunctionClass{}
|
|
_ functionClass = &sinFunctionClass{}
|
|
_ functionClass = &tanFunctionClass{}
|
|
_ functionClass = &truncateFunctionClass{}
|
|
)
|
|
|
|
var (
|
|
_ builtinFunc = &builtinAbsSig{}
|
|
_ builtinFunc = &builtinCeilSig{}
|
|
_ builtinFunc = &builtinFloorSig{}
|
|
_ builtinFunc = &builtinLogSig{}
|
|
_ builtinFunc = &builtinLog2Sig{}
|
|
_ builtinFunc = &builtinLog10Sig{}
|
|
_ builtinFunc = &builtinRandSig{}
|
|
_ builtinFunc = &builtinPowSig{}
|
|
_ builtinFunc = &builtinRoundSig{}
|
|
_ builtinFunc = &builtinConvSig{}
|
|
_ builtinFunc = &builtinCRC32Sig{}
|
|
_ builtinFunc = &builtinSignSig{}
|
|
_ builtinFunc = &builtinSqrtSig{}
|
|
_ builtinFunc = &builtinArithmeticSig{}
|
|
_ builtinFunc = &builtinAcosSig{}
|
|
_ builtinFunc = &builtinAsinSig{}
|
|
_ builtinFunc = &builtinAtanSig{}
|
|
_ builtinFunc = &builtinCosSig{}
|
|
_ builtinFunc = &builtinCotSig{}
|
|
_ builtinFunc = &builtinDegreesSig{}
|
|
_ builtinFunc = &builtinExpSig{}
|
|
_ builtinFunc = &builtinPISig{}
|
|
_ builtinFunc = &builtinRadiansSig{}
|
|
_ builtinFunc = &builtinSinSig{}
|
|
_ builtinFunc = &builtinTanSig{}
|
|
_ builtinFunc = &builtinTruncateSig{}
|
|
)
|
|
|
|
type absFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *absFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinAbsSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinAbsSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs
|
|
func (b *builtinAbsSig) eval(row []types.Datum) (types.Datum, error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
d := args[0]
|
|
switch d.Kind() {
|
|
case types.KindNull:
|
|
return d, nil
|
|
case types.KindUint64:
|
|
return d, nil
|
|
case types.KindInt64:
|
|
iv := d.GetInt64()
|
|
if iv >= 0 {
|
|
d.SetInt64(iv)
|
|
return d, nil
|
|
}
|
|
d.SetInt64(-iv)
|
|
return d, nil
|
|
default:
|
|
// we will try to convert other types to float
|
|
// TODO: if time has no precision, it will be a integer
|
|
f, err := d.ToFloat64(b.ctx.GetSessionVars().StmtCtx)
|
|
d.SetFloat64(math.Abs(f))
|
|
return d, errors.Trace(err)
|
|
}
|
|
}
|
|
|
|
type ceilFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *ceilFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinCeilSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinCeilSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling
|
|
func (b *builtinCeilSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() ||
|
|
args[0].Kind() == types.KindUint64 || args[0].Kind() == types.KindInt64 {
|
|
return args[0], nil
|
|
}
|
|
|
|
f, err := args[0].ToFloat64(b.ctx.GetSessionVars().StmtCtx)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
d.SetFloat64(math.Ceil(f))
|
|
return
|
|
}
|
|
|
|
type floorFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *floorFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinFloorSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinFloorSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor
|
|
func (b *builtinFloorSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() ||
|
|
args[0].Kind() == types.KindUint64 || args[0].Kind() == types.KindInt64 {
|
|
return args[0], nil
|
|
}
|
|
|
|
// have to set IgnoreTruncate to true in order to getValidPrefix
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
tmpIT := sc.IgnoreTruncate
|
|
sc.IgnoreTruncate = true
|
|
f, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
sc.IgnoreTruncate = tmpIT
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
sc.IgnoreTruncate = tmpIT
|
|
d.SetFloat64(math.Floor(f))
|
|
return
|
|
}
|
|
|
|
type logFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *logFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinLogSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinLogSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log
|
|
func (b *builtinLogSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
|
|
switch len(args) {
|
|
case 1:
|
|
x, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
if x <= 0 {
|
|
return d, nil
|
|
}
|
|
|
|
d.SetFloat64(math.Log(x))
|
|
return d, nil
|
|
case 2:
|
|
b, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
x, err := args[1].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
if b <= 1 || x <= 0 {
|
|
return d, nil
|
|
}
|
|
|
|
d.SetFloat64(math.Log(x) / math.Log(b))
|
|
return d, nil
|
|
}
|
|
return
|
|
}
|
|
|
|
type log2FunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *log2FunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinLog2Sig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinLog2Sig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log2
|
|
func (b *builtinLog2Sig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
x, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
if x <= 0 {
|
|
return
|
|
}
|
|
|
|
d.SetFloat64(math.Log2(x))
|
|
return
|
|
}
|
|
|
|
type log10FunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *log10FunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinLog10Sig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinLog10Sig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_log10
|
|
func (b *builtinLog10Sig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
x, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
if x <= 0 {
|
|
return
|
|
}
|
|
|
|
d.SetFloat64(math.Log10(x))
|
|
return
|
|
|
|
}
|
|
|
|
type randFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *randFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
err := errors.Trace(c.verifyArgs(args))
|
|
bt := &builtinRandSig{newBaseBuiltinFunc(args, ctx)}
|
|
bt.deterministic = false
|
|
return bt, errors.Trace(err)
|
|
}
|
|
|
|
type builtinRandSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand
|
|
func (b *builtinRandSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if len(args) == 1 && !args[0].IsNull() {
|
|
seed, err := args[0].ToInt64(b.ctx.GetSessionVars().StmtCtx)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
rand.Seed(seed)
|
|
}
|
|
d.SetFloat64(rand.Float64())
|
|
return d, nil
|
|
}
|
|
|
|
type powFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *powFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinPowSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinPowSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_pow
|
|
func (b *builtinPowSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
x, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
y, err := args[1].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
d.SetFloat64(math.Pow(x, y))
|
|
return d, nil
|
|
}
|
|
|
|
type roundFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *roundFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinRoundSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinRoundSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_round
|
|
func (b *builtinRoundSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() {
|
|
return
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
|
|
frac := 0
|
|
if len(args) == 2 {
|
|
frac64, err1 := args[1].ToInt64(sc)
|
|
if err1 != nil {
|
|
return d, errors.Trace(err1)
|
|
}
|
|
frac = int(frac64)
|
|
}
|
|
|
|
if args[0].Kind() == types.KindMysqlDecimal {
|
|
var dec types.MyDecimal
|
|
err = args[0].GetMysqlDecimal().Round(&dec, frac)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
d.SetMysqlDecimal(&dec)
|
|
return d, nil
|
|
}
|
|
|
|
x, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
val := types.Round(x, frac)
|
|
switch args[0].Kind() {
|
|
case types.KindInt64:
|
|
d.SetInt64(int64(val))
|
|
case types.KindUint64:
|
|
d.SetUint64(uint64(val))
|
|
default:
|
|
d.SetFloat64(val)
|
|
if frac > 0 {
|
|
d.SetFrac(frac)
|
|
}
|
|
}
|
|
return d, nil
|
|
}
|
|
|
|
type convFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *convFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinConvSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinConvSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_conv
|
|
func (b *builtinConvSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
var (
|
|
signed bool
|
|
negative bool
|
|
ignoreSign bool
|
|
)
|
|
for _, arg := range args {
|
|
if arg.IsNull() {
|
|
return d, nil
|
|
}
|
|
}
|
|
n, err := args[0].ToString()
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
fromBase, err := args[1].ToInt64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
toBase, err := args[2].ToInt64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
if fromBase < 0 {
|
|
fromBase = -fromBase
|
|
signed = true
|
|
}
|
|
if toBase < 0 {
|
|
ignoreSign = true
|
|
toBase = -toBase
|
|
}
|
|
if fromBase > 36 || fromBase < 2 || toBase > 36 || toBase < 2 {
|
|
return d, nil
|
|
}
|
|
n = getValidPrefix(strings.TrimSpace(n), fromBase)
|
|
if len(n) == 0 {
|
|
return d, nil
|
|
}
|
|
if n[0] == '-' {
|
|
negative = true
|
|
n = n[1:]
|
|
}
|
|
|
|
val, err := strconv.ParseUint(n, int(fromBase), 64)
|
|
if err != nil {
|
|
return d, errors.Trace(types.ErrOverflow)
|
|
}
|
|
// See https://github.com/mysql/mysql-server/blob/5.7/strings/ctype-simple.c#L598
|
|
if signed {
|
|
if negative && val > -math.MinInt64 {
|
|
val = -math.MinInt64
|
|
}
|
|
if !negative && val > math.MaxInt64 {
|
|
val = math.MaxInt64
|
|
}
|
|
}
|
|
if negative {
|
|
val = -val
|
|
}
|
|
// See https://github.com/mysql/mysql-server/blob/5.7/strings/longlong2str.c#L58
|
|
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
|
|
}
|
|
d.SetString(strings.ToUpper(s))
|
|
return d, nil
|
|
}
|
|
|
|
type crc32FunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *crc32FunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinCRC32Sig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinCRC32Sig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_crc32
|
|
func (b *builtinCRC32Sig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() {
|
|
return d, nil
|
|
}
|
|
x, err := args[0].ToString()
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
r := crc32.ChecksumIEEE([]byte(x))
|
|
d.SetUint64(uint64(r))
|
|
return d, nil
|
|
}
|
|
|
|
type signFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *signFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinSignSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinSignSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sign
|
|
func (b *builtinSignSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() {
|
|
return d, nil
|
|
}
|
|
cmp, err := args[0].CompareDatum(b.ctx.GetSessionVars().StmtCtx, types.NewIntDatum(0))
|
|
d.SetInt64(int64(cmp))
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
return d, nil
|
|
}
|
|
|
|
type sqrtFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *sqrtFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinSqrtSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinSqrtSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sqrt
|
|
func (b *builtinSqrtSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := b.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
if args[0].IsNull() {
|
|
return args[0], nil
|
|
}
|
|
|
|
sc := b.ctx.GetSessionVars().StmtCtx
|
|
f, err := args[0].ToFloat64(sc)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
// negative value does not have any square root in rational number
|
|
// Need return null directly.
|
|
if f < 0 {
|
|
d.SetNull()
|
|
return d, nil
|
|
}
|
|
|
|
d.SetFloat64(math.Sqrt(f))
|
|
return
|
|
}
|
|
|
|
type arithmeticFunctionClass struct {
|
|
baseFunctionClass
|
|
|
|
op opcode.Op
|
|
}
|
|
|
|
func (c *arithmeticFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinArithmeticSig{newBaseBuiltinFunc(args, ctx), c.op}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinArithmeticSig struct {
|
|
baseBuiltinFunc
|
|
|
|
op opcode.Op
|
|
}
|
|
|
|
func (s *builtinArithmeticSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
args, err := s.evalArgs(row)
|
|
if err != nil {
|
|
return types.Datum{}, errors.Trace(err)
|
|
}
|
|
sc := s.ctx.GetSessionVars().StmtCtx
|
|
a, err := types.CoerceArithmetic(sc, args[0])
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
|
|
b, err := types.CoerceArithmetic(sc, args[1])
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
a, b, err = types.CoerceDatum(sc, a, b)
|
|
if err != nil {
|
|
return d, errors.Trace(err)
|
|
}
|
|
if a.IsNull() || b.IsNull() {
|
|
return
|
|
}
|
|
|
|
switch s.op {
|
|
case opcode.Plus:
|
|
return types.ComputePlus(a, b)
|
|
case opcode.Minus:
|
|
return types.ComputeMinus(a, b)
|
|
case opcode.Mul:
|
|
return types.ComputeMul(a, b)
|
|
case opcode.Div:
|
|
return types.ComputeDiv(sc, a, b)
|
|
case opcode.Mod:
|
|
return types.ComputeMod(sc, a, b)
|
|
case opcode.IntDiv:
|
|
return types.ComputeIntDiv(sc, a, b)
|
|
default:
|
|
return d, errInvalidOperation.Gen("invalid op %v in arithmetic operation", s.op)
|
|
}
|
|
}
|
|
|
|
type acosFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *acosFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinAcosSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinAcosSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_acos
|
|
func (b *builtinAcosSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("acos")
|
|
}
|
|
|
|
type asinFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *asinFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinAsinSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinAsinSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_asin
|
|
func (b *builtinAsinSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("asin")
|
|
}
|
|
|
|
type atanFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *atanFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinAtanSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinAtanSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_atan
|
|
func (b *builtinAtanSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("atan")
|
|
}
|
|
|
|
type cosFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *cosFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinCosSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinCosSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_cos
|
|
func (b *builtinCosSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("cos")
|
|
}
|
|
|
|
type cotFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *cotFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinCotSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinCotSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_cot
|
|
func (b *builtinCotSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("cot")
|
|
}
|
|
|
|
type degreesFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *degreesFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinDegreesSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinDegreesSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_degrees
|
|
func (b *builtinDegreesSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("degrees")
|
|
}
|
|
|
|
type expFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *expFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinExpSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinExpSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_exp
|
|
func (b *builtinExpSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("exp")
|
|
}
|
|
|
|
type piFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *piFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinPISig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinPISig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_pi
|
|
func (b *builtinPISig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("pi")
|
|
}
|
|
|
|
type radiansFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *radiansFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinRadiansSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinRadiansSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_radians
|
|
func (b *builtinRadiansSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("radians")
|
|
}
|
|
|
|
type sinFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *sinFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinSinSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinSinSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_sin
|
|
func (b *builtinSinSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("sin")
|
|
}
|
|
|
|
type tanFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *tanFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinTanSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinTanSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_tan
|
|
func (b *builtinTanSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("tan")
|
|
}
|
|
|
|
type truncateFunctionClass struct {
|
|
baseFunctionClass
|
|
}
|
|
|
|
func (c *truncateFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
|
|
return &builtinTruncateSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
|
|
}
|
|
|
|
type builtinTruncateSig struct {
|
|
baseBuiltinFunc
|
|
}
|
|
|
|
// See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_truncate
|
|
func (b *builtinTruncateSig) eval(row []types.Datum) (d types.Datum, err error) {
|
|
return d, errFunctionNotExists.GenByArgs("truncate")
|
|
}
|