Skip to content

Commit 672f9ab

Browse files
authored
Name the iterator type returned from btree_scan (#1749)
1 parent 311054d commit 672f9ab

File tree

1 file changed

+58
-45
lines changed
  • crates/core/src/db/datastore/locking_tx_datastore

1 file changed

+58
-45
lines changed

crates/core/src/db/datastore/locking_tx_datastore/mut_tx.rs

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -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
};
1010
use crate::db::datastore::{
@@ -41,7 +41,7 @@ use spacetimedb_schema::{
4141
use spacetimedb_table::{
4242
blob_store::{BlobStore, HashMapBlobStore},
4343
indexes::{RowPointer, SquashedOffset},
44-
table::{InsertError, RowRef, Table},
44+
table::{IndexScanIter, InsertError, RowRef, Table},
4545
};
4646
use 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+
11041117
impl MutTxId {
11051118
/// Insert a row into a table.
11061119
///

0 commit comments

Comments
 (0)