From c01879ba2e334fb40fb3aee48a67148f263e2d2d Mon Sep 17 00:00:00 2001 From: sllt Date: Sat, 19 Dec 2015 23:51:04 +0800 Subject: [PATCH] parser: support built-in function pow --- expression/builtin/builtin.go | 6 ++++-- expression/builtin/math.go | 19 +++++++++++++++++ expression/builtin/math_test.go | 36 +++++++++++++++++++++++++++++++++ parser/parser.y | 12 +++++++++++ parser/scanner.l | 6 ++++++ 5 files changed, 77 insertions(+), 2 deletions(-) diff --git a/expression/builtin/builtin.go b/expression/builtin/builtin.go index d5c73d5b4e..15c20232fa 100644 --- a/expression/builtin/builtin.go +++ b/expression/builtin/builtin.go @@ -55,8 +55,10 @@ var Funcs = map[string]Func{ "coalesce": {builtinCoalesce, 1, -1, true, false}, // math functions - "abs": {builtinAbs, 1, 1, true, false}, - "rand": {builtinRand, 0, 1, true, false}, + "abs": {builtinAbs, 1, 1, true, false}, + "rand": {builtinRand, 0, 1, true, false}, + "pow": {builtinPow, 2, 2, true, false}, + "power": {builtinPower, 2, 2, true, false}, // group by functions "avg": {builtinAvg, 1, 1, false, true}, diff --git a/expression/builtin/math.go b/expression/builtin/math.go index d3cce6fe41..dc2b04971b 100644 --- a/expression/builtin/math.go +++ b/expression/builtin/math.go @@ -63,3 +63,22 @@ func builtinRand(args []interface{}, ctx map[interface{}]interface{}) (v interfa return rand.Float64(), nil } + +func builtinPow(args []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + x, err := types.ToFloat64(args[0]) + if err != nil { + return nil, errors.Trace(err) + } + + y, err := types.ToFloat64(args[1]) + if err != nil { + return nil, errors.Trace(err) + } + + return math.Pow(x, y), nil + +} + +func builtinPower(args []interface{}, ctx map[interface{}]interface{}) (v interface{}, err error) { + return builtinPow(args, ctx) +} diff --git a/expression/builtin/math_test.go b/expression/builtin/math_test.go index 255238e70a..a89d07fdb5 100644 --- a/expression/builtin/math_test.go +++ b/expression/builtin/math_test.go @@ -43,3 +43,39 @@ func (s *testBuiltinSuite) TestRand(c *C) { c.Assert(v, Less, float64(1)) c.Assert(v, GreaterEqual, float64(0)) } + +func (s *testBuiltinSuite) TestPow(c *C) { + tbl := []struct { + Arg []interface{} + Ret float64 + }{ + {[]interface{}{1, 3}, 1}, + {[]interface{}{2, 2}, 4}, + {[]interface{}{4, 0.5}, 2}, + {[]interface{}{4, -2}, 0.0625}, + } + + for _, t := range tbl { + v, err := builtinPow(t.Arg, nil) + c.Assert(err, IsNil) + c.Assert(v, DeepEquals, t.Ret) + } +} + +func (s *testBuiltinSuite) TestPower(c *C) { + tbl := []struct { + Arg []interface{} + Ret float64 + }{ + {[]interface{}{1, 3}, 1}, + {[]interface{}{2, 2}, 4}, + {[]interface{}{4, 0.5}, 2}, + {[]interface{}{4, -2}, 0.0625}, + } + + for _, t := range tbl { + v, err := builtinPower(t.Arg, nil) + c.Assert(err, IsNil) + c.Assert(v, DeepEquals, t.Ret) + } +} diff --git a/parser/parser.y b/parser/parser.y index b421325596..c797b0bb28 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -210,6 +210,8 @@ import ( outer "OUTER" password "PASSWORD" placeholder "PLACEHOLDER" + pow "POW" + power "POWER" prepare "PREPARE" primary "PRIMARY" quarter "QUARTER" @@ -2257,6 +2259,16 @@ FunctionCallNonKeyword: { $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: $3.([]ast.ExprNode)} } +| "POW" '(' Expression ',' Expression ')' + { + args := []ast.ExprNode{$3.(ast.ExprNode), $5.(ast.ExprNode)} + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: args} + } +| "POWER" '(' Expression ',' Expression ')' + { + args := []ast.ExprNode{$3.(ast.ExprNode), $5.(ast.ExprNode)} + $$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: args} + } | "RAND" '(' ExpressionOpt ')' { diff --git a/parser/scanner.l b/parser/scanner.l index af5d5d6acd..0433f776e5 100644 --- a/parser/scanner.l +++ b/parser/scanner.l @@ -414,6 +414,8 @@ or {o}{r} order {o}{r}{d}{e}{r} outer {o}{u}{t}{e}{r} password {p}{a}{s}{s}{w}{o}{r}{d} +pow {p}{o}{w} +power {p}{o}{w}{e}{r} prepare {p}{r}{e}{p}{a}{r}{e} primary {p}{r}{i}{m}{a}{r}{y} quarter {q}{u}{a}{r}{t}{e}{r} @@ -850,6 +852,10 @@ year_month {y}{e}{a}{r}_{m}{o}{n}{t}{h} {outer} return outer {password} lval.item = string(l.val) return password +{pow} lval.item = string(l.val) + return pow +{power} lval.item = string(l.val) + return power {prepare} lval.item = string(l.val) return prepare {primary} return primary