diff --git a/ast/flag.go b/ast/flag.go index b3c6829e28..80469a9206 100644 --- a/ast/flag.go +++ b/ast/flag.go @@ -68,8 +68,6 @@ func (f *flagSetter) Leave(in Node) (Node, bool) { x.SetFlag(FlagHasFunc | x.Expr.GetFlag()) case *FuncDateArithExpr: f.funcDateArith(x) - case *FuncTrimExpr: - f.funcTrim(x) case *IsNullExpr: x.SetFlag(x.Expr.GetFlag()) case *IsTruthExpr: @@ -160,14 +158,6 @@ func (f *flagSetter) funcCall(x *FuncCallExpr) { x.SetFlag(flag) } -func (f *flagSetter) funcTrim(x *FuncTrimExpr) { - flag := FlagHasFunc | x.Str.GetFlag() - if x.RemStr != nil { - flag |= x.RemStr.GetFlag() - } - x.SetFlag(flag) -} - func (f *flagSetter) funcDateArith(x *FuncDateArithExpr) { flag := FlagHasFunc | x.Date.GetFlag() if x.Interval != nil { diff --git a/ast/functions.go b/ast/functions.go index cda21dedfe..f557fbc4d5 100644 --- a/ast/functions.go +++ b/ast/functions.go @@ -29,7 +29,6 @@ var ( _ FuncNode = &FuncCallExpr{} _ FuncNode = &FuncCastExpr{} _ FuncNode = &FuncDateArithExpr{} - _ FuncNode = &FuncTrimExpr{} ) // UnquoteString is not quoted when printed. @@ -112,38 +111,6 @@ const ( TrimTrailing ) -// FuncTrimExpr remove leading/trailing/both remstr. -// See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_trim -type FuncTrimExpr struct { - funcNode - - Str ExprNode - RemStr ExprNode - Direction TrimDirectionType -} - -// Accept implements Node Accept interface. -func (n *FuncTrimExpr) Accept(v Visitor) (Node, bool) { - newNode, skipChildren := v.Enter(n) - if skipChildren { - return v.Leave(newNode) - } - n = newNode.(*FuncTrimExpr) - node, ok := n.Str.Accept(v) - if !ok { - return n, false - } - n.Str = node.(ExprNode) - if n.RemStr != nil { - node, ok = n.RemStr.Accept(v) - if !ok { - return n, false - } - n.RemStr = node.(ExprNode) - } - return v.Leave(n) -} - // DateArithType is type for DateArith type. type DateArithType byte diff --git a/evaluator/builtin/builtin.go b/evaluator/builtin/builtin.go index cc05fd28c9..9367edb1c7 100644 --- a/evaluator/builtin/builtin.go +++ b/evaluator/builtin/builtin.go @@ -92,6 +92,7 @@ var Funcs = map[string]Func{ "substring": {builtinSubstring, 2, 3, true, false}, "substring_index": {builtinSubstringIndex, 3, 3, true, false}, "locate": {builtinLocate, 2, 3, true, false}, + "trim": {builtinTrim, 1, 3, true, false}, // information functions "current_user": {builtinCurrentUser, 0, 0, false, false}, diff --git a/evaluator/builtin/string.go b/evaluator/builtin/string.go index 8c8e7f9c5d..b4efdf5834 100644 --- a/evaluator/builtin/string.go +++ b/evaluator/builtin/string.go @@ -23,6 +23,7 @@ import ( "github.com/juju/errors" "github.com/ngaut/log" + "github.com/pingcap/tidb/ast" "github.com/pingcap/tidb/context" "github.com/pingcap/tidb/util/charset" "github.com/pingcap/tidb/util/types" @@ -276,9 +277,9 @@ func builtinSubstring(args []interface{}, _ context.Context) (interface{}, error // See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substring-index func builtinSubstringIndex(args []interface{}, _ context.Context) (interface{}, error) { // The meaning of the elements of args. - //args[0] -> StrExpr - //args[1] -> Delim - //args[2] -> Count + // args[0] -> StrExpr + // args[1] -> Delim + // args[2] -> Count fs := args[0] str, err := types.ToString(fs) if err != nil { @@ -324,9 +325,9 @@ func builtinSubstringIndex(args []interface{}, _ context.Context) (interface{}, // See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_locate func builtinLocate(args []interface{}, _ context.Context) (interface{}, error) { // The meaning of the elements of args. - //args[0] -> SubStr - //args[1] -> Str - //args[2] -> Pos + // args[0] -> SubStr + // args[1] -> Str + // args[2] -> Pos // eval str fs := args[1] if fs == nil { @@ -370,3 +371,79 @@ func builtinLocate(args []interface{}, _ context.Context) (interface{}, error) { } return int64(i) + pos + 1, nil } + +const spaceChars = "\n\t\r " + +// See: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_trim +func builtinTrim(args []interface{}, _ context.Context) (interface{}, error) { + // args[0] -> Str + // args[1] -> RemStr + // args[2] -> Direction + // eval str + fs := args[0] + if fs == nil { + return nil, nil + } + str, err := types.ToString(fs) + if err != nil { + return nil, errors.Trace(err) + } + remstr := "" + // eval remstr + if len(args) > 1 { + fs = args[1] + if fs != nil { + remstr, err = types.ToString(fs) + if err != nil { + return nil, errors.Trace(err) + } + } + } + // do trim + var result string + var direction ast.TrimDirectionType + if len(args) > 2 { + direction = args[2].(ast.TrimDirectionType) + } else { + direction = ast.TrimBothDefault + } + if direction == ast.TrimLeading { + if len(remstr) > 0 { + result = trimLeft(str, remstr) + } else { + result = strings.TrimLeft(str, spaceChars) + } + } else if direction == ast.TrimTrailing { + if len(remstr) > 0 { + result = trimRight(str, remstr) + } else { + result = strings.TrimRight(str, spaceChars) + } + } else if len(remstr) > 0 { + x := trimLeft(str, remstr) + result = trimRight(x, remstr) + } else { + result = strings.Trim(str, spaceChars) + } + return result, nil +} + +func trimLeft(str, remstr string) string { + for { + x := strings.TrimPrefix(str, remstr) + if len(x) == len(str) { + return x + } + str = x + } +} + +func trimRight(str, remstr string) string { + for { + x := strings.TrimSuffix(str, remstr) + if len(x) == len(str) { + return x + } + str = x + } +} diff --git a/evaluator/evaluator.go b/evaluator/evaluator.go index 3d93081b95..a7def07a2d 100644 --- a/evaluator/evaluator.go +++ b/evaluator/evaluator.go @@ -125,8 +125,6 @@ func (e *Evaluator) Leave(in ast.Node) (out ast.Node, ok bool) { ok = e.funcCast(v) case *ast.FuncDateArithExpr: ok = e.funcDateArith(v) - case *ast.FuncTrimExpr: - ok = e.funcTrim(v) case *ast.IsNullExpr: ok = e.isNull(v) case *ast.IsTruthExpr: @@ -709,78 +707,6 @@ func (e *Evaluator) funcCast(v *ast.FuncCastExpr) bool { return true } -const spaceChars = "\n\t\r " - -func (e *Evaluator) funcTrim(v *ast.FuncTrimExpr) bool { - // eval str - fs := v.Str.GetValue() - if fs == nil { - v.SetValue(nil) - return true - } - str, err := types.ToString(fs) - if err != nil { - e.err = errors.Trace(err) - return false - } - remstr := "" - // eval remstr - if v.RemStr != nil { - fs = v.RemStr.GetValue() - if fs == nil { - v.SetValue(nil) - return true - } - remstr, err = types.ToString(fs) - if err != nil { - e.err = errors.Trace(err) - return false - } - } - // Do trim - var result string - if v.Direction == ast.TrimLeading { - if len(remstr) > 0 { - result = trimLeft(str, remstr) - } else { - result = strings.TrimLeft(str, spaceChars) - } - } else if v.Direction == ast.TrimTrailing { - if len(remstr) > 0 { - result = trimRight(str, remstr) - } else { - result = strings.TrimRight(str, spaceChars) - } - } else if len(remstr) > 0 { - x := trimLeft(str, remstr) - result = trimRight(x, remstr) - } else { - result = strings.Trim(str, spaceChars) - } - v.SetValue(result) - return true -} - -func trimLeft(str, remstr string) string { - for { - x := strings.TrimPrefix(str, remstr) - if len(x) == len(str) { - return x - } - str = x - } -} - -func trimRight(str, remstr string) string { - for { - x := strings.TrimSuffix(str, remstr) - if len(x) == len(str) { - return x - } - str = x - } -} - func (e *Evaluator) funcDateArith(v *ast.FuncDateArithExpr) bool { // health check for date and interval nodeDate := v.Date.GetValue() diff --git a/evaluator/evaluator_test.go b/evaluator/evaluator_test.go index 07e4bfaa55..68ae5f53fe 100644 --- a/evaluator/evaluator_test.go +++ b/evaluator/evaluator_test.go @@ -1108,14 +1108,14 @@ func (s *testEvaluatorSuite) TestTrim(c *C) { } ctx := mock.NewContext() for _, v := range tbl { - f := &ast.FuncTrimExpr{ - Str: ast.NewValueExpr(v.str), - Direction: v.dir, + f := &ast.FuncCallExpr{ + FnName: model.NewCIStr("TRIM"), + Args: []ast.ExprNode{ + ast.NewValueExpr(v.str), + ast.NewValueExpr(v.remstr), + ast.NewValueExpr(v.dir), + }, } - if v.remstr != nil { - f.RemStr = ast.NewValueExpr(v.remstr) - } - r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r, Equals, v.result) diff --git a/optimizer/typeinferer.go b/optimizer/typeinferer.go index 869bf5da0a..85ad8f1ab4 100644 --- a/optimizer/typeinferer.go +++ b/optimizer/typeinferer.go @@ -274,7 +274,7 @@ func (v *typeInferrer) handleFuncCallExpr(x *ast.FuncCallExpr) { tp.Decimal = v.getFsp(x) case "dayname", "version", "database", "user", "current_user", "concat", "concat_ws", "left", "lower", "repeat", "replace", "upper", "convert", - "substring", "substring_index": + "substring", "substring_index", "trim": tp = types.NewFieldType(mysql.TypeVarString) chs = v.defaultCharset case "strcmp": diff --git a/parser/parser.go b/parser/parser.go index f9cbe669c6..ce46eb661a 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -734,8 +734,8 @@ var ( 57372: 354, // by (3x) 57673: 355, // ByItem (3x) 57677: 356, // ColumnDef (3x) - 57691: 357, // Constraint (3x) - 57393: 358, // constraint (3x) + 57393: 357, // constraint (3x) + 57691: 358, // Constraint (3x) 57693: 359, // ConstraintKeywordOpt (3x) 57715: 360, // DeleteFromStmt (3x) 57740: 361, // FieldOpt (3x) @@ -1302,8 +1302,8 @@ var ( "by", "ByItem", "ColumnDef", - "Constraint", "constraint", + "Constraint", "ConstraintKeywordOpt", "DeleteFromStmt", "FieldOpt", @@ -2214,7 +2214,7 @@ var ( 698: {473, 1}, 699: {522, 1}, 700: {522, 3}, - 701: {357, 2}, + 701: {358, 2}, 702: {438, 1}, 703: {438, 1}, 704: {438, 4}, @@ -5315,7 +5315,7 @@ var ( {673, 673, 673, 673, 6: 673, 9: 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 673, 123: 673}, {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 198: 1043, 926, 925, 295: 2047}, {125: 2048}, - {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 195: 834, 834, 2055, 1075, 926, 925, 234: 2050, 236: 834, 238: 834, 255: 834, 257: 834, 356: 2053, 2054, 2049, 2052, 438: 2056, 525: 2051}, + {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 195: 834, 834, 2055, 1075, 926, 925, 234: 2050, 236: 834, 238: 834, 255: 834, 257: 834, 356: 2053, 2049, 2054, 2052, 438: 2056, 525: 2051}, // 1195 {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 195: 833, 833, 198: 2309, 926, 925, 236: 833, 238: 833, 255: 833, 257: 833, 437: 2308}, {25: 2219, 27: 2216, 2215, 39: 2218, 55: 2198, 2192, 2191, 67: 2206, 72: 2212, 2217, 145: 2205, 189: 2200, 253: 87, 258: 2193, 2189, 261: 87, 263: 2190, 2208, 2197, 2204, 2175, 2176, 2195, 2177, 2188, 2210, 2214, 2209, 2187, 2213, 2194, 279: 2196, 2186, 2178, 2207, 2185, 2211, 2180, 2179, 2201, 453: 2184, 2202, 466: 2174, 478: 2182, 2183, 486: 2181, 492: 2199, 2172, 523: 2173, 529: 2203, 532: 2171}, @@ -5398,7 +5398,7 @@ var ( {7: 2115, 2077}, {4: 800, 800, 7: 800, 800}, {2123, 2124, 4: 132, 132, 760, 9: 2128, 2125, 2127, 2129, 2126, 2133, 2121, 2130, 2131, 2132, 128: 2120, 142: 760, 202: 760, 324: 2122, 341: 2135, 370: 2134, 2119}, - {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 195: 834, 834, 2055, 1075, 926, 925, 234: 2050, 236: 834, 238: 834, 255: 834, 257: 834, 356: 2053, 2054, 2049, 2052, 438: 2118}, + {927, 976, 928, 945, 6: 934, 9: 950, 977, 979, 980, 978, 991, 942, 981, 982, 983, 941, 957, 959, 951, 944, 999, 968, 935, 938, 937, 1009, 989, 1018, 992, 1023, 1025, 1027, 949, 986, 1032, 961, 965, 966, 970, 1002, 930, 936, 939, 940, 974, 1028, 953, 955, 956, 964, 973, 931, 933, 932, 975, 994, 943, 946, 958, 988, 998, 947, 969, 984, 996, 993, 997, 954, 960, 962, 963, 990, 995, 967, 1000, 1001, 971, 929, 1033, 1003, 1004, 1005, 1006, 1008, 1007, 1010, 1011, 1012, 1013, 1014, 1015, 987, 1016, 1017, 924, 1019, 1020, 1021, 1022, 1024, 948, 1026, 1029, 1030, 952, 1031, 985, 972, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 195: 834, 834, 2055, 1075, 926, 925, 234: 2050, 236: 834, 238: 834, 255: 834, 257: 834, 356: 2053, 2049, 2054, 2052, 438: 2118}, {7: 148, 148}, // 1265 {4: 764, 764}, @@ -5661,7 +5661,7 @@ var ( // 1480 {4: 851, 851, 8: 2358}, {4: 850, 850, 8: 850}, - {841, 841, 841, 841, 6: 841, 9: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 195: 834, 834, 236: 834, 238: 834, 255: 834, 257: 834, 357: 2352, 2049, 2052, 384: 2345, 2351}, + {841, 841, 841, 841, 6: 841, 9: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 195: 834, 834, 236: 834, 238: 834, 255: 834, 257: 834, 357: 2049, 2352, 2052, 384: 2345, 2351}, {841, 841, 841, 841, 6: 841, 9: 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 841, 195: 2340, 236: 2343, 238: 2344, 255: 2342, 384: 2345, 2339, 488: 2341}, {4: 836, 836, 8: 836}, // 1485 @@ -7275,30 +7275,33 @@ yynewstate: } case 437: { - yyVAL.item = &ast.FuncTrimExpr{ - Str: yyS[yypt-1].item.(ast.ExprNode), + yyVAL.item = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-3].item.(string)), + Args: []ast.ExprNode{yyS[yypt-1].item.(ast.ExprNode)}, } } case 438: { - yyVAL.item = &ast.FuncTrimExpr{ - Str: yyS[yypt-1].item.(ast.ExprNode), - RemStr: yyS[yypt-3].item.(ast.ExprNode), + yyVAL.item = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].item.(string)), + Args: []ast.ExprNode{yyS[yypt-1].item.(ast.ExprNode), yyS[yypt-3].item.(ast.ExprNode)}, } } case 439: { - yyVAL.item = &ast.FuncTrimExpr{ - Str: yyS[yypt-1].item.(ast.ExprNode), - Direction: yyS[yypt-3].item.(ast.TrimDirectionType), + nilVal := ast.NewValueExpr(nil) + direction := ast.NewValueExpr(yyS[yypt-3].item) + yyVAL.item = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-5].item.(string)), + Args: []ast.ExprNode{yyS[yypt-1].item.(ast.ExprNode), nilVal, direction}, } } case 440: { - yyVAL.item = &ast.FuncTrimExpr{ - Str: yyS[yypt-1].item.(ast.ExprNode), - RemStr: yyS[yypt-3].item.(ast.ExprNode), - Direction: yyS[yypt-4].item.(ast.TrimDirectionType), + direction := ast.NewValueExpr(yyS[yypt-4].item) + yyVAL.item = &ast.FuncCallExpr{ + FnName: model.NewCIStr(yyS[yypt-6].item.(string)), + Args: []ast.ExprNode{yyS[yypt-1].item.(ast.ExprNode), yyS[yypt-3].item.(ast.ExprNode), direction}, } } case 441: diff --git a/parser/parser.y b/parser/parser.y index 9679e6d406..3909cf43f4 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -2363,31 +2363,34 @@ FunctionCallNonKeyword: } | "TRIM" '(' Expression ')' { - $$ = &ast.FuncTrimExpr{ - Str: $3.(ast.ExprNode), - } + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1.(string)), + Args: []ast.ExprNode{$3.(ast.ExprNode)}, + } } | "TRIM" '(' Expression "FROM" Expression ')' { - $$ = &ast.FuncTrimExpr{ - Str: $5.(ast.ExprNode), - RemStr: $3.(ast.ExprNode), - } + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1.(string)), + Args: []ast.ExprNode{$5.(ast.ExprNode), $3.(ast.ExprNode)}, + } } | "TRIM" '(' TrimDirection "FROM" Expression ')' { - $$ = &ast.FuncTrimExpr{ - Str: $5.(ast.ExprNode), - Direction: $3.(ast.TrimDirectionType), - } + nilVal := ast.NewValueExpr(nil) + direction := ast.NewValueExpr($3) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1.(string)), + Args: []ast.ExprNode{$5.(ast.ExprNode), nilVal, direction}, + } } | "TRIM" '(' TrimDirection Expression "FROM" Expression ')' { - $$ = &ast.FuncTrimExpr{ - Str: $6.(ast.ExprNode), - RemStr: $4.(ast.ExprNode), - Direction: $3.(ast.TrimDirectionType), - } + direction := ast.NewValueExpr($3) + $$ = &ast.FuncCallExpr{ + FnName: model.NewCIStr($1.(string)), + Args: []ast.ExprNode{$6.(ast.ExprNode),$4.(ast.ExprNode), direction}, + } } | "UPPER" '(' Expression ')' {