func (s *testEvalSuite) TestEvalIsNull(c *C) { colID := int64(1) xevaluator := NewEvaluator(new(variable.StatementContext)) xevaluator.Row[colID] = types.NewIntDatum(100) null, trueAns, falseAns := types.Datum{}, types.NewIntDatum(1), types.NewIntDatum(0) cases := []struct { expr *tipb.Expr result types.Datum }{ { expr: buildExpr(tipb.ExprType_IsNull, types.NewStringDatum("abc")), result: falseAns, }, { expr: buildExpr(tipb.ExprType_IsNull, null), result: trueAns, }, { expr: buildExpr(tipb.ExprType_IsNull, types.NewIntDatum(0)), result: falseAns, }, } 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(xevaluator.sc, ca.result) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
func (s *testEvaluatorSuite) TestSleep(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() sessVars := ctx.GetSessionVars() // non-strict model sessVars.StrictSQLMode = false d := make([]types.Datum, 1) ret, err := builtinSleep(d, ctx) c.Assert(err, IsNil) c.Assert(ret, DeepEquals, types.NewIntDatum(0)) d[0].SetInt64(-1) ret, err = builtinSleep(d, ctx) c.Assert(err, IsNil) c.Assert(ret, DeepEquals, types.NewIntDatum(0)) // for error case under the strict model sessVars.StrictSQLMode = true d[0].SetNull() _, err = builtinSleep(d, ctx) c.Assert(err, NotNil) d[0].SetFloat64(-2.5) _, err = builtinSleep(d, ctx) c.Assert(err, NotNil) // strict model d[0].SetFloat64(0.5) start := time.Now() ret, err = builtinSleep(d, ctx) c.Assert(err, IsNil) c.Assert(ret, DeepEquals, types.NewIntDatum(0)) sub := time.Since(start) c.Assert(sub.Nanoseconds(), GreaterEqual, int64(0.5*1e9)) }
func (s *testEvaluatorSuite) TestEvaluatedFlag(c *C) { l := ast.NewValueExpr(int64(1)) r := ast.NewValueExpr(int64(2)) b := &ast.BinaryOperationExpr{L: l, R: r, Op: opcode.Plus} ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, true) d, err := Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, true) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) funcCall := &ast.FuncCallExpr{ FnName: model.NewCIStr("abs"), Args: []ast.ExprNode{ast.NewValueExpr(int(-1))}, } b = &ast.BinaryOperationExpr{L: funcCall, R: r, Op: opcode.Plus} ast.ResetEvaluatedFlag(b) ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, true) d, err = Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, false) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) rf := &ast.ResultField{Expr: ast.NewValueExpr(int64(1))} colExpr := &ast.ColumnNameExpr{Refer: rf} b = &ast.BinaryOperationExpr{L: colExpr, R: r, Op: opcode.Plus} ast.ResetEvaluatedFlag(b) ast.SetFlag(b) c.Assert(ast.IsPreEvaluable(b), Equals, false) d, err = Eval(s.ctx, b) c.Assert(ast.IsEvaluated(b), Equals, false) c.Assert(err, IsNil) c.Assert(d, testutil.DatumEquals, types.NewIntDatum(3)) }
func (s *testEvalSuite) TestEvalIf(c *C) { colID := int64(1) xevaluator := NewEvaluator(new(variable.StatementContext)) xevaluator.Row[colID] = types.NewIntDatum(100) trueCond, falseCond, null := types.NewIntDatum(1), types.NewIntDatum(0), types.Datum{} expr1, expr2 := types.NewStringDatum("expr1"), types.NewStringDatum("expr2") cases := []struct { expr *tipb.Expr result types.Datum }{ { expr: buildExpr(tipb.ExprType_If, trueCond, types.NewStringDatum("expr1"), types.NewStringDatum("expr2")), result: expr1, }, { expr: buildExpr(tipb.ExprType_If, falseCond, types.NewStringDatum("expr1"), types.NewStringDatum("expr2")), result: expr2, }, { expr: buildExpr(tipb.ExprType_If, null, types.NewStringDatum("expr1"), types.NewStringDatum("expr2")), result: expr2, }, { expr: buildExpr(tipb.ExprType_If, trueCond, null, types.NewStringDatum("expr2")), result: null, }, { expr: buildExpr(tipb.ExprType_If, falseCond, types.NewStringDatum("expr1"), null), result: null, }, { expr: buildExpr(tipb.ExprType_If, trueCond, types.NewStringDatum("expr1"), types.NewStringDatum("expr2")), result: expr1, }, { expr: buildExpr(tipb.ExprType_If, buildExpr(tipb.ExprType_If, trueCond, null, trueCond), buildExpr(tipb.ExprType_If, trueCond, expr1, expr2), buildExpr(tipb.ExprType_If, falseCond, expr1, expr2)), result: expr2, }, } 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(xevaluator.sc, ca.result) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
func (s *testEvaluatorSuite) TestFromUnixTime(c *C) { defer testleak.AfterTest(c)() tbl := []struct { isDecimal bool integralPart int64 fractionalPart int64 decimal float64 format string ansLen int }{ {false, 1451606400, 0, 0, "", 19}, {true, 1451606400, 123456000, 1451606400.123456, "", 26}, {true, 1451606400, 999999000, 1451606400.999999, "", 26}, {true, 1451606400, 999999900, 1451606400.9999999, "", 19}, {false, 1451606400, 0, 0, "%Y %D %M %h:%i:%s %x", 19}, {true, 1451606400, 123456000, 1451606400.123456, "%Y %D %M %h:%i:%s %x", 26}, {true, 1451606400, 999999000, 1451606400.999999, "%Y %D %M %h:%i:%s %x", 26}, {true, 1451606400, 999999900, 1451606400.9999999, "%Y %D %M %h:%i:%s %x", 19}, } for _, t := range tbl { var timestamp types.Datum if !t.isDecimal { timestamp.SetInt64(t.integralPart) } else { timestamp.SetFloat64(t.decimal) } // result of from_unixtime() is dependent on specific time zone. unixTime := time.Unix(t.integralPart, t.fractionalPart).Round(time.Microsecond).String()[:t.ansLen] if len(t.format) == 0 { v, err := builtinFromUnixTime([]types.Datum{timestamp}, s.ctx) c.Assert(err, IsNil) ans := v.GetMysqlTime() c.Assert(ans.String(), Equals, unixTime) } else { format := types.NewStringDatum(t.format) v, err := builtinFromUnixTime([]types.Datum{timestamp, format}, s.ctx) c.Assert(err, IsNil) result, err := builtinDateFormat([]types.Datum{types.NewStringDatum(unixTime), format}, s.ctx) c.Assert(err, IsNil) c.Assert(v.GetString(), Equals, result.GetString()) } } v, err := builtinFromUnixTime([]types.Datum{types.NewIntDatum(-12345)}, s.ctx) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) _, err = builtinFromUnixTime([]types.Datum{types.NewIntDatum(math.MaxInt32 + 1)}, s.ctx) c.Assert(err, IsNil) c.Assert(v.Kind(), Equals, types.KindNull) }
func (e *Evaluator) evalIsNull(expr *tipb.Expr) (types.Datum, error) { if len(expr.Children) != 1 { return types.Datum{}, ErrInvalid.Gen("ISNULL need 1 operand, got %d", len(expr.Children)) } d, err := e.Eval(expr.Children[0]) if err != nil { return types.Datum{}, errors.Trace(err) } if d.IsNull() { return types.NewIntDatum(1), nil } return types.NewIntDatum(0), nil }
func (e *Evaluator) evalGT(expr *tipb.Expr) (types.Datum, error) { cmp, err := e.compareTwoChildren(expr) if err != nil { return types.Datum{}, errors.Trace(err) } if cmp == compareResultNull { return types.Datum{}, nil } else if cmp > 0 { return types.NewIntDatum(1), nil } else { return types.NewIntDatum(0), nil } }
func (e *Evaluator) evalNullEQ(expr *tipb.Expr) (types.Datum, error) { left, right, err := e.evalTwoChildren(expr) if err != nil { return types.Datum{}, errors.Trace(err) } cmp, err := left.CompareDatum(right) if err != nil { return types.Datum{}, errors.Trace(err) } if cmp == 0 { return types.NewIntDatum(1), nil } return types.NewIntDatum(0), nil }
// HashCode implements Expression interface. func (col *Column) HashCode() []byte { if len(col.hashcode) != 0 { return col.hashcode } col.hashcode, _ = codec.EncodeValue(col.hashcode, types.NewStringDatum(col.FromID), types.NewIntDatum(int64(col.Position))) return col.hashcode }
// handleRowData deals with raw row data: // 1. Decodes row from raw byte slice. // 2. Checks if it fit where condition. // 3. Update aggregate functions. // returns true if got a row. func (rs *localRegion) handleRowData(ctx *selectContext, handle int64, value []byte) (bool, error) { columns := ctx.sel.TableInfo.Columns values, err := rs.getRowData(value, ctx.colTps) if err != nil { return false, errors.Trace(err) } // Fill handle and null columns. for _, col := range columns { if col.GetPkHandle() { var handleDatum types.Datum if mysql.HasUnsignedFlag(uint(col.Flag)) { // PK column is Unsigned handleDatum = types.NewUintDatum(uint64(handle)) } else { handleDatum = types.NewIntDatum(handle) } handleData, err1 := codec.EncodeValue(nil, handleDatum) if err1 != nil { return false, errors.Trace(err1) } values[col.GetColumnId()] = handleData } else { _, ok := values[col.GetColumnId()] if !ok { if mysql.HasNotNullFlag(uint(col.GetFlag())) { return false, errors.New("Miss column") } values[col.GetColumnId()] = []byte{codec.NilFlag} } } } return rs.valuesToRow(ctx, handle, values) }
// See http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep func builtinSleep(args []types.Datum, ctx context.Context) (d types.Datum, err error) { if ctx == nil { return d, errors.Errorf("Missing context when evalue builtin") } sessVars := variable.GetSessionVars(ctx) if args[0].IsNull() { if sessVars.StrictSQLMode { return d, errors.New("Incorrect arguments to sleep.") } d.SetInt64(0) return } // processing argument is negative zero := types.NewIntDatum(0) ret, err := args[0].CompareDatum(zero) if err != nil { return d, errors.Trace(err) } if ret == -1 { if sessVars.StrictSQLMode { return d, errors.New("Incorrect arguments to sleep.") } d.SetInt64(0) return } // TODO: consider it's interrupted using KILL QUERY from other session, or // interrupted by time out. duration := time.Duration(args[0].GetFloat64() * float64(time.Second.Nanoseconds())) time.Sleep(duration) d.SetInt64(0) return }
func (rs *localRegion) evalWhereForRow(ctx *selectContext, h int64, row map[int64][]byte) (bool, error) { if ctx.sel.Where == nil { return true, nil } for colID, col := range ctx.whereColumns { if col.GetPkHandle() { ctx.eval.Row[colID] = types.NewIntDatum(h) } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return false, errors.Trace(err) } ctx.eval.Row[colID] = datum } } result, err := ctx.eval.Eval(ctx.sel.Where) if err != nil { return false, errors.Trace(err) } if result.IsNull() { return false, nil } boolResult, err := result.ToBool() if err != nil { return false, errors.Trace(err) } return boolResult == 1, nil }
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))}) er.ctxStack = er.ctxStack[:l-2] er.ctxStack = append(er.ctxStack, function) }
func (s *testEvalSuite) TestEvalCoalesce(c *C) { colID := int64(1) row := make(map[int64]types.Datum) row[colID] = types.NewIntDatum(100) xevaluator := &Evaluator{Row: row} nullDatum := types.Datum{} nullDatum.SetNull() notNullDatum := types.NewStringDatum("not-null") cases := []struct { expr *tipb.Expr result types.Datum }{ { expr: buildExpr(tipb.ExprType_Coalesce, nullDatum, nullDatum, nullDatum), result: nullDatum, }, { expr: buildExpr(tipb.ExprType_Coalesce, nullDatum, notNullDatum, nullDatum), result: notNullDatum, }, { expr: buildExpr(tipb.ExprType_Coalesce, nullDatum, notNullDatum, types.NewStringDatum("not-null-2"), nullDatum), result: notNullDatum, }, } 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(xevaluator.sc, ca.result) c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } }
func (t *Table) addUpdateBinlog(ctx context.Context, h int64, old []types.Datum, newValue []byte, colIDs []int64) error { mutation := t.getMutation(ctx) hasPK := false if t.meta.PKIsHandle { hasPK = true } else { for _, idx := range t.meta.Indices { if idx.Primary { hasPK = true break } } } var bin []byte if hasPK { handleData, _ := codec.EncodeValue(nil, types.NewIntDatum(h)) bin = append(handleData, newValue...) } else { oldData, err := tablecodec.EncodeRow(old, colIDs) if err != nil { return errors.Trace(err) } bin = append(oldData, newValue...) } mutation.UpdatedRows = append(mutation.UpdatedRows, bin) mutation.Sequence = append(mutation.Sequence, binlog.MutationType_Update) return nil }
// IterRecords implements table.Table IterRecords interface. func (t *Table) IterRecords(ctx context.Context, startKey kv.Key, cols []*table.Column, fn table.RecordIterFunc) error { txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } it, err := txn.Seek(startKey) if err != nil { return errors.Trace(err) } defer it.Close() if !it.Valid() { return nil } log.Debugf("startKey:%q, key:%q, value:%q", startKey, it.Key(), it.Value()) colMap := make(map[int64]*types.FieldType) for _, col := range cols { colMap[col.ID] = &col.FieldType } prefix := t.RecordPrefix() for it.Valid() && it.Key().HasPrefix(prefix) { // first kv pair is row lock information. // TODO: check valid lock // get row handle handle, err := tablecodec.DecodeRowKey(it.Key()) if err != nil { return errors.Trace(err) } rowMap, err := tablecodec.DecodeRow(it.Value(), colMap) if err != nil { return errors.Trace(err) } data := make([]types.Datum, 0, len(cols)) for _, col := range cols { if col.IsPKHandleColumn(t.Meta()) { data = append(data, types.NewIntDatum(handle)) } else { data = append(data, rowMap[col.ID]) } } more, err := fn(handle, data, cols) if !more || err != nil { return errors.Trace(err) } rk := t.RecordKey(handle) err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)) if err != nil { return errors.Trace(err) } } return nil }
func (s *testStatisticsSuite) TestTable(c *C) { tblInfo := &model.TableInfo{ ID: 1, } columns := []*model.ColumnInfo{ { ID: 2, FieldType: *types.NewFieldType(mysql.TypeLonglong), }, } tblInfo.Columns = columns timestamp := int64(10) bucketCount := int64(256) sc := new(variable.StatementContext) t, err := NewTable(sc, tblInfo, timestamp, s.count, bucketCount, [][]types.Datum{s.samples}) c.Check(err, IsNil) col := t.Columns[0] count, err := col.EqualRowCount(sc, types.NewIntDatum(1000)) c.Check(err, IsNil) c.Check(count, Equals, int64(2)) count, err = col.LessRowCount(sc, types.NewIntDatum(2000)) c.Check(err, IsNil) c.Check(count, Equals, int64(19955)) count, err = col.BetweenRowCount(sc, types.NewIntDatum(3000), types.NewIntDatum(3500)) c.Check(err, IsNil) c.Check(count, Equals, int64(5075)) str := t.String() log.Debug(str) c.Check(len(str), Greater, 0) tpb, err := t.ToPB() c.Check(err, IsNil) data, err := proto.Marshal(tpb) c.Check(err, IsNil) ntpb := &TablePB{} err = proto.Unmarshal(data, ntpb) c.Check(err, IsNil) nt, err := TableFromPB(tblInfo, ntpb) c.Check(err, IsNil) c.Check(nt.String(), Equals, str) }
func (er *expressionRewriter) likeToScalarFunc(v *ast.PatternLikeExpr) { l := len(er.ctxStack) er.checkArgsOneColumn(er.ctxStack[l-2:]...) if er.err != nil { return } function := er.notToExpression(v.Not, ast.Like, &v.Type, er.ctxStack[l-2], er.ctxStack[l-1], &expression.Constant{Value: types.NewIntDatum(int64(v.Escape))}) er.ctxStack = er.ctxStack[:l-2] er.ctxStack = append(er.ctxStack, function) }
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)) }
func (s *testStatisticsSuite) TestPseudoTable(c *C) { ti := &model.TableInfo{} ti.Columns = append(ti.Columns, &model.ColumnInfo{ ID: 1, FieldType: *types.NewFieldType(mysql.TypeLonglong), }) tbl := PseudoTable(ti) c.Assert(tbl.Count, Greater, int64(0)) c.Assert(tbl.TS, Greater, int64(0)) col := tbl.Columns[0] c.Assert(col.ID, Greater, int64(0)) c.Assert(col.NDV, Greater, int64(0)) count, err := col.LessRowCount(types.NewIntDatum(100)) c.Assert(err, IsNil) c.Assert(count, Equals, int64(3333)) count, err = col.EqualRowCount(types.NewIntDatum(1000)) c.Assert(err, IsNil) c.Assert(count, Equals, int64(1000)) count, err = col.BetweenRowCount(types.NewIntDatum(1000), types.NewIntDatum(5000)) c.Assert(err, IsNil) c.Assert(count, Equals, int64(2500)) }
func (e *Evaluator) evalLike(expr *tipb.Expr) (types.Datum, error) { target, pattern, err := e.evalTwoChildren(expr) if err != nil { return types.Datum{}, errors.Trace(err) } if target.IsNull() || pattern.IsNull() { return types.Datum{}, nil } targetStr, err := target.ToString() if err != nil { return types.Datum{}, errors.Trace(err) } patternStr, err := pattern.ToString() if err != nil { return types.Datum{}, errors.Trace(err) } if containsAlphabet(patternStr) { patternStr = strings.ToLower(patternStr) targetStr = strings.ToLower(targetStr) } mType, trimmedPattern := matchType(patternStr) var matched bool switch mType { case matchExact: matched = targetStr == trimmedPattern case matchPrefix: matched = strings.HasPrefix(targetStr, trimmedPattern) case matchSuffix: matched = strings.HasSuffix(targetStr, trimmedPattern) case matchMiddle: matched = strings.Index(targetStr, trimmedPattern) != -1 } if matched { return types.NewIntDatum(1), nil } return types.NewIntDatum(0), nil }
// Put column values into ctx, the values will be used for expr evaluation. func (rs *localRegion) setColumnValueToCtx(ctx *selectContext, h int64, row map[int64][]byte, cols map[int64]*tipb.ColumnInfo) error { for colID, col := range cols { if col.GetPkHandle() { ctx.eval.Row[colID] = types.NewIntDatum(h) } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return errors.Trace(err) } ctx.eval.Row[colID] = datum } } return nil }
func (e *XSelectIndexExec) indexRowToTableRow(handle int64, indexRow []types.Datum) []types.Datum { tableRow := make([]types.Datum, len(e.indexPlan.Columns)) for i, tblCol := range e.indexPlan.Columns { if mysql.HasPriKeyFlag(tblCol.Flag) && e.indexPlan.Table.PKIsHandle { tableRow[i] = types.NewIntDatum(handle) continue } for j, idxCol := range e.indexPlan.Index.Columns { if tblCol.Name.L == idxCol.Name.L { tableRow[i] = indexRow[j] break } } } return tableRow }
func (h *rpcHandler) evalWhereForRow(ctx *selectContext, handle int64) (bool, error) { if ctx.sel.Where == nil { return true, nil } tid := ctx.sel.TableInfo.GetTableId() for colID, col := range ctx.whereColumns { if col.GetPkHandle() { if mysql.HasUnsignedFlag(uint(col.GetFlag())) { ctx.eval.Row[colID] = types.NewUintDatum(uint64(handle)) } else { ctx.eval.Row[colID] = types.NewIntDatum(handle) } } else { key := tablecodec.EncodeColumnKey(tid, handle, colID) data, err := h.mvccStore.Get(key, ctx.sel.GetStartTs()) if err != nil { return false, errors.Trace(err) } if data == nil { if mysql.HasNotNullFlag(uint(col.GetFlag())) { return false, errors.Trace(kv.ErrNotExist) } ctx.eval.Row[colID] = types.Datum{} } else { var d types.Datum d, err = tablecodec.DecodeColumnValue(data, col) if err != nil { return false, errors.Trace(err) } ctx.eval.Row[colID] = d } } } result, err := ctx.eval.Eval(ctx.sel.Where) if err != nil { return false, errors.Trace(err) } if result.IsNull() { return false, nil } boolResult, err := result.ToBool() if err != nil { return false, errors.Trace(err) } return boolResult == 1, nil }
// EncodeRow encode row data and column ids into a slice of byte. // Row layout: colID1, value1, colID2, value2, ..... func EncodeRow(row []types.Datum, colIDs []int64) ([]byte, error) { if len(row) != len(colIDs) { return nil, errors.Errorf("EncodeRow error: data and columnID count not match %d vs %d", len(row), len(colIDs)) } values := make([]types.Datum, 2*len(row)) for i, c := range row { id := colIDs[i] idv := types.NewIntDatum(id) values[2*i] = idv fc, err := flatten(c) if err != nil { return nil, errors.Trace(err) } values[2*i+1] = fc } return codec.EncodeValue(nil, values...) }
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 (e *XSelectIndexExec) indexRowToTableRow(handle int64, indexRow []types.Datum) []types.Datum { tableRow := make([]types.Datum, len(e.indexPlan.Columns)) for i, tblCol := range e.indexPlan.Columns { if table.ToColumn(tblCol).IsPKHandleColumn(e.indexPlan.Table) { if mysql.HasUnsignedFlag(tblCol.FieldType.Flag) { tableRow[i] = types.NewUintDatum(uint64(handle)) } else { tableRow[i] = types.NewIntDatum(handle) } continue } for j, idxCol := range e.indexPlan.Index.Columns { if tblCol.Name.L == idxCol.Name.L { tableRow[i] = indexRow[j] break } } } return tableRow }
// Put column values into ctx, the values will be used for expr evaluation. func (h *rpcHandler) setColumnValueToCtx(ctx *selectContext, handle int64, row map[int64][]byte, cols map[int64]*tipb.ColumnInfo) error { for colID, col := range cols { if col.GetPkHandle() { if mysql.HasUnsignedFlag(uint(col.GetFlag())) { ctx.eval.Row[colID] = types.NewUintDatum(uint64(handle)) } else { ctx.eval.Row[colID] = types.NewIntDatum(handle) } } else { data := row[colID] ft := xapi.FieldTypeFromPBColumn(col) datum, err := tablecodec.DecodeColumnValue(data, ft) if err != nil { return errors.Trace(err) } ctx.eval.Row[colID] = datum } } return nil }
// See http://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_time func builtinTime(args []types.Datum, _ context.Context) (d types.Datum, err error) { if args[0].IsNull() { return } str, err := args[0].ToString() if err != nil { return d, errors.Trace(err) } idx := strings.Index(str, ".") fsp := 0 if idx != -1 { fsp = len(str) - idx - 1 } fspD := types.NewIntDatum(int64(fsp)) if fsp, err = checkFsp(fspD); err != nil { return d, errors.Trace(err) } return convertToDuration(args[0], fsp) }
func (h *rpcHandler) valuesToRow(ctx *selectContext, handle int64, values map[int64][]byte) (*tipb.Row, error) { var columns []*tipb.ColumnInfo if ctx.sel.TableInfo != nil { columns = ctx.sel.TableInfo.Columns } else { columns = ctx.sel.IndexInfo.Columns } // Evaluate where match, err := h.evalWhereForRow(ctx, handle, values) if err != nil { return nil, errors.Trace(err) } if !match { return nil, nil } var row *tipb.Row if ctx.aggregate { // Update aggregate functions. err = h.aggregate(ctx, handle, values) if err != nil { return nil, errors.Trace(err) } } else { var handleData []byte handleData, err = codec.EncodeValue(nil, types.NewIntDatum(handle)) if err != nil { return nil, errors.Trace(err) } row = new(tipb.Row) row.Handle = handleData // If without aggregate functions, just return raw row data. for _, col := range columns { row.Data = append(row.Data, values[col.GetColumnId()]...) } } return row, nil }