Skip to content

Commit 1ad1680

Browse files
committed
refactor(ftindex): preserve full-text engine error sources
Map FtIndexError and the roaring row-id filter serialization error into UnexpectedError { source: Some(Box::new(e)) } instead of discarding the underlying error, matching the vindex/lumina convention so the engine error chain survives. Add a regression test asserting an empty or disjoint include-set admits no rows (not all rows), locking in the search_with_include filter semantics.
1 parent 217b73d commit 1ad1680

1 file changed

Lines changed: 36 additions & 2 deletions

File tree

crates/paimon/src/ftindex/reader.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl<R: SeekRead + 'static> FullTextArchiveReader<R> {
8282
.serialize_into(&mut filter_bytes)
8383
.map_err(|e| crate::Error::UnexpectedError {
8484
message: format!("failed to serialize row-id filter: {e}"),
85-
source: None,
85+
source: Some(Box::new(e)),
8686
})?;
8787
self.inner
8888
.search_with_roaring_filter(query_json, limit, &filter_bytes)
@@ -107,7 +107,7 @@ impl FullTextArchiveReader<SliceReader> {
107107
fn map_ft_err(e: paimon_ftindex_core::FtIndexError) -> crate::Error {
108108
crate::Error::UnexpectedError {
109109
message: format!("full-text index engine error: {e}"),
110-
source: None,
110+
source: Some(Box::new(e)),
111111
}
112112
}
113113

@@ -181,4 +181,38 @@ mod tests {
181181
ids.sort_unstable();
182182
assert_eq!(ids, vec![0, 2]);
183183
}
184+
185+
#[tokio::test]
186+
async fn test_search_with_include_empty_or_disjoint_returns_no_hits() {
187+
let bytes = build_archive(&[
188+
(0, "shared token here"),
189+
(1, "shared token here"),
190+
(2, "shared token here"),
191+
]);
192+
let input = archive_input(bytes).await;
193+
let reader = FullTextArchiveReader::from_input_file(&input)
194+
.await
195+
.unwrap();
196+
197+
// Empty allow-list: an empty include-set admits no rows (not all rows).
198+
let empty = roaring::RoaringTreemap::new();
199+
let hits = reader
200+
.search_with_include(r#"{"match":{"query":"token"}}"#, 10, empty)
201+
.unwrap();
202+
assert!(
203+
hits.row_ids.is_empty(),
204+
"empty include-set must admit no rows"
205+
);
206+
207+
// Allow-list disjoint from the matches (row 99 never indexed): still nothing.
208+
let mut disjoint = roaring::RoaringTreemap::new();
209+
disjoint.insert(99);
210+
let hits = reader
211+
.search_with_include(r#"{"match":{"query":"token"}}"#, 10, disjoint)
212+
.unwrap();
213+
assert!(
214+
hits.row_ids.is_empty(),
215+
"include-set disjoint from matches must admit no rows"
216+
);
217+
}
184218
}

0 commit comments

Comments
 (0)