|
|
|
@ -756,39 +756,19 @@ impl StoredRA {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn prefix_join<'a>(
|
|
|
|
|
fn point_lookup_join<'a>(
|
|
|
|
|
&'a self,
|
|
|
|
|
tx: &'a SessionTx<'_>,
|
|
|
|
|
left_iter: TupleIter<'a>,
|
|
|
|
|
(left_join_indices, right_join_indices): (Vec<usize>, Vec<usize>),
|
|
|
|
|
key_len: usize,
|
|
|
|
|
left_to_prefix_indices: Vec<usize>,
|
|
|
|
|
eliminate_indices: BTreeSet<usize>,
|
|
|
|
|
left_tuple_len: usize,
|
|
|
|
|
) -> Result<TupleIter<'a>> {
|
|
|
|
|
let mut right_invert_indices = right_join_indices.iter().enumerate().collect_vec();
|
|
|
|
|
right_invert_indices.sort_by_key(|(_, b)| **b);
|
|
|
|
|
let left_to_prefix_indices = right_invert_indices
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|(a, _)| left_join_indices[a])
|
|
|
|
|
.collect_vec();
|
|
|
|
|
|
|
|
|
|
let key_len = self.storage.metadata.keys.len();
|
|
|
|
|
if left_to_prefix_indices.len() >= key_len {
|
|
|
|
|
let val_len = self.storage.metadata.non_keys.len();
|
|
|
|
|
let all_right_val_indices: BTreeSet<usize> =
|
|
|
|
|
(0..val_len).map(|i| left_tuple_len + key_len + i).collect();
|
|
|
|
|
let mut need_to_filter_values = false;
|
|
|
|
|
for f in self.filters.iter() {
|
|
|
|
|
let bind_indices = f.binding_indices();
|
|
|
|
|
if !all_right_val_indices.is_disjoint(&bind_indices) {
|
|
|
|
|
need_to_filter_values = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// We can use point lookups, finally
|
|
|
|
|
// TODO can use this branch if no values are touched!
|
|
|
|
|
return if !need_to_filter_values
|
|
|
|
|
&& eliminate_indices.is_superset(&all_right_val_indices)
|
|
|
|
|
{
|
|
|
|
|
return if self.filters.is_empty() && eliminate_indices.is_superset(&all_right_val_indices) {
|
|
|
|
|
let it = left_iter
|
|
|
|
|
.map_ok(move |tuple| -> Result<Option<Tuple>> {
|
|
|
|
|
let prefix = left_to_prefix_indices
|
|
|
|
@ -851,7 +831,35 @@ impl StoredRA {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn prefix_join<'a>(
|
|
|
|
|
&'a self,
|
|
|
|
|
tx: &'a SessionTx<'_>,
|
|
|
|
|
left_iter: TupleIter<'a>,
|
|
|
|
|
(left_join_indices, right_join_indices): (Vec<usize>, Vec<usize>),
|
|
|
|
|
eliminate_indices: BTreeSet<usize>,
|
|
|
|
|
left_tuple_len: usize,
|
|
|
|
|
) -> Result<TupleIter<'a>> {
|
|
|
|
|
let mut right_invert_indices = right_join_indices.iter().enumerate().collect_vec();
|
|
|
|
|
right_invert_indices.sort_by_key(|(_, b)| **b);
|
|
|
|
|
let left_to_prefix_indices = right_invert_indices
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|(a, _)| left_join_indices[a])
|
|
|
|
|
.collect_vec();
|
|
|
|
|
|
|
|
|
|
let key_len = self.storage.metadata.keys.len();
|
|
|
|
|
if left_to_prefix_indices.len() >= key_len {
|
|
|
|
|
return self.point_lookup_join(
|
|
|
|
|
tx,
|
|
|
|
|
left_iter,
|
|
|
|
|
key_len,
|
|
|
|
|
left_to_prefix_indices,
|
|
|
|
|
eliminate_indices,
|
|
|
|
|
left_tuple_len,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut skip_range_check = false;
|
|
|
|
|
// In some cases, maybe we can stop as soon as we get one result?
|
|
|
|
|
let it = left_iter
|
|
|
|
|
.map_ok(move |tuple| {
|
|
|
|
|
let prefix = left_to_prefix_indices
|
|
|
|
|