@@ -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 > {
@@ -648,39 +655,59 @@ impl<Clock: LogicalClock + 'static> CursorTrait for MvccLazyCursor<Clock> {
648655 }
649656
650657 fn exists ( & mut self , key : & Value ) -> Result < IOResult < bool > > {
651- self . invalidate_record ( ) ;
652- let int_key = match key {
653- Value :: Integer ( i) => i,
654- _ => unreachable ! ( "btree tables are indexed by integers!" ) ,
655- } ;
656- let rowid = self . db . seek_rowid (
657- Bound :: Included ( & RowID {
658- table_id : self . table_id ,
659- row_id : RowKey :: Int ( * int_key) ,
660- } ) ,
661- true ,
662- self . tx_id ,
663- ) ;
664- tracing:: trace!( "found {rowid:?}" ) ;
665- let exists = if let Some ( rowid) = rowid {
666- let RowKey :: Int ( rowid) = rowid. row_id else {
667- panic ! ( "Rowid is not an integer in mvcc table cursor" ) ;
658+ if self . state . borrow ( ) . is_none ( ) {
659+ self . invalidate_record ( ) ;
660+ let int_key = match key {
661+ Value :: Integer ( i) => i,
662+ _ => unreachable ! ( "btree tables are indexed by integers!" ) ,
668663 } ;
669- rowid == * int_key
670- } else {
671- false
672- } ;
673- if exists {
674- self . current_pos . replace ( CursorPosition :: Loaded {
675- row_id : RowID {
664+ let rowid = self . db . seek_rowid (
665+ Bound :: Included ( & RowID {
676666 table_id : self . table_id ,
677667 row_id : RowKey :: Int ( * int_key) ,
678- } ,
679- in_btree : false ,
680- btree_consumed : false ,
681- } ) ;
668+ } ) ,
669+ true ,
670+ self . tx_id ,
671+ ) ;
672+ tracing:: trace!( "found {rowid:?}" ) ;
673+ let exists = if let Some ( rowid) = rowid {
674+ let RowKey :: Int ( rowid) = rowid. row_id else {
675+ panic ! ( "Rowid is not an integer in mvcc table cursor" ) ;
676+ } ;
677+ rowid == * int_key
678+ } else {
679+ false
680+ } ;
681+ if exists {
682+ self . current_pos . replace ( CursorPosition :: Loaded {
683+ row_id : RowID {
684+ table_id : self . table_id ,
685+ row_id : RowKey :: Int ( * int_key) ,
686+ } ,
687+ in_btree : false ,
688+ btree_consumed : false ,
689+ } ) ;
690+ return Ok ( IOResult :: Done ( exists) ) ;
691+ } else if self . is_btree_allocated ( ) {
692+ self . state
693+ . replace ( Some ( MvccLazyCursorState :: Exists ( ExistsState :: ExistsBtree ) ) ) ;
694+ } else {
695+ return Ok ( IOResult :: Done ( false ) ) ;
696+ }
682697 }
683- Ok ( IOResult :: Done ( exists) )
698+
699+ let Some ( MvccLazyCursorState :: Exists ( ExistsState :: ExistsBtree ) ) =
700+ self . state . borrow ( ) . clone ( )
701+ else {
702+ panic ! ( "Invalid state {:?}" , self . state. borrow( ) ) ;
703+ } ;
704+ assert ! (
705+ self . is_btree_allocated( ) ,
706+ "BTree should be allocated when we are in ExistsBtree state"
707+ ) ;
708+ self . state . replace ( None ) ;
709+ let found = return_if_io ! ( self . btree_cursor. exists( key) ) ;
710+ Ok ( IOResult :: Done ( found) )
684711 }
685712
686713 fn clear_btree ( & mut self ) -> Result < IOResult < Option < usize > > > {
0 commit comments