Skip to content

Commit

Permalink
*: add three more builtin definitions (pingcap#3016)
Browse files Browse the repository at this point in the history
  • Loading branch information
zyguan authored and hanfei1991 committed Apr 10, 2017
1 parent d88fdec commit 1ec85a7
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 5 deletions.
3 changes: 3 additions & 0 deletions ast/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const (
SetVar = "setvar"
GetVar = "getvar"
Values = "values"
BitCount = "bit_count"

// common functions
Coalesce = "coalesce"
Expand Down Expand Up @@ -191,12 +192,14 @@ const (
Repeat = "repeat"
Replace = "replace"
Reverse = "reverse"
Right = "right"
RTrim = "rtrim"
Space = "space"
Strcmp = "strcmp"
Substring = "substring"
Substr = "substr"
SubstringIndex = "substring_index"
ToBase64 = "to_base64"
Trim = "trim"
Upper = "upper"
Ucase = "ucase"
Expand Down
3 changes: 3 additions & 0 deletions expression/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ var funcs = map[string]functionClass{
ast.Instr: &instrFunctionClass{baseFunctionClass{ast.Instr, 2, 2}},
ast.Lcase: &lowerFunctionClass{baseFunctionClass{ast.Lcase, 1, 1}},
ast.Left: &leftFunctionClass{baseFunctionClass{ast.Left, 2, 2}},
ast.Right: &rightFunctionClass{baseFunctionClass{ast.Right, 2, 2}},
ast.Length: &lengthFunctionClass{baseFunctionClass{ast.Length, 1, 1}},
ast.LoadFile: &loadFileFunctionClass{baseFunctionClass{ast.LoadFile, 1, 1}},
ast.Locate: &locateFunctionClass{baseFunctionClass{ast.Locate, 2, 3}},
Expand All @@ -259,6 +260,7 @@ var funcs = map[string]functionClass{
ast.Substring: &substringFunctionClass{baseFunctionClass{ast.Substring, 2, 3}},
ast.Substr: &substringFunctionClass{baseFunctionClass{ast.Substr, 2, 3}},
ast.SubstringIndex: &substringIndexFunctionClass{baseFunctionClass{ast.SubstringIndex, 3, 3}},
ast.ToBase64: &toBase64FunctionClass{baseFunctionClass{ast.ToBase64, 1, 1}},
ast.Trim: &trimFunctionClass{baseFunctionClass{ast.Trim, 1, 3}},
ast.Upper: &upperFunctionClass{baseFunctionClass{ast.Upper, 1, 1}},
ast.Ucase: &upperFunctionClass{baseFunctionClass{ast.Ucase, 1, 1}},
Expand Down Expand Up @@ -353,6 +355,7 @@ var funcs = map[string]functionClass{
ast.RowFunc: &rowFunctionClass{baseFunctionClass{ast.RowFunc, 2, -1}},
ast.SetVar: &setVarFunctionClass{baseFunctionClass{ast.SetVar, 2, 2}},
ast.GetVar: &getVarFunctionClass{baseFunctionClass{ast.GetVar, 1, 1}},
ast.BitCount: &bitCountFunctionClass{baseFunctionClass{ast.BitCount, 1, 1}},

// encryption and compression functions
ast.AesDecrypt: &aesDecryptFunctionClass{baseFunctionClass{ast.AesDecrypt, 2, 3}},
Expand Down
19 changes: 19 additions & 0 deletions expression/builtin_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
_ functionClass = &lockFunctionClass{}
_ functionClass = &releaseLockFunctionClass{}
_ functionClass = &valuesFunctionClass{}
_ functionClass = &bitCountFunctionClass{}
)

var (
Expand All @@ -44,6 +45,7 @@ var (
_ builtinFunc = &builtinLockSig{}
_ builtinFunc = &builtinReleaseLockSig{}
_ builtinFunc = &builtinValuesSig{}
_ builtinFunc = &builtinBitCountSig{}
)

type inFunctionClass struct {
Expand Down Expand Up @@ -246,3 +248,20 @@ func (b *builtinValuesSig) eval(_ []types.Datum) (types.Datum, error) {
}
return types.Datum{}, errors.Errorf("Session current insert values len %d and column's offset %v don't match", len(row), b.offset)
}

type bitCountFunctionClass struct {
baseFunctionClass
}

func (c *bitCountFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
return &builtinBitCountSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
}

type builtinBitCountSig struct {
baseBuiltinFunc
}

// See https://dev.mysql.com/doc/refman/5.7/en/bit-functions.html#function_bit-count
func (b *builtinBitCountSig) eval(row []types.Datum) (d types.Datum, err error) {
return d, errFunctionNotExists.GenByArgs("BIT_COUNT")
}
35 changes: 35 additions & 0 deletions expression/builtin_string.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var (
_ functionClass = &exportSetFunctionClass{}
_ functionClass = &formatFunctionClass{}
_ functionClass = &fromBase64FunctionClass{}
_ functionClass = &toBase64FunctionClass{}
_ functionClass = &insertFuncFunctionClass{}
_ functionClass = &instrFunctionClass{}
_ functionClass = &loadFileFunctionClass{}
Expand Down Expand Up @@ -118,6 +119,7 @@ var (
_ builtinFunc = &builtinExportSetSig{}
_ builtinFunc = &builtinFormatSig{}
_ builtinFunc = &builtinFromBase64Sig{}
_ builtinFunc = &builtinToBase64Sig{}
_ builtinFunc = &builtinInsertFuncSig{}
_ builtinFunc = &builtinInstrSig{}
_ builtinFunc = &builtinLoadFileSig{}
Expand Down Expand Up @@ -303,6 +305,22 @@ func (b *builtinLeftSig) eval(row []types.Datum) (d types.Datum, err error) {
return d, nil
}

type rightFunctionClass struct {
baseFunctionClass
}

func (c *rightFunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
return &builtinRightSig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
}

type builtinRightSig struct {
baseBuiltinFunc
}

func (b *builtinRightSig) eval(row []types.Datum) (d types.Datum, err error) {
return d, errFunctionNotExists.GenByArgs("RIGHT")
}

type repeatFunctionClass struct {
baseFunctionClass
}
Expand Down Expand Up @@ -1763,6 +1781,23 @@ func (b *builtinFromBase64Sig) eval(row []types.Datum) (d types.Datum, err error

}

type toBase64FunctionClass struct {
baseFunctionClass
}

func (c *toBase64FunctionClass) getFunction(args []Expression, ctx context.Context) (builtinFunc, error) {
return &builtinToBase64Sig{newBaseBuiltinFunc(args, ctx)}, errors.Trace(c.verifyArgs(args))
}

type builtinToBase64Sig struct {
baseBuiltinFunc
}

// See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_to-base64
func (b *builtinToBase64Sig) eval(row []types.Datum) (d types.Datum, err error) {
return d, errFunctionNotExists.GenByArgs("TO_BASE64")
}

type insertFuncFunctionClass struct {
baseFunctionClass
}
Expand Down
2 changes: 2 additions & 0 deletions parser/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ var tokenMap = map[string]int{
"THAN": than,
"THEN": then,
"TO": to,
"TO_BASE64": toBase64,
"TO_DAYS": toDays,
"TO_SECONDS": toSeconds,
"TRAILING": trailing,
Expand Down Expand Up @@ -544,6 +545,7 @@ var tokenMap = map[string]int{
"PARTITION": partition,
"PARTITIONS": partitions,
"RPAD": rpad,
"BIT_COUNT": bitCount,
"BIT_LENGTH": bitLength,
"CHAR_FUNC": charFunc,
"CHAR_LENGTH": charLength,
Expand Down
21 changes: 19 additions & 2 deletions parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,14 @@ import (
yearweek "YEARWEEK"
round "ROUND"
statsPersistent "STATS_PERSISTENT"
toBase64 "TO_BASE64"
toDays "TO_DAYS"
toSeconds "TO_SECONDS"
getLock "GET_LOCK"
releaseLock "RELEASE_LOCK"
rpad "RPAD"
utcTime "UTC_TIME"
bitCount "BIT_COUNT"
bitLength "BIT_LENGTH"
charFunc "CHAR_FUNC"
charLength "CHAR_LENGTH"
Expand Down Expand Up @@ -2285,12 +2287,12 @@ ReservedKeyword:


NotKeywordToken:
"ABS" | "ACOS" | "ADDTIME" | "ADDDATE" | "ADMIN" | "ASIN" | "ATAN" | "ATAN2" | "BENCHMARK" | "BIN" | "COALESCE" | "COERCIBILITY" | "CONCAT" | "CONCAT_WS" | "CONNECTION_ID" | "CONVERT_TZ" | "CUR_TIME"| "COS" | "COT" | "COUNT" | "DAY"
"ABS" | "ACOS" | "ADDTIME" | "ADDDATE" | "ADMIN" | "ASIN" | "ATAN" | "ATAN2" | "BENCHMARK" | "BIN" | "BIT_COUNT" | "BIT_LENGTH" | "COALESCE" | "COERCIBILITY" | "CONCAT" | "CONCAT_WS" | "CONNECTION_ID" | "CONVERT_TZ" | "CUR_TIME"| "COS" | "COT" | "COUNT" | "DAY"
| "DATEDIFF" | "DATE_ADD" | "DATE_FORMAT" | "DATE_SUB" | "DAYNAME" | "DAYOFMONTH" | "DAYOFWEEK" | "DAYOFYEAR" | "DEGREES" | "ELT" | "EXP" | "EXPORT_SET" | "FROM_DAYS" | "FROM_BASE64" | "FIND_IN_SET" | "FOUND_ROWS"
| "GET_FORMAT" | "GROUP_CONCAT" | "GREATEST" | "LEAST" | "HOUR" | "HEX" | "UNHEX" | "IFNULL" | "INSTR" | "ISNULL" | "LAST_INSERT_ID" | "LCASE" | "LENGTH" | "LOAD_FILE" | "LOCATE" | "LOWER" | "LPAD" | "LTRIM"
| "MAKE_SET" | "MAX" | "MAKEDATE" | "MAKETIME" | "MICROSECOND" | "MID" | "MIN" | "MINUTE" | "NULLIF" | "MONTH" | "MONTHNAME" | "NOW" | "OCT" | "OCTET_LENGTH" | "ORD" | "POSITION" | "PERIOD_ADD" | "PERIOD_DIFF" | "PI" | "POW" | "POWER" | "RAND" | "RADIANS" | "ROW_COUNT"
"QUOTE" | "SEC_TO_TIME" | "SECOND" | "SIGN" | "SIN" | "SLEEP" | "SQRT" | "SQL_CALC_FOUND_ROWS" | "STR_TO_DATE" | "SUBTIME" | "SUBDATE" | "SUBSTRING" %prec lowerThanLeftParen |
"SESSION_USER" | "SUBSTRING_INDEX" | "SUM" | "SYSTEM_USER" | "TAN" | "TIME_FORMAT" | "TIME_TO_SEC" | "TIMESTAMPADD" | "TO_DAYS" | "TO_SECONDS" | "TRIM" | "RTRIM" | "UCASE" | "UTC_TIME" | "UPPER" | "VERSION" | "WEEKDAY" | "WEEKOFYEAR" | "YEARWEEK" | "ROUND"
"SESSION_USER" | "SUBSTRING_INDEX" | "SUM" | "SYSTEM_USER" | "TAN" | "TIME_FORMAT" | "TIME_TO_SEC" | "TIMESTAMPADD" | "TO_BASE64" | "TO_DAYS" | "TO_SECONDS" | "TRIM" | "RTRIM" | "UCASE" | "UTC_TIME" | "UPPER" | "VERSION" | "WEEKDAY" | "WEEKOFYEAR" | "YEARWEEK" | "ROUND"
| "STATS_PERSISTENT" | "GET_LOCK" | "RELEASE_LOCK" | "CEIL" | "CEILING" | "FLOOR" | "FROM_UNIXTIME" | "TIMEDIFF" | "LN" | "LOG" | "LOG2" | "LOG10" | "FIELD_KWD"
| "AES_DECRYPT" | "AES_ENCRYPT" | "QUOTE"
| "ANY_VALUE" | "INET_ATON" | "INET_NTOA" | "INET6_ATON" | "INET6_NTOA" | "IS_FREE_LOCK" | "IS_IPV4" | "IS_IPV4_COMPAT" | "IS_IPV4_MAPPED" | "IS_IPV6" | "IS_USED_LOCK" | "MASTER_POS_WAIT" | "NAME_CONST" | "RELEASE_ALL_LOCKS" | "UUID" | "UUID_SHORT"
Expand Down Expand Up @@ -2639,6 +2641,7 @@ FunctionNameConflict:
| "SCHEMA"
| "IF"
| "LEFT"
| "RIGHT"
| "REPEAT"
| "CURRENT_USER"
| "UTC_DATE"
Expand Down Expand Up @@ -3481,6 +3484,13 @@ FunctionCallNonKeyword:
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($1), Args: $3.([]ast.ExprNode)}
}
| "TO_BASE64" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
Args: []ast.ExprNode{$3.(ast.ExprNode)},
}
}
| "TO_DAYS" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{
Expand Down Expand Up @@ -3597,6 +3607,13 @@ FunctionCallNonKeyword:
Args: []ast.ExprNode{$3.(ast.ExprNode), $5.(ast.ExprNode), $7.(ast.ExprNode)},
}
}
| "BIT_COUNT" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
Args: []ast.ExprNode{$3.(ast.ExprNode)},
}
}
| "BIT_LENGTH" '(' Expression ')'
{
$$ = &ast.FuncCallExpr{
Expand Down
6 changes: 6 additions & 0 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,9 @@ func (s *testParserSuite) TestBuiltin(c *C) {
// for binary operator
{"SELECT binary 'a';", true},

// for bit_count
{`SELECT BIT_COUNT(1);`, true},

// select time
{"select current_timestamp", true},
{"select current_timestamp()", true},
Expand Down Expand Up @@ -770,9 +773,12 @@ func (s *testParserSuite) TestBuiltin(c *C) {
{`SELECT EXPORT_SET(5,'Y','N'), EXPORT_SET(5,'Y','N',','), EXPORT_SET(5,'Y','N',',',4)`, true},
{`SELECT FORMAT(12332.2,2,'de_DE'), FORMAT(12332.123456, 4)`, true},
{`SELECT FROM_BASE64('abc')`, true},
{`SELECT TO_BASE64('abc')`, true},
{`SELECT INSERT('Quadratic', 3, 4, 'What'), INSTR('foobarbar', 'bar')`, true},
{`SELECT LOAD_FILE('/tmp/picture')`, true},
{`SELECT LPAD('hi',4,'??')`, true},
{`SELECT LEFT("foobar", 3)`, true},
{`SELECT RIGHT("foobar", 3)`, true},

// repeat
{`SELECT REPEAT("a", 10);`, true},
Expand Down
6 changes: 3 additions & 3 deletions plan/typeinferer.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,15 +373,15 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) {
case "str_to_date":
tp = types.NewFieldType(mysql.TypeDatetime)
case "dayname", "version", "database", "user", "current_user", "schema",
"concat", "concat_ws", "left", "lcase", "lower", "repeat",
"concat", "concat_ws", "left", "right", "lcase", "lower", "repeat",
"replace", "ucase", "upper", "convert", "substring", "elt",
"substring_index", "trim", "ltrim", "rtrim", "reverse", "hex", "unhex",
"date_format", "rpad", "lpad", "char_func", "conv", "make_set", "oct", "uuid",
"insert_func", "bin", "quote", "format", "from_base64":
"insert_func", "bin", "quote", "format", "from_base64", "to_base64":
tp = types.NewFieldType(mysql.TypeVarString)
chs = v.defaultCharset
case "strcmp", "isnull", "bit_length", "char_length", "character_length", "crc32", "timestampdiff",
"sign", "is_ipv6", "ord", "instr":
"sign", "is_ipv6", "ord", "instr", "bit_count":
tp = types.NewFieldType(mysql.TypeLonglong)
case "connection_id":
tp = types.NewFieldType(mysql.TypeLonglong)
Expand Down
3 changes: 3 additions & 0 deletions plan/typeinferer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) {
{"CONCAT('T', 'i', 'DB')", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"CONCAT_WS('-', 'T', 'i', 'DB')", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"left('TiDB', 2)", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"right('TiDB', 2)", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"lower('TiDB')", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"lcase('TiDB')", mysql.TypeVarString, charset.CharsetUTF8, 0},
{"repeat('TiDB', 3)", mysql.TypeVarString, charset.CharsetUTF8, 0},
Expand Down Expand Up @@ -264,6 +265,7 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) {
{`sha2(123, 256)`, mysql.TypeVarString, charset.CharsetUTF8, 0},
{`uuid()`, mysql.TypeVarString, charset.CharsetUTF8, 0},
{`from_base64('YWJj')`, mysql.TypeVarString, charset.CharsetUTF8, 0},
{`to_base64('abc')`, mysql.TypeVarString, charset.CharsetUTF8, 0},
{`random_bytes(32)`, mysql.TypeVarString, charset.CharsetBin, mysql.BinaryFlag},
{`coalesce(null, 0)`, mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag},
{`coalesce(null, 0.1)`, mysql.TypeNewDecimal, charset.CharsetBin, mysql.BinaryFlag},
Expand Down Expand Up @@ -294,6 +296,7 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) {
{`ord(true)`, mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag},
{`ord(null)`, mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag},
{`bin(1)`, mysql.TypeVarString, charset.CharsetUTF8, 0},
{`bit_count(1)`, mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag},
}
for _, ca := range cases {
ctx := testKit.Se.(context.Context)
Expand Down

0 comments on commit 1ec85a7

Please sign in to comment.