/* * Convert sorted handle to kv ranges. * For continuous handles, we should merge them to a single key range. */ func tableHandlesToKVRanges(tid int64, handles []int64) []kv.KeyRange { krs := make([]kv.KeyRange, 0, len(handles)) i := 0 for i < len(handles) { h := handles[i] if h == math.MaxInt64 { // We can't convert MaxInt64 into an left closed, right open range. i++ continue } j := i + 1 endHandle := h + 1 for ; j < len(handles); j++ { if handles[j] == endHandle { endHandle = handles[j] + 1 continue } break } startKey := tablecodec.EncodeRowKeyWithHandle(tid, h) endKey := tablecodec.EncodeRowKeyWithHandle(tid, endHandle) krs = append(krs, kv.KeyRange{StartKey: startKey, EndKey: endKey}) i = j } return krs }
func getExpectedRanges(tid int64, hrs []*handleRange) []kv.KeyRange { krs := make([]kv.KeyRange, 0, len(hrs)) for _, hr := range hrs { startKey := tablecodec.EncodeRowKeyWithHandle(tid, hr.start) endKey := tablecodec.EncodeRowKeyWithHandle(tid, hr.end) krs = append(krs, kv.KeyRange{StartKey: startKey, EndKey: endKey}) } return krs }
func tableRangesToKVRanges(tid int64, tableRanges []plan.TableRange) []kv.KeyRange { krs := make([]kv.KeyRange, 0, len(tableRanges)) for _, tableRange := range tableRanges { startKey := tablecodec.EncodeRowKeyWithHandle(tid, tableRange.LowVal) hi := tableRange.HighVal if hi != math.MaxInt64 { hi++ } endKey := tablecodec.EncodeRowKeyWithHandle(tid, hi) krs = append(krs, kv.KeyRange{StartKey: startKey, EndKey: endKey}) } return krs }
// Seek implements table.Table Seek interface. func (t *Table) Seek(ctx context.Context, h int64) (int64, bool, error) { seekKey := tablecodec.EncodeRowKeyWithHandle(t.ID, h) txn, err := ctx.GetTxn(false) if err != nil { return 0, false, errors.Trace(err) } iter, err := txn.Seek(seekKey) if !iter.Valid() || !iter.Key().HasPrefix(t.RecordPrefix()) { // No more records in the table, skip to the end. return 0, false, nil } handle, err := tablecodec.DecodeRowKey(iter.Key()) if err != nil { return 0, false, errors.Trace(err) } return handle, true, nil }
func (ts *testSuite) TestRowKeyCodec(c *C) { table := []struct { tableID int64 h int64 ID int64 }{ {1, 1234567890, 0}, {2, 1, 0}, {3, -1, 0}, {4, -1, 1}, } for _, t := range table { b := tablecodec.EncodeRowKeyWithHandle(t.tableID, t.h) tableID, handle, err := tablecodec.DecodeRecordKey(b) c.Assert(err, IsNil) c.Assert(tableID, Equals, t.tableID) c.Assert(handle, Equals, t.h) handle, err = tablecodec.DecodeRowKey(b) c.Assert(err, IsNil) c.Assert(handle, Equals, t.h) } // test error tbl := []string{ "", "x", "t1", "t12345678", "t12345678_i", "t12345678_r1", "t12345678_r1234567", } for _, t := range tbl { _, err := tablecodec.DecodeRowKey(kv.Key(t)) c.Assert(err, NotNil) } }
// Next implements the Executor Next interface. func (e *SelectLockExec) Next() (*Row, error) { row, err := e.Src.Next() if err != nil { return nil, errors.Trace(err) } if row == nil { return nil, nil } if len(row.RowKeys) != 0 && e.Lock == ast.SelectLockForUpdate { e.ctx.GetSessionVars().TxnCtx.ForUpdate = true txn, err := e.ctx.GetTxn(false) if err != nil { return nil, errors.Trace(err) } for _, k := range row.RowKeys { lockKey := tablecodec.EncodeRowKeyWithHandle(k.Tbl.Meta().ID, k.Handle) err = txn.LockKeys(lockKey) if err != nil { return nil, errors.Trace(err) } } } return row, nil }
func (h *rpcHandler) getRowByHandle(ctx *selectContext, handle int64) (*tipb.Row, error) { tid := ctx.sel.TableInfo.GetTableId() columns := ctx.sel.TableInfo.Columns row := new(tipb.Row) var d types.Datum d.SetInt64(handle) var err error row.Handle, err = codec.EncodeValue(nil, d) if err != nil { return nil, errors.Trace(err) } rowData := make([][]byte, len(columns)) colTps := make(map[int64]*types.FieldType, len(columns)) for i, col := range columns { var colVal []byte if col.GetPkHandle() { if mysql.HasUnsignedFlag(uint(*col.Flag)) { // PK column is Unsigned var ud types.Datum ud.SetUint64(uint64(handle)) var err1 error colVal, err1 = codec.EncodeValue(nil, ud) if err1 != nil { return nil, errors.Trace(err1) } } else { colVal = row.Handle } rowData[i] = colVal } else { colTps[col.GetColumnId()] = xapi.FieldTypeFromPBColumn(col) } } key := tablecodec.EncodeRowKeyWithHandle(tid, handle) value, err := h.mvccStore.Get(key, ctx.sel.GetStartTs()) if err != nil { return nil, errors.Trace(err) } values, err := h.getRowData(value, colTps) if err != nil { return nil, errors.Trace(err) } for i, col := range columns { if col.GetPkHandle() { continue } v, ok := values[col.GetColumnId()] if !ok { if mysql.HasNotNullFlag(uint(col.GetFlag())) { return nil, errors.New("Miss column") } v = []byte{codec.NilFlag} values[col.GetColumnId()] = v } rowData[i] = v } // Evalue where match, err := h.evalWhereForRow(ctx, handle, values) if err != nil { return nil, errors.Trace(err) } if !match { return nil, nil } for _, d := range rowData { row.Data = append(row.Data, d...) } return row, nil }