func (ts *testDatumSuite) TestCoerceDatum(c *C) { testCases := []struct { a Datum b Datum kind byte }{ {NewIntDatum(1), NewIntDatum(1), KindInt64}, {NewUintDatum(1), NewDecimalDatum(mysql.NewDecFromInt(1)), KindMysqlDecimal}, {NewFloat64Datum(1), NewDecimalDatum(mysql.NewDecFromInt(1)), KindFloat64}, {NewFloat64Datum(1), NewFloat64Datum(1), KindFloat64}, } for _, ca := range testCases { x, y, err := CoerceDatum(ca.a, ca.b) c.Check(err, IsNil) c.Check(x.Kind(), Equals, y.Kind()) c.Check(x.Kind(), Equals, ca.kind) } }
func (s *testDecimalSuite) TestFrac(c *C) { defer testleak.AfterTest(c)() inputs := []struct { Input *mysql.MyDecimal }{ {mysql.NewDecFromInt(3)}, {mysql.NewDecFromFloatForTest(0.03)}, } for _, v := range inputs { testFrac(c, v.Input) } }
func (ts *testFunctionsSuite) TestAggFuncSum(c *C) { args := make([]ExprNode, 1) // sum with distinct agg := &AggregateFuncExpr{ Args: args, F: AggFuncSum, Distinct: true, } agg.CurrentGroup = []byte("xx") expr := NewValueExpr(1) expr1 := NewValueExpr(nil) expr2 := NewValueExpr(1) exprs := []ExprNode{expr, expr1, expr2} for _, e := range exprs { args[0] = e agg.Update() } ctx := agg.GetContext() expect := mysql.NewDecFromInt(1) c.Assert(ctx.Value.Kind(), Equals, types.KindMysqlDecimal) c.Assert(ctx.Value.GetMysqlDecimal().Compare(expect), Equals, 0) // sum without distinct agg = &AggregateFuncExpr{ Args: args, F: AggFuncSum, } agg.CurrentGroup = []byte("xx") expr = NewValueExpr(2) expr1 = NewValueExpr(nil) expr2 = NewValueExpr(2) exprs = []ExprNode{expr, expr1, expr2} for _, e := range exprs { args[0] = e agg.Update() } ctx = agg.GetContext() expect = mysql.NewDecFromInt(4) c.Assert(ctx.Value.Kind(), Equals, types.KindMysqlDecimal) c.Assert(ctx.Value.GetMysqlDecimal().Compare(expect), Equals, 0) }
func (af *avgFunction) calculateResult(ctx *ast.AggEvaluateContext) (d types.Datum) { switch ctx.Value.Kind() { case types.KindFloat64: t := ctx.Value.GetFloat64() / float64(ctx.Count) d.SetValue(t) case types.KindMysqlDecimal: x := ctx.Value.GetMysqlDecimal() y := mysql.NewDecFromInt(ctx.Count) to := new(mysql.MyDecimal) mysql.DecimalDiv(x, y, to, mysql.DivFracIncr) to.Round(to, ctx.Value.Frac()+mysql.DivFracIncr) d.SetMysqlDecimal(to) } return }
// GetGroupResult implements AggregationFunction interface. func (af *avgFunction) GetGroupResult(groupKey []byte) (d types.Datum) { ctx := af.getContext(groupKey) switch ctx.Value.Kind() { case types.KindFloat64: t := ctx.Value.GetFloat64() / float64(ctx.Count) d.SetValue(t) case types.KindMysqlDecimal: x := ctx.Value.GetMysqlDecimal() y := mysql.NewDecFromInt(ctx.Count) to := new(mysql.MyDecimal) mysql.DecimalDiv(x, y, to, mysql.DivFracIncr) to.Round(to, ctx.Value.Frac()+mysql.DivFracIncr) d.SetMysqlDecimal(to) } return }
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 (s *testCompareSuite) TestCompare(c *C) { defer testleak.AfterTest(c)() cmpTbl := []struct { lhs interface{} rhs interface{} ret int // 0, 1, -1 }{ {float64(1), float64(1), 0}, {float64(1), "1", 0}, {int64(1), int64(1), 0}, {int64(-1), uint64(1), -1}, {int64(-1), "-1", 0}, {uint64(1), uint64(1), 0}, {uint64(1), int64(-1), 1}, {uint64(1), "1", 0}, {mysql.NewDecFromInt(1), mysql.NewDecFromInt(1), 0}, {mysql.NewDecFromInt(1), "1", 0}, {mysql.NewDecFromInt(1), []byte("1"), 0}, {"1", "1", 0}, {"1", int64(-1), 1}, {"1", float64(2), -1}, {"1", uint64(1), 0}, {"1", mysql.NewDecFromInt(1), 0}, {"2011-01-01 11:11:11", mysql.Time{Time: time.Now(), Type: mysql.TypeDatetime, Fsp: 0}, -1}, {"12:00:00", mysql.ZeroDuration, 1}, {mysql.ZeroDuration, mysql.ZeroDuration, 0}, {mysql.Time{Time: time.Now().Add(time.Second * 10), Type: mysql.TypeDatetime, Fsp: 0}, mysql.Time{Time: time.Now(), Type: mysql.TypeDatetime, Fsp: 0}, 1}, {nil, 2, -1}, {nil, nil, 0}, {false, nil, 1}, {false, true, -1}, {true, true, 0}, {false, false, 0}, {true, 2, -1}, {float64(1.23), nil, 1}, {float64(0.0), float64(3.45), -1}, {float64(354.23), float64(3.45), 1}, {float64(3.452), float64(3.452), 0}, {int(432), nil, 1}, {-4, int(32), -1}, {int(4), -32, 1}, {int(432), int64(12), 1}, {int(23), int64(128), -1}, {int(123), int64(123), 0}, {int(432), int(12), 1}, {int(23), int(123), -1}, {int64(133), int(183), -1}, {uint64(133), uint64(183), -1}, {uint64(2), int64(-2), 1}, {uint64(2), int64(1), 1}, {"", nil, 1}, {"", "24", -1}, {"aasf", "4", 1}, {"", "", 0}, {[]byte(""), nil, 1}, {[]byte(""), []byte("sff"), -1}, {mysql.Time{}, nil, 1}, {mysql.Time{}, mysql.Time{Time: time.Now(), Type: mysql.TypeDatetime, Fsp: 3}, -1}, {mysql.Time{Time: time.Now(), Type: mysql.TypeDatetime, Fsp: 3}, "0000-00-00 00:00:00", 1}, {mysql.Duration{Duration: time.Duration(34), Fsp: 2}, nil, 1}, {mysql.Duration{Duration: time.Duration(34), Fsp: 2}, mysql.Duration{Duration: time.Duration(29034), Fsp: 2}, -1}, {mysql.Duration{Duration: time.Duration(3340), Fsp: 2}, mysql.Duration{Duration: time.Duration(34), Fsp: 2}, 1}, {mysql.Duration{Duration: time.Duration(34), Fsp: 2}, mysql.Duration{Duration: time.Duration(34), Fsp: 2}, 0}, {[]byte{}, []byte{}, 0}, {[]byte("abc"), []byte("ab"), 1}, {[]byte("123"), 1234, -1}, {[]byte{}, nil, 1}, {[]interface{}{1, 2, 3}, []interface{}{1, 2, 3}, 0}, {[]interface{}{1, 3, 3}, []interface{}{1, 2, 3}, 1}, {[]interface{}{1, 2, 3}, []interface{}{2, 2, 3}, -1}, {mysql.Hex{Value: 1}, 1, 0}, {mysql.Hex{Value: 0x4D7953514C}, "MySQL", 0}, {mysql.Hex{Value: 0}, uint64(10), -1}, {mysql.Hex{Value: 1}, float64(0), 1}, {mysql.Hex{Value: 1}, mysql.NewDecFromInt(1), 0}, {mysql.Hex{Value: 1}, mysql.Bit{Value: 0, Width: 1}, 1}, {mysql.Hex{Value: 1}, mysql.Hex{Value: 1}, 0}, {mysql.Bit{Value: 1, Width: 1}, 1, 0}, {mysql.Bit{Value: 0x41, Width: 8}, "A", 0}, {mysql.Bit{Value: 1, Width: 1}, uint64(10), -1}, {mysql.Bit{Value: 1, Width: 1}, float64(0), 1}, {mysql.Bit{Value: 1, Width: 1}, mysql.NewDecFromInt(1), 0}, {mysql.Bit{Value: 1, Width: 1}, mysql.Hex{Value: 2}, -1}, {mysql.Bit{Value: 1, Width: 1}, mysql.Bit{Value: 1, Width: 1}, 0}, {mysql.Enum{Name: "a", Value: 1}, 1, 0}, {mysql.Enum{Name: "a", Value: 1}, "a", 0}, {mysql.Enum{Name: "a", Value: 1}, uint64(10), -1}, {mysql.Enum{Name: "a", Value: 1}, float64(0), 1}, {mysql.Enum{Name: "a", Value: 1}, mysql.NewDecFromInt(1), 0}, {mysql.Enum{Name: "a", Value: 1}, mysql.Hex{Value: 2}, -1}, {mysql.Enum{Name: "a", Value: 1}, mysql.Bit{Value: 1, Width: 1}, 0}, {mysql.Enum{Name: "a", Value: 1}, mysql.Hex{Value: 1}, 0}, {mysql.Enum{Name: "a", Value: 1}, mysql.Enum{Name: "a", Value: 1}, 0}, {mysql.Set{Name: "a", Value: 1}, 1, 0}, {mysql.Set{Name: "a", Value: 1}, "a", 0}, {mysql.Set{Name: "a", Value: 1}, uint64(10), -1}, {mysql.Set{Name: "a", Value: 1}, float64(0), 1}, {mysql.Set{Name: "a", Value: 1}, mysql.NewDecFromInt(1), 0}, {mysql.Set{Name: "a", Value: 1}, mysql.Hex{Value: 2}, -1}, {mysql.Set{Name: "a", Value: 1}, mysql.Bit{Value: 1, Width: 1}, 0}, {mysql.Set{Name: "a", Value: 1}, mysql.Hex{Value: 1}, 0}, {mysql.Set{Name: "a", Value: 1}, mysql.Enum{Name: "a", Value: 1}, 0}, {mysql.Set{Name: "a", Value: 1}, mysql.Set{Name: "a", Value: 1}, 0}, } for i, t := range cmpTbl { comment := Commentf("%d %v %v", i, t.lhs, t.rhs) ret, err := Compare(t.lhs, t.rhs) c.Assert(err, IsNil) c.Assert(ret, Equals, t.ret, comment) ret, err = Compare(t.rhs, t.lhs) c.Assert(err, IsNil) c.Assert(ret, Equals, -t.ret, comment) } }
func (s *testTypeConvertSuite) TestConvert(c *C) { defer testleak.AfterTest(c)() // integer ranges signedDeny(c, mysql.TypeTiny, -129, "-128") signedAccept(c, mysql.TypeTiny, -128, "-128") signedAccept(c, mysql.TypeTiny, 127, "127") signedDeny(c, mysql.TypeTiny, 128, "127") unsignedDeny(c, mysql.TypeTiny, -1, "0") unsignedAccept(c, mysql.TypeTiny, 0, "0") unsignedAccept(c, mysql.TypeTiny, 255, "255") unsignedDeny(c, mysql.TypeTiny, 256, "255") signedDeny(c, mysql.TypeShort, int64(math.MinInt16)-1, strvalue(int64(math.MinInt16))) signedAccept(c, mysql.TypeShort, int64(math.MinInt16), strvalue(int64(math.MinInt16))) signedAccept(c, mysql.TypeShort, int64(math.MaxInt16), strvalue(int64(math.MaxInt16))) signedDeny(c, mysql.TypeShort, int64(math.MaxInt16)+1, strvalue(int64(math.MaxInt16))) unsignedDeny(c, mysql.TypeShort, -1, "0") unsignedAccept(c, mysql.TypeShort, 0, "0") unsignedAccept(c, mysql.TypeShort, uint64(math.MaxUint16), strvalue(uint64(math.MaxUint16))) unsignedDeny(c, mysql.TypeShort, uint64(math.MaxUint16)+1, strvalue(uint64(math.MaxUint16))) signedDeny(c, mysql.TypeInt24, -1<<23-1, strvalue(-1<<23)) signedAccept(c, mysql.TypeInt24, -1<<23, strvalue(-1<<23)) signedAccept(c, mysql.TypeInt24, 1<<23-1, strvalue(1<<23-1)) signedDeny(c, mysql.TypeInt24, 1<<23, strvalue(1<<23-1)) unsignedDeny(c, mysql.TypeInt24, -1, "0") unsignedAccept(c, mysql.TypeInt24, 0, "0") unsignedAccept(c, mysql.TypeInt24, 1<<24-1, strvalue(1<<24-1)) unsignedDeny(c, mysql.TypeInt24, 1<<24, strvalue(1<<24-1)) signedDeny(c, mysql.TypeLong, int64(math.MinInt32)-1, strvalue(int64(math.MinInt32))) signedAccept(c, mysql.TypeLong, int64(math.MinInt32), strvalue(int64(math.MinInt32))) signedAccept(c, mysql.TypeLong, int64(math.MaxInt32), strvalue(int64(math.MaxInt32))) signedDeny(c, mysql.TypeLong, uint64(math.MaxUint64), strvalue(uint64(math.MaxInt32))) signedDeny(c, mysql.TypeLong, int64(math.MaxInt32)+1, strvalue(int64(math.MaxInt32))) unsignedDeny(c, mysql.TypeLong, -1, "0") unsignedAccept(c, mysql.TypeLong, 0, "0") unsignedAccept(c, mysql.TypeLong, uint64(math.MaxUint32), strvalue(uint64(math.MaxUint32))) unsignedDeny(c, mysql.TypeLong, uint64(math.MaxUint32)+1, strvalue(uint64(math.MaxUint32))) signedDeny(c, mysql.TypeLonglong, math.MinInt64*1.1, strvalue(int64(math.MinInt64))) signedAccept(c, mysql.TypeLonglong, int64(math.MinInt64), strvalue(int64(math.MinInt64))) signedAccept(c, mysql.TypeLonglong, int64(math.MaxInt64), strvalue(int64(math.MaxInt64))) signedDeny(c, mysql.TypeLonglong, math.MaxInt64*1.1, strvalue(int64(math.MaxInt64))) unsignedDeny(c, mysql.TypeLonglong, -1, "0") unsignedAccept(c, mysql.TypeLonglong, 0, "0") unsignedAccept(c, mysql.TypeLonglong, uint64(math.MaxUint64), strvalue(uint64(math.MaxUint64))) unsignedDeny(c, mysql.TypeLonglong, math.MaxUint64*1.1, strvalue(uint64(math.MaxUint64))) // integer from string signedAccept(c, mysql.TypeLong, " 234 ", "234") signedAccept(c, mysql.TypeLong, " 2.35e3 ", "2350") signedAccept(c, mysql.TypeLong, " +2.51 ", "3") signedAccept(c, mysql.TypeLong, " -3.58", "-4") // integer from float signedAccept(c, mysql.TypeLong, 234.5456, "235") signedAccept(c, mysql.TypeLong, -23.45, "-23") // float from string signedAccept(c, mysql.TypeFloat, "23.523", "23.523") signedAccept(c, mysql.TypeFloat, int64(123), "123") signedAccept(c, mysql.TypeFloat, uint64(123), "123") signedAccept(c, mysql.TypeFloat, int(123), "123") signedAccept(c, mysql.TypeFloat, float32(123), "123") signedAccept(c, mysql.TypeFloat, float64(123), "123") signedAccept(c, mysql.TypeDouble, " -23.54", "-23.54") // year signedDeny(c, mysql.TypeYear, 123, "<nil>") signedDeny(c, mysql.TypeYear, 3000, "<nil>") signedAccept(c, mysql.TypeYear, "2000", "2000") // time from string signedAccept(c, mysql.TypeDate, "2012-08-23", "2012-08-23") signedAccept(c, mysql.TypeDatetime, "2012-08-23 12:34:03.123456", "2012-08-23 12:34:03") signedAccept(c, mysql.TypeDatetime, mysql.ZeroDatetime, "0000-00-00 00:00:00") signedAccept(c, mysql.TypeDatetime, int64(0), "0000-00-00 00:00:00") signedAccept(c, mysql.TypeTimestamp, "2012-08-23 12:34:03.123456", "2012-08-23 12:34:03") signedAccept(c, mysql.TypeDuration, "10:11:12", "10:11:12") signedAccept(c, mysql.TypeDuration, mysql.ZeroDatetime, "00:00:00") signedAccept(c, mysql.TypeDuration, mysql.ZeroDuration, "00:00:00") signedDeny(c, mysql.TypeDate, "2012-08-x", "0000-00-00") signedDeny(c, mysql.TypeDatetime, "2012-08-x", "0000-00-00 00:00:00") signedDeny(c, mysql.TypeTimestamp, "2012-08-x", "0000-00-00 00:00:00") signedDeny(c, mysql.TypeDuration, "2012-08-x", "00:00:00") signedDeny(c, mysql.TypeDuration, 0, "<nil>") // string from string signedAccept(c, mysql.TypeString, "abc", "abc") // string from integer signedAccept(c, mysql.TypeString, 5678, "5678") signedAccept(c, mysql.TypeString, mysql.ZeroDuration, "00:00:00") signedAccept(c, mysql.TypeString, mysql.ZeroDatetime, "0000-00-00 00:00:00") signedAccept(c, mysql.TypeString, []byte("123"), "123") //TODO add more tests signedAccept(c, mysql.TypeNewDecimal, 123, "123") signedAccept(c, mysql.TypeNewDecimal, int64(123), "123") signedAccept(c, mysql.TypeNewDecimal, uint64(123), "123") signedAccept(c, mysql.TypeNewDecimal, float32(123), "123") signedAccept(c, mysql.TypeNewDecimal, 123.456, "123.456") signedAccept(c, mysql.TypeNewDecimal, "-123.456", "-123.456") signedAccept(c, mysql.TypeNewDecimal, mysql.NewDecFromInt(12300000), "12300000") dec := mysql.NewDecFromInt(-123) dec.Shift(-5) dec.Round(dec, 5) signedAccept(c, mysql.TypeNewDecimal, dec, "-0.00123") }
func (s *testCodecSuite) TestCut(c *C) { defer testleak.AfterTest(c)() table := []struct { Input []types.Datum Expect []types.Datum }{ { types.MakeDatums(int64(1)), types.MakeDatums(int64(1)), }, { types.MakeDatums(float32(1), float64(3.15), []byte("123"), "123"), types.MakeDatums(float64(1), float64(3.15), []byte("123"), []byte("123")), }, { types.MakeDatums(uint64(1), float64(3.15), []byte("123"), int64(-1)), types.MakeDatums(uint64(1), float64(3.15), []byte("123"), int64(-1)), }, { types.MakeDatums(true, false), types.MakeDatums(int64(1), int64(0)), }, { types.MakeDatums(nil), types.MakeDatums(nil), }, { types.MakeDatums(mysql.Hex{Value: 100}, mysql.Bit{Value: 100, Width: 8}), types.MakeDatums(int64(100), uint64(100)), }, { types.MakeDatums(mysql.Enum{Name: "a", Value: 1}, mysql.Set{Name: "a", Value: 1}), types.MakeDatums(uint64(1), uint64(1)), }, { types.MakeDatums(float32(1), float64(3.15), []byte("123456789012345")), types.MakeDatums(float64(1), float64(3.15), []byte("123456789012345")), }, { types.MakeDatums(mysql.NewDecFromInt(0), mysql.NewDecFromFloatForTest(-1.3)), types.MakeDatums(mysql.NewDecFromInt(0), mysql.NewDecFromFloatForTest(-1.3)), }, } for i, t := range table { comment := Commentf("%d %v", i, t) b, err := EncodeKey(nil, t.Input...) c.Assert(err, IsNil, comment) var d []byte for j, e := range t.Expect { d, b, err = CutOne(b) c.Assert(err, IsNil) c.Assert(d, NotNil) ed, err1 := EncodeKey(nil, e) c.Assert(err1, IsNil) c.Assert(d, DeepEquals, ed, Commentf("%d:%d %#v", i, j, e)) } c.Assert(b, HasLen, 0) } for i, t := range table { comment := Commentf("%d %v", i, t) b, err := EncodeValue(nil, t.Input...) c.Assert(err, IsNil, comment) var d []byte for j, e := range t.Expect { d, b, err = CutOne(b) c.Assert(err, IsNil) c.Assert(d, NotNil) ed, err1 := EncodeValue(nil, e) c.Assert(err1, IsNil) c.Assert(d, DeepEquals, ed, Commentf("%d:%d %#v", i, j, e)) } c.Assert(b, HasLen, 0) } }
func (s *testColumnSuite) TestGetZeroValue(c *C) { cases := []struct { ft *types.FieldType value types.Datum }{ { types.NewFieldType(mysql.TypeLong), types.NewIntDatum(0), }, { &types.FieldType{ Tp: mysql.TypeLonglong, Flag: mysql.UnsignedFlag, }, types.NewUintDatum(0), }, { types.NewFieldType(mysql.TypeFloat), types.NewFloat32Datum(0), }, { types.NewFieldType(mysql.TypeDouble), types.NewFloat64Datum(0), }, { types.NewFieldType(mysql.TypeNewDecimal), types.NewDecimalDatum(mysql.NewDecFromInt(0)), }, { types.NewFieldType(mysql.TypeVarchar), types.NewStringDatum(""), }, { types.NewFieldType(mysql.TypeBlob), types.NewBytesDatum([]byte{}), }, { types.NewFieldType(mysql.TypeDuration), types.NewDurationDatum(mysql.ZeroDuration), }, { types.NewFieldType(mysql.TypeDatetime), types.NewDatum(mysql.ZeroDatetime), }, { types.NewFieldType(mysql.TypeTimestamp), types.NewDatum(mysql.ZeroTimestamp), }, { types.NewFieldType(mysql.TypeDate), types.NewDatum(mysql.ZeroDate), }, { types.NewFieldType(mysql.TypeBit), types.NewDatum(mysql.Bit{Value: 0, Width: mysql.MinBitWidth}), }, { types.NewFieldType(mysql.TypeSet), types.NewDatum(mysql.Set{}), }, } for _, ca := range cases { colInfo := &model.ColumnInfo{FieldType: *ca.ft} zv := GetZeroValue(colInfo) c.Assert(zv.Kind(), Equals, ca.value.Kind()) cmp, err := zv.CompareDatum(ca.value) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
func (s *testEvaluatorSuite) TestUnaryOp(c *C) { defer testleak.AfterTest(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)}, {int64(1), opcode.Plus, int64(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)}, {int64(1), opcode.Minus, int64(-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() for i, t := range tbl { expr := &ast.UnaryOperationExpr{} expr.Op = t.op expr.V = ast.NewValueExpr(t.arg) result, err := Eval(ctx, expr) c.Assert(err, IsNil) c.Assert(result, testutil.DatumEquals, types.NewDatum(t.result), Commentf("%d", i)) } tbl = []struct { arg interface{} op opcode.Op result interface{} }{ {mysql.NewDecFromInt(1), opcode.Plus, mysql.NewDecFromInt(1)}, {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.NewDecFromInt(1), opcode.Minus, mysql.NewDecFromInt(-1)}, {mysql.ZeroDuration, opcode.Minus, new(mysql.MyDecimal)}, {mysql.Time{Time: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Minus, mysql.NewDecFromInt(-20091110230000)}, } 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 := result.CompareDatum(types.NewDatum(t.result)) c.Assert(err, IsNil) c.Assert(ret, Equals, 0) } }
func (s *testEvaluatorSuite) TestBinopNumeric(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() tbl := []struct { lhs interface{} op opcode.Op rhs interface{} ret interface{} }{ // plus {1, opcode.Plus, 1, 2}, {1, opcode.Plus, uint64(1), 2}, {1, opcode.Plus, "1", 2}, {1, opcode.Plus, mysql.NewDecFromInt(1), 2}, {uint64(1), opcode.Plus, 1, 2}, {uint64(1), opcode.Plus, uint64(1), 2}, {uint64(1), opcode.Plus, -1, 0}, {1, opcode.Plus, []byte("1"), 2}, {1, opcode.Plus, mysql.Hex{Value: 1}, 2}, {1, opcode.Plus, mysql.Bit{Value: 1, Width: 1}, 2}, {1, opcode.Plus, mysql.Enum{Name: "a", Value: 1}, 2}, {1, opcode.Plus, mysql.Set{Name: "a", Value: 1}, 2}, // minus {1, opcode.Minus, 1, 0}, {1, opcode.Minus, uint64(1), 0}, {1, opcode.Minus, float64(1), 0}, {1, opcode.Minus, mysql.NewDecFromInt(1), 0}, {uint64(1), opcode.Minus, 1, 0}, {uint64(1), opcode.Minus, uint64(1), 0}, {mysql.NewDecFromInt(1), opcode.Minus, 1, 0}, {"1", opcode.Minus, []byte("1"), 0}, // mul {1, opcode.Mul, 1, 1}, {1, opcode.Mul, uint64(1), 1}, {1, opcode.Mul, float64(1), 1}, {1, opcode.Mul, mysql.NewDecFromInt(1), 1}, {uint64(1), opcode.Mul, 1, 1}, {uint64(1), opcode.Mul, uint64(1), 1}, {mysql.Time{}, opcode.Mul, 0, 0}, {mysql.ZeroDuration, opcode.Mul, 0, 0}, {mysql.Time{Time: time.Now(), Fsp: 0, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0}, {mysql.Time{Time: time.Now(), Fsp: 6, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0}, {mysql.Duration{Duration: 100000000, Fsp: 6}, opcode.Mul, 0, 0}, // div {1, opcode.Div, float64(1), 1}, {1, opcode.Div, float64(0), nil}, {1, opcode.Div, 2, 0.5}, {1, opcode.Div, 0, nil}, // int div {1, opcode.IntDiv, 2, 0}, {1, opcode.IntDiv, uint64(2), 0}, {1, opcode.IntDiv, 0, nil}, {1, opcode.IntDiv, uint64(0), nil}, {uint64(1), opcode.IntDiv, 2, 0}, {uint64(1), opcode.IntDiv, uint64(2), 0}, {uint64(1), opcode.IntDiv, 0, nil}, {uint64(1), opcode.IntDiv, uint64(0), nil}, {1.0, opcode.IntDiv, 2.0, 0}, {1.0, opcode.IntDiv, 0, nil}, // mod {10, opcode.Mod, 2, 0}, {10, opcode.Mod, uint64(2), 0}, {10, opcode.Mod, 0, nil}, {10, opcode.Mod, uint64(0), nil}, {-10, opcode.Mod, uint64(2), 0}, {uint64(10), opcode.Mod, 2, 0}, {uint64(10), opcode.Mod, uint64(2), 0}, {uint64(10), opcode.Mod, 0, nil}, {uint64(10), opcode.Mod, uint64(0), nil}, {uint64(10), opcode.Mod, -2, 0}, {float64(10), opcode.Mod, 2, 0}, {float64(10), opcode.Mod, 0, nil}, {mysql.NewDecFromInt(10), opcode.Mod, 2, 0}, {mysql.NewDecFromInt(10), opcode.Mod, 0, 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 v.Kind() { case types.KindNull: c.Assert(t.ret, IsNil) default: // we use float64 as the result type check for all. f, err := v.ToFloat64() c.Assert(err, IsNil) d := types.NewDatum(t.ret) r, err := d.ToFloat64() c.Assert(err, IsNil) c.Assert(r, Equals, f) } } }
func (s *testTableCodecSuite) TestRowCodec(c *C) { defer testleak.AfterTest(c)() c1 := &column{id: 1, tp: types.NewFieldType(mysql.TypeLonglong)} c2 := &column{id: 2, tp: types.NewFieldType(mysql.TypeVarchar)} c3 := &column{id: 3, tp: types.NewFieldType(mysql.TypeNewDecimal)} cols := []*column{c1, c2, c3} row := make([]types.Datum, 3) row[0] = types.NewIntDatum(100) row[1] = types.NewBytesDatum([]byte("abc")) row[2] = types.NewDecimalDatum(mysql.NewDecFromInt(1)) // Encode colIDs := make([]int64, 0, 3) for _, col := range cols { colIDs = append(colIDs, col.id) } bs, err := EncodeRow(row, colIDs) c.Assert(err, IsNil) c.Assert(bs, NotNil) // Decode colMap := make(map[int64]*types.FieldType, 3) for _, col := range cols { colMap[col.id] = col.tp } r, err := DecodeRow(bs, colMap) c.Assert(err, IsNil) c.Assert(r, NotNil) c.Assert(r, HasLen, 3) // Compare decoded row and original row for i, col := range cols { v, ok := r[col.id] c.Assert(ok, IsTrue) equal, err1 := v.CompareDatum(row[i]) c.Assert(err1, IsNil) c.Assert(equal, Equals, 0) } // colMap may contains more columns than encoded row. colMap[4] = types.NewFieldType(mysql.TypeFloat) r, err = DecodeRow(bs, colMap) c.Assert(err, IsNil) c.Assert(r, NotNil) c.Assert(r, HasLen, 3) for i, col := range cols { v, ok := r[col.id] c.Assert(ok, IsTrue) equal, err1 := v.CompareDatum(row[i]) c.Assert(err1, IsNil) c.Assert(equal, Equals, 0) } // colMap may contains less columns than encoded row. delete(colMap, 3) delete(colMap, 4) r, err = DecodeRow(bs, colMap) c.Assert(err, IsNil) c.Assert(r, NotNil) c.Assert(r, HasLen, 2) for i, col := range cols { if i > 1 { break } v, ok := r[col.id] c.Assert(ok, IsTrue) equal, err1 := v.CompareDatum(row[i]) c.Assert(err1, IsNil) c.Assert(equal, Equals, 0) } // Make sure empty row return not nil value. bs, err = EncodeRow([]types.Datum{}, []int64{}) c.Assert(err, IsNil) c.Assert(bs, HasLen, 1) r, err = DecodeRow(bs, colMap) c.Assert(err, IsNil) c.Assert(r, IsNil) }
func (s *testAggFuncSuite) TestXAPIAvg(c *C) { defer testleak.AfterTest(c)() // Compose aggregate exec for "select avg(c2) from t groupby c1"; // // Data in region1: // c1 c2 // 1 11 // 2 21 // 1 1 // 3 2 // // Partial aggregate result for region1: // groupkey cnt sum // 1 2 12 // 2 1 21 // 3 1 2 // // Data in region2: // 1 nil // 1 3 // 3 31 // // Partial aggregate result for region2: // groupkey cnt sum // 1 1 3 // 3 1 31 // // Expected final aggregate result: // avg(c2) // 5 // 21 // 16.500000 c1 := ast.NewValueExpr([]byte{0}) rf1 := &ast.ResultField{Expr: c1} c2 := ast.NewValueExpr(0) rf2 := &ast.ResultField{Expr: c2} c3 := ast.NewValueExpr(0) rf3 := &ast.ResultField{Expr: c3} col2 := &ast.ColumnNameExpr{Refer: rf2} fc := &ast.AggregateFuncExpr{ F: ast.AggFuncAvg, Args: []ast.ExprNode{col2}, } // Return row: // GroupKey, Sum // Partial result from region1 row1 := types.MakeDatums([]byte{1}, 2, 12) row2 := types.MakeDatums([]byte{2}, 1, 21) row3 := types.MakeDatums([]byte{3}, 1, 2) // Partial result from region2 row4 := types.MakeDatums([]byte{1}, 1, 3) row5 := types.MakeDatums([]byte{3}, 1, 31) data := []([]types.Datum){row1, row2, row3, row4, row5} rows := make([]*Row, 0, 5) for _, d := range data { rows = append(rows, &Row{Data: d}) } src := &mockExec{ rows: rows, fields: []*ast.ResultField{rf1, rf2, rf3}, // groupby, cnt, sum } agg := &XAggregateExec{ AggFuncs: []*ast.AggregateFuncExpr{fc}, Src: src, } ast.SetFlag(fc) // First row: 5 row, err := agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) ctx := mock.NewContext() val, err := evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(mysql.NewDecFromInt(5))) // Second row: 21 row, err = agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) val, err = evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(mysql.NewDecFromInt(21))) // Third row: 16.5000 row, err = agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) val, err = evaluator.Eval(ctx, fc) c.Assert(err, IsNil) d := mysql.NewDecFromFloatForTest(16.5) c.Logf("d1 %s, d2 %s, cmp %d", d.String(), val.GetMysqlDecimal().String(), val.GetMysqlDecimal().Compare(d)) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(d)) // Forth row: nil row, err = agg.Next() c.Assert(err, IsNil) c.Assert(row, IsNil) // Close executor err = agg.Close() c.Assert(err, IsNil) }
func (s *testAggFuncSuite) TestXAPISum(c *C) { defer testleak.AfterTest(c)() // Compose aggregate exec for "select sum(c2) from t groupby c1"; // // Data in region1: // c1 c2 // 1 11 // 2 21 // 1 1 // // Partial aggregate result for region1: // groupkey sum // 1 12 // 2 21 // // Data in region2: // 1 nil // 1 3 // 3 31 // // Partial aggregate result for region2: // groupkey sum // 1 3 // 3 31 // // Expected final aggregate result: // sum(c2) // 15 // 21 // 31 c1 := ast.NewValueExpr([]byte{0}) rf1 := &ast.ResultField{Expr: c1} c2 := ast.NewValueExpr(0) rf2 := &ast.ResultField{Expr: c2} col2 := &ast.ColumnNameExpr{Refer: rf2} fc := &ast.AggregateFuncExpr{ F: ast.AggFuncSum, Args: []ast.ExprNode{col2}, } // Return row: // GroupKey, Sum // Partial result from region1 row1 := types.MakeDatums([]byte{1}, 12) row2 := types.MakeDatums([]byte{2}, 21) // Partial result from region2 row3 := types.MakeDatums([]byte{1}, 3) row4 := types.MakeDatums([]byte{3}, 31) data := []([]types.Datum){row1, row2, row3, row4} 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 := &XAggregateExec{ AggFuncs: []*ast.AggregateFuncExpr{fc}, Src: src, } ast.SetFlag(fc) // First row: 15 row, err := agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) ctx := mock.NewContext() val, err := evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(mysql.NewDecFromInt(15))) // Second row: 21 row, err = agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) val, err = evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(mysql.NewDecFromInt(21))) // Third row: 31 row, err = agg.Next() c.Assert(err, IsNil) c.Assert(row, NotNil) val, err = evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDecimalDatum(mysql.NewDecFromInt(31))) agg.Close() // After clear up, fc's value should be default. val, err = evaluator.Eval(ctx, fc) c.Assert(err, IsNil) c.Assert(val, testutil.DatumEquals, types.NewDatum(nil)) }