mirror of https://github.com/tikv/client-go.git
add rawkv/ReverseScan (#13)
Signed-off-by: kamijin_fanta <kamijin@live.jp>
This commit is contained in:
parent
2130e26d4f
commit
112f5cb76e
|
|
@ -302,6 +302,53 @@ func (c *Client) Scan(startKey, endKey []byte, limit int) (keys [][]byte, values
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReverseScan queries continuous kv pairs in range [endKey, startKey), up to limit pairs.
|
||||||
|
// Direction is different from Scan, upper to lower.
|
||||||
|
// If endKey is empty, it means unbounded.
|
||||||
|
// If you want to include the startKey or exclude the endKey, append a '\0' to the key. For example, to scan
|
||||||
|
// (endKey, startKey], you can write:
|
||||||
|
// `ReverseScan(append(startKey, '\0'), append(endKey, '\0'), limit)`.
|
||||||
|
// It doesn't support Scanning from "", because locating the last Region is not yet implemented.
|
||||||
|
func (c *Client) ReverseScan(startKey, endKey []byte, limit int) (keys [][]byte, values [][]byte, err error) {
|
||||||
|
start := time.Now()
|
||||||
|
defer func() {
|
||||||
|
metrics.RawkvCmdHistogram.WithLabelValues("raw_reverse_scan").Observe(time.Since(start).Seconds())
|
||||||
|
}()
|
||||||
|
|
||||||
|
if limit > config.MaxRawKVScanLimit {
|
||||||
|
return nil, nil, errors.WithStack(ErrMaxScanLimitExceeded)
|
||||||
|
}
|
||||||
|
|
||||||
|
for len(keys) < limit {
|
||||||
|
req := &rpc.Request{
|
||||||
|
Type: rpc.CmdRawScan,
|
||||||
|
RawScan: &kvrpcpb.RawScanRequest{
|
||||||
|
StartKey: startKey,
|
||||||
|
EndKey: endKey,
|
||||||
|
Limit: uint32(limit - len(keys)),
|
||||||
|
Reverse: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
resp, loc, err := c.sendReq(startKey, req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
cmdResp := resp.RawScan
|
||||||
|
if cmdResp == nil {
|
||||||
|
return nil, nil, errors.WithStack(rpc.ErrBodyMissing)
|
||||||
|
}
|
||||||
|
for _, pair := range cmdResp.Kvs {
|
||||||
|
keys = append(keys, pair.Key)
|
||||||
|
values = append(values, pair.Value)
|
||||||
|
}
|
||||||
|
startKey = loc.EndKey
|
||||||
|
if len(startKey) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) sendReq(key []byte, req *rpc.Request) (*rpc.Response, *locate.KeyLocation, error) {
|
func (c *Client) sendReq(key []byte, req *rpc.Request) (*rpc.Response, *locate.KeyLocation, error) {
|
||||||
bo := retry.NewBackoffer(context.Background(), retry.RawkvMaxBackoff)
|
bo := retry.NewBackoffer(context.Background(), retry.RawkvMaxBackoff)
|
||||||
sender := rpc.NewRegionRequestSender(c.regionCache, c.rpcClient)
|
sender := rpc.NewRegionRequestSender(c.regionCache, c.rpcClient)
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,26 @@ func (s *testRawKVSuite) mustScanRange(c *C, startKey string, endKey string, lim
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *testRawKVSuite) mustReverseScan(c *C, startKey []byte, limit int, expect ...string) {
|
||||||
|
keys, values, err := s.client.ReverseScan(startKey, nil, limit)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(len(keys)*2, Equals, len(expect))
|
||||||
|
for i := range keys {
|
||||||
|
c.Assert(string(keys[i]), Equals, expect[i*2])
|
||||||
|
c.Assert(string(values[i]), Equals, expect[i*2+1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *testRawKVSuite) mustReverseScanRange(c *C, startKey, endKey []byte, limit int, expect ...string) {
|
||||||
|
keys, values, err := s.client.ReverseScan(startKey, endKey, limit)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
c.Assert(len(keys)*2, Equals, len(expect))
|
||||||
|
for i := range keys {
|
||||||
|
c.Assert(string(keys[i]), Equals, expect[i*2])
|
||||||
|
c.Assert(string(values[i]), Equals, expect[i*2+1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *testRawKVSuite) mustDeleteRange(c *C, startKey, endKey []byte, expected map[string]string) {
|
func (s *testRawKVSuite) mustDeleteRange(c *C, startKey, endKey []byte, expected map[string]string) {
|
||||||
err := s.client.DeleteRange(startKey, endKey)
|
err := s.client.DeleteRange(startKey, endKey)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue