// GetTableRecordsCount returns the total number of table records from startHandle. // If startHandle = 0, returns the total number of table records. func GetTableRecordsCount(txn kv.Transaction, t table.Table, startHandle int64) (int64, error) { startKey := t.RecordKey(startHandle, nil) it, err := txn.Seek(startKey) if err != nil { return 0, errors.Trace(err) } var cnt int64 prefix := t.RecordPrefix() for it.Valid() && it.Key().HasPrefix(prefix) { handle, err := tablecodec.DecodeRowKey(it.Key()) if err != nil { return 0, errors.Trace(err) } it.Close() rk := t.RecordKey(handle+1, nil) it, err = txn.Seek(rk) if err != nil { return 0, errors.Trace(err) } cnt++ } it.Close() return cnt, 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 (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.EncodeColumnKey(t.tableID, t.h, t.ID) tableID, handle, columnID, err := tablecodec.DecodeRecordKey(b) c.Assert(err, IsNil) c.Assert(tableID, Equals, t.tableID) c.Assert(handle, Equals, t.h) c.Assert(columnID, Equals, t.ID) 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", "t12345678_r123456781", } for _, t := range tbl { _, err := tablecodec.DecodeRowKey(kv.Key(t)) c.Assert(err, NotNil) } }
func (d *ddl) getSnapshotRows(t table.Table, version uint64, seekHandle int64) ([]int64, error) { ver := kv.Version{Ver: version} snap, err := d.store.GetSnapshot(ver) if err != nil { return nil, errors.Trace(err) } defer snap.Release() firstKey := t.RecordKey(seekHandle) it, err := snap.Seek(firstKey) if err != nil { return nil, errors.Trace(err) } defer it.Close() handles := make([]int64, 0, maxBatchSize) for it.Valid() { if !it.Key().HasPrefix(t.RecordPrefix()) { break } var handle int64 handle, err = tablecodec.DecodeRowKey(it.Key()) if err != nil { return nil, errors.Trace(err) } rk := t.RecordKey(handle) handles = append(handles, handle) if len(handles) == maxBatchSize { break } err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)) if terror.ErrorEqual(err, kv.ErrNotExist) { break } else if err != nil { return nil, errors.Trace(err) } } return handles, nil }
// 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 iterRecords(retriever kv.Retriever, t table.Table, startKey kv.Key, cols []*table.Column, fn table.RecordIterFunc) error { it, err := retriever.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()) 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) } data, err := rowWithCols(retriever, t, handle, cols) if err != nil { return errors.Trace(err) } more, err := fn(handle, data, cols) if !more || err != nil { return errors.Trace(err) } rk := t.RecordKey(handle, nil) err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)) if err != nil { return errors.Trace(err) } } return nil }
func (rs *localRegion) getRowsFromRange(ctx *selectContext, ran kv.KeyRange, limit int64, desc bool) (count int64, err error) { if limit == 0 { return 0, nil } if ran.IsPoint() { var value []byte value, err = ctx.txn.Get(ran.StartKey) if terror.ErrorEqual(err, kv.ErrNotExist) { return 0, nil } else if err != nil { return 0, errors.Trace(err) } var h int64 h, err = tablecodec.DecodeRowKey(ran.StartKey) if err != nil { return 0, errors.Trace(err) } gotRow, err1 := rs.handleRowData(ctx, h, value) if err1 != nil { return 0, errors.Trace(err1) } if gotRow { count++ } return } var seekKey kv.Key if desc { seekKey = ran.EndKey } else { seekKey = ran.StartKey } for { if limit == 0 { break } var ( it kv.Iterator err error ) if desc { it, err = ctx.txn.SeekReverse(seekKey) } else { it, err = ctx.txn.Seek(seekKey) } if err != nil { return 0, errors.Trace(err) } if !it.Valid() { break } if desc { if it.Key().Cmp(ran.StartKey) < 0 { break } seekKey = tablecodec.TruncateToRowKeyLen(it.Key()) } else { if it.Key().Cmp(ran.EndKey) >= 0 { break } seekKey = it.Key().PrefixNext() } h, err := tablecodec.DecodeRowKey(it.Key()) if err != nil { return 0, errors.Trace(err) } gotRow, err := rs.handleRowData(ctx, h, it.Value()) if err != nil { return 0, errors.Trace(err) } if gotRow { limit-- count++ } } return count, nil }
func (h *rpcHandler) getRowsFromRange(ctx *selectContext, ran kv.KeyRange, limit int64, desc bool) ([]*tipb.Row, error) { startKey := maxStartKey(ran.StartKey, h.startKey) endKey := minEndKey(ran.EndKey, h.endKey) if limit == 0 || bytes.Compare(startKey, endKey) >= 0 { return nil, nil } var rows []*tipb.Row if ran.IsPoint() { val, err := h.mvccStore.Get(startKey, ctx.sel.GetStartTs()) if len(val) == 0 { return nil, nil } else if err != nil { return nil, errors.Trace(err) } handle, err := tablecodec.DecodeRowKey(kv.Key(startKey)) if err != nil { return nil, errors.Trace(err) } row, err := h.handleRowData(ctx, handle, val) if err != nil { return nil, errors.Trace(err) } if row != nil { rows = append(rows, row) } return rows, nil } var seekKey []byte if desc { seekKey = endKey } else { seekKey = startKey } for { if limit == 0 { break } var ( pairs []Pair pair Pair err error ) if desc { pairs = h.mvccStore.ReverseScan(startKey, seekKey, 1, ctx.sel.GetStartTs()) } else { pairs = h.mvccStore.Scan(seekKey, endKey, 1, ctx.sel.GetStartTs()) } if len(pairs) > 0 { pair = pairs[0] } if pair.Err != nil { // TODO: handle lock error. return nil, errors.Trace(pair.Err) } if pair.Key == nil { break } if desc { if bytes.Compare(pair.Key, startKey) < 0 { break } seekKey = []byte(tablecodec.TruncateToRowKeyLen(kv.Key(pair.Key))) } else { if bytes.Compare(pair.Key, endKey) >= 0 { break } seekKey = []byte(kv.Key(pair.Key).PrefixNext()) } handle, err := tablecodec.DecodeRowKey(pair.Key) if err != nil { return nil, errors.Trace(err) } row, err := h.handleRowData(ctx, handle, pair.Value) if err != nil { return nil, errors.Trace(err) } if row != nil { rows = append(rows, row) limit-- } } return rows, nil }
func (rs *localRegion) getRowsFromRange(ctx *selectContext, ran kv.KeyRange, limit int64, desc bool) ([]*tipb.Row, error) { if limit == 0 { return nil, nil } var rows []*tipb.Row if ran.IsPoint() { value, err := ctx.txn.Get(ran.StartKey) if terror.ErrorEqual(err, kv.ErrNotExist) { return nil, nil } else if err != nil { return nil, errors.Trace(err) } h, err := tablecodec.DecodeRowKey(ran.StartKey) if err != nil { return nil, errors.Trace(err) } row, err := rs.handleRowData(ctx, h, value) if err != nil { return nil, errors.Trace(err) } if row != nil { rows = append(rows, row) } return rows, nil } var seekKey kv.Key if desc { seekKey = ran.EndKey } else { seekKey = ran.StartKey } for { if limit == 0 { break } var ( it kv.Iterator err error ) if desc { it, err = ctx.txn.SeekReverse(seekKey) } else { it, err = ctx.txn.Seek(seekKey) } if err != nil { return nil, errors.Trace(err) } if !it.Valid() { break } if desc { if it.Key().Cmp(ran.StartKey) < 0 { break } seekKey = tablecodec.TruncateToRowKeyLen(it.Key()) } else { if it.Key().Cmp(ran.EndKey) >= 0 { break } seekKey = it.Key().PrefixNext() } h, err := tablecodec.DecodeRowKey(it.Key()) if err != nil { return nil, errors.Trace(err) } row, err := rs.handleRowData(ctx, h, it.Value()) if err != nil { return nil, errors.Trace(err) } if row != nil { rows = append(rows, row) limit-- } } return rows, nil }