コード例 #1
0
ファイル: functions_test.go プロジェクト: pingcap/tidb
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)
}
コード例 #2
0
ファイル: decimal_test.go プロジェクト: pingcap/tidb
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)
	}
}
コード例 #3
0
ファイル: aggregation.go プロジェクト: pingcap/tidb
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
}
コード例 #4
0
ファイル: evaluator_test.go プロジェクト: pingcap/tidb
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)
}
コード例 #5
0
ファイル: tablecodec_test.go プロジェクト: pingcap/tidb
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)
}
コード例 #6
0
ファイル: column_test.go プロジェクト: pingcap/tidb
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)
	}
}
コード例 #7
0
ファイル: codec_test.go プロジェクト: pingcap/tidb
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)
	}
}
コード例 #8
0
ファイル: evaluator_test.go プロジェクト: pingcap/tidb
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)
	}
}
コード例 #9
0
ファイル: evaluator_test.go プロジェクト: pingcap/tidb
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)
		}
	}
}