Skip to content

Commit 0abbd0c

Browse files
committed
fix
Signed-off-by: Mikhail Kot <mikhail@spiraldb.com>
1 parent c6c62f8 commit 0abbd0c

3 files changed

Lines changed: 53 additions & 4 deletions

File tree

benchmarks/lance-bench/src/random_access.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub async fn nested_structs_lance() -> anyhow::Result<PathBuf> {
8282
pub struct LanceRandomAccessor {
8383
name: String,
8484
dataset: Dataset,
85+
projection: ProjectionRequest,
8586
}
8687

8788
impl LanceRandomAccessor {
@@ -92,9 +93,11 @@ impl LanceRandomAccessor {
9293
.ok_or_else(|| anyhow!("Invalid dataset path"))?,
9394
)
9495
.await?;
96+
let projection = ProjectionRequest::from_schema(dataset.schema().clone());
9597
Ok(Self {
9698
name: name.into(),
9799
dataset,
100+
projection,
98101
})
99102
}
100103
}
@@ -110,8 +113,7 @@ impl RandomAccessor for LanceRandomAccessor {
110113
}
111114

112115
async fn take(&self, indices: &[u64]) -> anyhow::Result<usize> {
113-
let projection = ProjectionRequest::from_schema(self.dataset.schema().clone());
114-
let result = self.dataset.take(indices, projection).await?;
116+
let result = self.dataset.take(indices, self.projection.clone()).await?;
115117
Ok(result.num_rows())
116118
}
117119
}

vortex-layout/src/scan/repeated_scan.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ use vortex_array::iter::ArrayIterator;
1717
use vortex_array::iter::ArrayIteratorAdapter;
1818
use vortex_array::stream::ArrayStream;
1919
use vortex_array::stream::ArrayStreamAdapter;
20+
use vortex_error::VortexExpect;
2021
use vortex_error::VortexResult;
2122
use vortex_io::runtime::BlockingRuntime;
2223
use vortex_io::session::RuntimeSessionExt;
2324
use vortex_scan::selection::Selection;
25+
use vortex_scan::selection::selection_roaring_intersects;
2426
use vortex_session::VortexSession;
2527
use vortex_utils::parallelism::get_available_parallelism;
2628

@@ -130,7 +132,17 @@ impl<A: 'static + Send> RepeatedScan<A> {
130132
mapper: Arc::clone(&self.map_fn),
131133
});
132134

135+
let selection_range: Option<Range<u64>> = match &self.selection {
136+
Selection::IncludeByIndex(buf) if !buf.is_empty() => {
137+
Some(buf[0]..buf[buf.len() - 1] + 1)
138+
}
139+
Selection::IncludeRoaring(roaring) if !roaring.is_empty() => {
140+
Some(roaring.min().vortex_expect("empty")..roaring.max().vortex_expect("empty") + 1)
141+
}
142+
_ => None,
143+
};
133144
let row_range = intersect_ranges(self.row_range.as_ref(), row_range);
145+
let row_range = intersect_ranges(row_range.as_ref(), selection_range);
134146

135147
let ranges = match &self.splits {
136148
Splits::Natural(btree_set) => {
@@ -167,17 +179,33 @@ impl<A: 'static + Send> RepeatedScan<A> {
167179

168180
let mut limit = self.limit;
169181
let mut tasks = Vec::new();
182+
let mut cursor = 0usize;
170183

171184
for range in ranges {
172185
if range.start >= range.end {
173186
continue;
174187
}
175188

176-
if limit.is_some_and(|l| l == 0) {
177-
break;
189+
let selection_intersects = match &self.selection {
190+
Selection::IncludeByIndex(buf) => {
191+
// "ranges" and "buf" are sorted so we can use two pointers
192+
// to intersect.
193+
while cursor < buf.len() && buf[cursor] < range.start {
194+
cursor += 1;
195+
}
196+
cursor < buf.len() && buf[cursor] < range.end
197+
}
198+
Selection::IncludeRoaring(roaring) => selection_roaring_intersects(roaring, &range),
199+
_ => true,
200+
};
201+
if !selection_intersects {
202+
continue;
178203
}
179204

180205
tasks.push(split_exec(Arc::clone(&ctx), range, limit.as_mut())?);
206+
if limit.is_some_and(|l| l == 0) {
207+
break;
208+
}
181209
}
182210

183211
Ok(tasks)

vortex-scan/src/selection.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,25 @@ impl Selection {
152152
}
153153
}
154154

155+
#[cfg(not(target_arch = "wasm32"))]
156+
/// true if "roaring" contains an element that's in "range"
157+
pub fn selection_roaring_intersects(roaring: &roaring::RoaringTreemap, range: &Range<u64>) -> bool {
158+
roaring.range_cardinality(range.clone()) > 0
159+
}
160+
161+
// vortex-web's wasm has roaring 0.11.3 which doesn't have range_cardinality
162+
#[cfg(target_arch = "wasm32")]
163+
/// true if "roaring" contains an element that's in "range"
164+
pub fn selection_roaring_intersects(roaring: &roaring::RoaringTreemap, range: &Range<u64>) -> bool {
165+
let before_end = roaring.rank(range.end - 1);
166+
let before_start = if range.start > 0 {
167+
roaring.rank(range.start - 1)
168+
} else {
169+
0
170+
};
171+
before_end > before_start
172+
}
173+
155174
/// Find the positional range within row_indices that covers all rows in the given range.
156175
fn indices_range(range: &Range<u64>, row_indices: &[u64]) -> Option<Range<usize>> {
157176
if row_indices.first().is_some_and(|&first| first >= range.end)

0 commit comments

Comments
 (0)