예제 #1
0
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)
}
예제 #2
0
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))
		}
	}
}
예제 #3
0
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))
}
예제 #4
0
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))
	}
}
예제 #5
0
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))
	}
}
예제 #6
0
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)
	}
}
예제 #7
0
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)
}
예제 #8
0
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)))
		}
	}
}
예제 #9
0
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))
}
예제 #10
0
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))
	}
}
예제 #11
0
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)
}
예제 #12
0
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)
}
예제 #13
0
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)
}
예제 #14
0
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)
}
예제 #15
0
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)
	}
}
예제 #16
0
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)))
}
예제 #17
0
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)
	}
}
예제 #18
0
파일: prepared.go 프로젝트: anywhy/tidb
// 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
}
예제 #19
0
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)
	}
}
예제 #20
0
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)
}
예제 #21
0
파일: prepared.go 프로젝트: pingcap/tidb
// 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
}
예제 #22
0
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)
}
예제 #23
0
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)))
		}
	}
}
예제 #24
0
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)
}
예제 #25
0
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)
}
예제 #26
0
파일: plan_test.go 프로젝트: yubobo/tidb
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
}
예제 #27
0
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)
}
예제 #28
0
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)
}
예제 #29
0
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))
	}
}
예제 #30
0
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)
	}
}