示例#1
0
func getSumValue(item *aggItem) (types.Datum, error) {
	v := item.value
	var d types.Datum
	if !v.IsNull() {
		// For sum result, we should convert it to decimal.
		de, err1 := v.ToDecimal()
		if err1 != nil {
			return d, errors.Trace(err1)
		}
		d = types.NewDecimalDatum(de)
	}
	return d, nil
}
示例#2
0
func (n *aggregateFuncExpr) toDatums() (ds []types.Datum, err error) {
	switch n.expr.GetTp() {
	case tipb.ExprType_Count:
		ds = n.getCountDatum()
	case tipb.ExprType_First:
		ds = n.getValueDatum()
	case tipb.ExprType_Sum:
		v := n.getAggItem().value
		var d types.Datum
		if !v.IsNull() {
			// For sum result, we should convert it to decimal.
			de, err1 := v.ToDecimal()
			if err1 != nil {
				return nil, errors.Trace(err1)
			}
			d = types.NewDecimalDatum(de)
		}
		ds = []types.Datum{d}
	}
	return
}
示例#3
0
// TODO: add more tests.
func (s *testEvalSuite) TestEval(c *C) {
	colID := int64(1)
	row := make(map[int64]types.Datum)
	row[colID] = types.NewIntDatum(100)
	xevaluator := &Evaluator{Row: row}
	cases := []struct {
		expr   *tipb.Expr
		result types.Datum
	}{
		// Datums.
		{
			datumExpr(types.NewFloat32Datum(1.1)),
			types.NewFloat32Datum(1.1),
		},
		{
			datumExpr(types.NewFloat64Datum(1.1)),
			types.NewFloat64Datum(1.1),
		},
		{
			datumExpr(types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			datumExpr(types.NewUintDatum(1)),
			types.NewUintDatum(1),
		},
		{
			datumExpr(types.NewBytesDatum([]byte("abc"))),
			types.NewBytesDatum([]byte("abc")),
		},
		{
			datumExpr(types.NewStringDatum("abc")),
			types.NewStringDatum("abc"),
		},
		{
			datumExpr(types.Datum{}),
			types.Datum{},
		},
		{
			datumExpr(types.NewDurationDatum(mysql.Duration{Duration: time.Hour})),
			types.NewDurationDatum(mysql.Duration{Duration: time.Hour}),
		},
		{
			datumExpr(types.NewDecimalDatum(mysql.NewDecFromFloatForTest(1.1))),
			types.NewDecimalDatum(mysql.NewDecFromFloatForTest(1.1)),
		},
		{
			columnExpr(1),
			types.NewIntDatum(100),
		},
		// Comparison operations.
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LT),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_LT),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LT),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LE),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_LE),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LE),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_EQ),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_EQ),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_EQ),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_NE),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_NE),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_NE),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_GE),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GE),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GE),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GT),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_GT),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GT),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_NullEQ),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.Datum{}, types.Datum{}, tipb.ExprType_NullEQ),
			types.NewIntDatum(1),
		},
		// Logic operation.
		{
			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_And),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_And),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_And),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_And),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(0), tipb.ExprType_Or),
			types.NewIntDatum(0),
		},
		{
			binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_Or),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_Or),
			types.Datum{},
		},
		{
			binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_Or),
			types.NewIntDatum(1),
		},
		{
			binaryExpr(
				binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ),
				binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ),
				tipb.ExprType_And),
			types.NewIntDatum(1),
		},
		{
			notExpr(datumExpr(types.NewIntDatum(1))),
			types.NewIntDatum(0),
		},
		{
			notExpr(datumExpr(types.NewIntDatum(0))),
			types.NewIntDatum(1),
		},
		{
			notExpr(datumExpr(types.Datum{})),
			types.Datum{},
		},
	}
	for _, ca := range cases {
		result, err := xevaluator.Eval(ca.expr)
		c.Assert(err, IsNil)
		c.Assert(result.Kind(), Equals, ca.result.Kind())
		cmp, err := result.CompareDatum(ca.result)
		c.Assert(err, IsNil)
		c.Assert(cmp, Equals, 0)
	}
}
示例#4
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.NewDecimalFromInt(0, 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)
	}
}
示例#5
0
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.NewDecimalFromInt(int64(5), 0)))
	// 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.NewDecimalFromInt(int64(21), 0)))
	// 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.NewDecimalFromFloat(float64(16.5))
	d.SetFracDigits(4) // For div operator, default frac is 4.
	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)
}
示例#6
0
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.NewDecimalFromInt(int64(15), 0)))
	// 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.NewDecimalFromInt(int64(21), 0)))
	// 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.NewDecimalFromInt(int64(31), 0)))
	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))
}
示例#7
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)
}
示例#8
0
// TODO: add more tests.
func (s *testEvalSuite) TestEval(c *C) {
	colID := int64(1)
	row := make(map[int64]types.Datum)
	row[colID] = types.NewIntDatum(100)
	xevaluator := &Evaluator{Row: row}
	cases := []struct {
		expr   *tipb.Expr
		result types.Datum
	}{
		// Datums.
		{
			datumExpr(types.NewFloat32Datum(1.1)),
			types.NewFloat32Datum(1.1),
		},
		{
			datumExpr(types.NewFloat64Datum(1.1)),
			types.NewFloat64Datum(1.1),
		},
		{
			datumExpr(types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			datumExpr(types.NewUintDatum(1)),
			types.NewUintDatum(1),
		},
		{
			datumExpr(types.NewBytesDatum([]byte("abc"))),
			types.NewBytesDatum([]byte("abc")),
		},
		{
			datumExpr(types.NewStringDatum("abc")),
			types.NewStringDatum("abc"),
		},
		{
			datumExpr(types.Datum{}),
			types.Datum{},
		},
		{
			datumExpr(types.NewDurationDatum(mysql.Duration{Duration: time.Hour})),
			types.NewDurationDatum(mysql.Duration{Duration: time.Hour}),
		},
		{
			datumExpr(types.NewDecimalDatum(mysql.NewDecFromFloatForTest(1.1))),
			types.NewDecimalDatum(mysql.NewDecFromFloatForTest(1.1)),
		},
		{
			columnExpr(1),
			types.NewIntDatum(100),
		},
		// Comparison operations.
		{
			buildExpr(tipb.ExprType_LT, types.NewIntDatum(100), types.NewIntDatum(1)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_LT, types.NewIntDatum(1), types.NewIntDatum(100)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_LT, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_LE, types.NewIntDatum(100), types.NewIntDatum(1)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_LE, types.NewIntDatum(1), types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_LE, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_EQ, types.NewIntDatum(100), types.NewIntDatum(1)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_EQ, types.NewIntDatum(100), types.NewIntDatum(100)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_EQ, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_NE, types.NewIntDatum(100), types.NewIntDatum(100)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_NE, types.NewIntDatum(100), types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_NE, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_GE, types.NewIntDatum(1), types.NewIntDatum(100)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_GE, types.NewIntDatum(100), types.NewIntDatum(100)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_GE, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_GT, types.NewIntDatum(100), types.NewIntDatum(100)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_GT, types.NewIntDatum(100), types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_GT, types.NewIntDatum(100), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_NullEQ, types.NewIntDatum(1), types.Datum{}),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_NullEQ, types.Datum{}, types.Datum{}),
			types.NewIntDatum(1),
		},
		// Logic operation.
		{
			buildExpr(tipb.ExprType_And, types.NewIntDatum(0), types.NewIntDatum(1)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_And, types.NewIntDatum(1), types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_And, types.NewIntDatum(0), types.Datum{}),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_And, types.NewIntDatum(1), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_Or, types.NewIntDatum(0), types.NewIntDatum(0)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_Or, types.NewIntDatum(0), types.NewIntDatum(1)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_Or, types.NewIntDatum(0), types.Datum{}),
			types.Datum{},
		},
		{
			buildExpr(tipb.ExprType_Or, types.NewIntDatum(1), types.Datum{}),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_And,
				buildExpr(tipb.ExprType_EQ, types.NewIntDatum(1), types.NewIntDatum(1)),
				buildExpr(tipb.ExprType_EQ, types.NewIntDatum(1), types.NewIntDatum(1))),
			types.NewIntDatum(1),
		},
		{
			notExpr(datumExpr(types.NewIntDatum(1))),
			types.NewIntDatum(0),
		},
		{
			notExpr(datumExpr(types.NewIntDatum(0))),
			types.NewIntDatum(1),
		},
		{
			notExpr(datumExpr(types.Datum{})),
			types.Datum{},
		},
		// Arithmetic operation.
		{
			buildExpr(tipb.ExprType_Plus, types.NewIntDatum(-1), types.NewIntDatum(1)),
			types.NewIntDatum(0),
		},
		{
			buildExpr(tipb.ExprType_Plus, types.NewIntDatum(-1), types.NewFloat64Datum(1.5)),
			types.NewFloat64Datum(0.5),
		},
		{
			buildExpr(tipb.ExprType_Minus, types.NewIntDatum(-1), types.NewIntDatum(1)),
			types.NewIntDatum(-2),
		},
		{
			buildExpr(tipb.ExprType_Minus, types.NewIntDatum(-1), types.NewFloat64Datum(1.5)),
			types.NewFloat64Datum(-2.5),
		},
		{
			buildExpr(tipb.ExprType_Mul, types.NewFloat64Datum(-1), types.NewFloat64Datum(1)),
			types.NewFloat64Datum(-1),
		},
		{
			buildExpr(tipb.ExprType_Mul, types.NewFloat64Datum(-1.5), types.NewFloat64Datum(2)),
			types.NewFloat64Datum(-3),
		},
		{
			buildExpr(tipb.ExprType_Div, types.NewFloat64Datum(-3), types.NewFloat64Datum(2)),
			types.NewFloat64Datum(-1.5),
		},
		{
			buildExpr(tipb.ExprType_Div, types.NewFloat64Datum(-3), types.NewFloat64Datum(0)),
			types.NewDatum(nil),
		},
		{
			buildExpr(tipb.ExprType_IntDiv, types.NewIntDatum(3), types.NewIntDatum(2)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_IntDiv, types.NewFloat64Datum(3.0), types.NewFloat64Datum(1.9)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_Mod, types.NewIntDatum(3), types.NewIntDatum(2)),
			types.NewIntDatum(1),
		},
		{
			buildExpr(tipb.ExprType_Mod, types.NewFloat64Datum(3.0), types.NewFloat64Datum(1.9)),
			types.NewFloat64Datum(1.1),
		},
	}
	for _, ca := range cases {
		result, err := xevaluator.Eval(ca.expr)
		c.Assert(err, IsNil)
		c.Assert(result.Kind(), Equals, ca.result.Kind())
		cmp, err := result.CompareDatum(ca.result)
		c.Assert(err, IsNil)
		c.Assert(cmp, Equals, 0)
	}
}