Beispiel #1
0
func (er *expressionRewriter) likeToScalarFunc(v *ast.PatternLikeExpr) {
	l := len(er.ctxStack)
	function := er.notToScalarFunc(v.Not, ast.Like, v.Type,
		er.ctxStack[l-2], er.ctxStack[l-1], &expression.Constant{Value: types.NewIntDatum(int64(v.Escape))},
		&expression.Constant{Value: types.NewBytesDatum(v.PatChars)},
		&expression.Constant{Value: types.NewBytesDatum(v.PatTypes)})
	er.ctxStack = er.ctxStack[:l-2]
	er.ctxStack = append(er.ctxStack, function)
}
Beispiel #2
0
// HashCode implements Expression interface.
func (sf *ScalarFunction) HashCode() []byte {
	var bytes []byte
	v := make([]types.Datum, 0, len(sf.Args)+1)
	bytes, _ = codec.EncodeValue(bytes, types.NewStringDatum(sf.FuncName.L))
	v = append(v, types.NewBytesDatum(bytes))
	for _, arg := range sf.Args {
		v = append(v, types.NewBytesDatum(arg.HashCode()))
	}
	bytes = bytes[:0]
	bytes, _ = codec.EncodeValue(bytes, v...)
	return bytes
}
Beispiel #3
0
/*
 * Convert aggregate partial result to rows.
 * Data layout example:
 *	SQL:	select count(c1), sum(c2), avg(c3) from t;
 *	Aggs:	count(c1), sum(c2), avg(c3)
 *	Rows:	groupKey1, count1, value2, count3, value3
 *		groupKey2, count1, value2, count3, value3
 */
func (rs *localRegion) getRowsFromAgg(ctx *selectContext) error {
	for _, gk := range ctx.groupKeys {
		chunk := rs.getChunk(ctx)
		// Each aggregate partial result will be converted to one or two datums.
		rowData := make([]types.Datum, 0, 1+2*len(ctx.aggregates))
		// The first column is group key.
		rowData = append(rowData, types.NewBytesDatum(gk))
		for _, agg := range ctx.aggregates {
			agg.currentGroup = gk
			ds, err := agg.toDatums()
			if err != nil {
				return errors.Trace(err)
			}
			rowData = append(rowData, ds...)
		}
		var err error
		beforeLen := len(chunk.RowsData)
		chunk.RowsData, err = codec.EncodeValue(chunk.RowsData, rowData...)
		if err != nil {
			return errors.Trace(err)
		}
		var rowMeta tipb.RowMeta
		rowMeta.Length = int64(len(chunk.RowsData) - beforeLen)
		chunk.RowsMeta = append(chunk.RowsMeta, rowMeta)
	}
	return nil
}
Beispiel #4
0
func (h *rpcHandler) getRowsFromAgg(ctx *selectContext) ([]*tipb.Row, error) {
	rows := make([]*tipb.Row, 0, len(ctx.groupKeys))
	for _, gk := range ctx.groupKeys {
		row := new(tipb.Row)
		// Each aggregate partial result will be converted to one or two datums.
		rowData := make([]types.Datum, 0, 1+2*len(ctx.aggregates))
		// The first column is group key.
		rowData = append(rowData, types.NewBytesDatum(gk))
		for _, agg := range ctx.aggregates {
			agg.currentGroup = gk
			ds, err := agg.toDatums()
			if err != nil {
				return nil, errors.Trace(err)
			}
			rowData = append(rowData, ds...)
		}
		var err error
		row.Data, err = codec.EncodeValue(nil, rowData...)
		if err != nil {
			return nil, errors.Trace(err)
		}
		rows = append(rows, row)
	}
	return rows, nil
}
Beispiel #5
0
func (e *Evaluator) evalDataType(expr *tipb.Expr) (types.Datum, error) {
	switch op := expr.GetTp(); op {
	case tipb.ExprType_Null:
		return types.Datum{}, nil
	case tipb.ExprType_Int64:
		return e.evalInt(expr.Val)
	case tipb.ExprType_Uint64:
		return e.evalUint(expr.Val)
	case tipb.ExprType_String:
		return e.evalString(expr.Val)
	case tipb.ExprType_Bytes:
		return types.NewBytesDatum(expr.Val), nil
	case tipb.ExprType_Float32:
		return e.evalFloat(expr.Val, true)
	case tipb.ExprType_Float64:
		return e.evalFloat(expr.Val, false)
	case tipb.ExprType_MysqlDecimal:
		return e.evalDecimal(expr.Val)
	case tipb.ExprType_MysqlDuration:
		return e.evalDuration(expr.Val)
	case tipb.ExprType_ColumnRef:
		return e.evalColumnRef(expr.Val)
	default:
		return types.Datum{}, errors.Errorf("Unknown binop type: %v", op)
	}
}
Beispiel #6
0
// Eval evaluates expr to a Datum.
func (e *Evaluator) Eval(expr *tipb.Expr) (types.Datum, error) {
	switch expr.GetTp() {
	case tipb.ExprType_Null:
		return types.Datum{}, nil
	case tipb.ExprType_Int64:
		return e.evalInt(expr.Val)
	case tipb.ExprType_Uint64:
		return e.evalUint(expr.Val)
	case tipb.ExprType_String:
		return e.evalString(expr.Val)
	case tipb.ExprType_Bytes:
		return types.NewBytesDatum(expr.Val), nil
	case tipb.ExprType_Float32:
		return e.evalFloat(expr.Val, true)
	case tipb.ExprType_Float64:
		return e.evalFloat(expr.Val, false)
	case tipb.ExprType_MysqlDecimal:
		return e.evalDecimal(expr.Val)
	case tipb.ExprType_MysqlDuration:
		return e.evalDuration(expr.Val)
	case tipb.ExprType_ColumnRef:
		return e.evalColumnRef(expr.Val)
	case tipb.ExprType_LT:
		return e.evalLT(expr)
	case tipb.ExprType_LE:
		return e.evalLE(expr)
	case tipb.ExprType_EQ:
		return e.evalEQ(expr)
	case tipb.ExprType_NE:
		return e.evalNE(expr)
	case tipb.ExprType_GE:
		return e.evalGE(expr)
	case tipb.ExprType_GT:
		return e.evalGT(expr)
	case tipb.ExprType_NullEQ:
		return e.evalNullEQ(expr)
	case tipb.ExprType_And:
		return e.evalAnd(expr)
	case tipb.ExprType_Or:
		return e.evalOr(expr)
	case tipb.ExprType_Like:
		return e.evalLike(expr)
	case tipb.ExprType_Not:
		return e.evalNot(expr)
	case tipb.ExprType_In:
		return e.evalIn(expr)
	case tipb.ExprType_Plus, tipb.ExprType_Div:
		return e.evalArithmetic(expr)
	}
	return types.Datum{}, nil
}
Beispiel #7
0
func (s *testTableCodecSuite) TestTimeCodec(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.TypeTimestamp)}
	cols := []*column{c1, c2, c3}

	row := make([]types.Datum, 3)
	row[0] = types.NewIntDatum(100)
	row[1] = types.NewBytesDatum([]byte("abc"))
	ts, err := types.ParseTimestamp("2016-06-23 11:30:45")
	c.Assert(err, IsNil)
	row[2] = types.NewDatum(ts)
	// 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)
	}
}
Beispiel #8
0
func (s *testTableCodecSuite) TestCutKey(c *C) {
	colIDs := []int64{1, 2, 3}
	values := []types.Datum{types.NewIntDatum(1), types.NewBytesDatum([]byte("abc")), types.NewFloat64Datum(5.5)}
	handle := types.NewIntDatum(100)
	values = append(values, handle)
	encodedValue, err := codec.EncodeKey(nil, values...)
	c.Assert(err, IsNil)
	tableID := int64(4)
	indexID := int64(5)
	indexKey := EncodeIndexSeekKey(tableID, indexID, encodedValue)
	valuesMap, handleBytes, err := CutIndexKey(indexKey, colIDs)
	c.Assert(err, IsNil)
	for i, colID := range colIDs {
		valueBytes := valuesMap[colID]
		var val types.Datum
		_, val, _ = codec.DecodeOne(valueBytes)
		c.Assert(val, DeepEquals, values[i])
	}
	_, handleVal, _ := codec.DecodeOne(handleBytes)
	c.Assert(handleVal, DeepEquals, types.NewIntDatum(100))
}
Beispiel #9
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)
	}
}
Beispiel #10
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)
	}
}
Beispiel #11
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)
}
Beispiel #12
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)
	}
}