use arrow_array::Array as ArrowArray;
use arrow_array::ArrayRef as ArrowArrayRef;
use arrow_array::Datum as ArrowDatum;
use arrow_schema::DataType;
use arrow_schema::Field;
use vortex_array::ArrayRef;
use vortex_array::ExecutionCtx;
use vortex_array::IntoArray;
use vortex_array::arrays::Constant;
use vortex_array::arrays::ConstantArray;
use vortex_error::VortexResult;
use vortex_error::vortex_panic;
use crate::ArrowSessionExt;
#[derive(Debug)]
pub struct Datum {
array: ArrowArrayRef,
is_scalar: bool,
}
impl Datum {
pub fn try_new(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
let session = ctx.session().clone();
if array.is::<Constant>() {
Ok(Self {
array: session
.arrow()
.execute_arrow(array.slice(0..1)?, None, ctx)?,
is_scalar: true,
})
} else {
Ok(Self {
array: session.arrow().execute_arrow(array.clone(), None, ctx)?,
is_scalar: false,
})
}
}
pub fn try_new_array(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult<Self> {
let session = ctx.session().clone();
Ok(Self {
array: session.arrow().execute_arrow(array.clone(), None, ctx)?,
is_scalar: false,
})
}
pub fn try_new_with_target_datatype(
array: &ArrayRef,
target_datatype: &DataType,
ctx: &mut ExecutionCtx,
) -> VortexResult<Self> {
let session = ctx.session().clone();
let target_field = Field::new(
String::new(),
target_datatype.clone(),
array.dtype().is_nullable(),
);
if array.is::<Constant>() {
Ok(Self {
array: session.arrow().execute_arrow(
array.slice(0..1)?,
Some(&target_field),
ctx,
)?,
is_scalar: true,
})
} else {
Ok(Self {
array: session
.arrow()
.execute_arrow(array.clone(), Some(&target_field), ctx)?,
is_scalar: false,
})
}
}
pub fn data_type(&self) -> &DataType {
self.array.data_type()
}
}
impl ArrowDatum for Datum {
fn get(&self) -> (&dyn ArrowArray, bool) {
(&self.array, self.is_scalar)
}
}
pub fn from_arrow_columnar(
array: ArrowArrayRef,
len: usize,
nullable: bool,
ctx: &mut ExecutionCtx,
) -> VortexResult<ArrayRef> {
let session = ctx.session().clone();
let array = session.arrow().from_arrow_array(array, nullable)?;
if array.len() == len {
return Ok(array);
}
if array.len() != 1 {
vortex_panic!(
"Array length mismatch, expected {} got {} for encoding {}",
len,
array.len(),
array.encoding_id()
);
}
Ok(ConstantArray::new(array.execute_scalar(0, ctx)?, len).into_array())
}