*: parser support crc32 conv bit_xor (#2347)
*: parser support crc32 conv bit_xor
This commit is contained in:
@ -79,6 +79,8 @@ const (
|
||||
Abs = "abs"
|
||||
Ceil = "ceil"
|
||||
Ceiling = "ceiling"
|
||||
Conv = "conv"
|
||||
CRC32 = "crc32"
|
||||
Ln = "ln"
|
||||
Log = "log"
|
||||
Log2 = "log2"
|
||||
|
||||
@ -138,6 +138,8 @@ var Funcs = map[string]Func{
|
||||
ast.Power: {builtinPow, 2, 2},
|
||||
ast.Rand: {builtinRand, 0, 1},
|
||||
ast.Round: {builtinRound, 1, 2},
|
||||
ast.Conv: {builtinConv, 3, 3},
|
||||
ast.CRC32: {builtinCRC32, 1, 1},
|
||||
|
||||
// time functions
|
||||
ast.Curdate: {builtinCurrentDate, 0, 0},
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
package expression
|
||||
|
||||
import (
|
||||
"hash/crc32"
|
||||
"math"
|
||||
"math/rand"
|
||||
|
||||
@ -185,3 +186,23 @@ func builtinRound(args []types.Datum, ctx context.Context) (d types.Datum, err e
|
||||
d.SetFloat64(types.Round(x, dec))
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_conv
|
||||
func builtinConv(args []types.Datum, ctx context.Context) (d types.Datum, err error) {
|
||||
//TODO implement
|
||||
return d, errors.New("Function unimplement")
|
||||
}
|
||||
|
||||
// See http://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_crc32
|
||||
func builtinCRC32(args []types.Datum, ctx context.Context) (d types.Datum, err error) {
|
||||
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
|
||||
}
|
||||
|
||||
@ -171,3 +171,23 @@ func (s *testEvaluatorSuite) TestRound(c *C) {
|
||||
c.Assert(v, testutil.DatumEquals, t["Ret"][0])
|
||||
}
|
||||
}
|
||||
|
||||
func (s *testEvaluatorSuite) TestCRC32(c *C) {
|
||||
defer testleak.AfterTest(c)()
|
||||
tbl := []struct {
|
||||
Arg []interface{}
|
||||
Ret uint64
|
||||
}{
|
||||
{[]interface{}{"mysql"}, 2501908538},
|
||||
{[]interface{}{"MySQL"}, 3259397556},
|
||||
{[]interface{}{"hello"}, 907060870},
|
||||
}
|
||||
|
||||
Dtbl := tblToDtbl(tbl)
|
||||
|
||||
for _, t := range Dtbl {
|
||||
v, err := builtinCRC32(t["Arg"], s.ctx)
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(v, testutil.DatumEquals, t["Ret"][0])
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,6 +484,9 @@ var tokenMap = map[string]int{
|
||||
"CHAR_FUNC": charFunc,
|
||||
"CHAR_LENGTH": charLength,
|
||||
"CHARACTER_LENGTH": charLength,
|
||||
"CONV": conv,
|
||||
"BIT_XOR": bitXor,
|
||||
"CRC32": crc32,
|
||||
}
|
||||
|
||||
func isTokenIdentifier(s string, buf *bytes.Buffer) int {
|
||||
|
||||
@ -291,6 +291,9 @@ import (
|
||||
charFunc "CHAR_FUNC"
|
||||
charLength "CHAR_LENGTH"
|
||||
characterLength "CHARACTER_LENGTH"
|
||||
conv "CONV"
|
||||
bitXor "BIT_XOR"
|
||||
crc32 "CRC32"
|
||||
|
||||
/* the following tokens belong to UnReservedKeyword*/
|
||||
action "ACTION"
|
||||
@ -3021,6 +3024,21 @@ FunctionCallNonKeyword:
|
||||
Args: []ast.ExprNode{$3.(ast.ExprNode)},
|
||||
}
|
||||
}
|
||||
| "CONV" '(' Expression ',' Expression ',' Expression ')'
|
||||
{
|
||||
$$ = &ast.FuncCallExpr{
|
||||
FnName: model.NewCIStr($1),
|
||||
Args: []ast.ExprNode{$3.(ast.ExprNode), $5.(ast.ExprNode), $7.(ast.ExprNode)},
|
||||
}
|
||||
}
|
||||
| "CRC32" '(' Expression ')'
|
||||
{
|
||||
$$ = &ast.FuncCallExpr{
|
||||
FnName: model.NewCIStr($1),
|
||||
Args: []ast.ExprNode{$3.(ast.ExprNode)},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DateArithOpt:
|
||||
"DATE_ADD"
|
||||
@ -3099,6 +3117,10 @@ FunctionCallAgg:
|
||||
{
|
||||
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4.(ast.ExprNode)}, Distinct: $3.(bool)}
|
||||
}
|
||||
| "BIT_XOR" '(' DistinctOpt Expression ')'
|
||||
{
|
||||
$$ = &ast.AggregateFuncExpr{F: $1, Args: []ast.ExprNode{$4.(ast.ExprNode)}, Distinct: $3.(bool)}
|
||||
}
|
||||
|
||||
FuncDatetimePrec:
|
||||
{
|
||||
|
||||
@ -511,6 +511,8 @@ func (s *testParserSuite) TestBuiltin(c *C) {
|
||||
{"SELECT LOG(2, 65536);", true},
|
||||
{"SELECT LOG2(2);", true},
|
||||
{"SELECT LOG10(10);", true},
|
||||
{"SELECT CONV(10+'10'+'10'+X'0a',10,10);", true},
|
||||
{"SELECT CRC32('MySQL');", true},
|
||||
|
||||
{"SELECT SUBSTR('Quadratically',5);", true},
|
||||
{"SELECT SUBSTR('Quadratically',5, 3);", true},
|
||||
|
||||
@ -314,7 +314,7 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) {
|
||||
"substring_index", "trim", "ltrim", "rtrim", "reverse", "hex", "unhex", "date_format", "rpad", "char_func":
|
||||
tp = types.NewFieldType(mysql.TypeVarString)
|
||||
chs = v.defaultCharset
|
||||
case "strcmp", "isnull", "bit_length", "char_length", "character_length":
|
||||
case "strcmp", "isnull", "bit_length", "char_length", "character_length", "crc32":
|
||||
tp = types.NewFieldType(mysql.TypeLonglong)
|
||||
case "connection_id":
|
||||
tp = types.NewFieldType(mysql.TypeLonglong)
|
||||
|
||||
@ -158,6 +158,7 @@ func (ts *testTypeInferrerSuite) TestInferType(c *C) {
|
||||
{"char(66)", mysql.TypeVarString, charset.CharsetUTF8},
|
||||
{"char_length('TiDB')", mysql.TypeLonglong, charset.CharsetBin},
|
||||
{"character_length('TiDB')", mysql.TypeLonglong, charset.CharsetBin},
|
||||
{"crc32('TiDB')", mysql.TypeLonglong, charset.CharsetBin},
|
||||
}
|
||||
for _, ca := range cases {
|
||||
ctx := testKit.Se.(context.Context)
|
||||
|
||||
Reference in New Issue
Block a user