Skip to content

Commit

Permalink
*: add builtin string function SPACE (#1332)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiancaiamao authored Jun 21, 2016
1 parent dd6bfac commit b3bd0dc
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 2 deletions.
1 change: 1 addition & 0 deletions evaluator/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ var Funcs = map[string]Func{
"replace": {builtinReplace, 3, 3},
"reverse": {builtinReverse, 1, 1},
"rtrim": {trimFn(strings.TrimRight, spaceChars), 1, 1},
"space": {builtinSpace, 1, 1},
"strcmp": {builtinStrcmp, 2, 2},
"substring": {builtinSubstring, 2, 3},
"substring_index": {builtinSubstringIndex, 3, 3},
Expand Down
32 changes: 32 additions & 0 deletions evaluator/builtin_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package evaluator

import (
"fmt"
"math"
"strconv"
"strings"

"github.com/juju/errors"
Expand Down Expand Up @@ -186,6 +188,36 @@ func builtinReverse(args []types.Datum, _ context.Context) (d types.Datum, err e
}
}

// See: http://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_space
func builtinSpace(args []types.Datum, _ context.Context) (d types.Datum, err error) {
x := args[0]
if x.IsNull() {
return d, nil
}

if x.Kind() == types.KindString || x.Kind() == types.KindBytes {
if _, e := strconv.ParseInt(x.GetString(), 10, 64); e != nil {
return d, errors.Trace(e)
}
}

v, err := x.ToInt64()
if err != nil {
return d, errors.Trace(err)
}

if v < 0 {
v = 0
}

if v > math.MaxInt32 {
d.SetNull()
} else {
d.SetString(strings.Repeat(" ", int(v)))
}
return d, nil
}

// See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_upper
func builtinUpper(args []types.Datum, _ context.Context) (d types.Datum, err error) {
x := args[0]
Expand Down
43 changes: 43 additions & 0 deletions evaluator/builtin_string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,49 @@ func (s *testEvaluatorSuite) TestSubstringIndex(c *C) {
}
}

func (s *testEvaluatorSuite) TestSpace(c *C) {
defer testleak.AfterTest(c)()
d, err := builtinSpace(types.MakeDatums([]interface{}{nil}...), nil)
c.Assert(err, IsNil)
c.Assert(d.Kind(), Equals, types.KindNull)

d, err = builtinSpace(types.MakeDatums([]interface{}{8888888888}...), nil)
c.Assert(err, IsNil)
c.Assert(d.Kind(), Equals, types.KindNull)

tbl := []struct {
Input interface{}
Expect string
}{
{5, " "},
{0, ""},
{-1, ""},
{"5", " "},
}

dtbl := tblToDtbl(tbl)

for _, t := range dtbl {
d, err = builtinSpace(t["Input"], nil)
c.Assert(err, IsNil)
c.Assert(d, testutil.DatumEquals, t["Expect"][0])
}

wrong := []struct {
Input string
}{
{"abc"},
{"3.3"},
{""},
}

dwrong := tblToDtbl(wrong)
for _, t := range dwrong {
_, err = builtinSpace(t["Input"], nil)
c.Assert(err, NotNil)
}
}

func (s *testEvaluatorSuite) TestLocate(c *C) {
defer testleak.AfterTest(c)()
tbl := []struct {
Expand Down
7 changes: 6 additions & 1 deletion parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ import (
show "SHOW"
signed "SIGNED"
some "SOME"
space "SPACE"
start "START"
status "STATUS"
stringType "string"
Expand Down Expand Up @@ -1954,7 +1955,7 @@ UnReservedKeyword:
| "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MAX_ROWS" | "MIN_ROWS"
| "NATIONAL" | "ROW" | "ROW_FORMAT" | "QUARTER" | "ESCAPE" | "GRANTS" | "FIELDS" | "TRIGGERS" | "DELAY_KEY_WRITE"
| "ISOLATION" | "REPEATABLE" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES"
| "SQL_CACHE" | "SQL_NO_CACHE" | "ACTION" | "DISABLE" | "ENABLE" | "REVERSE"
| "SQL_CACHE" | "SQL_NO_CACHE" | "ACTION" | "DISABLE" | "ENABLE" | "REVERSE" | "SPACE"

NotKeywordToken:
"ABS" | "ADDDATE" | "ADMIN" | "COALESCE" | "CONCAT" | "CONCAT_WS" | "CONNECTION_ID" | "CUR_TIME"| "COUNT" | "DAY"
Expand Down Expand Up @@ -2647,6 +2648,10 @@ FunctionCallNonKeyword:
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode)}}
}
| "SPACE" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode)}}
}
| "STRCMP" '(' Expression ',' Expression ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1.(string)), Args: []ast.ExprNode{$3.(ast.ExprNode), $5.(ast.ExprNode)}}
Expand Down
2 changes: 1 addition & 1 deletion parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func (s *testParserSuite) TestSimple(c *C) {
"delay_key_write", "isolation", "repeatable", "committed", "uncommitted", "only", "serializable", "level",
"curtime", "variables", "dayname", "version", "btree", "hash", "row_format", "dynamic", "fixed", "compressed",
"compact", "redundant", "sql_no_cache sql_no_cache", "sql_cache sql_cache", "action", "round",
"enable", "disable", "reverse",
"enable", "disable", "reverse", "space",
}
for _, kw := range unreservedKws {
src := fmt.Sprintf("SELECT %s FROM tbl;", kw)
Expand Down
3 changes: 3 additions & 0 deletions parser/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ set {s}{e}{t}
share {s}{h}{a}{r}{e}
show {s}{h}{o}{w}
some {s}{o}{m}{e}
space {s}{p}{a}{c}{e}
start {s}{t}{a}{r}{t}
status {s}{t}{a}{t}{u}{s}
subdate {s}{u}{b}{d}{a}{t}{e}
Expand Down Expand Up @@ -972,6 +973,8 @@ redundant lval.item = string(l.val)
return session
{some} lval.item = string(l.val)
return some
{space} lval.item = string(l.val)
return space
{start} lval.item = string(l.val)
return start
{status} lval.item = string(l.val)
Expand Down

0 comments on commit b3bd0dc

Please sign in to comment.