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) }
// 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 }
/* * 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 }
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 }
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) } }
// 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 }
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) } }
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)) }
// 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) } }
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) } }
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) }
// 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) } }