@@ -43,10 +43,17 @@ enum PrevState {
4343 new_position_in_mvcc : CursorPosition ,
4444 } ,
4545}
46+
47+ #[ derive( Debug , Clone ) ]
48+ enum ExistsState {
49+ ExistsBtree ,
50+ }
51+
4652#[ derive( Debug , Clone ) ]
4753enum MvccLazyCursorState {
4854 Next ( NextState ) ,
4955 Prev ( PrevState ) ,
56+ Exists ( ExistsState ) ,
5057}
5158
5259pub struct MvccLazyCursor < Clock : LogicalClock > {
@@ -632,39 +639,59 @@ impl<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
632639 }
633640
634641 fn exists ( & mut self , key : & Value ) -> Result < IOResult < bool > > {
635- self . invalidate_record ( ) ;
636- let int_key = match key {
637- Value :: Integer ( i) => i,
638- _ => unreachable ! ( "btree tables are indexed by integers!" ) ,
639- } ;
640- let rowid = self . db . seek_rowid (
641- Bound :: Included ( & RowID {
642- table_id : self . table_id ,
643- row_id : RowKey :: Int ( * int_key) ,
644- } ) ,
645- true ,
646- self . tx_id ,
647- ) ;
648- tracing:: trace!( "found {rowid:?}" ) ;
649- let exists = if let Some ( rowid) = rowid {
650- let RowKey :: Int ( rowid) = rowid. row_id else {
651- panic ! ( "Rowid is not an integer in mvcc table cursor" ) ;
642+ if self . state . borrow ( ) . is_none ( ) {
643+ self . invalidate_record ( ) ;
644+ let int_key = match key {
645+ Value :: Integer ( i) => i,
646+ _ => unreachable ! ( "btree tables are indexed by integers!" ) ,
652647 } ;
653- rowid == * int_key
654- } else {
655- false
656- } ;
657- if exists {
658- self . current_pos . replace ( CursorPosition :: Loaded {
659- row_id : RowID {
648+ let rowid = self . db . seek_rowid (
649+ Bound :: Included ( & RowID {
660650 table_id : self . table_id ,
661651 row_id : RowKey :: Int ( * int_key) ,
662- } ,
663- in_btree : false ,
664- btree_consumed : false ,
665- } ) ;
652+ } ) ,
653+ true ,
654+ self . tx_id ,
655+ ) ;
656+ tracing:: trace!( "found {rowid:?}" ) ;
657+ let exists = if let Some ( rowid) = rowid {
658+ let RowKey :: Int ( rowid) = rowid. row_id else {
659+ panic ! ( "Rowid is not an integer in mvcc table cursor" ) ;
660+ } ;
661+ rowid == * int_key
662+ } else {
663+ false
664+ } ;
665+ if exists {
666+ self . current_pos . replace ( CursorPosition :: Loaded {
667+ row_id : RowID {
668+ table_id : self . table_id ,
669+ row_id : RowKey :: Int ( * int_key) ,
670+ } ,
671+ in_btree : false ,
672+ btree_consumed : false ,
673+ } ) ;
674+ return Ok ( IOResult :: Done ( exists) ) ;
675+ } else if self . is_btree_allocated ( ) {
676+ self . state
677+ . replace ( Some ( MvccLazyCursorState :: Exists ( ExistsState :: ExistsBtree ) ) ) ;
678+ } else {
679+ return Ok ( IOResult :: Done ( false ) ) ;
680+ }
666681 }
667- Ok ( IOResult :: Done ( exists) )
682+
683+ let Some ( MvccLazyCursorState :: Exists ( ExistsState :: ExistsBtree ) ) =
684+ self . state . borrow ( ) . clone ( )
685+ else {
686+ panic ! ( "Invalid state {:?}" , self . state. borrow( ) ) ;
687+ } ;
688+ assert ! (
689+ self . is_btree_allocated( ) ,
690+ "BTree should be allocated when we are in ExistsBtree state"
691+ ) ;
692+ self . state . replace ( None ) ;
693+ let found = return_if_io ! ( self . btree_cursor. exists( key) ) ;
694+ Ok ( IOResult :: Done ( found) )
668695 }
669696
670697 fn clear_btree ( & mut self ) -> Result < IOResult < Option < usize > > > {
0 commit comments