@@ -4,7 +4,7 @@ use super::{
44 sequence:: { Sequence , SequencesState } ,
55 state_view:: { IndexSeekIterMutTxId , Iter , IterByColRange , ScanIterByColRange , StateView } ,
66 tx:: TxId ,
7- tx_state:: { IndexIdMap , TxState } ,
7+ tx_state:: { DeleteTable , IndexIdMap , TxState } ,
88 SharedMutexGuard , SharedWriteGuard ,
99} ;
1010use crate :: db:: datastore:: {
@@ -41,7 +41,7 @@ use spacetimedb_schema::{
4141use spacetimedb_table:: {
4242 blob_store:: { BlobStore , HashMapBlobStore } ,
4343 indexes:: { RowPointer , SquashedOffset } ,
44- table:: { InsertError , RowRef , Table } ,
44+ table:: { IndexScanIter , InsertError , RowRef , Table } ,
4545} ;
4646use std:: {
4747 sync:: Arc ,
@@ -519,7 +519,7 @@ impl MutTxId {
519519 prefix_elems : ColId ,
520520 rstart : & [ u8 ] ,
521521 rend : & [ u8 ] ,
522- ) -> Result < ( TableId , impl Iterator < Item = RowRef < ' a > > ) > {
522+ ) -> Result < ( TableId , BTreeScan < ' a > ) > {
523523 // Extract the table and index type for the tx state.
524524 let ( table_id, col_list, tx_idx_key_type) = self
525525 . get_table_and_index_type ( index_id)
@@ -538,51 +538,23 @@ impl MutTxId {
538538
539539 // Chain together the indexed rows in the tx and committed state,
540540 // but don't yield rows deleted in the tx state.
541- use itertools:: Either :: { Left , Right } ;
542- // this is gross, but nested `Either`s don't optimize
543- enum Choice < A , B , C , D , E , F > {
544- A ( A ) ,
545- B ( B ) ,
546- C ( C ) ,
547- D ( D ) ,
548- E ( E ) ,
549- F ( F ) ,
550- }
551- impl <
552- T ,
553- A : Iterator < Item = T > ,
554- B : Iterator < Item = T > ,
555- C : Iterator < Item = T > ,
556- D : Iterator < Item = T > ,
557- E : Iterator < Item = T > ,
558- F : Iterator < Item = T > ,
559- > Iterator for Choice < A , B , C , D , E , F >
560- {
561- type Item = T ;
562- fn next ( & mut self ) -> Option < Self :: Item > {
563- match self {
564- Self :: A ( i) => i. next ( ) ,
565- Self :: B ( i) => i. next ( ) ,
566- Self :: C ( i) => i. next ( ) ,
567- Self :: D ( i) => i. next ( ) ,
568- Self :: E ( i) => i. next ( ) ,
569- Self :: F ( i) => i. next ( ) ,
570- }
571- }
572- }
573- let commit_iter = commit_iter. map ( |commit_iter| match self . tx_state . delete_tables . get ( & table_id) {
574- None => Left ( commit_iter) ,
575- Some ( tx_dels) => Right ( commit_iter. filter ( move |row| !tx_dels. contains ( & row. pointer ( ) ) ) ) ,
541+ use itertools:: Either :: * ;
542+ use BTreeScanInner :: * ;
543+ let commit_iter = commit_iter. map ( |iter| match self . tx_state . delete_tables . get ( & table_id) {
544+ None => Left ( iter) ,
545+ Some ( deletes) => Right ( IndexScanFilterDeleted { iter, deletes } ) ,
576546 } ) ;
547+ // this is effectively just `tx_iter.into_iter().flatten().chain(commit_iter.into_iter().flatten())`,
548+ // but with all the branching and `Option`s flattened to just one layer.
577549 let iter = match ( tx_iter, commit_iter) {
578- ( None , None ) => Choice :: A ( std :: iter:: empty ( ) ) ,
579- ( Some ( tx_iter) , None ) => Choice :: B ( tx_iter) ,
580- ( None , Some ( Left ( commit_iter) ) ) => Choice :: C ( commit_iter) ,
581- ( None , Some ( Right ( commit_iter) ) ) => Choice :: D ( commit_iter) ,
582- ( Some ( tx_iter) , Some ( Left ( commit_iter) ) ) => Choice :: E ( tx_iter. chain ( commit_iter) ) ,
583- ( Some ( tx_iter) , Some ( Right ( commit_iter) ) ) => Choice :: F ( tx_iter. chain ( commit_iter) ) ,
550+ ( None , None ) => Empty ( iter:: empty ( ) ) ,
551+ ( Some ( tx_iter) , None ) => TxOnly ( tx_iter) ,
552+ ( None , Some ( Left ( commit_iter) ) ) => CommitOnly ( commit_iter) ,
553+ ( None , Some ( Right ( commit_iter) ) ) => CommitOnlyWithDeletes ( commit_iter) ,
554+ ( Some ( tx_iter) , Some ( Left ( commit_iter) ) ) => Both ( tx_iter. chain ( commit_iter) ) ,
555+ ( Some ( tx_iter) , Some ( Right ( commit_iter) ) ) => BothWithDeletes ( tx_iter. chain ( commit_iter) ) ,
584556 } ;
585- Ok ( ( table_id, iter) )
557+ Ok ( ( table_id, BTreeScan { inner : iter } ) )
586558 }
587559
588560 /// Translate `index_id` to the table id, the column list and index key type.
@@ -1101,6 +1073,47 @@ impl<'a> RowRefInsertion<'a> {
11011073 }
11021074}
11031075
1076+ /// The iterator returned by [`MutTx::btree_scan`].
1077+ pub struct BTreeScan < ' a > {
1078+ inner : BTreeScanInner < ' a > ,
1079+ }
1080+
1081+ enum BTreeScanInner < ' a > {
1082+ Empty ( iter:: Empty < RowRef < ' a > > ) ,
1083+ TxOnly ( IndexScanIter < ' a > ) ,
1084+ CommitOnly ( IndexScanIter < ' a > ) ,
1085+ CommitOnlyWithDeletes ( IndexScanFilterDeleted < ' a > ) ,
1086+ Both ( iter:: Chain < IndexScanIter < ' a > , IndexScanIter < ' a > > ) ,
1087+ BothWithDeletes ( iter:: Chain < IndexScanIter < ' a > , IndexScanFilterDeleted < ' a > > ) ,
1088+ }
1089+
1090+ struct IndexScanFilterDeleted < ' a > {
1091+ iter : IndexScanIter < ' a > ,
1092+ deletes : & ' a DeleteTable ,
1093+ }
1094+
1095+ impl < ' a > Iterator for BTreeScan < ' a > {
1096+ type Item = RowRef < ' a > ;
1097+
1098+ fn next ( & mut self ) -> Option < Self :: Item > {
1099+ match & mut self . inner {
1100+ BTreeScanInner :: Empty ( it) => it. next ( ) ,
1101+ BTreeScanInner :: TxOnly ( it) => it. next ( ) ,
1102+ BTreeScanInner :: CommitOnly ( it) => it. next ( ) ,
1103+ BTreeScanInner :: CommitOnlyWithDeletes ( it) => it. next ( ) ,
1104+ BTreeScanInner :: Both ( it) => it. next ( ) ,
1105+ BTreeScanInner :: BothWithDeletes ( it) => it. next ( ) ,
1106+ }
1107+ }
1108+ }
1109+
1110+ impl < ' a > Iterator for IndexScanFilterDeleted < ' a > {
1111+ type Item = RowRef < ' a > ;
1112+ fn next ( & mut self ) -> Option < Self :: Item > {
1113+ self . iter . find ( |row| !self . deletes . contains ( & row. pointer ( ) ) )
1114+ }
1115+ }
1116+
11041117impl MutTxId {
11051118 /// Insert a row into a table.
11061119 ///
0 commit comments