func (ts *testFunctionsSuite) TestAggFuncSum(c *C) { sc := new(variable.StatementContext) 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(sc) } ctx := agg.GetContext() expect := types.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(sc) } ctx = agg.GetContext() expect = types.NewDecFromInt(4) c.Assert(ctx.Value.Kind(), Equals, types.KindMysqlDecimal) c.Assert(ctx.Value.GetMysqlDecimal().Compare(expect), Equals, 0) }
func (s *testDecimalSuite) TestFrac(c *C) { defer testleak.AfterTest(c)() inputs := []struct { Input *types.MyDecimal }{ {types.NewDecFromInt(3)}, {types.NewDecFromFloatForTest(0.03)}, } for _, v := range inputs { testFrac(c, v.Input) } }
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 := types.NewDecFromInt(ctx.Count) to := new(types.MyDecimal) types.DecimalDiv(x, y, to, types.DivFracIncr) to.Round(to, ctx.Value.Frac()+types.DivFracIncr) d.SetMysqlDecimal(to) } return }
func (s *testEvaluatorSuite) TestAggFuncAvg(c *C) { defer testleak.AfterTest(c)() avg := &ast.AggregateFuncExpr{ F: ast.AggFuncAvg, } avg.CurrentGroup = []byte("emptyGroup") ast.SetFlag(avg) result, err := Eval(s.ctx, avg) c.Assert(err, IsNil) // Empty group should return nil. c.Assert(result.Kind(), Equals, types.KindNull) sc := s.ctx.GetSessionVars().StmtCtx avg.Args = []ast.ExprNode{ast.NewValueExpr(2)} avg.Update(sc) avg.Args = []ast.ExprNode{ast.NewValueExpr(4)} avg.Update(sc) result, err = Eval(s.ctx, avg) c.Assert(err, IsNil) expect := types.NewDecFromInt(3) c.Assert(result.Kind(), Equals, types.KindMysqlDecimal) c.Assert(result.GetMysqlDecimal().Compare(expect), Equals, 0) }
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(types.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) sc := new(variable.StatementContext) // Compare decoded row and original row for i, col := range cols { v, ok := r[col.id] c.Assert(ok, IsTrue) equal, err1 := v.CompareDatum(sc, 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(sc, 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(sc, 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 *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(types.NewDecFromInt(0)), }, { types.NewFieldType(mysql.TypeVarchar), types.NewStringDatum(""), }, { types.NewFieldType(mysql.TypeBlob), types.NewBytesDatum([]byte{}), }, { types.NewFieldType(mysql.TypeDuration), types.NewDurationDatum(types.ZeroDuration), }, { types.NewFieldType(mysql.TypeDatetime), types.NewDatum(types.ZeroDatetime), }, { types.NewFieldType(mysql.TypeTimestamp), types.NewDatum(types.ZeroTimestamp), }, { types.NewFieldType(mysql.TypeDate), types.NewDatum(types.ZeroDate), }, { types.NewFieldType(mysql.TypeBit), types.NewDatum(types.Bit{Value: 0, Width: types.MinBitWidth}), }, { types.NewFieldType(mysql.TypeSet), types.NewDatum(types.Set{}), }, } sc := new(variable.StatementContext) 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(sc, ca.value) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
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(types.Hex{Value: 100}, types.Bit{Value: 100, Width: 8}), types.MakeDatums(int64(100), uint64(100)), }, { types.MakeDatums(types.Enum{Name: "a", Value: 1}, types.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(types.NewDecFromInt(0), types.NewDecFromFloatForTest(-1.3)), types.MakeDatums(types.NewDecFromInt(0), types.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 *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}, {types.Hex{Value: 0}, opcode.Not, int64(1)}, {types.Bit{Value: 0, Width: 1}, opcode.Not, int64(1)}, {types.Enum{Name: "a", Value: 1}, opcode.Not, int64(0)}, {types.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")}, {types.Hex{Value: 1}, opcode.Plus, types.Hex{Value: 1}}, {types.Bit{Value: 1, Width: 1}, opcode.Plus, types.Bit{Value: 1, Width: 1}}, {true, opcode.Plus, int64(1)}, {false, opcode.Plus, int64(0)}, {types.Enum{Name: "a", Value: 1}, opcode.Plus, types.Enum{Name: "a", Value: 1}}, {types.Set{Name: "a", Value: 1}, opcode.Plus, types.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}, {types.Hex{Value: 1}, opcode.Minus, -1.0}, {types.Bit{Value: 1, Width: 1}, opcode.Minus, -1.0}, {true, opcode.Minus, int64(-1)}, {false, opcode.Minus, int64(0)}, {types.Enum{Name: "a", Value: 1}, opcode.Minus, -1.0}, {types.Set{Name: "a", Value: 1}, opcode.Minus, -1.0}, } for i, t := range tbl { expr := &ast.UnaryOperationExpr{} expr.Op = t.op expr.V = ast.NewValueExpr(t.arg) result, err := Eval(s.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{} }{ {types.NewDecFromInt(1), opcode.Plus, types.NewDecFromInt(1)}, {types.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: types.DefaultFsp}, opcode.Plus, types.Duration{Duration: time.Duration(838*3600 + 59*60 + 59), Fsp: types.DefaultFsp}}, {types.Time{ Time: types.FromGoTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Plus, types.Time{ Time: types.FromGoTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), Type: mysql.TypeDatetime, Fsp: 0}}, {types.NewDecFromInt(1), opcode.Minus, types.NewDecFromInt(-1)}, {types.ZeroDuration, opcode.Minus, new(types.MyDecimal)}, {types.Time{Time: types.FromGoTime(time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)), Type: mysql.TypeDatetime, Fsp: 0}, opcode.Minus, types.NewDecFromInt(-20091110230000)}, } for _, t := range tbl { expr := &ast.UnaryOperationExpr{Op: t.op, V: ast.NewValueExpr(t.arg)} result, err := Eval(s.ctx, expr) c.Assert(err, IsNil) ret, err := result.CompareDatum(s.ctx.GetSessionVars().StmtCtx, types.NewDatum(t.result)) c.Assert(err, IsNil) c.Assert(ret, Equals, 0) } }
func (s *testEvaluatorSuite) TestBinopNumeric(c *C) { defer testleak.AfterTest(c)() 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, types.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, types.Hex{Value: 1}, 2}, {1, opcode.Plus, types.Bit{Value: 1, Width: 1}, 2}, {1, opcode.Plus, types.Enum{Name: "a", Value: 1}, 2}, {1, opcode.Plus, types.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, types.NewDecFromInt(1), 0}, {uint64(1), opcode.Minus, 1, 0}, {uint64(1), opcode.Minus, uint64(1), 0}, {types.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, types.NewDecFromInt(1), 1}, {uint64(1), opcode.Mul, 1, 1}, {uint64(1), opcode.Mul, uint64(1), 1}, {types.Time{Time: types.FromDate(0, 0, 0, 0, 0, 0, 0)}, opcode.Mul, 0, 0}, {types.ZeroDuration, opcode.Mul, 0, 0}, {types.Time{Time: types.FromGoTime(time.Now()), Fsp: 0, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0}, {types.Time{Time: types.FromGoTime(time.Now()), Fsp: 6, Type: mysql.TypeDatetime}, opcode.Mul, 0, 0}, {types.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}, {types.NewDecFromInt(10), opcode.Mod, 2, 0}, {types.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(s.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. sc := s.ctx.GetSessionVars().StmtCtx f, err := v.ToFloat64(sc) c.Assert(err, IsNil) d := types.NewDatum(t.ret) r, err := d.ToFloat64(sc) c.Assert(err, IsNil) c.Assert(r, Equals, f) } } }