func (s *testEvaluatorSuite) TestCast(c *C) { f := types.NewFieldType(mysql.TypeLonglong) expr := &ast.FuncCastExpr{ Expr: ast.NewValueExpr(1), Tp: f, } ctx := mock.NewContext() v, err := Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, Equals, int64(1)) f.Flag |= mysql.UnsignedFlag v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, Equals, uint64(1)) f.Tp = mysql.TypeString f.Charset = charset.CharsetBin v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, DeepEquals, []byte("1")) f.Tp = mysql.TypeString f.Charset = "utf8" v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, DeepEquals, "1") expr.Expr = ast.NewValueExpr(nil) v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, IsNil) }
func (s *testEvaluatorSuite) TestBinopBitop(c *C) { ctx := mock.NewContext() tbl := []struct { lhs interface{} op opcode.Op rhs interface{} ret interface{} }{ {1, opcode.And, 1, 1}, {1, opcode.Or, 1, 1}, {1, opcode.Xor, 1, 0}, {1, opcode.LeftShift, 1, 2}, {2, opcode.RightShift, 1, 1}, {nil, opcode.And, 1, nil}, {1, opcode.And, nil, nil}, {nil, opcode.Or, 1, nil}, {nil, opcode.Xor, 1, nil}, {nil, opcode.LeftShift, 1, nil}, {nil, opcode.RightShift, 1, nil}, } for _, t := range tbl { expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)} v, err := Eval(ctx, expr) c.Assert(err, IsNil) switch x := t.ret.(type) { case nil: c.Assert(v, IsNil) case int: c.Assert(v, DeepEquals, uint64(x)) } } }
func (s *testAggFuncSuite) TestCount(c *C) { // Compose aggregate exec for "select c1, count(c2) from t"; // c1 c2 // 1 1 // 2 1 // 3 nil c1 := ast.NewValueExpr(0) rf1 := &ast.ResultField{Expr: c1} col1 := &ast.ColumnNameExpr{Refer: rf1} fc1 := &ast.AggregateFuncExpr{ F: ast.AggFuncFirstRow, Args: []ast.ExprNode{col1}, } c2 := ast.NewValueExpr(0) rf2 := &ast.ResultField{Expr: c2} col2 := &ast.ColumnNameExpr{Refer: rf2} fc2 := &ast.AggregateFuncExpr{ F: ast.AggFuncCount, Args: []ast.ExprNode{col2}, } row1 := []interface{}{1, 1} row2 := []interface{}{2, 1} row3 := []interface{}{3, nil} data := []([]interface{}){row1, row2, row3} rows := make([]*Row, 0, 3) for _, d := range data { rows = append(rows, &Row{Data: d}) } src := &mockExec{ rows: rows, fields: []*ast.ResultField{rf1, rf2}, } agg := &AggregateExec{ AggFuncs: []*ast.AggregateFuncExpr{fc1, fc2}, Src: src, } var ( row *Row cnt int ) for { r, err := agg.Next() c.Assert(err, IsNil) if r == nil { break } row = r cnt++ } c.Assert(cnt, Equals, 1) c.Assert(row, NotNil) ctx := mock.NewContext() val, err := evaluator.Eval(ctx, fc1) c.Assert(err, IsNil) c.Assert(val, Equals, 1) val, err = evaluator.Eval(ctx, fc2) c.Assert(err, IsNil) c.Assert(val, Equals, int64(2)) }
func (s *testEvaluatorSuite) TestRegexp(c *C) { defer testleak.AfterTest(c)() tbl := []struct { pattern string input string match int64 }{ {"^$", "a", 0}, {"a", "a", 1}, {"a", "b", 0}, {"aA", "aA", 1}, {".", "a", 1}, {"^.$", "ab", 0}, {"..", "b", 0}, {".ab", "aab", 1}, {".*", "abcd", 1}, } for _, v := range tbl { pattern := &ast.PatternRegexpExpr{ Pattern: ast.NewValueExpr(v.pattern), Expr: ast.NewValueExpr(v.input), } match, err := Eval(s.ctx, pattern) c.Assert(err, IsNil) c.Assert(match, testutil.DatumEquals, types.NewDatum(v.match), Commentf("%v", v)) } }
func (s *testEvaluatorSuite) TestRegexp(c *C) { tbl := []struct { pattern string input string match int64 }{ {"^$", "a", 0}, {"a", "a", 1}, {"a", "b", 0}, {"aA", "aA", 1}, {".", "a", 1}, {"^.$", "ab", 0}, {"..", "b", 0}, {".ab", "aab", 1}, {".*", "abcd", 1}, } ctx := mock.NewContext() for _, v := range tbl { pattern := &ast.PatternRegexpExpr{ Pattern: ast.NewValueExpr(v.pattern), Expr: ast.NewValueExpr(v.input), } match, err := Eval(ctx, pattern) c.Assert(err, IsNil) c.Assert(match, Equals, v.match, Commentf("%v", v)) } }
func (s *testEvaluatorSuite) TestTrim(c *C) { tbl := []struct { str interface{} remstr interface{} dir ast.TrimDirectionType result interface{} }{ {" bar ", nil, ast.TrimBothDefault, "bar"}, {"xxxbarxxx", "x", ast.TrimLeading, "barxxx"}, {"xxxbarxxx", "x", ast.TrimBoth, "bar"}, {"barxxyz", "xyz", ast.TrimTrailing, "barx"}, {nil, "xyz", ast.TrimBoth, nil}, {1, 2, ast.TrimBoth, "1"}, {" \t\rbar\n ", nil, ast.TrimBothDefault, "bar"}, } ctx := mock.NewContext() for _, v := range tbl { f := &ast.FuncTrimExpr{ Str: ast.NewValueExpr(v.str), Direction: 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) } }
func (s *testEvaluatorSuite) TestCast(c *C) { defer testleak.AfterTest(c)() f := types.NewFieldType(mysql.TypeLonglong) expr := &ast.FuncCastExpr{ Expr: ast.NewValueExpr(1), Tp: f, } ast.SetFlag(expr) v, err := Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(1))) f.Flag |= mysql.UnsignedFlag v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(1))) f.Tp = mysql.TypeString f.Charset = charset.CharsetBin v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum([]byte("1"))) f.Tp = mysql.TypeString f.Charset = "utf8" v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum("1")) expr.Expr = ast.NewValueExpr(nil) v, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) }
func (s *testEvaluatorSuite) TestBinopBitop(c *C) { defer testleak.AfterTest(c)() tbl := []struct { lhs interface{} op opcode.Op rhs interface{} ret interface{} }{ {1, opcode.And, 1, 1}, {1, opcode.Or, 1, 1}, {1, opcode.Xor, 1, 0}, {1, opcode.LeftShift, 1, 2}, {2, opcode.RightShift, 1, 1}, {nil, opcode.And, 1, nil}, {1, opcode.And, nil, nil}, {nil, opcode.Or, 1, nil}, {nil, opcode.Xor, 1, nil}, {nil, opcode.LeftShift, 1, nil}, {nil, opcode.RightShift, 1, nil}, } for _, t := range tbl { expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)} v, err := Eval(s.ctx, expr) c.Assert(err, IsNil) switch x := t.ret.(type) { case nil: c.Assert(v.Kind(), Equals, types.KindNull) case int: c.Assert(v, testutil.DatumEquals, types.NewDatum(uint64(x))) } } }
func (s *testEvaluatorSuite) TestEvaluatedFlag(c *C) { l := ast.NewValueExpr(int64(1)) r := ast.NewValueExpr(int64(2)) b := &ast.BinaryOperationExpr{L: l, R: r, Op: opcode.Plus} ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, true) d, err := Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, true) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) funcCall := &ast.FuncCallExpr{ FnName: model.NewCIStr("abs"), Args: []ast.ExprNode{ast.NewValueExpr(int(-1))}, } b = &ast.BinaryOperationExpr{L: funcCall, R: r, Op: opcode.Plus} ast.ResetEvaluatedFlag(b) ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, true) d, err = Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, false) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) rf := &ast.ResultField{Expr: ast.NewValueExpr(int64(1))} colExpr := &ast.ColumnNameExpr{Refer: rf} b = &ast.BinaryOperationExpr{L: colExpr, R: r, Op: opcode.Plus} ast.ResetEvaluatedFlag(b) ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, false) d, err = Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, false) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) }
func (s *testEvaluatorSuite) TestTrim(c *C) { defer testleak.AfterTest(c)() tbl := []struct { str interface{} remstr interface{} dir ast.TrimDirectionType result interface{} }{ {" bar ", nil, ast.TrimBothDefault, "bar"}, {"xxxbarxxx", "x", ast.TrimLeading, "barxxx"}, {"xxxbarxxx", "x", ast.TrimBoth, "bar"}, {"barxxyz", "xyz", ast.TrimTrailing, "barx"}, {nil, "xyz", ast.TrimBoth, nil}, {1, 2, ast.TrimBoth, "1"}, {" \t\rbar\n ", nil, ast.TrimBothDefault, "bar"}, } ctx := mock.NewContext() for _, v := range tbl { f := &ast.FuncCallExpr{ FnName: model.NewCIStr("TRIM"), Args: []ast.ExprNode{ ast.NewValueExpr(v.str), ast.NewValueExpr(v.remstr), ast.NewValueExpr(v.dir), }, } r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result)) } for _, v := range []struct { str, result interface{} fn string }{ {" ", "", "LTRIM"}, {" ", "", "RTRIM"}, {"foo0", "foo0", "LTRIM"}, {"bar0", "bar0", "RTRIM"}, {" foo1", "foo1", "LTRIM"}, {"bar1 ", "bar1", "RTRIM"}, {spaceChars + "foo2 ", "foo2 ", "LTRIM"}, {" bar2" + spaceChars, " bar2", "RTRIM"}, {nil, nil, "LTRIM"}, {nil, nil, "RTRIM"}, } { f := &ast.FuncCallExpr{ FnName: model.NewCIStr(v.fn), Args: []ast.ExprNode{ast.NewValueExpr(v.str)}, } r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r, testutil.DatumEquals, types.NewDatum(v.result)) } }
func (s *testEvaluatorSuite) TestExtract(c *C) { defer testleak.AfterTest(c)() str := "2011-11-11 10:10:10.123456" tbl := []struct { Unit string Expect int64 }{ {"MICROSECOND", 123456}, {"SECOND", 10}, {"MINUTE", 10}, {"HOUR", 10}, {"DAY", 11}, {"WEEK", 45}, {"MONTH", 11}, {"QUARTER", 4}, {"YEAR", 2011}, {"SECOND_MICROSECOND", 10123456}, {"MINUTE_MICROSECOND", 1010123456}, {"MINUTE_SECOND", 1010}, {"HOUR_MICROSECOND", 101010123456}, {"HOUR_SECOND", 101010}, {"HOUR_MINUTE", 1010}, {"DAY_MICROSECOND", 11101010123456}, {"DAY_SECOND", 11101010}, {"DAY_MINUTE", 111010}, {"DAY_HOUR", 1110}, {"YEAR_MONTH", 201111}, } ctx := mock.NewContext() for _, t := range tbl { e := &ast.FuncCallExpr{ FnName: model.NewCIStr("EXTRACT"), Args: []ast.ExprNode{ast.NewValueExpr(t.Unit), ast.NewValueExpr(str)}, } v, err := Eval(ctx, e) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(t.Expect)) } // Test nil e := &ast.FuncCallExpr{ FnName: model.NewCIStr("EXTRACT"), Args: []ast.ExprNode{ast.NewValueExpr("SECOND"), ast.NewValueExpr(nil)}, } v, err := Eval(ctx, e) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) }
func (s *testEvaluatorSuite) TestExtract(c *C) { str := "2011-11-11 10:10:10.123456" tbl := []struct { Unit string Expect int64 }{ {"MICROSECOND", 123456}, {"SECOND", 10}, {"MINUTE", 10}, {"HOUR", 10}, {"DAY", 11}, {"WEEK", 45}, {"MONTH", 11}, {"QUARTER", 4}, {"YEAR", 2011}, {"SECOND_MICROSECOND", 10123456}, {"MINUTE_MICROSECOND", 1010123456}, {"MINUTE_SECOND", 1010}, {"HOUR_MICROSECOND", 101010123456}, {"HOUR_SECOND", 101010}, {"HOUR_MINUTE", 1010}, {"DAY_MICROSECOND", 11101010123456}, {"DAY_SECOND", 11101010}, {"DAY_MINUTE", 111010}, {"DAY_HOUR", 1110}, {"YEAR_MONTH", 201111}, } ctx := mock.NewContext() for _, t := range tbl { e := &ast.FuncExtractExpr{ Unit: t.Unit, Date: ast.NewValueExpr(str), } v, err := Eval(ctx, e) c.Assert(err, IsNil) c.Assert(v, Equals, t.Expect) } // Test nil e := &ast.FuncExtractExpr{ Unit: "SECOND", Date: ast.NewValueExpr(nil), } v, err := Eval(ctx, e) c.Assert(err, IsNil) c.Assert(v, IsNil) }
func (s *testEvaluatorSuite) TestColumnNameExpr(c *C) { ctx := mock.NewContext() value1 := ast.NewValueExpr(1) rf := &ast.ResultField{Expr: value1} expr := &ast.ColumnNameExpr{Refer: rf} result, err := Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(result, Equals, 1) value2 := ast.NewValueExpr(2) rf.Expr = value2 result, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(result, Equals, 2) }
func (s *testEvaluatorSuite) TestIsCurrentTimeExpr(c *C) { v := IsCurrentTimeExpr(ast.NewValueExpr("abc")) c.Assert(v, IsFalse) v = IsCurrentTimeExpr(&ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}) c.Assert(v, IsTrue) }
func (s *testEvaluatorSuite) TestConvert(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() tbl := []struct { str string cs string result string }{ {"haha", "utf8", "haha"}, {"haha", "ascii", "haha"}, } for _, v := range tbl { f := &ast.FuncCallExpr{ FnName: model.NewCIStr("CONVERT"), Args: []ast.ExprNode{ ast.NewValueExpr(v.str), ast.NewValueExpr(v.cs), }, } r, err := Eval(ctx, f) c.Assert(err, IsNil) c.Assert(r.Kind(), Equals, types.KindString) c.Assert(r.GetString(), Equals, v.result) } // Test case for error errTbl := []struct { str interface{} cs string result string }{ {"haha", "wrongcharset", "haha"}, } for _, v := range errTbl { f := &ast.FuncCallExpr{ FnName: model.NewCIStr("CONVERT"), Args: []ast.ExprNode{ ast.NewValueExpr(v.str), ast.NewValueExpr(v.cs), }, } _, err := Eval(ctx, f) c.Assert(err, NotNil) } }
func (s *testEvaluatorSuite) TestColumnNameExpr(c *C) { defer testleak.AfterTest(c)() value1 := ast.NewValueExpr(1) rf := &ast.ResultField{Expr: value1} expr := &ast.ColumnNameExpr{Refer: rf} ast.SetFlag(expr) result, err := Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(result, testutil.DatumEquals, types.NewDatum(int64(1))) value2 := ast.NewValueExpr(2) rf.Expr = value2 result, err = Eval(s.ctx, expr) c.Assert(err, IsNil) c.Assert(result, testutil.DatumEquals, types.NewDatum(int64(2))) }
func (s *testEvaluatorSuite) TestConvert(c *C) { ctx := mock.NewContext() tbl := []struct { str string cs string result string }{ {"haha", "utf8", "haha"}, {"haha", "ascii", "haha"}, } for _, v := range tbl { f := &ast.FuncConvertExpr{ Expr: ast.NewValueExpr(v.str), Charset: v.cs, } fs := f.String() c.Assert(len(fs), Greater, 0) r, err := Eval(ctx, f) c.Assert(err, IsNil) s, ok := r.(string) c.Assert(ok, IsTrue) c.Assert(s, Equals, v.result) } // Test case for error errTbl := []struct { str interface{} cs string result string }{ {"haha", "wrongcharset", "haha"}, } for _, v := range errTbl { f := &ast.FuncConvertExpr{ Expr: ast.NewValueExpr(v.str), Charset: v.cs, } _, err := Eval(ctx, f) c.Assert(err, NotNil) } }
// CompileExecutePreparedStmt compiles a session Execute command to a stmt.Statement. func CompileExecutePreparedStmt(ctx context.Context, ID uint32, args ...interface{}) ast.Statement { execPlan := &plan.Execute{ID: ID} execPlan.UsingVars = make([]ast.ExprNode, len(args)) for i, val := range args { execPlan.UsingVars[i] = ast.NewValueExpr(val) } sa := &statement{ is: sessionctx.GetDomain(ctx).InfoSchema(), plan: execPlan, } return sa }
func (s *testEvaluatorSuite) TestSubstring(c *C) { tbl := []struct { str string pos int64 slen int64 result string }{ {"Quadratically", 5, -1, "ratically"}, {"foobarbar", 4, -1, "barbar"}, {"Quadratically", 5, 6, "ratica"}, {"Sakila", -3, -1, "ila"}, {"Sakila", -5, 3, "aki"}, {"Sakila", -4, 2, "ki"}, {"Sakila", 1000, 2, ""}, {"", 2, 3, ""}, } ctx := mock.NewContext() for _, v := range tbl { f := &ast.FuncSubstringExpr{ StrExpr: ast.NewValueExpr(v.str), Pos: ast.NewValueExpr(v.pos), } if v.slen != -1 { f.Len = ast.NewValueExpr(v.slen) } r, err := Eval(ctx, f) c.Assert(err, IsNil) s, ok := r.(string) c.Assert(ok, IsTrue) c.Assert(s, Equals, v.result) r1, err := Eval(ctx, f) c.Assert(err, IsNil) s1, ok := r1.(string) c.Assert(ok, IsTrue) c.Assert(s, Equals, s1) } errTbl := []struct { str interface{} pos interface{} len interface{} result string }{ {1, 5, -1, "ratically"}, {"foobarbar", "4", -1, "barbar"}, {"Quadratically", 5, "6", "ratica"}, } for _, v := range errTbl { f := &ast.FuncSubstringExpr{ StrExpr: ast.NewValueExpr(v.str), Pos: ast.NewValueExpr(v.pos), } if v.len != -1 { f.Len = ast.NewValueExpr(v.len) } _, err := Eval(ctx, f) c.Assert(err, NotNil) } }
func (s *testEvaluatorSuite) TestCaseWhen(c *C) { defer testleak.AfterTest(c)() cases := []testCase{ { exprStr: "case 1 when 1 then 'str1' when 2 then 'str2' end", resultStr: "str1", }, { exprStr: "case 2 when 1 then 'str1' when 2 then 'str2' end", resultStr: "str2", }, { exprStr: "case 3 when 1 then 'str1' when 2 then 'str2' end", resultStr: "<nil>", }, { exprStr: "case 4 when 1 then 'str1' when 2 then 'str2' else 'str3' end", resultStr: "str3", }, } s.runTests(c, cases) // When expression value changed, result set back to null. valExpr := ast.NewValueExpr(1) whenClause := &ast.WhenClause{Expr: ast.NewValueExpr(1), Result: ast.NewValueExpr(1)} caseExpr := &ast.CaseExpr{ Value: valExpr, WhenClauses: []*ast.WhenClause{whenClause}, } ctx := mock.NewContext() v, err := Eval(ctx, caseExpr) c.Assert(err, IsNil) c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(1))) valExpr.SetValue(4) ast.ResetEvaluatedFlag(caseExpr) v, err = Eval(ctx, caseExpr) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) }
// CompileExecutePreparedStmt compiles a session Execute command to a stmt.Statement. func CompileExecutePreparedStmt(ctx context.Context, ID uint32, args ...interface{}) ast.Statement { execPlan := &plan.Execute{ID: ID} execPlan.UsingVars = make([]expression.Expression, len(args)) for i, val := range args { value := ast.NewValueExpr(val) execPlan.UsingVars[i] = &expression.Constant{Value: value.Datum, RetType: &value.Type} } sa := &statement{ is: GetInfoSchema(ctx), plan: execPlan, } return sa }
func (s *testEvaluatorSuite) TestAggFuncAvg(c *C) { ctx := mock.NewContext() avg := &ast.AggregateFuncExpr{ F: ast.AggFuncAvg, } avg.CurrentGroup = "emptyGroup" result, err := Eval(ctx, avg) c.Assert(err, IsNil) // Empty group should return nil. c.Assert(result, IsNil) avg.Args = []ast.ExprNode{ast.NewValueExpr(2)} avg.Update() avg.Args = []ast.ExprNode{ast.NewValueExpr(4)} avg.Update() result, err = Eval(ctx, avg) c.Assert(err, IsNil) expect, _ := mysql.ConvertToDecimal(3) v, ok := result.(mysql.Decimal) c.Assert(ok, IsTrue) c.Assert(v.Equals(expect), IsTrue) }
func (s *testEvaluatorSuite) TestBinopLogic(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() tbl := []struct { lhs interface{} op opcode.Op rhs interface{} ret interface{} }{ {nil, opcode.AndAnd, 1, nil}, {nil, opcode.AndAnd, 0, 0}, {nil, opcode.OrOr, 1, 1}, {nil, opcode.OrOr, 0, nil}, {nil, opcode.LogicXor, 1, nil}, {nil, opcode.LogicXor, 0, nil}, {1, opcode.AndAnd, 0, 0}, {1, opcode.AndAnd, 1, 1}, {1, opcode.OrOr, 0, 1}, {1, opcode.OrOr, 1, 1}, {0, opcode.OrOr, 0, 0}, {1, opcode.LogicXor, 0, 1}, {1, opcode.LogicXor, 1, 0}, {0, opcode.LogicXor, 0, 0}, {0, opcode.LogicXor, 1, 1}, } for _, t := range tbl { expr := &ast.BinaryOperationExpr{Op: t.op, L: ast.NewValueExpr(t.lhs), R: ast.NewValueExpr(t.rhs)} v, err := Eval(ctx, expr) c.Assert(err, IsNil) switch x := t.ret.(type) { case nil: c.Assert(v.Kind(), Equals, types.KindNull) case int: c.Assert(v, testutil.DatumEquals, types.NewDatum(int64(x))) } } }
func (s *testEvaluatorSuite) TestCaseWhen(c *C) { cases := []testCase{ { exprStr: "case 1 when 1 then 'str1' when 2 then 'str2' end", resultStr: "str1", }, { exprStr: "case 2 when 1 then 'str1' when 2 then 'str2' end", resultStr: "str2", }, { exprStr: "case 3 when 1 then 'str1' when 2 then 'str2' end", resultStr: "<nil>", }, { exprStr: "case 4 when 1 then 'str1' when 2 then 'str2' else 'str3' end", resultStr: "str3", }, } s.runTests(c, cases) // When expression value changed, result set back to null. valExpr := ast.NewValueExpr(1) whenClause := &ast.WhenClause{Expr: ast.NewValueExpr(1), Result: ast.NewValueExpr(1)} caseExpr := &ast.CaseExpr{ Value: valExpr, WhenClauses: []*ast.WhenClause{whenClause}, } ctx := mock.NewContext() v, err := Eval(ctx, caseExpr) c.Assert(err, IsNil) c.Assert(v, Equals, 1) valExpr.SetValue(4) v, err = Eval(ctx, caseExpr) c.Assert(err, IsNil) c.Assert(v, IsNil) }
func (s *testEvaluatorSuite) TestAggFuncAvg(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() avg := &ast.AggregateFuncExpr{ F: ast.AggFuncAvg, } avg.CurrentGroup = []byte("emptyGroup") ast.SetFlag(avg) result, err := Eval(ctx, avg) c.Assert(err, IsNil) // Empty group should return nil. c.Assert(result.Kind(), Equals, types.KindNull) avg.Args = []ast.ExprNode{ast.NewValueExpr(2)} avg.Update() avg.Args = []ast.ExprNode{ast.NewValueExpr(4)} avg.Update() result, err = Eval(ctx, avg) c.Assert(err, IsNil) expect := mysql.NewDecFromInt(3) c.Assert(result.Kind(), Equals, types.KindMysqlDecimal) c.Assert(result.GetMysqlDecimal().Compare(expect), Equals, 0) }
func (b *mockJoinResolver) Leave(in ast.Node) (ast.Node, bool) { switch x := in.(type) { case *ast.TableName: if b.tables[x.Name.L] == nil { b.tables[x.Name.L] = x x.TableInfo = &model.TableInfo{ Name: x.Name, PKIsHandle: true, } } case *ast.ColumnNameExpr: tn := b.tables[x.Name.Table.L] b.c.Assert(tn, NotNil) for _, cn := range tn.TableInfo.Columns { if cn.Name.L == x.Name.Name.L { x.Refer = b.refers[cn] return in, true } } columnInfo := &model.ColumnInfo{Name: x.Name.Name} tn.TableInfo.Columns = append(tn.TableInfo.Columns, columnInfo) refer := &ast.ResultField{ Column: columnInfo, Table: tn.TableInfo, TableName: tn, Expr: ast.NewValueExpr(99), } b.refers[columnInfo] = refer x.Refer = refer if x.Name.Name.L == "id" { columnInfo.Flag = mysql.PriKeyFlag } else if x.Name.Name.L[0] == 'i' { idxInfo := &model.IndexInfo{ Name: x.Name.Name, Columns: []*model.IndexColumn{ { Name: x.Name.Name, }, }, } tn.TableInfo.Indices = append(tn.TableInfo.Indices, idxInfo) } } return in, true }
func (s *testEvaluatorSuite) TestCall(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() // Test case for correct number of arguments expr := &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{ast.NewValueExpr("2015-12-21 11:11:11")}, } v, err := Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindMysqlTime) c.Assert(v.GetMysqlTime().String(), Equals, "2015-12-21") // Test case for unlimited upper bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("concat"), Args: []ast.ExprNode{ast.NewValueExpr("Ti"), ast.NewValueExpr("D"), ast.NewValueExpr("B")}, } v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindString) c.Assert(v.GetString(), Equals, "TiDB") // Test case for unknown function expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("unknown"), Args: []ast.ExprNode{}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) // Test case for invalid number of arguments, violating the lower bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) // Test case for invalid number of arguments, violating the upper bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{ast.NewValueExpr("2015-12-21"), ast.NewValueExpr("2015-12-22")}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) }
func (s *testEvaluatorSuite) TestCall(c *C) { ctx := mock.NewContext() // Test case for correct number of arguments expr := &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{ast.NewValueExpr("2015-12-21 11:11:11")}, } v, err := Eval(ctx, expr) c.Assert(err, IsNil) value, ok := v.(mysql.Time) c.Assert(ok, IsTrue) c.Assert(value.String(), Equals, "2015-12-21") // Test case for unlimited upper bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("concat"), Args: []ast.ExprNode{ast.NewValueExpr("Ti"), ast.NewValueExpr("D"), ast.NewValueExpr("B")}, } v, err = Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(v, Equals, "TiDB") // Test case for unknown function expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("unknown"), Args: []ast.ExprNode{}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) // Test case for invalid number of arguments, violating the lower bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) // Test case for invalid number of arguments, violating the upper bound expr = &ast.FuncCallExpr{ FnName: model.NewCIStr("date"), Args: []ast.ExprNode{ast.NewValueExpr("2015-12-21"), ast.NewValueExpr("2015-12-22")}, } _, err = Eval(ctx, expr) c.Assert(err, NotNil) }
func (s *testEvaluatorSuite) TestLastInsertID(c *C) { defer testleak.AfterTest(c)() cases := []struct { exprStr []ast.ExprNode resultStr string }{ {nil, "0"}, {[]ast.ExprNode{ast.NewValueExpr(1)}, "1"}, } c.Log(s.ctx) for _, ca := range cases { expr := &ast.FuncCallExpr{ FnName: model.NewCIStr("last_insert_id"), Args: ca.exprStr, } val, err := Eval(s.ctx, expr) c.Assert(err, IsNil) valStr := fmt.Sprintf("%v", val.GetValue()) c.Assert(valStr, Equals, ca.resultStr, Commentf("for %s", ca.exprStr)) } }
func (s *testEvaluatorSuite) TestUnaryOp(c *C) { tbl := []struct { arg interface{} op opcode.Op result interface{} }{ // test NOT. {1, opcode.Not, int64(0)}, {0, opcode.Not, int64(1)}, {nil, opcode.Not, nil}, {mysql.Hex{Value: 0}, opcode.Not, int64(1)}, {mysql.Bit{Value: 0, Width: 1}, opcode.Not, int64(1)}, {mysql.Enum{Name: "a", Value: 1}, opcode.Not, int64(0)}, {mysql.Set{Name: "a", Value: 1}, opcode.Not, int64(0)}, // test BitNeg. {nil, opcode.BitNeg, nil}, {-1, opcode.BitNeg, uint64(0)}, // test Plus. {nil, opcode.Plus, nil}, {float64(1.0), opcode.Plus, float64(1.0)}, {int(1), opcode.Plus, int(1)}, {int64(1), opcode.Plus, int64(1)}, {uint64(1), opcode.Plus, uint64(1)}, {"1.0", opcode.Plus, "1.0"}, {[]byte("1.0"), opcode.Plus, []byte("1.0")}, {mysql.Hex{Value: 1}, opcode.Plus, mysql.Hex{Value: 1}}, {mysql.Bit{Value: 1, Width: 1}, opcode.Plus, mysql.Bit{Value: 1, Width: 1}}, {true, opcode.Plus, int64(1)}, {false, opcode.Plus, int64(0)}, {mysql.Enum{Name: "a", Value: 1}, opcode.Plus, mysql.Enum{Name: "a", Value: 1}}, {mysql.Set{Name: "a", Value: 1}, opcode.Plus, mysql.Set{Name: "a", Value: 1}}, // test Minus. {nil, opcode.Minus, nil}, {float64(1.0), opcode.Minus, float64(-1.0)}, {int(1), opcode.Minus, int(-1)}, {int64(1), opcode.Minus, int64(-1)}, {uint64(1), opcode.Minus, -int64(1)}, {"1.0", opcode.Minus, -1.0}, {[]byte("1.0"), opcode.Minus, -1.0}, {mysql.Hex{Value: 1}, opcode.Minus, -1.0}, {mysql.Bit{Value: 1, Width: 1}, opcode.Minus, -1.0}, {true, opcode.Minus, int64(-1)}, {false, opcode.Minus, int64(0)}, {mysql.Enum{Name: "a", Value: 1}, opcode.Minus, -1.0}, {mysql.Set{Name: "a", Value: 1}, opcode.Minus, -1.0}, } ctx := mock.NewContext() expr := &ast.UnaryOperationExpr{} for _, t := range tbl { expr.Op = t.op expr.V = ast.NewValueExpr(t.arg) result, err := Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(result, DeepEquals, t.result) } tbl = []struct { arg interface{} op opcode.Op result interface{} }{ {mysql.NewDecimalFromInt(1, 0), opcode.Plus, mysql.NewDecimalFromInt(1, 0)}, {mysql.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: mysql.DefaultFsp}, opcode.Plus, mysql.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: mysql.DefaultFsp}}, {mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Plus, mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}}, {mysql.NewDecimalFromInt(1, 0), opcode.Minus, mysql.NewDecimalFromInt(-1, 0)}, {mysql.ZeroDuration, opcode.Minus, mysql.NewDecimalFromInt(0, 0)}, {mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Minus, mysql.NewDecimalFromInt(-20091110230000, 0)}, } for _, t := range tbl { expr := &ast.UnaryOperationExpr{Op: t.op, V: ast.NewValueExpr(t.arg)} result, err := Eval(ctx, expr) c.Assert(err, IsNil) ret, err := types.Compare(result, t.result) c.Assert(err, IsNil) c.Assert(ret, Equals, 0) } }