Merge pull request #474 from pingcap/zimuxia/replace-func

Replace func
This commit is contained in:
zimulala
2015-10-29 09:55:20 +08:00
7 changed files with 67 additions and 6 deletions

View File

@ -100,6 +100,7 @@ var Funcs = map[string]Func{
"length": {builtinLength, 1, 1, true, false},
"lower": {builtinLower, 1, 1, true, false},
"repeat": {builtinRepeat, 2, 2, true, false},
"replace": {builtinReplace, 3, 3, true, false},
"upper": {builtinUpper, 1, 1, true, false},
// information functions

View File

@ -146,3 +146,27 @@ func builtinUpper(args []interface{}, ctx map[interface{}]interface{}) (interfac
return strings.ToUpper(s), nil
}
}
// See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_replace
func builtinReplace(args []interface{}, ctx map[interface{}]interface{}) (interface{}, error) {
for _, arg := range args {
if types.IsNil(arg) {
return nil, nil
}
}
str, err := types.ToString(args[0])
if err != nil {
return nil, errors.Trace(err)
}
oldStr, err := types.ToString(args[1])
if err != nil {
return nil, errors.Trace(err)
}
newStr, err := types.ToString(args[2])
if err != nil {
return nil, errors.Trace(err)
}
return strings.Replace(str, oldStr, newStr, -1), nil
}

View File

@ -166,3 +166,23 @@ func (s *testBuiltinSuite) TestLowerAndUpper(c *C) {
c.Assert(v, Equals, strings.ToUpper(t.Expect))
}
}
func (s *testBuiltinSuite) TestReplace(c *C) {
tbl := []struct {
Input []interface{}
Expect interface{}
}{
{[]interface{}{nil, nil, nil}, nil},
{[]interface{}{1, nil, 2}, nil},
{[]interface{}{1, 1, nil}, nil},
{[]interface{}{"12345", 2, 222}, "1222345"},
{[]interface{}{"12325", 2, "a"}, "1a3a5"},
{[]interface{}{12345, 2, "aa"}, "1aa345"},
}
for _, t := range tbl {
v, err := builtinReplace(t.Input, nil)
c.Assert(err, IsNil)
c.Assert(v, Equals, t.Expect)
}
}

View File

@ -63,18 +63,18 @@ func NewCall(f string, args []Expression, distinct bool) (v Expression, err erro
}
c := Call{F: f, Distinct: distinct, distinctKey: new(int)}
for _, Val := range args {
if !Val.IsStatic() {
c.Args = append(c.Args, Val)
for _, val := range args {
if !val.IsStatic() {
c.Args = append(c.Args, val)
continue
}
eVal, err := Val.Eval(nil, nil)
v, err := val.Eval(nil, nil)
if err != nil {
return nil, err
}
c.Args = append(c.Args, Value{eVal})
c.Args = append(c.Args, Value{v})
}
return &c, nil

View File

@ -2439,6 +2439,19 @@ FunctionCallNonKeyword:
return 1
}
}
| "REPLACE" '(' Expression ',' Expression ',' Expression ')'
{
args := []expression.Expression{$3.(expression.Expression),
$5.(expression.Expression),
$7.(expression.Expression)}
var err error
$$, err = expression.NewCall($1.(string), args, false)
if err != nil {
l := yylex.(*lexer)
l.err(err)
return 1
}
}
| "SECOND" '(' Expression ')'
{
args := []expression.Expression{$3.(expression.Expression)}

View File

@ -349,6 +349,8 @@ func (s *testParserSuite) TestBuiltin(c *C) {
{`SELECT LOWER("A"), UPPER("a")`, true},
{`SELECT REPLACE('www.mysql.com', 'w', 'Ww')`, true},
{`SELECT LOCATE('bar', 'foobarbar');`, true},
{`SELECT LOCATE('bar', 'foobarbar', 5);`, true},

View File

@ -816,7 +816,8 @@ year_month {y}{e}{a}{r}_{m}{o}{n}{t}{h}
return repeat
{regexp} return regexp
{references} return references
{replace} return replace
{replace} lval.item = string(l.val)
return replace
{rlike} return rlike
{sys_var} lval.item = string(l.val)