1313// limitations under the License.
1414
1515use crate :: errors:: DatabaseError ;
16- use crate :: storage:: table_codec:: { Bytes , TableCodec } ;
16+ use crate :: storage:: table_codec:: TableCodec ;
1717use crate :: storage:: {
1818 CheckpointableStorage , InnerIter , Storage , Transaction , TransactionIsolationLevel ,
1919} ;
@@ -665,6 +665,7 @@ macro_rules! impl_transaction {
665665 read_opts. set_prefix_same_as_start( true ) ;
666666 }
667667 }
668+ set_iterate_upper_bound( & mut read_opts, max) ;
668669
669670 let mut iter = self . tx. raw_iterator_opt( read_opts) ;
670671 match & min {
@@ -679,7 +680,6 @@ macro_rules! impl_transaction {
679680 }
680681
681682 Ok ( $iter {
682- upper: owned_bound( max) ,
683683 iter,
684684 advanced: false ,
685685 done: false ,
@@ -698,7 +698,6 @@ impl_transaction!(RocksTransaction, RocksIter);
698698impl_transaction ! ( OptimisticRocksTransaction , OptimisticRocksIter ) ;
699699
700700pub struct OptimisticRocksIter < ' txn , ' iter > {
701- upper : Bound < Bytes > ,
702701 iter : DBRawIteratorWithThreadMode < ' iter , rocksdb:: Transaction < ' txn , OptimisticTransactionDB > > ,
703702 advanced : bool ,
704703 done : bool ,
@@ -707,17 +706,11 @@ pub struct OptimisticRocksIter<'txn, 'iter> {
707706impl InnerIter for OptimisticRocksIter < ' _ , ' _ > {
708707 #[ inline]
709708 fn try_next ( & mut self ) -> Result < Option < crate :: storage:: KeyValueRef < ' _ > > , DatabaseError > {
710- next (
711- & mut self . iter ,
712- & self . upper ,
713- & mut self . advanced ,
714- & mut self . done ,
715- )
709+ next ( & mut self . iter , & mut self . advanced , & mut self . done )
716710 }
717711}
718712
719713pub struct RocksIter < ' txn , ' iter > {
720- upper : Bound < Bytes > ,
721714 iter : DBRawIteratorWithThreadMode <
722715 ' iter ,
723716 rocksdb:: Transaction < ' txn , TransactionDB < rocksdb:: MultiThreaded > > ,
@@ -729,19 +722,27 @@ pub struct RocksIter<'txn, 'iter> {
729722impl InnerIter for RocksIter < ' _ , ' _ > {
730723 #[ inline]
731724 fn try_next ( & mut self ) -> Result < Option < crate :: storage:: KeyValueRef < ' _ > > , DatabaseError > {
732- next (
733- & mut self . iter ,
734- & self . upper ,
735- & mut self . advanced ,
736- & mut self . done ,
737- )
725+ next ( & mut self . iter , & mut self . advanced , & mut self . done )
726+ }
727+ }
728+
729+ #[ inline]
730+ fn set_iterate_upper_bound ( read_opts : & mut ReadOptions , upper : Bound < & [ u8 ] > ) {
731+ match upper {
732+ Bound :: Included ( bytes) => {
733+ let mut exclusive_upper = Vec :: with_capacity ( bytes. len ( ) + 1 ) ;
734+ exclusive_upper. extend_from_slice ( bytes) ;
735+ exclusive_upper. push ( 0 ) ;
736+ read_opts. set_iterate_upper_bound ( exclusive_upper) ;
737+ }
738+ Bound :: Excluded ( bytes) => read_opts. set_iterate_upper_bound ( bytes) ,
739+ Bound :: Unbounded => { }
738740 }
739741}
740742
741743#[ inline]
742744fn next < ' a , D : rocksdb:: DBAccess > (
743745 iter : & ' a mut DBRawIteratorWithThreadMode < ' _ , D > ,
744- upper : & Bound < Bytes > ,
745746 advanced : & mut bool ,
746747 done : & mut bool ,
747748) -> Result < Option < crate :: storage:: KeyValueRef < ' a > > , DatabaseError > {
@@ -762,28 +763,11 @@ fn next<'a, D: rocksdb::DBAccess>(
762763 iter. status ( ) ?;
763764 return Ok ( None ) ;
764765 } ;
765- let upper_bound_check = match upper {
766- Bound :: Included ( upper) => key <= upper. as_slice ( ) ,
767- Bound :: Excluded ( upper) => key < upper. as_slice ( ) ,
768- Bound :: Unbounded => true ,
769- } ;
770- if !upper_bound_check {
771- * done = true ;
772- return Ok ( None ) ;
773- }
774766
775767 * advanced = true ;
776768 Ok ( Some ( ( key, value) ) )
777769}
778770
779- fn owned_bound ( bound : Bound < & [ u8 ] > ) -> Bound < Bytes > {
780- match bound {
781- Bound :: Included ( bytes) => Bound :: Included ( bytes. to_vec ( ) ) ,
782- Bound :: Excluded ( bytes) => Bound :: Excluded ( bytes. to_vec ( ) ) ,
783- Bound :: Unbounded => Bound :: Unbounded ,
784- }
785- }
786-
787771#[ cfg( all( test, not( target_arch = "wasm32" ) ) ) ]
788772mod test {
789773 use crate :: catalog:: { ColumnCatalog , ColumnDesc , ColumnRef , TableName } ;
@@ -792,8 +776,8 @@ mod test {
792776 use crate :: expression:: range_detacher:: Range ;
793777 use crate :: storage:: rocksdb:: RocksStorage ;
794778 use crate :: storage:: {
795- IndexImplEnum , IndexImplParams , IndexIter , IndexIterState , IterBounds , PrimaryKeyIndexImpl ,
796- Storage , Transaction ,
779+ IndexImplEnum , IndexImplParams , IndexIter , IndexIterState , InnerIter , IterBounds ,
780+ PrimaryKeyIndexImpl , Storage , Transaction ,
797781 } ;
798782 use crate :: types:: index:: { IndexMeta , IndexType } ;
799783 use crate :: types:: tuple:: Tuple ;
@@ -837,6 +821,34 @@ mod test {
837821 Ok ( ( ) )
838822 }
839823
824+ #[ test]
825+ fn test_rocksdb_range_uses_iterate_upper_bound ( ) -> Result < ( ) , DatabaseError > {
826+ let temp_dir = TempDir :: new ( ) . expect ( "unable to create temporary working directory" ) ;
827+ let storage = RocksStorage :: new ( temp_dir. path ( ) ) ?;
828+ let mut transaction = storage. transaction ( ) ?;
829+
830+ transaction. set ( b"a" , b"1" ) ?;
831+ transaction. set ( b"b" , b"2" ) ?;
832+ transaction. set ( b"b\0 " , b"3" ) ?;
833+ transaction. set ( b"c" , b"4" ) ?;
834+
835+ let mut inclusive_iter = transaction. range ( Bound :: Included ( b"a" ) , Bound :: Included ( b"b" ) ) ?;
836+ let mut inclusive_keys = Vec :: new ( ) ;
837+ while let Some ( ( key, _) ) = inclusive_iter. try_next ( ) ? {
838+ inclusive_keys. push ( key. to_vec ( ) ) ;
839+ }
840+ assert_eq ! ( inclusive_keys, vec![ b"a" . to_vec( ) , b"b" . to_vec( ) ] ) ;
841+
842+ let mut exclusive_iter = transaction. range ( Bound :: Included ( b"a" ) , Bound :: Excluded ( b"b" ) ) ?;
843+ let mut exclusive_keys = Vec :: new ( ) ;
844+ while let Some ( ( key, _) ) = exclusive_iter. try_next ( ) ? {
845+ exclusive_keys. push ( key. to_vec ( ) ) ;
846+ }
847+ assert_eq ! ( exclusive_keys, vec![ b"a" . to_vec( ) ] ) ;
848+
849+ Ok ( ( ) )
850+ }
851+
840852 #[ test]
841853 fn test_in_rocksdb_storage_works_with_data ( ) -> Result < ( ) , DatabaseError > {
842854 let temp_dir = TempDir :: new ( ) . expect ( "unable to create temporary working directory" ) ;
0 commit comments