@@ -15,7 +15,16 @@ pub const KEYSPACE_PREFIX_LEN: usize = 4;
1515#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
1616pub enum Keyspace {
1717 Disable ,
18- Enable { keyspace_id : u32 } ,
18+ Enable {
19+ keyspace_id : u32 ,
20+ } ,
21+ /// Use API V2 without adding or removing the API V2 keyspace/key-mode prefix.
22+ ///
23+ /// This mode is intended for **server-side embedding** use cases (e.g. embedding this client in
24+ /// `tikv-server`) where keys are already in API V2 "logical key bytes" form and must be passed
25+ /// through unchanged.
26+ #[ cfg( feature = "apiv2-no-prefix" ) ]
27+ ApiV2NoPrefix ,
1928}
2029
2130#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash , Serialize , Deserialize ) ]
@@ -29,6 +38,8 @@ impl Keyspace {
2938 match self {
3039 Keyspace :: Disable => kvrpcpb:: ApiVersion :: V1 ,
3140 Keyspace :: Enable { .. } => kvrpcpb:: ApiVersion :: V2 ,
41+ #[ cfg( feature = "apiv2-no-prefix" ) ]
42+ Keyspace :: ApiV2NoPrefix => kvrpcpb:: ApiVersion :: V2 ,
3243 }
3344 }
3445}
@@ -43,12 +54,10 @@ pub trait TruncateKeyspace {
4354
4455impl EncodeKeyspace for Key {
4556 fn encode_keyspace ( mut self , keyspace : Keyspace , key_mode : KeyMode ) -> Self {
46- let prefix = match keyspace {
47- Keyspace :: Disable => {
48- return self ;
49- }
50- Keyspace :: Enable { keyspace_id } => keyspace_prefix ( keyspace_id, key_mode) ,
57+ let Keyspace :: Enable { keyspace_id } = keyspace else {
58+ return self ;
5159 } ;
60+ let prefix = keyspace_prefix ( keyspace_id, key_mode) ;
5261
5362 prepend_bytes ( & mut self . 0 , & prefix) ;
5463
@@ -68,28 +77,25 @@ impl EncodeKeyspace for BoundRange {
6877 self . from = match self . from {
6978 Bound :: Included ( key) => Bound :: Included ( key. encode_keyspace ( keyspace, key_mode) ) ,
7079 Bound :: Excluded ( key) => Bound :: Excluded ( key. encode_keyspace ( keyspace, key_mode) ) ,
71- Bound :: Unbounded => {
72- let key = Key :: from ( vec ! [ ] ) ;
73- Bound :: Included ( key. encode_keyspace ( keyspace, key_mode) )
74- }
80+ Bound :: Unbounded => Bound :: Included ( Key :: EMPTY . encode_keyspace ( keyspace, key_mode) ) ,
7581 } ;
82+
7683 self . to = match self . to {
7784 Bound :: Included ( key) if !key. is_empty ( ) => {
7885 Bound :: Included ( key. encode_keyspace ( keyspace, key_mode) )
7986 }
8087 Bound :: Excluded ( key) if !key. is_empty ( ) => {
8188 Bound :: Excluded ( key. encode_keyspace ( keyspace, key_mode) )
8289 }
83- _ => {
84- let key = Key :: from ( vec ! [ ] ) ;
85- let keyspace = match keyspace {
86- Keyspace :: Disable => Keyspace :: Disable ,
87- Keyspace :: Enable { keyspace_id } => Keyspace :: Enable {
90+ _ => match keyspace {
91+ Keyspace :: Enable { keyspace_id } => Bound :: Excluded ( Key :: EMPTY . encode_keyspace (
92+ Keyspace :: Enable {
8893 keyspace_id : keyspace_id + 1 ,
8994 } ,
90- } ;
91- Bound :: Excluded ( key. encode_keyspace ( keyspace, key_mode) )
92- }
95+ key_mode,
96+ ) ) ,
97+ _ => Bound :: Excluded ( Key :: EMPTY ) ,
98+ } ,
9399 } ;
94100 self
95101 }
@@ -106,7 +112,7 @@ impl EncodeKeyspace for Mutation {
106112
107113impl TruncateKeyspace for Key {
108114 fn truncate_keyspace ( mut self , keyspace : Keyspace ) -> Self {
109- if let Keyspace :: Disable = keyspace {
115+ if ! matches ! ( keyspace , Keyspace :: Enable { .. } ) {
110116 return self ;
111117 }
112118
@@ -133,6 +139,9 @@ impl TruncateKeyspace for Range<Key> {
133139
134140impl TruncateKeyspace for Vec < Range < Key > > {
135141 fn truncate_keyspace ( mut self , keyspace : Keyspace ) -> Self {
142+ if !matches ! ( keyspace, Keyspace :: Enable { .. } ) {
143+ return self ;
144+ }
136145 for range in & mut self {
137146 take_mut:: take ( range, |range| range. truncate_keyspace ( keyspace) ) ;
138147 }
@@ -142,6 +151,9 @@ impl TruncateKeyspace for Vec<Range<Key>> {
142151
143152impl TruncateKeyspace for Vec < KvPair > {
144153 fn truncate_keyspace ( mut self , keyspace : Keyspace ) -> Self {
154+ if !matches ! ( keyspace, Keyspace :: Enable { .. } ) {
155+ return self ;
156+ }
145157 for pair in & mut self {
146158 take_mut:: take ( pair, |pair| pair. truncate_keyspace ( keyspace) ) ;
147159 }
@@ -151,6 +163,9 @@ impl TruncateKeyspace for Vec<KvPair> {
151163
152164impl TruncateKeyspace for Vec < crate :: proto:: kvrpcpb:: LockInfo > {
153165 fn truncate_keyspace ( mut self , keyspace : Keyspace ) -> Self {
166+ if !matches ! ( keyspace, Keyspace :: Enable { .. } ) {
167+ return self ;
168+ }
154169 for lock in & mut self {
155170 take_mut:: take ( & mut lock. key , |key| {
156171 Key :: from ( key) . truncate_keyspace ( keyspace) . into ( )
@@ -277,4 +292,66 @@ mod tests {
277292 let expected_key = Key :: from ( vec ! [ 0xBE , 0xEF ] ) ;
278293 assert_eq ! ( key. truncate_keyspace( keyspace) , expected_key) ;
279294 }
295+
296+ #[ cfg( feature = "apiv2-no-prefix" ) ]
297+ #[ test]
298+ fn test_apiv2_no_prefix_api_version ( ) {
299+ assert_eq ! (
300+ Keyspace :: ApiV2NoPrefix . api_version( ) ,
301+ kvrpcpb:: ApiVersion :: V2
302+ ) ;
303+ }
304+
305+ #[ cfg( feature = "apiv2-no-prefix" ) ]
306+ #[ test]
307+ fn test_apiv2_no_prefix_encode_is_noop ( ) {
308+ let keyspace = Keyspace :: ApiV2NoPrefix ;
309+ let key_mode = KeyMode :: Txn ;
310+
311+ let key = Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ) ;
312+ assert_eq ! ( key. clone( ) . encode_keyspace( keyspace, key_mode) , key) ;
313+
314+ let pair = KvPair ( Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ) , vec ! [ b'v' ] ) ;
315+ assert_eq ! ( pair. clone( ) . encode_keyspace( keyspace, key_mode) , pair) ;
316+
317+ let bound: BoundRange =
318+ ( Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'a' ] ) ..Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'b' ] ) ) . into ( ) ;
319+ assert_eq ! ( bound. clone( ) . encode_keyspace( keyspace, key_mode) , bound) ;
320+
321+ let mutation = Mutation :: Put ( Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ) , vec ! [ 1 , 2 , 3 ] ) ;
322+ assert_eq ! (
323+ mutation. clone( ) . encode_keyspace( keyspace, key_mode) ,
324+ mutation
325+ ) ;
326+ }
327+
328+ #[ cfg( feature = "apiv2-no-prefix" ) ]
329+ #[ test]
330+ fn test_apiv2_no_prefix_truncate_is_noop ( ) {
331+ let keyspace = Keyspace :: ApiV2NoPrefix ;
332+
333+ let key = Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ) ;
334+ assert_eq ! ( key. clone( ) . truncate_keyspace( keyspace) , key) ;
335+
336+ let pair = KvPair ( Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ) , vec ! [ b'v' ] ) ;
337+ assert_eq ! ( pair. clone( ) . truncate_keyspace( keyspace) , pair) ;
338+
339+ let range = Range {
340+ start : Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'a' ] ) ,
341+ end : Key :: from ( vec ! [ b'x' , 0 , 0 , 0 , b'b' ] ) ,
342+ } ;
343+ assert_eq ! ( range. clone( ) . truncate_keyspace( keyspace) , range) ;
344+
345+ let pairs = vec ! [ pair] ;
346+ assert_eq ! ( pairs. clone( ) . truncate_keyspace( keyspace) , pairs) ;
347+
348+ let lock = crate :: proto:: kvrpcpb:: LockInfo {
349+ key : vec ! [ b'x' , 0 , 0 , 0 , b'k' ] ,
350+ primary_lock : vec ! [ b'x' , 0 , 0 , 0 , b'p' ] ,
351+ secondaries : vec ! [ vec![ b'x' , 0 , 0 , 0 , b's' ] ] ,
352+ ..Default :: default ( )
353+ } ;
354+ let locks = vec ! [ lock] ;
355+ assert_eq ! ( locks. clone( ) . truncate_keyspace( keyspace) , locks) ;
356+ }
280357}
0 commit comments