func (rs *localRegion) getIndexRowFromRange(ctx *selectContext, ran kv.KeyRange, desc bool, limit int64) (count int64, err error) { idxInfo := ctx.sel.IndexInfo txn := ctx.txn var seekKey kv.Key if desc { seekKey = ran.EndKey } else { seekKey = ran.StartKey } ids := make([]int64, len(idxInfo.Columns)) for i, col := range idxInfo.Columns { ids[i] = col.GetColumnId() } for { if limit == 0 { break } var it kv.Iterator if desc { it, err = txn.SeekReverse(seekKey) if err != nil { return 0, errors.Trace(err) } seekKey = it.Key() } else { it, err = txn.Seek(seekKey) if err != nil { return 0, errors.Trace(err) } seekKey = it.Key().PrefixNext() } if !it.Valid() { break } if desc { if it.Key().Cmp(ran.StartKey) < 0 { break } } else { if it.Key().Cmp(ran.EndKey) >= 0 { break } } values, b, err1 := tablecodec.CutIndexKey(it.Key(), ids) if err1 != nil { return 0, errors.Trace(err1) } var handle int64 if len(b) > 0 { var handleDatum types.Datum _, handleDatum, err = codec.DecodeOne(b) if err != nil { return 0, errors.Trace(err) } handle = handleDatum.GetInt64() } else { handle, err = decodeHandle(it.Value()) if err != nil { return 0, errors.Trace(err) } } gotRow, err := rs.valuesToRow(ctx, handle, values) if err != nil { return 0, errors.Trace(err) } if gotRow { limit-- count++ } } return count, nil }
func (h *rpcHandler) getIndexRowFromRange(ctx *selectContext, ran kv.KeyRange, desc bool, limit int64) ([]*tipb.Row, error) { idxInfo := ctx.sel.IndexInfo 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 var seekKey kv.Key if desc { seekKey = endKey } else { seekKey = startKey } ids := make([]int64, len(idxInfo.Columns)) for i, col := range idxInfo.Columns { ids[i] = col.GetColumnId() } 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 = pair.Key } else { if bytes.Compare(pair.Key, endKey) >= 0 { break } seekKey = []byte(kv.Key(pair.Key).PrefixNext()) } values, b, err := tablecodec.CutIndexKey(pair.Key, ids) var handle int64 if len(b) > 0 { var handleDatum types.Datum _, handleDatum, err = codec.DecodeOne(b) if err != nil { return nil, errors.Trace(err) } handle = handleDatum.GetInt64() } else { handle, err = decodeHandle(pair.Value) if err != nil { return nil, errors.Trace(err) } } row, err := h.valuesToRow(ctx, handle, values) if err != nil { return nil, errors.Trace(err) } if row != nil { rows = append(rows, row) limit-- } } return rows, nil }