@@ -4,7 +4,7 @@ use super::{
4
4
sequence:: { Sequence , SequencesState } ,
5
5
state_view:: { IndexSeekIterMutTxId , Iter , IterByColRange , ScanIterByColRange , StateView } ,
6
6
tx:: TxId ,
7
- tx_state:: { IndexIdMap , TxState } ,
7
+ tx_state:: { DeleteTable , IndexIdMap , TxState } ,
8
8
SharedMutexGuard , SharedWriteGuard ,
9
9
} ;
10
10
use crate :: db:: datastore:: {
@@ -41,7 +41,7 @@ use spacetimedb_schema::{
41
41
use spacetimedb_table:: {
42
42
blob_store:: { BlobStore , HashMapBlobStore } ,
43
43
indexes:: { RowPointer , SquashedOffset } ,
44
- table:: { InsertError , RowRef , Table } ,
44
+ table:: { IndexScanIter , InsertError , RowRef , Table } ,
45
45
} ;
46
46
use std:: {
47
47
sync:: Arc ,
@@ -519,7 +519,7 @@ impl MutTxId {
519
519
prefix_elems : ColId ,
520
520
rstart : & [ u8 ] ,
521
521
rend : & [ u8 ] ,
522
- ) -> Result < ( TableId , impl Iterator < Item = RowRef < ' a > > ) > {
522
+ ) -> Result < ( TableId , BTreeScan < ' a > ) > {
523
523
// Extract the table and index type for the tx state.
524
524
let ( table_id, col_list, tx_idx_key_type) = self
525
525
. get_table_and_index_type ( index_id)
@@ -538,51 +538,23 @@ impl MutTxId {
538
538
539
539
// Chain together the indexed rows in the tx and committed state,
540
540
// 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 } ) ,
576
546
} ) ;
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.
577
549
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) ) ,
584
556
} ;
585
- Ok ( ( table_id, iter) )
557
+ Ok ( ( table_id, BTreeScan { inner : iter } ) )
586
558
}
587
559
588
560
/// Translate `index_id` to the table id, the column list and index key type.
@@ -1101,6 +1073,47 @@ impl<'a> RowRefInsertion<'a> {
1101
1073
}
1102
1074
}
1103
1075
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
+
1104
1117
impl MutTxId {
1105
1118
/// Insert a row into a table.
1106
1119
///
0 commit comments