@@ -488,7 +488,10 @@ impl MutTxId {
488
488
}
489
489
// Remove the `index_id -> (table_id, col_list)` association.
490
490
idx_map. remove ( & index_id) ;
491
- self . tx_state . index_id_map_removals . push ( index_id) ;
491
+ self . tx_state
492
+ . index_id_map_removals
493
+ . get_or_insert_with ( Default :: default)
494
+ . insert ( index_id) ;
492
495
493
496
log:: trace!( "INDEX DROPPED: {}" , index_id) ;
494
497
Ok ( ( ) )
@@ -530,34 +533,54 @@ impl MutTxId {
530
533
. map_err ( IndexError :: Decode ) ?;
531
534
532
535
// Get an index seek iterator for the tx and committed state.
533
- let tx_iter = self . tx_state . index_seek ( table_id, col_list, & bounds) . unwrap ( ) ;
536
+ let tx_iter = self . tx_state . index_seek ( table_id, col_list, & bounds) ;
534
537
let commit_iter = self . committed_state_write_lock . index_seek ( table_id, col_list, & bounds) ;
535
538
536
539
// Chain together the indexed rows in the tx and committed state,
537
540
// but don't yield rows deleted in the tx state.
538
- enum Choice < A , B , C > {
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 > {
539
544
A ( A ) ,
540
545
B ( B ) ,
541
546
C ( C ) ,
547
+ D ( D ) ,
548
+ E ( E ) ,
549
+ F ( F ) ,
542
550
}
543
- impl < T , A : Iterator < Item = T > , B : Iterator < Item = T > , C : Iterator < Item = T > > Iterator for Choice < A , B , C > {
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
+ {
544
561
type Item = T ;
545
562
fn next ( & mut self ) -> Option < Self :: Item > {
546
563
match self {
547
564
Self :: A ( i) => i. next ( ) ,
548
565
Self :: B ( i) => i. next ( ) ,
549
566
Self :: C ( i) => i. next ( ) ,
567
+ Self :: D ( i) => i. next ( ) ,
568
+ Self :: E ( i) => i. next ( ) ,
569
+ Self :: F ( i) => i. next ( ) ,
550
570
}
551
571
}
552
572
}
553
- let iter = match commit_iter {
554
- None => Choice :: A ( tx_iter) ,
555
- Some ( commit_iter) => match self . tx_state . delete_tables . get ( & table_id) {
556
- None => Choice :: B ( tx_iter. chain ( commit_iter) ) ,
557
- Some ( tx_dels) => {
558
- Choice :: C ( tx_iter. chain ( commit_iter. filter ( move |row| !tx_dels. contains ( & row. pointer ( ) ) ) ) )
559
- }
560
- } ,
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 ( ) ) ) ) ,
576
+ } ) ;
577
+ 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) ) ,
561
584
} ;
562
585
Ok ( ( table_id, iter) )
563
586
}
@@ -567,16 +590,34 @@ impl MutTxId {
567
590
// The order of querying the committed vs. tx state for the translation is not important.
568
591
// But it is vastly more likely that it is in the committed state,
569
592
// so query that first to avoid two lookups.
570
- let ( table_id, col_list) = self
593
+ let & ( table_id, ref col_list) = self
571
594
. committed_state_write_lock
572
595
. index_id_map
573
596
. get ( & index_id)
574
597
. or_else ( || self . tx_state . index_id_map . get ( & index_id) ) ?;
598
+
575
599
// The tx state must have the index.
576
600
// If the index was e.g., dropped from the tx state but exists physically in the committed state,
577
601
// the index does not exist, semantically.
578
- let key_ty = self . tx_state . get_table_and_index_type ( * table_id, col_list) ?;
579
- Some ( ( * table_id, col_list, key_ty) )
602
+ // TODO: handle the case where the table has been dropped in this transaction.
603
+ let key_ty = if let Some ( key_ty) = self
604
+ . committed_state_write_lock
605
+ . get_table_and_index_type ( table_id, col_list)
606
+ {
607
+ if self
608
+ . tx_state
609
+ . index_id_map_removals
610
+ . as_ref ( )
611
+ . is_some_and ( |s| s. contains ( & index_id) )
612
+ {
613
+ return None ;
614
+ }
615
+ key_ty
616
+ } else {
617
+ self . tx_state . get_table_and_index_type ( table_id, col_list) ?
618
+ } ;
619
+
620
+ Some ( ( table_id, col_list, key_ty) )
580
621
}
581
622
582
623
/// Decode the bounds for a btree scan for an index typed at `key_type`.
0 commit comments