@@ -18,7 +18,8 @@ pub struct UtilArgs {
1818
1919#[ derive( Debug , Clone , Subcommand ) ]
2020enum UtilCommands {
21- /// Transaction-id conversion utilities
21+ /// Version and pagination-key conversion utilities
22+ #[ command( name = "version" ) ]
2223 Xact ( XactArgs ) ,
2324}
2425
@@ -36,7 +37,7 @@ enum XactCommands {
3637 FromPretty ( FromPrettyArgs ) ,
3738 /// Convert a transaction id to a timestamp
3839 ToTime ( ToTimeArgs ) ,
39- /// Convert a timestamp to a transaction id
40+ /// Convert a timestamp to a transaction id or pagination key
4041 FromTime ( FromTimeArgs ) ,
4142 /// Decode and display transaction id details
4243 Inspect ( InspectArgs ) ,
@@ -91,6 +92,10 @@ struct FromTimeArgs {
9192 /// Low 16-bit transaction counter value
9293 #[ arg( long, default_value_t = 0 ) ]
9394 counter : u16 ,
95+
96+ /// Output a pagination key instead of a transaction id
97+ #[ arg( long) ]
98+ pagination_key : bool ,
9499}
95100
96101#[ derive( Debug , Clone , Copy , ValueEnum , Eq , PartialEq ) ]
@@ -212,21 +217,32 @@ fn run_from_time(json: bool, args: FromTimeArgs) -> Result<()> {
212217 let unix_seconds = parse_timestamp_or_now ( args. timestamp . as_deref ( ) , args. input ) ?;
213218 let xact = build_xact_id ( unix_seconds, args. counter ) ;
214219 let pretty = prettify_xact ( xact) ;
220+ let pagination_key = build_pagination_key ( unix_seconds, args. counter , 0 ) ;
221+ let output_kind = if args. pagination_key {
222+ "pagination_key"
223+ } else {
224+ "xact_id"
225+ } ;
215226 if json {
216- println ! (
217- "{}" ,
218- serde_json:: to_string( & serde_json:: json!( {
219- "input_timestamp" : args. timestamp,
220- "input_format" : match args. input {
221- TimeInputFormat :: Iso => "iso" ,
222- TimeInputFormat :: Unix => "unix" ,
223- } ,
224- "unix_seconds" : unix_seconds,
225- "counter" : args. counter,
226- "xact_id" : xact. to_string( ) ,
227- "pretty_version" : pretty,
228- } ) ) ?
229- ) ;
227+ let mut payload = serde_json:: json!( {
228+ "output_kind" : output_kind,
229+ "input_timestamp" : args. timestamp,
230+ "input_format" : match args. input {
231+ TimeInputFormat :: Iso => "iso" ,
232+ TimeInputFormat :: Unix => "unix" ,
233+ } ,
234+ "unix_seconds" : unix_seconds,
235+ "counter" : args. counter,
236+ "xact_id" : xact. to_string( ) ,
237+ "pretty_version" : pretty,
238+ } ) ;
239+ if args. pagination_key {
240+ payload[ "pagination_key" ] = serde_json:: json!( format_pagination_key( pagination_key) ) ;
241+ payload[ "pagination_row_num" ] = serde_json:: json!( 0 ) ;
242+ }
243+ println ! ( "{}" , serde_json:: to_string( & payload) ?) ;
244+ } else if args. pagination_key {
245+ println ! ( "{}" , format_pagination_key( pagination_key) ) ;
230246 } else {
231247 println ! ( "{xact}" ) ;
232248 }
@@ -401,6 +417,10 @@ fn build_xact_id(unix_seconds: u64, counter: u16) -> u64 {
401417 TOP_BITS | ( ( unix_seconds & 0xffff_ffff_ffff ) << 16 ) | u64:: from ( counter)
402418}
403419
420+ fn build_pagination_key ( unix_seconds : u64 , counter : u16 , row_num : u16 ) -> u64 {
421+ ( ( unix_seconds & 0xffff_ffff ) << 32 ) | ( u64:: from ( counter) << 16 ) | u64:: from ( row_num)
422+ }
423+
404424fn format_pagination_key ( pagination_key : u64 ) -> String {
405425 format ! ( "p{pagination_key:020}" )
406426}
@@ -507,6 +527,20 @@ mod tests {
507527 assert_eq ! ( xact_counter( xact) , counter) ;
508528 }
509529
530+ #[ test]
531+ fn from_time_to_pagination_key_uses_xact_counter ( ) {
532+ let unix_seconds = 1_778_727_718u64 ;
533+ let counter = 31_627u16 ;
534+ let pagination_key = build_pagination_key ( unix_seconds, counter, 0 ) ;
535+ assert_eq ! (
536+ format_pagination_key( pagination_key) ,
537+ "p07639577379371417600"
538+ ) ;
539+ assert_eq ! ( pagination_key_to_unix_seconds( pagination_key) , unix_seconds) ;
540+ assert_eq ! ( pagination_key_xact_counter( pagination_key) , counter) ;
541+ assert_eq ! ( pagination_key_row_num( pagination_key) , 0 ) ;
542+ }
543+
510544 #[ test]
511545 fn load_pretty_passthrough_for_non_pretty_input ( ) {
512546 assert_eq ! ( load_pretty_xact( "123" ) . unwrap( ) , "123" ) ;
0 commit comments