use std::cell::RefCell;
use std::cmp::Ordering;
use vortex_error::VortexResult;
use crate::ArrayRef;
use crate::ExecutionCtx;
use crate::RepeatedArrayProbe;
use crate::scalar::Scalar;
use crate::search_sorted::IndexOrd;
pub struct SearchSortedArray<'a> {
probe: RefCell<RepeatedArrayProbe>,
len: usize,
ctx: RefCell<&'a mut ExecutionCtx>,
}
impl<'a> SearchSortedArray<'a> {
pub fn new(array: &ArrayRef, ctx: &'a mut ExecutionCtx) -> Self {
Self {
probe: RefCell::new(array.repeated_probe()),
len: array.len(),
ctx: RefCell::new(ctx),
}
}
}
impl IndexOrd<Scalar> for SearchSortedArray<'_> {
fn index_cmp(&self, idx: usize, elem: &Scalar) -> VortexResult<Option<Ordering>> {
let scalar = self
.probe
.borrow_mut()
.execute_scalar(idx, &mut self.ctx.borrow_mut())?;
Ok(scalar.partial_cmp(elem))
}
fn index_len(&self) -> usize {
self.len
}
}
#[cfg(test)]
mod tests {
use vortex_buffer::buffer;
use vortex_error::VortexResult;
use crate::IntoArray;
use crate::array_session;
use crate::arrays::PrimitiveArray;
use crate::executor::VortexSessionExecute;
use crate::scalar::Scalar;
use crate::search_sorted::SearchResult;
use crate::search_sorted::SearchSorted;
use crate::search_sorted::SearchSortedArray;
use crate::search_sorted::SearchSortedSide;
use crate::validity::Validity;
#[test]
fn search_sorted_scalar() -> VortexResult<()> {
let array =
PrimitiveArray::new(buffer![1i32, 2, 3, 3, 4], Validity::NonNullable).into_array();
let mut ctx = array_session().create_execution_ctx();
let searcher = SearchSortedArray::new(&array, &mut ctx);
assert_eq!(
searcher.search_sorted(&Scalar::from(3i32), SearchSortedSide::Left)?,
SearchResult::Found(2)
);
assert_eq!(
searcher.search_sorted(&Scalar::from(3i32), SearchSortedSide::Right)?,
SearchResult::Found(4)
);
assert_eq!(
searcher.search_sorted(&Scalar::from(5i32), SearchSortedSide::Left)?,
SearchResult::NotFound(5)
);
Ok(())
}
#[test]
fn search_sorted_scalar_with_nulls() -> VortexResult<()> {
let array =
PrimitiveArray::from_option_iter([None, None, Some(2i32), Some(3)]).into_array();
let mut ctx = array_session().create_execution_ctx();
let searcher = SearchSortedArray::new(&array, &mut ctx);
assert_eq!(
searcher.search_sorted(&Scalar::from(Some(2i32)), SearchSortedSide::Left)?,
SearchResult::Found(2)
);
Ok(())
}
}