diff --git a/vortex-array/public-api.lock b/vortex-array/public-api.lock index 9609ce9d79d..c5184c008cd 100644 --- a/vortex-array/public-api.lock +++ b/vortex-array/public-api.lock @@ -56,6 +56,8 @@ pub type vortex_array::aggregate_fn::combined::Combined::Partial = (alloc::bo pub fn vortex_array::aggregate_fn::combined::Combined::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::combined::Combined::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::combined::Combined::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::combined::Combined::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -174,6 +176,56 @@ pub type vortex_array::aggregate_fn::combined::CombinedOptions = vortex_array pub mod vortex_array::aggregate_fn::fns +pub mod vortex_array::aggregate_fn::fns::all_nan + +pub struct vortex_array::aggregate_fn::fns::all_nan::AllNan + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::all_nan::AllNan + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::clone(&self) -> vortex_array::aggregate_fn::fns::all_nan::AllNan + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::all_nan::AllNan + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_nan::AllNan + +pub type vortex_array::aggregate_fn::fns::all_nan::AllNan::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_nan::AllNan::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + pub mod vortex_array::aggregate_fn::fns::all_non_distinct pub struct vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct @@ -194,6 +246,8 @@ pub type vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::Part pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -226,6 +280,316 @@ pub struct vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinctPart pub fn vortex_array::aggregate_fn::fns::all_non_distinct::all_non_distinct(&vortex_array::ArrayRef, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +pub mod vortex_array::aggregate_fn::fns::all_non_nan + +pub struct vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::clone(&self) -> vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +pub type vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub mod vortex_array::aggregate_fn::fns::all_non_null + +pub struct vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::clone(&self) -> vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +pub type vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub mod vortex_array::aggregate_fn::fns::all_null + +pub struct vortex_array::aggregate_fn::fns::all_null::AllNull + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::all_null::AllNull + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::clone(&self) -> vortex_array::aggregate_fn::fns::all_null::AllNull + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::all_null::AllNull + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_null::AllNull + +pub type vortex_array::aggregate_fn::fns::all_null::AllNull::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_null::AllNull::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub mod vortex_array::aggregate_fn::fns::bounded_max + +pub struct vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::clone(&self) -> vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +pub type vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::Options = vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub type vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::Partial = vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxPartial + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub struct vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::max_bytes: core::num::nonzero::NonZeroUsize + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::clone(&self) -> vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +impl core::cmp::Eq for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +impl core::cmp::PartialEq for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::eq(&self, &vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions) -> bool + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::fmt::Display for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions::hash<__H: core::hash::Hasher>(&self, &mut __H) + +impl core::marker::StructuralPartialEq for vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub struct vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxPartial + +pub mod vortex_array::aggregate_fn::fns::bounded_min + +pub struct vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::clone(&self) -> vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +pub type vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::Options = vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub type vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::Partial = vortex_array::aggregate_fn::fns::bounded_min::BoundedMinPartial + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub struct vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::max_bytes: core::num::nonzero::NonZeroUsize + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::clone(&self) -> vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +impl core::cmp::Eq for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +impl core::cmp::PartialEq for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::eq(&self, &vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions) -> bool + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::fmt::Display for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions::hash<__H: core::hash::Hasher>(&self, &mut __H) + +impl core::marker::StructuralPartialEq for vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub struct vortex_array::aggregate_fn::fns::bounded_min::BoundedMinPartial + pub mod vortex_array::aggregate_fn::fns::count pub struct vortex_array::aggregate_fn::fns::count::Count @@ -246,6 +610,8 @@ pub type vortex_array::aggregate_fn::fns::count::Count::Partial = u64 pub fn vortex_array::aggregate_fn::fns::count::Count::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::count::Count::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::count::Count::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::count::Count::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -294,6 +660,8 @@ pub type vortex_array::aggregate_fn::fns::first::First::Partial = vortex_array:: pub fn vortex_array::aggregate_fn::fns::first::First::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::first::First::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::first::First::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::first::First::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -356,6 +724,8 @@ pub type vortex_array::aggregate_fn::fns::is_constant::IsConstant::Partial = vor pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -414,6 +784,8 @@ pub type vortex_array::aggregate_fn::fns::is_sorted::IsSorted::Partial = vortex_ pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -506,6 +878,8 @@ pub type vortex_array::aggregate_fn::fns::last::Last::Partial = vortex_array::ag pub fn vortex_array::aggregate_fn::fns::last::Last::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::last::Last::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::last::Last::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::last::Last::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -538,6 +912,58 @@ pub struct vortex_array::aggregate_fn::fns::last::LastPartial pub fn vortex_array::aggregate_fn::fns::last::last(&vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +pub mod vortex_array::aggregate_fn::fns::max + +pub struct vortex_array::aggregate_fn::fns::max::Max + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::max::Max + +pub fn vortex_array::aggregate_fn::fns::max::Max::clone(&self) -> vortex_array::aggregate_fn::fns::max::Max + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::max::Max + +pub fn vortex_array::aggregate_fn::fns::max::Max::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::max::Max + +pub type vortex_array::aggregate_fn::fns::max::Max::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::max::Max::Partial = vortex_array::aggregate_fn::fns::max::MaxPartial + +pub fn vortex_array::aggregate_fn::fns::max::Max::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::max::Max::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::max::Max::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::max::Max::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::max::Max::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::max::Max::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::max::Max::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::max::Max::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::max::Max::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::max::Max::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub struct vortex_array::aggregate_fn::fns::max::MaxPartial + pub mod vortex_array::aggregate_fn::fns::mean pub struct vortex_array::aggregate_fn::fns::mean::Mean @@ -586,6 +1012,58 @@ pub fn vortex_array::aggregate_fn::fns::mean::Mean::serialize(&self, &vortex_arr pub fn vortex_array::aggregate_fn::fns::mean::mean(&vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +pub mod vortex_array::aggregate_fn::fns::min + +pub struct vortex_array::aggregate_fn::fns::min::Min + +impl core::clone::Clone for vortex_array::aggregate_fn::fns::min::Min + +pub fn vortex_array::aggregate_fn::fns::min::Min::clone(&self) -> vortex_array::aggregate_fn::fns::min::Min + +impl core::fmt::Debug for vortex_array::aggregate_fn::fns::min::Min + +pub fn vortex_array::aggregate_fn::fns::min::Min::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::min::Min + +pub type vortex_array::aggregate_fn::fns::min::Min::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::min::Min::Partial = vortex_array::aggregate_fn::fns::min::MinPartial + +pub fn vortex_array::aggregate_fn::fns::min::Min::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::min::Min::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::min::Min::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::min::Min::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::min::Min::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::min::Min::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::min::Min::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::min::Min::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::min::Min::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::min::Min::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +pub struct vortex_array::aggregate_fn::fns::min::MinPartial + pub mod vortex_array::aggregate_fn::fns::min_max pub struct vortex_array::aggregate_fn::fns::min_max::MinMax @@ -606,6 +1084,8 @@ pub type vortex_array::aggregate_fn::fns::min_max::MinMax::Partial = vortex_arra pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -686,6 +1166,8 @@ pub type vortex_array::aggregate_fn::fns::nan_count::NanCount::Partial = u64 pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -736,6 +1218,8 @@ pub type vortex_array::aggregate_fn::fns::null_count::NullCount::Partial = u64 pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -800,6 +1284,8 @@ pub type vortex_array::aggregate_fn::fns::sum::Sum::Partial = vortex_array::aggr pub fn vortex_array::aggregate_fn::fns::sum::Sum::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::sum::Sum::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::sum::Sum::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::sum::Sum::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -852,6 +1338,8 @@ pub type vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::Uncompress pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -932,6 +1420,54 @@ pub fn S::aggregate_fns(&self) -> vortex_session::Ref<'_, vortex_array::aggregat pub type vortex_array::aggregate_fn::session::AggregateFnRegistry = vortex_session::registry::Registry +pub enum vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub vortex_array::aggregate_fn::AggregateFnSatisfaction::Approximate + +pub vortex_array::aggregate_fn::AggregateFnSatisfaction::Exact + +pub vortex_array::aggregate_fn::AggregateFnSatisfaction::No + +impl vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::is_exact(self) -> bool + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::is_satisfied(self) -> bool + +impl core::clone::Clone for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::clone(&self) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +impl core::cmp::Eq for vortex_array::aggregate_fn::AggregateFnSatisfaction + +impl core::cmp::Ord for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::cmp(&self, &vortex_array::aggregate_fn::AggregateFnSatisfaction) -> core::cmp::Ordering + +impl core::cmp::PartialEq for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::eq(&self, &vortex_array::aggregate_fn::AggregateFnSatisfaction) -> bool + +impl core::cmp::PartialOrd for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::partial_cmp(&self, &vortex_array::aggregate_fn::AggregateFnSatisfaction) -> core::option::Option + +impl core::default::Default for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::default() -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +impl core::fmt::Debug for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result + +impl core::hash::Hash for vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::AggregateFnSatisfaction::hash<__H: core::hash::Hasher>(&self, &mut __H) + +impl core::marker::Copy for vortex_array::aggregate_fn::AggregateFnSatisfaction + +impl core::marker::StructuralPartialEq for vortex_array::aggregate_fn::AggregateFnSatisfaction + pub struct vortex_array::aggregate_fn::Accumulator impl vortex_array::aggregate_fn::Accumulator @@ -1008,6 +1544,8 @@ pub fn vortex_array::aggregate_fn::AggregateFnRef::as_(&self) -> core::option::Option<&::Options> +pub fn vortex_array::aggregate_fn::AggregateFnRef::can_satisfy(&self, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::AggregateFnRef::coerce_args(&self, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::AggregateFnRef::id(&self) -> vortex_array::aggregate_fn::AggregateFnId @@ -1110,6 +1648,8 @@ pub type vortex_array::aggregate_fn::AggregateFnVTable::Partial: 'static + core: pub fn vortex_array::aggregate_fn::AggregateFnVTable::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::AggregateFnVTable::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::AggregateFnVTable::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::AggregateFnVTable::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1138,6 +1678,44 @@ pub fn vortex_array::aggregate_fn::AggregateFnVTable::to_scalar(&self, &Self::Pa pub fn vortex_array::aggregate_fn::AggregateFnVTable::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_nan::AllNan + +pub type vortex_array::aggregate_fn::fns::all_nan::AllNan::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_nan::AllNan::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_nan::AllNan::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct pub type vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::Options = vortex_array::aggregate_fn::EmptyOptions @@ -1146,6 +1724,8 @@ pub type vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::Part pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1174,6 +1754,196 @@ pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::to_sca pub fn vortex_array::aggregate_fn::fns::all_non_distinct::AllNonDistinct::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan + +pub type vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_nan::AllNonNan::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_non_null::AllNonNull + +pub type vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_non_null::AllNonNull::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::all_null::AllNull + +pub type vortex_array::aggregate_fn::fns::all_null::AllNull::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::all_null::AllNull::Partial = bool + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::all_null::AllNull::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::bounded_max::BoundedMax + +pub type vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::Options = vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxOptions + +pub type vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::Partial = vortex_array::aggregate_fn::fns::bounded_max::BoundedMaxPartial + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_max::BoundedMax::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::bounded_min::BoundedMin + +pub type vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::Options = vortex_array::aggregate_fn::fns::bounded_min::BoundedMinOptions + +pub type vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::Partial = vortex_array::aggregate_fn::fns::bounded_min::BoundedMinPartial + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::bounded_min::BoundedMin::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::count::Count pub type vortex_array::aggregate_fn::fns::count::Count::Options = vortex_array::aggregate_fn::EmptyOptions @@ -1182,6 +1952,8 @@ pub type vortex_array::aggregate_fn::fns::count::Count::Partial = u64 pub fn vortex_array::aggregate_fn::fns::count::Count::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::count::Count::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::count::Count::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::count::Count::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1218,6 +1990,8 @@ pub type vortex_array::aggregate_fn::fns::first::First::Partial = vortex_array:: pub fn vortex_array::aggregate_fn::fns::first::First::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::first::First::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::first::First::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::first::First::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1254,6 +2028,8 @@ pub type vortex_array::aggregate_fn::fns::is_constant::IsConstant::Partial = vor pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::is_constant::IsConstant::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1290,6 +2066,8 @@ pub type vortex_array::aggregate_fn::fns::is_sorted::IsSorted::Partial = vortex_ pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::is_sorted::IsSorted::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1326,6 +2104,8 @@ pub type vortex_array::aggregate_fn::fns::last::Last::Partial = vortex_array::ag pub fn vortex_array::aggregate_fn::fns::last::Last::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::last::Last::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::last::Last::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::last::Last::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1354,6 +2134,82 @@ pub fn vortex_array::aggregate_fn::fns::last::Last::to_scalar(&self, &Self::Part pub fn vortex_array::aggregate_fn::fns::last::Last::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::max::Max + +pub type vortex_array::aggregate_fn::fns::max::Max::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::max::Max::Partial = vortex_array::aggregate_fn::fns::max::MaxPartial + +pub fn vortex_array::aggregate_fn::fns::max::Max::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::max::Max::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::max::Max::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::max::Max::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::max::Max::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::max::Max::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::max::Max::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::max::Max::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::max::Max::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::max::Max::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::max::Max::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + +impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::min::Min + +pub type vortex_array::aggregate_fn::fns::min::Min::Options = vortex_array::aggregate_fn::EmptyOptions + +pub type vortex_array::aggregate_fn::fns::min::Min::Partial = vortex_array::aggregate_fn::fns::min::MinPartial + +pub fn vortex_array::aggregate_fn::fns::min::Min::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::min::Min::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + +pub fn vortex_array::aggregate_fn::fns::min::Min::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> + +pub fn vortex_array::aggregate_fn::fns::min::Min::deserialize(&self, &[u8], &vortex_session::VortexSession) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::empty_partial(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::finalize(&self, vortex_array::ArrayRef) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::finalize_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::id(&self) -> vortex_array::aggregate_fn::AggregateFnId + +pub fn vortex_array::aggregate_fn::fns::min::Min::is_saturated(&self, &Self::Partial) -> bool + +pub fn vortex_array::aggregate_fn::fns::min::Min::partial_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::min::Min::reset(&self, &mut Self::Partial) + +pub fn vortex_array::aggregate_fn::fns::min::Min::return_dtype(&self, &Self::Options, &vortex_array::dtype::DType) -> core::option::Option + +pub fn vortex_array::aggregate_fn::fns::min::Min::serialize(&self, &Self::Options) -> vortex_error::VortexResult>> + +pub fn vortex_array::aggregate_fn::fns::min::Min::to_scalar(&self, &Self::Partial) -> vortex_error::VortexResult + +pub fn vortex_array::aggregate_fn::fns::min::Min::try_accumulate(&self, &mut Self::Partial, &vortex_array::ArrayRef, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult + impl vortex_array::aggregate_fn::AggregateFnVTable for vortex_array::aggregate_fn::fns::min_max::MinMax pub type vortex_array::aggregate_fn::fns::min_max::MinMax::Options = vortex_array::aggregate_fn::EmptyOptions @@ -1362,6 +2218,8 @@ pub type vortex_array::aggregate_fn::fns::min_max::MinMax::Partial = vortex_arra pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::min_max::MinMax::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1398,6 +2256,8 @@ pub type vortex_array::aggregate_fn::fns::nan_count::NanCount::Partial = u64 pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::nan_count::NanCount::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1434,6 +2294,8 @@ pub type vortex_array::aggregate_fn::fns::null_count::NullCount::Partial = u64 pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::null_count::NullCount::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1470,6 +2332,8 @@ pub type vortex_array::aggregate_fn::fns::sum::Sum::Partial = vortex_array::aggr pub fn vortex_array::aggregate_fn::fns::sum::Sum::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::sum::Sum::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::sum::Sum::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::sum::Sum::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1506,6 +2370,8 @@ pub type vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::Uncompress pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -1542,6 +2408,8 @@ pub type vortex_array::aggregate_fn::combined::Combined::Partial = (alloc::bo pub fn vortex_array::aggregate_fn::combined::Combined::accumulate(&self, &mut Self::Partial, &vortex_array::Columnar, &mut vortex_array::ExecutionCtx) -> vortex_error::VortexResult<()> +pub fn vortex_array::aggregate_fn::combined::Combined::can_satisfy(&self, &Self::Options, &vortex_array::aggregate_fn::AggregateFnRef) -> vortex_array::aggregate_fn::AggregateFnSatisfaction + pub fn vortex_array::aggregate_fn::combined::Combined::coerce_args(&self, &Self::Options, &vortex_array::dtype::DType) -> vortex_error::VortexResult pub fn vortex_array::aggregate_fn::combined::Combined::combine_partials(&self, &mut Self::Partial, vortex_array::scalar::Scalar) -> vortex_error::VortexResult<()> @@ -12918,13 +13786,13 @@ pub fn vortex_array::expr::Expression::children(&self) -> &alloc::sync::Arc impl core::fmt::Display -pub fn vortex_array::expr::Expression::falsify(&self, &vortex_session::VortexSession) -> vortex_error::VortexResult> +pub fn vortex_array::expr::Expression::falsify(&self, &vortex_array::dtype::DType, &vortex_session::VortexSession) -> vortex_error::VortexResult> pub fn vortex_array::expr::Expression::fmt_sql(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result pub fn vortex_array::expr::Expression::return_dtype(&self, &vortex_array::dtype::DType) -> vortex_error::VortexResult -pub fn vortex_array::expr::Expression::satisfy(&self, &vortex_session::VortexSession) -> vortex_error::VortexResult> +pub fn vortex_array::expr::Expression::satisfy(&self, &vortex_array::dtype::DType, &vortex_session::VortexSession) -> vortex_error::VortexResult> pub fn vortex_array::expr::Expression::scalar_fn(&self) -> &vortex_array::scalar_fn::ScalarFnRef @@ -20144,6 +21012,14 @@ pub fn vortex_array::scalar_fn::fns::stat::StatOptions::hash<__H: core::hash::Ha impl core::marker::StructuralPartialEq for vortex_array::scalar_fn::fns::stat::StatOptions +pub fn vortex_array::stats::expr::all_nan(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::expr::all_non_nan(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::expr::all_non_null(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::expr::all_null(vortex_array::expr::Expression) -> vortex_array::expr::Expression + pub fn vortex_array::stats::expr::min_max(vortex_array::expr::Expression) -> vortex_array::expr::Expression pub fn vortex_array::stats::expr::nan_count(vortex_array::expr::Expression) -> vortex_array::expr::Expression @@ -20158,21 +21034,21 @@ pub mod vortex_array::stats::flatbuffers pub mod vortex_array::stats::session -pub struct vortex_array::stats::session::StatsRewriteSession +pub struct vortex_array::stats::session::StatsSession -impl core::default::Default for vortex_array::stats::StatsRewriteSession +impl core::default::Default for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::default() -> vortex_array::stats::StatsRewriteSession +pub fn vortex_array::stats::StatsSession::default() -> vortex_array::stats::StatsSession -impl core::fmt::Debug for vortex_array::stats::StatsRewriteSession +impl core::fmt::Debug for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn vortex_array::stats::StatsSession::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result -impl vortex_session::SessionVar for vortex_array::stats::StatsRewriteSession +impl vortex_session::SessionVar for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::as_any(&self) -> &dyn core::any::Any +pub fn vortex_array::stats::StatsSession::as_any(&self) -> &dyn core::any::Any -pub fn vortex_array::stats::StatsRewriteSession::as_any_mut(&mut self) -> &mut dyn core::any::Any +pub fn vortex_array::stats::StatsSession::as_any_mut(&mut self) -> &mut dyn core::any::Any pub struct vortex_array::stats::ArrayStats @@ -20234,21 +21110,21 @@ pub fn vortex_array::stats::MutTypedStatsSetRef<'_, '_>::is_empty(&self) -> bool pub fn vortex_array::stats::MutTypedStatsSetRef<'_, '_>::len(&self) -> usize -pub struct vortex_array::stats::StatsRewriteSession +pub struct vortex_array::stats::StatsSession -impl core::default::Default for vortex_array::stats::StatsRewriteSession +impl core::default::Default for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::default() -> vortex_array::stats::StatsRewriteSession +pub fn vortex_array::stats::StatsSession::default() -> vortex_array::stats::StatsSession -impl core::fmt::Debug for vortex_array::stats::StatsRewriteSession +impl core::fmt::Debug for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result +pub fn vortex_array::stats::StatsSession::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result -impl vortex_session::SessionVar for vortex_array::stats::StatsRewriteSession +impl vortex_session::SessionVar for vortex_array::stats::StatsSession -pub fn vortex_array::stats::StatsRewriteSession::as_any(&self) -> &dyn core::any::Any +pub fn vortex_array::stats::StatsSession::as_any(&self) -> &dyn core::any::Any -pub fn vortex_array::stats::StatsRewriteSession::as_any_mut(&mut self) -> &mut dyn core::any::Any +pub fn vortex_array::stats::StatsSession::as_any_mut(&mut self) -> &mut dyn core::any::Any pub struct vortex_array::stats::StatsSet @@ -20418,6 +21294,14 @@ pub fn vortex_array::stats::TypedStatsSetRef<'_, '_>::len(&self) -> usize pub const vortex_array::stats::PRUNING_STATS: &[vortex_array::expr::stats::Stat] +pub fn vortex_array::stats::all_nan(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::all_non_nan(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::all_non_null(vortex_array::expr::Expression) -> vortex_array::expr::Expression + +pub fn vortex_array::stats::all_null(vortex_array::expr::Expression) -> vortex_array::expr::Expression + pub fn vortex_array::stats::as_stat_bitset_bytes(&[vortex_array::expr::stats::Stat]) -> alloc::vec::Vec pub fn vortex_array::stats::min_max(vortex_array::expr::Expression) -> vortex_array::expr::Expression diff --git a/vortex-array/src/aggregate_fn/accumulator.rs b/vortex-array/src/aggregate_fn/accumulator.rs index ddc3bd9a86c..b3685d38884 100644 --- a/vortex-array/src/aggregate_fn/accumulator.rs +++ b/vortex-array/src/aggregate_fn/accumulator.rs @@ -124,14 +124,19 @@ impl DynAccumulator for Accumulator { if let Some(stat) = Stat::from_aggregate_fn(&self.aggregate_fn) && let Some(Precision::Exact(partial)) = batch.statistics().get(stat) { - vortex_ensure!( - partial.dtype() == &self.partial_dtype, - "Aggregate {} read legacy stat {} with dtype {}, expected {}", - self.aggregate_fn, - stat, - partial.dtype(), - self.partial_dtype, - ); + let partial = if partial.dtype() == &self.partial_dtype { + partial + } else { + vortex_ensure!( + partial.dtype().eq_ignore_nullability(&self.partial_dtype), + "Aggregate {} read legacy stat {} with dtype {}, expected {}", + self.aggregate_fn, + stat, + partial.dtype(), + self.partial_dtype, + ); + partial.cast(&self.partial_dtype)? + }; self.vtable.combine_partials(&mut self.partial, partial)?; return Ok(()); } diff --git a/vortex-array/src/aggregate_fn/erased.rs b/vortex-array/src/aggregate_fn/erased.rs index 750a7c24f77..0cf1f7c464d 100644 --- a/vortex-array/src/aggregate_fn/erased.rs +++ b/vortex-array/src/aggregate_fn/erased.rs @@ -16,6 +16,7 @@ use vortex_utils::debug_with::DebugWith; use crate::aggregate_fn::AccumulatorRef; use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnSatisfaction; use crate::aggregate_fn::AggregateFnVTable; use crate::aggregate_fn::GroupedAccumulatorRef; use crate::aggregate_fn::options::AggregateFnOptions; @@ -74,6 +75,11 @@ impl AggregateFnRef { AggregateFnOptions { inner: &*self.0 } } + /// Return whether this stored aggregate can satisfy `requested`. + pub fn can_satisfy(&self, requested: &AggregateFnRef) -> AggregateFnSatisfaction { + self.0.can_satisfy(requested) + } + /// Coerce the input type for this aggregate function. pub fn coerce_args(&self, input_dtype: &DType) -> VortexResult { self.0.coerce_args(input_dtype) diff --git a/vortex-array/src/aggregate_fn/fns/all_nan/mod.rs b/vortex-array/src/aggregate_fn/fns/all_nan/mod.rs new file mode 100644 index 00000000000..c33443dd02b --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/all_nan/mod.rs @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::nan_count::nan_count; +use crate::dtype::DType; +use crate::dtype::Nullability; +use crate::scalar::Scalar; + +/// Compute whether every value in an array is NaN. +/// +/// Like other `all` aggregates, this is vacuously true for empty input. +/// +/// This is a pruning aggregate, not just a convenience wrapper around +/// [`NanCount`][crate::aggregate_fn::fns::nan_count::NanCount]. Pruning aggregates must prove a +/// row-wise fact for every value in the scope, so their partials remain valid when a stats column is +/// sliced or concatenated alongside the data. [`NanCount`][crate::aggregate_fn::fns::nan_count::NanCount] +/// carries cross-row count information instead, so it is useful as a legacy storage format but not +/// as the pruning expression itself. +#[derive(Clone, Debug)] +pub struct AllNan; + +impl AggregateFnVTable for AllNan { + type Options = EmptyOptions; + type Partial = bool; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.all_nan") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, input_dtype: &DType) -> Option { + matches!(input_dtype, DType::Primitive(ptype, _) if ptype.is_float()) + .then_some(DType::Bool(Nullability::Nullable)) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + _input_dtype: &DType, + ) -> VortexResult { + Ok(true) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + *partial &= bool::try_from(&other)?; + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + Ok(Scalar::bool(*partial, Nullability::Nullable)) + } + + fn reset(&self, partial: &mut Self::Partial) { + *partial = true; + } + + fn is_saturated(&self, partial: &Self::Partial) -> bool { + !*partial + } + + fn try_accumulate( + &self, + state: &mut Self::Partial, + batch: &ArrayRef, + ctx: &mut ExecutionCtx, + ) -> VortexResult { + if !matches!(batch.dtype(), DType::Primitive(ptype, _) if ptype.is_float()) { + *state = false; + return Ok(true); + } + + *state &= nan_count(batch, ctx)? == batch.len(); + Ok(true) + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Normal array dispatch is handled by `try_accumulate`, which always short-circuits. + // Keep this fallback in sync for direct Columnar accumulation paths. + let array = match batch { + Columnar::Constant(c) => c.clone().into_array(), + Columnar::Canonical(c) => c.clone().into_array(), + }; + if !matches!(array.dtype(), DType::Primitive(ptype, _) if ptype.is_float()) { + *partial = false; + return Ok(()); + } + + *partial &= nan_count(&array, ctx)? == array.len(); + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_error::VortexResult; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::all_nan::AllNan; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + + #[test] + fn all_nan_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(f32::NAN), Some(f32::NAN)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_nan_false_with_non_nan() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(f32::NAN), Some(1.0f32)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(!bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_nan_unsupported_for_non_float_values() -> VortexResult<()> { + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + assert!(Accumulator::try_new(AllNan, EmptyOptions, dtype).is_err()); + Ok(()) + } + + #[test] + fn all_nan_false_with_null() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(f32::NAN), None]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(!bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_nan_true_for_empty_float_values() -> VortexResult<()> { + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNan, EmptyOptions, dtype)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/all_non_distinct/mod.rs b/vortex-array/src/aggregate_fn/fns/all_non_distinct/mod.rs index 10763ba42f3..445f4e17b6f 100644 --- a/vortex-array/src/aggregate_fn/fns/all_non_distinct/mod.rs +++ b/vortex-array/src/aggregate_fn/fns/all_non_distinct/mod.rs @@ -51,6 +51,7 @@ use crate::validity::Validity; /// Returns `true` if and only if: /// - Both arrays have the same dtype and length /// - At every position, both are null or both are non-null with the same value +/// - The arrays are empty, vacuously /// /// This is a fused `bool_all(non_distinct(lhs, rhs))` aggregate that allows early /// termination via accumulator saturation as soon as a mismatch is found. @@ -102,6 +103,8 @@ static NAMES: LazyLock = LazyLock::new(|| FieldNames::from(["lhs", " /// as the first distinct pair is found, the accumulator is saturated and remaining batches /// are skipped. /// +/// Like other `all` aggregates, this is vacuously true for empty input. +/// /// The input is a `Struct{lhs: T, rhs: T}` and the result is `Bool(NonNullable)`. #[derive(Clone, Debug)] pub struct AllNonDistinct; diff --git a/vortex-array/src/aggregate_fn/fns/all_non_nan/mod.rs b/vortex-array/src/aggregate_fn/fns/all_non_nan/mod.rs new file mode 100644 index 00000000000..f8d371cb776 --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/all_non_nan/mod.rs @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::nan_count::nan_count; +use crate::dtype::DType; +use crate::dtype::Nullability; +use crate::scalar::Scalar; + +/// Compute whether every value in an array is not NaN. +/// +/// Like other `all` aggregates, this is vacuously true for empty input. +/// +/// This is a pruning aggregate, not just a convenience wrapper around +/// [`NanCount`][crate::aggregate_fn::fns::nan_count::NanCount]. Pruning aggregates must prove a +/// row-wise fact for every value in the scope, so their partials remain valid when a stats column is +/// sliced or concatenated alongside the data. [`NanCount`][crate::aggregate_fn::fns::nan_count::NanCount] +/// carries cross-row count information instead, so it is useful as a legacy storage format but not +/// as the pruning expression itself. +#[derive(Clone, Debug)] +pub struct AllNonNan; + +impl AggregateFnVTable for AllNonNan { + type Options = EmptyOptions; + type Partial = bool; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.all_non_nan") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, input_dtype: &DType) -> Option { + matches!(input_dtype, DType::Primitive(ptype, _) if ptype.is_float()) + .then_some(DType::Bool(Nullability::Nullable)) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + _input_dtype: &DType, + ) -> VortexResult { + Ok(true) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + *partial &= bool::try_from(&other)?; + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + Ok(Scalar::bool(*partial, Nullability::Nullable)) + } + + fn reset(&self, partial: &mut Self::Partial) { + *partial = true; + } + + fn is_saturated(&self, partial: &Self::Partial) -> bool { + !*partial + } + + fn try_accumulate( + &self, + state: &mut Self::Partial, + batch: &ArrayRef, + ctx: &mut ExecutionCtx, + ) -> VortexResult { + *state &= nan_count(batch, ctx)? == 0; + Ok(true) + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Normal array dispatch is handled by `try_accumulate`, which always short-circuits. + // Keep this fallback in sync for direct Columnar accumulation paths. + let array = match batch { + Columnar::Constant(c) => c.clone().into_array(), + Columnar::Canonical(c) => c.clone().into_array(), + }; + *partial &= nan_count(&array, ctx)? == 0; + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_error::VortexResult; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::all_non_nan::AllNonNan; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + + #[test] + fn all_non_nan_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1.0f32), None, Some(3.0)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_non_nan_false_with_nan() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1.0f32), Some(f32::NAN)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(!bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_non_nan_unsupported_for_non_float() -> VortexResult<()> { + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + assert!(Accumulator::try_new(AllNonNan, EmptyOptions, dtype).is_err()); + Ok(()) + } + + #[test] + fn all_non_nan_true_for_empty_float() -> VortexResult<()> { + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNan, EmptyOptions, dtype)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_non_nan_true_with_nulls() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::F32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNan, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1.0f32), None]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/all_non_null/mod.rs b/vortex-array/src/aggregate_fn/fns/all_non_null/mod.rs new file mode 100644 index 00000000000..a297c318fc9 --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/all_non_null/mod.rs @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::dtype::DType; +use crate::dtype::Nullability; +use crate::scalar::Scalar; + +/// Compute whether every value in an array is non-null. +/// +/// Like other `all` aggregates, this is vacuously true for empty input. +#[derive(Clone, Debug)] +pub struct AllNonNull; + +impl AggregateFnVTable for AllNonNull { + type Options = EmptyOptions; + type Partial = bool; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.all_non_null") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, _input_dtype: &DType) -> Option { + Some(DType::Bool(Nullability::NonNullable)) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + _input_dtype: &DType, + ) -> VortexResult { + Ok(true) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + *partial &= bool::try_from(&other)?; + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + Ok(Scalar::bool(*partial, Nullability::NonNullable)) + } + + fn reset(&self, partial: &mut Self::Partial) { + *partial = true; + } + + fn is_saturated(&self, partial: &Self::Partial) -> bool { + !*partial + } + + fn try_accumulate( + &self, + state: &mut Self::Partial, + batch: &ArrayRef, + ctx: &mut ExecutionCtx, + ) -> VortexResult { + *state &= batch.invalid_count(ctx)? == 0; + Ok(true) + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Normal array dispatch is handled by `try_accumulate`, which always short-circuits. + // Keep this fallback in sync for direct Columnar accumulation paths. + *partial &= match batch { + Columnar::Constant(c) => c.is_empty() || !c.scalar().is_null(), + Columnar::Canonical(c) => c.clone().into_array().invalid_count(ctx)? == 0, + }; + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_error::VortexResult; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::all_non_null::AllNonNull; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + + #[test] + fn all_non_null_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1i32), Some(2), Some(3)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_non_null_false_with_nulls() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1i32), None, Some(3)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(!bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_non_null_true_for_empty_input() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNonNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::empty::(Nullability::Nullable).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/all_null/mod.rs b/vortex-array/src/aggregate_fn/fns/all_null/mod.rs new file mode 100644 index 00000000000..5476c7d534b --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/all_null/mod.rs @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::dtype::DType; +use crate::dtype::Nullability; +use crate::scalar::Scalar; + +/// Compute whether every value in an array is null. +/// +/// Like other `all` aggregates, this is vacuously true for empty input. +#[derive(Clone, Debug)] +pub struct AllNull; + +impl AggregateFnVTable for AllNull { + type Options = EmptyOptions; + type Partial = bool; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.all_null") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, _input_dtype: &DType) -> Option { + Some(DType::Bool(Nullability::NonNullable)) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + _input_dtype: &DType, + ) -> VortexResult { + Ok(true) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + *partial &= bool::try_from(&other)?; + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + Ok(Scalar::bool(*partial, Nullability::NonNullable)) + } + + fn reset(&self, partial: &mut Self::Partial) { + *partial = true; + } + + fn is_saturated(&self, partial: &Self::Partial) -> bool { + !*partial + } + + fn try_accumulate( + &self, + state: &mut Self::Partial, + batch: &ArrayRef, + ctx: &mut ExecutionCtx, + ) -> VortexResult { + *state &= batch.invalid_count(ctx)? == batch.len(); + Ok(true) + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Normal array dispatch is handled by `try_accumulate`, which always short-circuits. + // Keep this fallback in sync for direct Columnar accumulation paths. + *partial &= match batch { + Columnar::Constant(c) => c.is_empty() || c.scalar().is_null(), + Columnar::Canonical(c) => { + let array = c.clone().into_array(); + array.invalid_count(ctx)? == array.len() + } + }; + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_error::VortexResult; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::all_null::AllNull; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + + #[test] + fn all_null_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter::([None, None, None]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_null_false_with_non_nulls() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::from_option_iter([Some(1i32), None, Some(3)]).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(!bool::try_from(&acc.finish()?)?); + Ok(()) + } + + #[test] + fn all_null_true_for_empty_input() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::Nullable); + let mut acc = Accumulator::try_new(AllNull, EmptyOptions, dtype)?; + + let batch = PrimitiveArray::empty::(Nullability::Nullable).into_array(); + acc.accumulate(&batch, &mut ctx)?; + + assert!(bool::try_from(&acc.finish()?)?); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/bounded_max/mod.rs b/vortex-array/src/aggregate_fn/fns/bounded_max/mod.rs new file mode 100644 index 00000000000..d34d4033ce0 --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/bounded_max/mod.rs @@ -0,0 +1,432 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use std::fmt::Display; +use std::fmt::Formatter; +use std::num::NonZeroUsize; + +use vortex_buffer::BufferString; +use vortex_buffer::ByteBuffer; +use vortex_error::VortexExpect; +use vortex_error::VortexResult; +use vortex_error::vortex_ensure; +use vortex_session::VortexSession; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnRef; +use crate::aggregate_fn::AggregateFnSatisfaction; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::max::Max; +use crate::aggregate_fn::fns::min_max::MinMax; +use crate::aggregate_fn::fns::min_max::min_max; +use crate::dtype::DType; +use crate::partial_ord::partial_max; +use crate::scalar::Scalar; +use crate::scalar::ScalarTruncation; +use crate::scalar::upper_bound; + +/// Options for [`BoundedMax`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct BoundedMaxOptions { + /// Maximum byte length for UTF8/Binary bounds. + pub max_bytes: NonZeroUsize, +} + +impl Display for BoundedMaxOptions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.max_bytes.get()) + } +} + +/// Compute a byte-bounded upper bound for the maximum non-null value of a UTF8/Binary array. +#[derive(Clone, Debug)] +pub struct BoundedMax; + +enum BoundedMaxState { + Empty, + Value(Scalar), + Unknown, +} + +/// Partial accumulator state for the bounded maximum aggregate. +pub struct BoundedMaxPartial { + state: BoundedMaxState, + element_dtype: DType, + max_bytes: NonZeroUsize, +} + +impl BoundedMaxPartial { + fn merge(&mut self, max: Scalar) { + if max.is_null() { + // Serialized partials encode both empty input and unknown upper bounds as null. + // Treat null as unknown when merging; this may lose a bound from an empty shard, but + // it preserves pruning soundness. + self.state = BoundedMaxState::Unknown; + return; + } + + self.state = match std::mem::replace(&mut self.state, BoundedMaxState::Empty) { + BoundedMaxState::Empty => BoundedMaxState::Value(max), + BoundedMaxState::Value(current) => BoundedMaxState::Value( + partial_max(max, current).vortex_expect("incomparable bounded max scalars"), + ), + BoundedMaxState::Unknown => BoundedMaxState::Unknown, + }; + } + + fn unknown(&mut self) { + self.state = BoundedMaxState::Unknown; + } +} + +impl AggregateFnVTable for BoundedMax { + type Options = BoundedMaxOptions; + type Partial = BoundedMaxPartial; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.bounded_max") + } + + fn serialize(&self, options: &Self::Options) -> VortexResult>> { + let max_bytes = u64::try_from(options.max_bytes.get())?; + Ok(Some(max_bytes.to_le_bytes().to_vec())) + } + + fn deserialize( + &self, + metadata: &[u8], + _session: &VortexSession, + ) -> VortexResult { + vortex_ensure!( + metadata.len() == size_of::(), + "BoundedMax options expected {} bytes, got {}", + size_of::(), + metadata.len() + ); + let mut bytes = [0u8; size_of::()]; + bytes.copy_from_slice(metadata); + let max_bytes = usize::try_from(u64::from_le_bytes(bytes))?; + vortex_ensure!(max_bytes > 0, "BoundedMax requires max_bytes > 0"); + Ok(BoundedMaxOptions { + max_bytes: NonZeroUsize::new(max_bytes).vortex_expect("checked non-zero max_bytes"), + }) + } + + fn return_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + supported_dtype(options, input_dtype).map(DType::as_nullable) + } + + fn can_satisfy( + &self, + options: &Self::Options, + requested: &AggregateFnRef, + ) -> AggregateFnSatisfaction { + if requested + .as_opt::() + .is_some_and(|other| other == options) + { + return AggregateFnSatisfaction::Exact; + } + + if requested.is::() || requested.is::() { + AggregateFnSatisfaction::Approximate + } else { + AggregateFnSatisfaction::No + } + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + options: &Self::Options, + input_dtype: &DType, + ) -> VortexResult { + Ok(BoundedMaxPartial { + state: BoundedMaxState::Empty, + element_dtype: input_dtype.clone(), + max_bytes: options.max_bytes, + }) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + partial.merge(other); + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + let dtype = partial.element_dtype.as_nullable(); + match &partial.state { + BoundedMaxState::Value(max) => max.cast(&dtype), + BoundedMaxState::Empty | BoundedMaxState::Unknown => Ok(Scalar::null(dtype)), + } + } + + fn reset(&self, partial: &mut Self::Partial) { + partial.state = BoundedMaxState::Empty; + } + + fn is_saturated(&self, partial: &Self::Partial) -> bool { + matches!(partial.state, BoundedMaxState::Unknown) + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Delegate to the existing min_max implementation for now. A dedicated bounded-max + // aggregate would avoid computing min when only max is needed. + let array = match batch { + Columnar::Canonical(canonical) => canonical.clone().into_array(), + Columnar::Constant(constant) => constant.clone().into_array(), + }; + let Some(result) = min_max(&array, ctx)? else { + return Ok(()); + }; + match truncate_max(result.max, partial.max_bytes.get())? { + Some(bound) => partial.merge(bound), + None => partial.unknown(), + } + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +fn supported_dtype<'a>(_options: &BoundedMaxOptions, input_dtype: &'a DType) -> Option<&'a DType> { + MinMax + .return_dtype(&EmptyOptions, input_dtype) + .map(|_| input_dtype) +} + +fn truncate_max(value: Scalar, max_bytes: usize) -> VortexResult> { + let nullability = value.dtype().nullability(); + match value.dtype() { + DType::Utf8(_) => { + Ok( + upper_bound(BufferString::from_scalar(value)?, max_bytes, nullability) + .map(|(bound, _)| bound), + ) + } + DType::Binary(_) => { + Ok( + upper_bound(ByteBuffer::from_scalar(value)?, max_bytes, nullability) + .map(|(bound, _)| bound), + ) + } + _ => Ok(Some(value)), + } +} + +#[cfg(test)] +mod tests { + use std::num::NonZeroUsize; + + use vortex_buffer::buffer; + use vortex_error::VortexExpect; + use vortex_error::VortexResult; + use vortex_session::VortexSession; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::AggregateFnSatisfaction; + use crate::aggregate_fn::AggregateFnVTable; + use crate::aggregate_fn::AggregateFnVTableExt; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::bounded_max::BoundedMax; + use crate::aggregate_fn::fns::bounded_max::BoundedMaxOptions; + use crate::aggregate_fn::fns::max::Max; + use crate::aggregate_fn::fns::min::Min; + use crate::arrays::PrimitiveArray; + use crate::arrays::VarBinViewArray; + use crate::dtype::Nullability; + use crate::scalar::Scalar; + use crate::session::ArraySession; + use crate::validity::Validity; + + fn max_bytes(value: usize) -> NonZeroUsize { + NonZeroUsize::new(value).vortex_expect("non-zero max_bytes") + } + + fn fresh_session() -> VortexSession { + VortexSession::empty().with::() + } + + #[test] + fn bounded_max_truncates_utf8_to_upper_bound() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let array = VarBinViewArray::from_iter_str(["aardvark", "char🪩"]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(5), + }, + array.dtype().clone(), + )?; + + acc.accumulate(&array, &mut ctx)?; + + assert_eq!(acc.finish()?, Scalar::utf8("chas", Nullability::Nullable)); + Ok(()) + } + + #[test] + fn bounded_max_unknown_upper_bound_returns_null() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let array = VarBinViewArray::from_iter_bin([&[255u8, 255, 255][..]]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(2), + }, + array.dtype().clone(), + )?; + + acc.accumulate(&array, &mut ctx)?; + + assert_eq!(acc.finish()?, Scalar::null(array.dtype().as_nullable())); + Ok(()) + } + + #[test] + fn bounded_max_empty_does_not_poison_later_values() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let empty = VarBinViewArray::from_iter_bin(Vec::<&[u8]>::new()).into_array(); + let values = VarBinViewArray::from_iter_bin([&[1u8][..]]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(2), + }, + empty.dtype().clone(), + )?; + + acc.accumulate(&empty, &mut ctx)?; + acc.accumulate(&values, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::binary(buffer![1u8], Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn bounded_max_unknown_poisons_later_values() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let unknown = VarBinViewArray::from_iter_bin([&[255u8, 255, 255][..]]).into_array(); + let values = VarBinViewArray::from_iter_bin([&[1u8][..]]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(2), + }, + unknown.dtype().clone(), + )?; + + acc.accumulate(&unknown, &mut ctx)?; + acc.accumulate(&values, &mut ctx)?; + + assert_eq!(acc.finish()?, Scalar::null(unknown.dtype().as_nullable())); + Ok(()) + } + + #[test] + fn bounded_max_null_partial_poisons_existing_bound() -> VortexResult<()> { + let mut ctx = fresh_session().create_execution_ctx(); + let values = VarBinViewArray::from_iter_bin([&[1u8][..]]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(2), + }, + values.dtype().clone(), + )?; + + acc.accumulate(&values, &mut ctx)?; + acc.combine_partials(Scalar::null(values.dtype().as_nullable()))?; + + assert_eq!(acc.finish()?, Scalar::null(values.dtype().as_nullable())); + Ok(()) + } + + #[test] + fn bounded_max_keeps_fixed_width_values_exact() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let array = PrimitiveArray::new(buffer![10i32, 20, 5], Validity::NonNullable).into_array(); + let mut acc = Accumulator::try_new( + BoundedMax, + BoundedMaxOptions { + max_bytes: max_bytes(9), + }, + array.dtype().clone(), + )?; + + acc.accumulate(&array, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(20i32, Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn bounded_max_satisfies_max_bounds() { + let stored = BoundedMax.bind(BoundedMaxOptions { + max_bytes: max_bytes(5), + }); + let same = BoundedMax.bind(BoundedMaxOptions { + max_bytes: max_bytes(5), + }); + let other_bounded = BoundedMax.bind(BoundedMaxOptions { + max_bytes: max_bytes(6), + }); + + assert_eq!(stored.can_satisfy(&same), AggregateFnSatisfaction::Exact); + assert_eq!( + stored.can_satisfy(&other_bounded), + AggregateFnSatisfaction::Approximate + ); + assert_eq!( + stored.can_satisfy(&Max.bind(EmptyOptions)), + AggregateFnSatisfaction::Approximate + ); + assert_eq!( + stored.can_satisfy(&Min.bind(EmptyOptions)), + AggregateFnSatisfaction::No + ); + } + + #[test] + fn bounded_max_options_round_trip() -> VortexResult<()> { + let options = BoundedMaxOptions { + max_bytes: max_bytes(64), + }; + let metadata = BoundedMax + .serialize(&options)? + .expect("serializable options"); + let roundtrip = BoundedMax.deserialize(&metadata, &VortexSession::empty())?; + + assert_eq!(roundtrip, options); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/bounded_min/mod.rs b/vortex-array/src/aggregate_fn/fns/bounded_min/mod.rs new file mode 100644 index 00000000000..50608f3536c --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/bounded_min/mod.rs @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use std::fmt::Display; +use std::fmt::Formatter; +use std::num::NonZeroUsize; + +use vortex_buffer::BufferString; +use vortex_buffer::ByteBuffer; +use vortex_error::VortexExpect; +use vortex_error::VortexResult; +use vortex_error::vortex_ensure; +use vortex_session::VortexSession; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnRef; +use crate::aggregate_fn::AggregateFnSatisfaction; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::min::Min; +use crate::aggregate_fn::fns::min_max::MinMax; +use crate::aggregate_fn::fns::min_max::min_max; +use crate::dtype::DType; +use crate::partial_ord::partial_min; +use crate::scalar::Scalar; +use crate::scalar::ScalarTruncation; +use crate::scalar::lower_bound; + +/// Options for [`BoundedMin`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct BoundedMinOptions { + /// Maximum byte length for UTF8/Binary bounds. + pub max_bytes: NonZeroUsize, +} + +impl Display for BoundedMinOptions { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.max_bytes.get()) + } +} + +/// Compute a byte-bounded lower bound for the minimum non-null value of a UTF8/Binary array. +#[derive(Clone, Debug)] +pub struct BoundedMin; + +enum BoundedMinState { + Empty, + Value(Scalar), +} + +/// Partial accumulator state for the bounded minimum aggregate. +pub struct BoundedMinPartial { + state: BoundedMinState, + element_dtype: DType, + max_bytes: NonZeroUsize, +} + +impl BoundedMinPartial { + fn merge(&mut self, min: Scalar) { + if min.is_null() { + return; + } + + self.state = match std::mem::replace(&mut self.state, BoundedMinState::Empty) { + BoundedMinState::Empty => BoundedMinState::Value(min), + BoundedMinState::Value(current) => BoundedMinState::Value( + partial_min(min, current).vortex_expect("incomparable bounded min scalars"), + ), + }; + } +} + +impl AggregateFnVTable for BoundedMin { + type Options = BoundedMinOptions; + type Partial = BoundedMinPartial; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.bounded_min") + } + + fn serialize(&self, options: &Self::Options) -> VortexResult>> { + let max_bytes = u64::try_from(options.max_bytes.get())?; + Ok(Some(max_bytes.to_le_bytes().to_vec())) + } + + fn deserialize( + &self, + metadata: &[u8], + _session: &VortexSession, + ) -> VortexResult { + vortex_ensure!( + metadata.len() == size_of::(), + "BoundedMin options expected {} bytes, got {}", + size_of::(), + metadata.len() + ); + let mut bytes = [0u8; size_of::()]; + bytes.copy_from_slice(metadata); + let max_bytes = usize::try_from(u64::from_le_bytes(bytes))?; + vortex_ensure!(max_bytes > 0, "BoundedMin requires max_bytes > 0"); + Ok(BoundedMinOptions { + max_bytes: NonZeroUsize::new(max_bytes).vortex_expect("checked non-zero max_bytes"), + }) + } + + fn return_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + supported_dtype(options, input_dtype).map(DType::as_nullable) + } + + fn can_satisfy( + &self, + options: &Self::Options, + requested: &AggregateFnRef, + ) -> AggregateFnSatisfaction { + if requested + .as_opt::() + .is_some_and(|other| other == options) + { + return AggregateFnSatisfaction::Exact; + } + + if requested.is::() || requested.is::() { + AggregateFnSatisfaction::Approximate + } else { + AggregateFnSatisfaction::No + } + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + options: &Self::Options, + input_dtype: &DType, + ) -> VortexResult { + Ok(BoundedMinPartial { + state: BoundedMinState::Empty, + element_dtype: input_dtype.clone(), + max_bytes: options.max_bytes, + }) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + partial.merge(other); + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + let dtype = partial.element_dtype.as_nullable(); + match &partial.state { + BoundedMinState::Empty => Ok(Scalar::null(dtype)), + BoundedMinState::Value(min) => min.cast(&dtype), + } + } + + fn reset(&self, partial: &mut Self::Partial) { + partial.state = BoundedMinState::Empty; + } + + fn is_saturated(&self, _partial: &Self::Partial) -> bool { + false + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Delegate to the existing min_max implementation for now. A dedicated bounded-min + // aggregate would avoid computing max when only min is needed. + let array = match batch { + Columnar::Canonical(canonical) => canonical.clone().into_array(), + Columnar::Constant(constant) => constant.clone().into_array(), + }; + let Some(result) = min_max(&array, ctx)? else { + return Ok(()); + }; + if let Some(bound) = truncate_min(result.min, partial.max_bytes.get())? { + partial.merge(bound); + } + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +fn supported_dtype<'a>(_options: &BoundedMinOptions, input_dtype: &'a DType) -> Option<&'a DType> { + MinMax + .return_dtype(&EmptyOptions, input_dtype) + .map(|_| input_dtype) +} + +fn truncate_min(value: Scalar, max_bytes: usize) -> VortexResult> { + let nullability = value.dtype().nullability(); + match value.dtype() { + DType::Utf8(_) => { + Ok( + lower_bound(BufferString::from_scalar(value)?, max_bytes, nullability) + .map(|(bound, _)| bound), + ) + } + DType::Binary(_) => { + Ok( + lower_bound(ByteBuffer::from_scalar(value)?, max_bytes, nullability) + .map(|(bound, _)| bound), + ) + } + _ => Ok(Some(value)), + } +} +#[cfg(test)] +mod tests { + use std::num::NonZeroUsize; + + use vortex_buffer::buffer; + use vortex_error::VortexExpect; + use vortex_error::VortexResult; + use vortex_session::VortexSession; + + use crate::IntoArray; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::AggregateFnSatisfaction; + use crate::aggregate_fn::AggregateFnVTable; + use crate::aggregate_fn::AggregateFnVTableExt; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::bounded_min::BoundedMin; + use crate::aggregate_fn::fns::bounded_min::BoundedMinOptions; + use crate::aggregate_fn::fns::max::Max; + use crate::aggregate_fn::fns::min::Min; + use crate::arrays::PrimitiveArray; + use crate::arrays::VarBinViewArray; + use crate::dtype::Nullability; + use crate::scalar::Scalar; + use crate::session::ArraySession; + use crate::validity::Validity; + + fn max_bytes(value: usize) -> NonZeroUsize { + NonZeroUsize::new(value).vortex_expect("non-zero max_bytes") + } + + fn fresh_session() -> VortexSession { + VortexSession::empty().with::() + } + + #[test] + fn bounded_min_truncates_utf8_to_lower_bound() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let array = + VarBinViewArray::from_iter_str(["snowman⛄️snowman", "untruncated"]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMin, + BoundedMinOptions { + max_bytes: max_bytes(9), + }, + array.dtype().clone(), + )?; + + acc.accumulate(&array, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::utf8("snowman", Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn bounded_min_keeps_fixed_width_values_exact() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let array = PrimitiveArray::new(buffer![10i32, 20, 5], Validity::NonNullable).into_array(); + let mut acc = Accumulator::try_new( + BoundedMin, + BoundedMinOptions { + max_bytes: max_bytes(9), + }, + array.dtype().clone(), + )?; + + acc.accumulate(&array, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(5i32, Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn bounded_min_null_partial_does_not_poison_existing_bound() -> VortexResult<()> { + let mut ctx = fresh_session().create_execution_ctx(); + let values = VarBinViewArray::from_iter_bin([&[1u8][..]]).into_array(); + let mut acc = Accumulator::try_new( + BoundedMin, + BoundedMinOptions { + max_bytes: max_bytes(2), + }, + values.dtype().clone(), + )?; + + acc.accumulate(&values, &mut ctx)?; + acc.combine_partials(Scalar::null(values.dtype().as_nullable()))?; + + assert_eq!( + acc.finish()?, + Scalar::binary(buffer![1u8], Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn bounded_min_satisfies_min_bounds() { + let stored = BoundedMin.bind(BoundedMinOptions { + max_bytes: max_bytes(5), + }); + let same = BoundedMin.bind(BoundedMinOptions { + max_bytes: max_bytes(5), + }); + let other_bounded = BoundedMin.bind(BoundedMinOptions { + max_bytes: max_bytes(6), + }); + + assert_eq!(stored.can_satisfy(&same), AggregateFnSatisfaction::Exact); + assert_eq!( + stored.can_satisfy(&other_bounded), + AggregateFnSatisfaction::Approximate + ); + assert_eq!( + stored.can_satisfy(&Min.bind(EmptyOptions)), + AggregateFnSatisfaction::Approximate + ); + assert_eq!( + stored.can_satisfy(&Max.bind(EmptyOptions)), + AggregateFnSatisfaction::No + ); + } + + #[test] + fn bounded_min_options_round_trip() -> VortexResult<()> { + let options = BoundedMinOptions { + max_bytes: max_bytes(64), + }; + let metadata = BoundedMin + .serialize(&options)? + .expect("serializable options"); + let roundtrip = BoundedMin.deserialize(&metadata, &VortexSession::empty())?; + + assert_eq!(roundtrip, options); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/max/mod.rs b/vortex-array/src/aggregate_fn/fns/max/mod.rs new file mode 100644 index 00000000000..5cc10cf3cd7 --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/max/mod.rs @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexExpect; +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::min_max::MinMax; +use crate::aggregate_fn::fns::min_max::min_max; +use crate::dtype::DType; +use crate::partial_ord::partial_max; +use crate::scalar::Scalar; + +/// Compute the maximum non-null value of an array. +#[derive(Clone, Debug)] +pub struct Max; + +/// Partial accumulator state for the maximum aggregate. +pub struct MaxPartial { + max: Option, + element_dtype: DType, +} + +impl MaxPartial { + fn merge(&mut self, max: Scalar) { + if max.is_null() { + return; + } + + self.max = Some(match self.max.take() { + Some(current) => partial_max(max, current).vortex_expect("incomparable max scalars"), + None => max, + }); + } +} + +impl AggregateFnVTable for Max { + type Options = EmptyOptions; + type Partial = MaxPartial; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.max") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, input_dtype: &DType) -> Option { + MinMax + .return_dtype(&EmptyOptions, input_dtype) + .map(|_| input_dtype.as_nullable()) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + input_dtype: &DType, + ) -> VortexResult { + Ok(MaxPartial { + max: None, + element_dtype: input_dtype.clone(), + }) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + partial.merge(other); + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + let dtype = partial.element_dtype.as_nullable(); + match &partial.max { + Some(max) => max.cast(&dtype), + None => Ok(Scalar::null(dtype)), + } + } + + fn reset(&self, partial: &mut Self::Partial) { + partial.max = None; + } + + fn is_saturated(&self, _partial: &Self::Partial) -> bool { + false + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Delegate to the existing min_max implementation for now. A dedicated max aggregate + // would avoid computing min when only max is needed. + let array = match batch { + Columnar::Canonical(canonical) => canonical.clone().into_array(), + Columnar::Constant(constant) => constant.clone().into_array(), + }; + if let Some(result) = min_max(&array, ctx)? { + partial.merge(result.max); + } + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_buffer::buffer; + use vortex_error::VortexResult; + + use crate::IntoArray as _; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::max::Max; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + use crate::expr::stats::Precision; + use crate::expr::stats::Stat; + use crate::scalar::Scalar; + use crate::scalar::ScalarValue; + use crate::validity::Validity; + + #[test] + fn max_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + let mut acc = Accumulator::try_new(Max, EmptyOptions, dtype)?; + + let batch1 = PrimitiveArray::new(buffer![10i32, 20, 5], Validity::NonNullable).into_array(); + acc.accumulate(&batch1, &mut ctx)?; + + let batch2 = PrimitiveArray::new(buffer![3i32, 25], Validity::NonNullable).into_array(); + acc.accumulate(&batch2, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(25i32, Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn max_empty_group_returns_null() -> VortexResult<()> { + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + let mut acc = Accumulator::try_new(Max, EmptyOptions, dtype)?; + + assert_eq!( + acc.finish()?, + Scalar::null(DType::Primitive(PType::I32, Nullability::Nullable)) + ); + Ok(()) + } + + #[test] + fn max_casts_nonnullable_legacy_stat_to_nullable_partial() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let batch = PrimitiveArray::new(buffer![10i32, 20], Validity::NonNullable).into_array(); + batch + .statistics() + .set(Stat::Max, Precision::Exact(ScalarValue::from(25i32))); + let mut acc = Accumulator::try_new(Max, EmptyOptions, batch.dtype().clone())?; + + acc.accumulate(&batch, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(25i32, Nullability::Nullable) + ); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/min/mod.rs b/vortex-array/src/aggregate_fn/fns/min/mod.rs new file mode 100644 index 00000000000..1a9be7101bf --- /dev/null +++ b/vortex-array/src/aggregate_fn/fns/min/mod.rs @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +use vortex_error::VortexExpect; +use vortex_error::VortexResult; + +use crate::ArrayRef; +use crate::Columnar; +use crate::ExecutionCtx; +use crate::IntoArray; +use crate::aggregate_fn::AggregateFnId; +use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::min_max::MinMax; +use crate::aggregate_fn::fns::min_max::min_max; +use crate::dtype::DType; +use crate::partial_ord::partial_min; +use crate::scalar::Scalar; + +/// Compute the minimum non-null value of an array. +#[derive(Clone, Debug)] +pub struct Min; + +/// Partial accumulator state for the minimum aggregate. +pub struct MinPartial { + min: Option, + element_dtype: DType, +} + +impl MinPartial { + fn merge(&mut self, min: Scalar) { + if min.is_null() { + return; + } + + self.min = Some(match self.min.take() { + Some(current) => partial_min(min, current).vortex_expect("incomparable min scalars"), + None => min, + }); + } +} + +impl AggregateFnVTable for Min { + type Options = EmptyOptions; + type Partial = MinPartial; + + fn id(&self) -> AggregateFnId { + AggregateFnId::new("vortex.min") + } + + fn serialize(&self, _options: &Self::Options) -> VortexResult>> { + Ok(None) + } + + fn return_dtype(&self, _options: &Self::Options, input_dtype: &DType) -> Option { + MinMax + .return_dtype(&EmptyOptions, input_dtype) + .map(|_| input_dtype.as_nullable()) + } + + fn partial_dtype(&self, options: &Self::Options, input_dtype: &DType) -> Option { + self.return_dtype(options, input_dtype) + } + + fn empty_partial( + &self, + _options: &Self::Options, + input_dtype: &DType, + ) -> VortexResult { + Ok(MinPartial { + min: None, + element_dtype: input_dtype.clone(), + }) + } + + fn combine_partials(&self, partial: &mut Self::Partial, other: Scalar) -> VortexResult<()> { + partial.merge(other); + Ok(()) + } + + fn to_scalar(&self, partial: &Self::Partial) -> VortexResult { + let dtype = partial.element_dtype.as_nullable(); + match &partial.min { + Some(min) => min.cast(&dtype), + None => Ok(Scalar::null(dtype)), + } + } + + fn reset(&self, partial: &mut Self::Partial) { + partial.min = None; + } + + fn is_saturated(&self, _partial: &Self::Partial) -> bool { + false + } + + fn accumulate( + &self, + partial: &mut Self::Partial, + batch: &Columnar, + ctx: &mut ExecutionCtx, + ) -> VortexResult<()> { + // Delegate to the existing min_max implementation for now. A dedicated min aggregate + // would avoid computing max when only min is needed. + let array = match batch { + Columnar::Canonical(canonical) => canonical.clone().into_array(), + Columnar::Constant(constant) => constant.clone().into_array(), + }; + if let Some(result) = min_max(&array, ctx)? { + partial.merge(result.min); + } + Ok(()) + } + + fn finalize(&self, partials: ArrayRef) -> VortexResult { + Ok(partials) + } + + fn finalize_scalar(&self, partial: &Self::Partial) -> VortexResult { + self.to_scalar(partial) + } +} + +#[cfg(test)] +mod tests { + use vortex_buffer::buffer; + use vortex_error::VortexResult; + + use crate::IntoArray as _; + use crate::LEGACY_SESSION; + use crate::VortexSessionExecute; + use crate::aggregate_fn::Accumulator; + use crate::aggregate_fn::DynAccumulator; + use crate::aggregate_fn::EmptyOptions; + use crate::aggregate_fn::fns::min::Min; + use crate::arrays::PrimitiveArray; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; + use crate::expr::stats::Precision; + use crate::expr::stats::Stat; + use crate::scalar::Scalar; + use crate::scalar::ScalarValue; + use crate::validity::Validity; + + #[test] + fn min_aggregate_fn() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + let mut acc = Accumulator::try_new(Min, EmptyOptions, dtype)?; + + let batch1 = PrimitiveArray::new(buffer![10i32, 20, 5], Validity::NonNullable).into_array(); + acc.accumulate(&batch1, &mut ctx)?; + + let batch2 = PrimitiveArray::new(buffer![3i32, 25], Validity::NonNullable).into_array(); + acc.accumulate(&batch2, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(3i32, Nullability::Nullable) + ); + Ok(()) + } + + #[test] + fn min_empty_group_returns_null() -> VortexResult<()> { + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + let mut acc = Accumulator::try_new(Min, EmptyOptions, dtype)?; + + assert_eq!( + acc.finish()?, + Scalar::null(DType::Primitive(PType::I32, Nullability::Nullable)) + ); + Ok(()) + } + + #[test] + fn min_casts_nonnullable_legacy_stat_to_nullable_partial() -> VortexResult<()> { + let mut ctx = LEGACY_SESSION.create_execution_ctx(); + let batch = PrimitiveArray::new(buffer![10i32, 20], Validity::NonNullable).into_array(); + batch + .statistics() + .set(Stat::Min, Precision::Exact(ScalarValue::from(3i32))); + let mut acc = Accumulator::try_new(Min, EmptyOptions, batch.dtype().clone())?; + + acc.accumulate(&batch, &mut ctx)?; + + assert_eq!( + acc.finish()?, + Scalar::primitive(3i32, Nullability::Nullable) + ); + Ok(()) + } +} diff --git a/vortex-array/src/aggregate_fn/fns/min_max/mod.rs b/vortex-array/src/aggregate_fn/fns/min_max/mod.rs index 786a70e5ffa..03b10e32301 100644 --- a/vortex-array/src/aggregate_fn/fns/min_max/mod.rs +++ b/vortex-array/src/aggregate_fn/fns/min_max/mod.rs @@ -177,7 +177,7 @@ impl AggregateFnVTable for MinMax { } fn serialize(&self, _options: &Self::Options) -> VortexResult>> { - unimplemented!("MinMax is not yet serializable"); + Ok(None) } fn return_dtype(&self, _options: &Self::Options, input_dtype: &DType) -> Option { diff --git a/vortex-array/src/aggregate_fn/fns/mod.rs b/vortex-array/src/aggregate_fn/fns/mod.rs index a0a54f13f0e..da81e67ecb9 100644 --- a/vortex-array/src/aggregate_fn/fns/mod.rs +++ b/vortex-array/src/aggregate_fn/fns/mod.rs @@ -1,13 +1,21 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright the Vortex contributors +pub mod all_nan; pub mod all_non_distinct; +pub mod all_non_nan; +pub mod all_non_null; +pub mod all_null; +pub mod bounded_max; +pub mod bounded_min; pub mod count; pub mod first; pub mod is_constant; pub mod is_sorted; pub mod last; +pub mod max; pub mod mean; +pub mod min; pub mod min_max; pub mod nan_count; pub mod null_count; diff --git a/vortex-array/src/aggregate_fn/fns/nan_count/mod.rs b/vortex-array/src/aggregate_fn/fns/nan_count/mod.rs index 0e229ed7982..72427372609 100644 --- a/vortex-array/src/aggregate_fn/fns/nan_count/mod.rs +++ b/vortex-array/src/aggregate_fn/fns/nan_count/mod.rs @@ -29,6 +29,8 @@ use crate::scalar::ScalarValue; /// Return the number of NaN values in an array. /// +/// Null values are not NaN and are not counted. +/// /// See [`NanCount`] for details. pub fn nan_count(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult { // Short-circuit using cached array statistics. @@ -72,7 +74,7 @@ pub fn nan_count(array: &ArrayRef, ctx: &mut ExecutionCtx) -> VortexResult bool { + !matches!(self, Self::No) + } + + /// Returns whether the stored aggregate exactly satisfies the requested aggregate. + pub fn is_exact(self) -> bool { + matches!(self, Self::Exact) + } +} diff --git a/vortex-array/src/aggregate_fn/session.rs b/vortex-array/src/aggregate_fn/session.rs index 92eb9c0ed38..d89f9da069d 100644 --- a/vortex-array/src/aggregate_fn/session.rs +++ b/vortex-array/src/aggregate_fn/session.rs @@ -14,11 +14,19 @@ use vortex_utils::aliases::hash_map::HashMap; use crate::aggregate_fn::AggregateFnId; use crate::aggregate_fn::AggregateFnPluginRef; use crate::aggregate_fn::AggregateFnVTable; +use crate::aggregate_fn::fns::all_nan::AllNan; use crate::aggregate_fn::fns::all_non_distinct::AllNonDistinct; +use crate::aggregate_fn::fns::all_non_nan::AllNonNan; +use crate::aggregate_fn::fns::all_non_null::AllNonNull; +use crate::aggregate_fn::fns::all_null::AllNull; +use crate::aggregate_fn::fns::bounded_max::BoundedMax; +use crate::aggregate_fn::fns::bounded_min::BoundedMin; use crate::aggregate_fn::fns::first::First; use crate::aggregate_fn::fns::is_constant::IsConstant; use crate::aggregate_fn::fns::is_sorted::IsSorted; use crate::aggregate_fn::fns::last::Last; +use crate::aggregate_fn::fns::max::Max; +use crate::aggregate_fn::fns::min::Min; use crate::aggregate_fn::fns::min_max::MinMax; use crate::aggregate_fn::fns::nan_count::NanCount; use crate::aggregate_fn::fns::null_count::NullCount; @@ -69,10 +77,18 @@ impl Default for AggregateFnSession { // Register the built-in aggregate functions this.register(AllNonDistinct); + this.register(AllNonNan); + this.register(AllNonNull); + this.register(AllNan); + this.register(AllNull); + this.register(BoundedMax); + this.register(BoundedMin); this.register(First); this.register(IsConstant); this.register(IsSorted); this.register(Last); + this.register(Max); + this.register(Min); this.register(MinMax); this.register(NanCount); this.register(NullCount); diff --git a/vortex-array/src/aggregate_fn/typed.rs b/vortex-array/src/aggregate_fn/typed.rs index 3d1d4a8d15a..b399477c0a5 100644 --- a/vortex-array/src/aggregate_fn/typed.rs +++ b/vortex-array/src/aggregate_fn/typed.rs @@ -24,6 +24,7 @@ use crate::aggregate_fn::Accumulator; use crate::aggregate_fn::AccumulatorRef; use crate::aggregate_fn::AggregateFnId; use crate::aggregate_fn::AggregateFnRef; +use crate::aggregate_fn::AggregateFnSatisfaction; use crate::aggregate_fn::AggregateFnVTable; use crate::aggregate_fn::GroupedAccumulator; use crate::aggregate_fn::GroupedAccumulatorRef; @@ -39,6 +40,7 @@ pub(super) trait DynAggregateFn: 'static + Send + Sync + super::sealed::Sealed { fn options_any(&self) -> &dyn Any; fn coerce_args(&self, input_dtype: &DType) -> VortexResult; + fn can_satisfy(&self, requested: &AggregateFnRef) -> AggregateFnSatisfaction; fn return_dtype(&self, input_dtype: &DType) -> Option; fn state_dtype(&self, input_dtype: &DType) -> Option; fn accumulator(&self, input_dtype: &DType) -> VortexResult; @@ -80,6 +82,10 @@ impl DynAggregateFn for AggregateFnInner { V::coerce_args(&self.vtable, &self.options, input_dtype) } + fn can_satisfy(&self, requested: &AggregateFnRef) -> AggregateFnSatisfaction { + V::can_satisfy(&self.vtable, &self.options, requested) + } + fn return_dtype(&self, input_dtype: &DType) -> Option { V::return_dtype(&self.vtable, &self.options, input_dtype) } diff --git a/vortex-array/src/aggregate_fn/vtable.rs b/vortex-array/src/aggregate_fn/vtable.rs index da6fcbc4165..28b91d45166 100644 --- a/vortex-array/src/aggregate_fn/vtable.rs +++ b/vortex-array/src/aggregate_fn/vtable.rs @@ -17,6 +17,7 @@ use crate::ExecutionCtx; use crate::aggregate_fn::AggregateFn; use crate::aggregate_fn::AggregateFnId; use crate::aggregate_fn::AggregateFnRef; +use crate::aggregate_fn::AggregateFnSatisfaction; use crate::dtype::DType; use crate::scalar::Scalar; @@ -66,6 +67,25 @@ pub trait AggregateFnVTable: 'static + Sized + Clone + Send + Sync { Ok(input_dtype.clone()) } + /// Return whether this stored aggregate can satisfy `requested`. + /// + /// The default implementation only treats exactly equal aggregate functions as satisfying the + /// request. Approximate pruning aggregates can override this to expose looser-but-sound bounds. + fn can_satisfy( + &self, + options: &Self::Options, + requested: &AggregateFnRef, + ) -> AggregateFnSatisfaction { + if requested + .as_opt::() + .is_some_and(|other| other == options) + { + AggregateFnSatisfaction::Exact + } else { + AggregateFnSatisfaction::No + } + } + /// The return [`DType`] of the aggregate. /// /// Returns `None` if the aggregate function cannot be applied to the input dtype. diff --git a/vortex-array/src/expr/expression.rs b/vortex-array/src/expr/expression.rs index 10b4389f6e8..cc21fb9a9a6 100644 --- a/vortex-array/src/expr/expression.rs +++ b/vortex-array/src/expr/expression.rs @@ -138,18 +138,30 @@ impl Expression { /// Returns an expression that proves this predicate is definitely false from stats. /// + /// `scope` is the dtype of the row this expression evaluates over. + /// /// If the returned expression evaluates to `true` for a stats scope, this expression is /// guaranteed to be false for every row in that scope. `false` and `null` are unknown. - pub fn falsify(&self, session: &VortexSession) -> VortexResult> { - crate::stats::rewrite::StatsRewriteCtx::new(session).falsify(self) + pub fn falsify( + &self, + scope: &DType, + session: &VortexSession, + ) -> VortexResult> { + crate::stats::rewrite::StatsRewriteCtx::new(session, scope).falsify(self) } /// Returns an expression that proves this predicate is definitely true from stats. /// + /// `scope` is the dtype of the row this expression evaluates over. + /// /// If the returned expression evaluates to `true` for a stats scope, this expression is /// guaranteed to be true for every row in that scope. `false` and `null` are unknown. - pub fn satisfy(&self, session: &VortexSession) -> VortexResult> { - crate::stats::rewrite::StatsRewriteCtx::new(session).satisfy(self) + pub fn satisfy( + &self, + scope: &DType, + session: &VortexSession, + ) -> VortexResult> { + crate::stats::rewrite::StatsRewriteCtx::new(session, scope).satisfy(self) } /// Returns an expression representing the zoned statistic for the given stat, if available. diff --git a/vortex-array/src/expr/stats/mod.rs b/vortex-array/src/expr/stats/mod.rs index 181eea5446b..cd5da7811e9 100644 --- a/vortex-array/src/expr/stats/mod.rs +++ b/vortex-array/src/expr/stats/mod.rs @@ -194,6 +194,8 @@ impl Stat { /// Return the built-in aggregate function corresponding to this statistic, if one exists. pub fn aggregate_fn(&self) -> Option { Some(match self { + Self::Max => aggregate_fn::fns::max::Max.bind(EmptyOptions), + Self::Min => aggregate_fn::fns::min::Min.bind(EmptyOptions), Self::Sum => aggregate_fn::fns::sum::Sum.bind(EmptyOptions), Self::NullCount => aggregate_fn::fns::null_count::NullCount.bind(EmptyOptions), Self::NaNCount => aggregate_fn::fns::nan_count::NanCount.bind(EmptyOptions), @@ -201,9 +203,7 @@ impl Stat { aggregate_fn::fns::uncompressed_size_in_bytes::UncompressedSizeInBytes .bind(EmptyOptions) } - Self::IsConstant | Self::IsSorted | Self::IsStrictSorted | Self::Max | Self::Min => { - return None; - } + Self::IsConstant | Self::IsSorted | Self::IsStrictSorted => return None, }) } @@ -218,6 +218,12 @@ impl Stat { if aggregate_fn.is::() { return Some(Self::NullCount); } + if aggregate_fn.is::() { + return Some(Self::Min); + } + if aggregate_fn.is::() { + return Some(Self::Max); + } if aggregate_fn .is::() { diff --git a/vortex-array/src/scalar_fn/fns/stat.rs b/vortex-array/src/scalar_fn/fns/stat.rs index 540d4bcaff6..82ea4c6b86c 100644 --- a/vortex-array/src/scalar_fn/fns/stat.rs +++ b/vortex-array/src/scalar_fn/fns/stat.rs @@ -13,12 +13,19 @@ use crate::ArrayRef; use crate::ExecutionCtx; use crate::IntoArray; use crate::aggregate_fn::AggregateFnRef; +use crate::aggregate_fn::fns::all_nan::AllNan; +use crate::aggregate_fn::fns::all_non_nan::AllNonNan; +use crate::aggregate_fn::fns::all_non_null::AllNonNull; +use crate::aggregate_fn::fns::all_null::AllNull; use crate::arrays::ConstantArray; use crate::dtype::DType; use crate::expr::Expression; +use crate::expr::stats::Precision; use crate::expr::stats::Stat; use crate::expr::stats::StatsProvider; +use crate::expr::stats::StatsProviderExt; use crate::scalar::Scalar; +use crate::scalar::ScalarValue; use crate::scalar_fn::Arity; use crate::scalar_fn::ChildName; use crate::scalar_fn::ExecutionArgs; @@ -49,7 +56,7 @@ impl Display for StatOptions { } } -/// Scalar function that broadcasts a stored aggregate statistic over the input rows. +/// Scalar function that broadcasts a stored aggregate partial over the input rows. /// /// The only current consumer is **row-wise pruning**: substituting `stat(col, agg)` into a /// predicate produces a cheap, row-aligned approximation whose constant runs let downstream @@ -64,10 +71,10 @@ impl Display for StatOptions { /// yields a constant per chunk; a zone-mapped array would yield a run-end-encoded array, /// one run per zone. If the requested stat is not available, the result is a null constant. /// -/// Pruning only makes sense for aggregates that bound individual rows — `min`, `max`, -/// `has_nulls`, bloom filters, etc. Non-idempotent aggregates like `sum`, `count`, `mean`, -/// `null_count`, and `nan_count` still produce a meaningful per-chunk value but do **not** -/// bound any single row. +/// Pruning only makes sense for aggregates that can prove something about every row in the scope +/// — `min`, `max`, `all_null`, `all_non_null`, bloom filters, etc. Non-idempotent aggregates like +/// `sum`, `count`, `mean`, `null_count`, and `nan_count` still produce a meaningful per-chunk +/// value but do **not** bound any single row. #[derive(Clone)] pub struct StatFn; @@ -117,7 +124,7 @@ impl ScalarFnVTable for StatFn { } fn stat_dtype(aggregate_fn: &AggregateFnRef, input_dtype: &DType) -> VortexResult { - let Some(dtype) = aggregate_fn.return_dtype(input_dtype) else { + let Some(dtype) = aggregate_fn.state_dtype(input_dtype) else { vortex_bail!( "Aggregate function {} does not support input dtype {}", aggregate_fn, @@ -133,7 +140,47 @@ fn stat_array( dtype: DType, len: usize, ) -> VortexResult { - let value = if let Some(stat) = Stat::from_aggregate_fn(aggregate_fn) { + let value = if aggregate_fn.is::() { + let len = u64::try_from(len)?; + array + .statistics() + .get_as::(Stat::NullCount) + .and_then(|null_count| match null_count { + Precision::Exact(count) => Some(count == len), + Precision::Inexact(count) => (count < len).then_some(false), + }) + .map(ScalarValue::Bool) + } else if aggregate_fn.is::() { + array + .statistics() + .get_as::(Stat::NullCount) + .and_then(|null_count| match null_count { + Precision::Exact(count) => Some(count == 0), + Precision::Inexact(0) => Some(true), + Precision::Inexact(_) => None, + }) + .map(ScalarValue::Bool) + } else if aggregate_fn.is::() { + let len = u64::try_from(len)?; + array + .statistics() + .get_as::(Stat::NaNCount) + .and_then(|nan_count| match nan_count { + Precision::Exact(count) => Some(count == len), + Precision::Inexact(count) => (count < len).then_some(false), + }) + .map(ScalarValue::Bool) + } else if aggregate_fn.is::() { + array + .statistics() + .get_as::(Stat::NaNCount) + .and_then(|nan_count| match nan_count { + Precision::Exact(count) => Some(count == 0), + Precision::Inexact(0) => Some(true), + Precision::Inexact(_) => None, + }) + .map(ScalarValue::Bool) + } else if let Some(stat) = Stat::from_aggregate_fn(aggregate_fn) { array .statistics() .with_typed_stats_set(|stats| stats.get(stat)) diff --git a/vortex-array/src/scalar_fn/internal/row_count.rs b/vortex-array/src/scalar_fn/internal/row_count.rs index f411626321d..ea349f2ddf8 100644 --- a/vortex-array/src/scalar_fn/internal/row_count.rs +++ b/vortex-array/src/scalar_fn/internal/row_count.rs @@ -24,6 +24,12 @@ use vortex_error::vortex_ensure; /// Zero-argument placeholder for the row count of the current evaluation scope. /// +/// This is a legacy pruning hack for readers that only have a `null_count` +/// stat and need to support `is_not_null` pruning. It is currently substituted +/// by the zoned/file stats pruning paths before execution. New stats rewrites +/// should prefer boolean `all_null` and `all_non_null` aggregates instead of +/// depending on this scope-level placeholder. +/// /// This expression *MUST* be replaced with a concrete array before evaluation. /// Currently, the rewrite only happens in the context of stats pruning. /// diff --git a/vortex-array/src/stats/expr.rs b/vortex-array/src/stats/expr.rs index 479908acb92..32fd48804de 100644 --- a/vortex-array/src/stats/expr.rs +++ b/vortex-array/src/stats/expr.rs @@ -6,6 +6,10 @@ use crate::aggregate_fn::AggregateFnRef; use crate::aggregate_fn::AggregateFnVTableExt; use crate::aggregate_fn::EmptyOptions; +use crate::aggregate_fn::fns::all_nan::AllNan; +use crate::aggregate_fn::fns::all_non_nan::AllNonNan; +use crate::aggregate_fn::fns::all_non_null::AllNonNull; +use crate::aggregate_fn::fns::all_null::AllNull; use crate::aggregate_fn::fns::min_max::MinMax; use crate::aggregate_fn::fns::nan_count::NanCount; use crate::aggregate_fn::fns::null_count::NullCount; @@ -38,6 +42,26 @@ pub fn null_count(expr: Expression) -> Expression { stat(expr, NullCount.bind(EmptyOptions)) } +/// Creates `stat(expr, all_null)`, returning a nullable all-null statistic. +pub fn all_null(expr: Expression) -> Expression { + stat(expr, AllNull.bind(EmptyOptions)) +} + +/// Creates `stat(expr, all_nan)`, returning a nullable all-NaN statistic. +pub fn all_nan(expr: Expression) -> Expression { + stat(expr, AllNan.bind(EmptyOptions)) +} + +/// Creates `stat(expr, all_non_null)`, returning a nullable all-non-null statistic. +pub fn all_non_null(expr: Expression) -> Expression { + stat(expr, AllNonNull.bind(EmptyOptions)) +} + +/// Creates `stat(expr, all_non_nan)`, returning a nullable all-non-NaN statistic. +pub fn all_non_nan(expr: Expression) -> Expression { + stat(expr, AllNonNan.bind(EmptyOptions)) +} + /// Creates `stat(expr, nan_count)`, returning a nullable NaN-count statistic. pub fn nan_count(expr: Expression) -> Expression { stat(expr, NanCount.bind(EmptyOptions)) @@ -45,18 +69,23 @@ pub fn nan_count(expr: Expression) -> Expression { #[cfg(test)] mod tests { + use std::sync::LazyLock; + use vortex_buffer::buffer; use vortex_error::VortexExpect; use vortex_error::VortexResult; + use vortex_session::VortexSession; + use super::all_nan; + use super::all_non_nan; + use super::all_non_null; + use super::all_null; + use super::null_count; use super::stat; + use super::sum; use crate::Canonical; use crate::IntoArray; - use crate::LEGACY_SESSION; use crate::VortexSessionExecute; - use crate::aggregate_fn::AggregateFn; - use crate::aggregate_fn::EmptyOptions; - use crate::aggregate_fn::fns::sum::Sum; use crate::arrays::Chunked; use crate::arrays::ChunkedArray; use crate::arrays::ConstantArray; @@ -70,8 +99,13 @@ mod tests { use crate::expr::stats::Precision; use crate::expr::stats::Stat; use crate::scalar::Scalar; + use crate::scalar::ScalarValue; + use crate::session::ArraySession; use crate::validity::Validity; + static SESSION: LazyLock = + LazyLock::new(|| VortexSession::empty().with::()); + #[test] fn stat_expr_reads_cached_sum() -> VortexResult<()> { let array = buffer![1i32, 2, 3].into_array(); @@ -82,8 +116,8 @@ mod tests { ); let result = array - .apply(&stat(root(), AggregateFn::new(Sum, EmptyOptions).erased()))? - .execute::(&mut LEGACY_SESSION.create_execution_ctx())? + .apply(&sum(root()))? + .execute::(&mut SESSION.create_execution_ctx())? .into_array(); let expected = @@ -98,8 +132,8 @@ mod tests { let array = buffer![1i32, 2, 3].into_array(); let result = array - .apply(&stat(root(), AggregateFn::new(Sum, EmptyOptions).erased()))? - .execute::(&mut LEGACY_SESSION.create_execution_ctx())? + .apply(&sum(root()))? + .execute::(&mut SESSION.create_execution_ctx())? .into_array(); let expected = ConstantArray::new( @@ -127,7 +161,7 @@ mod tests { )? .into_array(); - let result = chunked.apply(&stat(root(), AggregateFn::new(Sum, EmptyOptions).erased()))?; + let result = chunked.apply(&sum(root()))?; let chunked_result = result .as_opt::() @@ -135,7 +169,7 @@ mod tests { assert_eq!(chunked_result.nchunks(), 2); let result = result - .execute::(&mut LEGACY_SESSION.create_execution_ctx())? + .execute::(&mut SESSION.create_execution_ctx())? .into_array(); let expected = PrimitiveArray::new( buffer![3i64, 3, 0, 0, 0], @@ -162,8 +196,8 @@ mod tests { ); let result = array - .apply(&super::null_count(root()))? - .execute::(&mut LEGACY_SESSION.create_execution_ctx())? + .apply(&null_count(root()))? + .execute::(&mut SESSION.create_execution_ctx())? .into_array(); let expected = @@ -172,4 +206,274 @@ mod tests { Ok(()) } + + #[test] + fn stat_expr_reads_cached_all_null_from_null_count() -> VortexResult<()> { + let array = PrimitiveArray::from_option_iter::([None, None, None]).into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::exact(ScalarValue::from(3u64))); + + let result = array + .apply(&all_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(true, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_null_false_from_inexact_low_null_count() -> VortexResult<()> { + let array = PrimitiveArray::from_option_iter::([None, Some(2), None]).into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::inexact(ScalarValue::from(2u64))); + + let result = array + .apply(&all_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(false, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_returns_null_for_inexact_full_null_count_as_all_null() -> VortexResult<()> { + let array = PrimitiveArray::from_option_iter::([None, Some(2), None]).into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::inexact(ScalarValue::from(3u64))); + + let result = array + .apply(&all_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::null(DType::Bool(Nullability::Nullable)), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_non_null_from_null_count() -> VortexResult<()> { + let array = buffer![1i32, 2, 3].into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::exact(ScalarValue::from(0u64))); + + let result = array + .apply(&all_non_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(true, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_non_null_true_from_inexact_zero_null_count() -> VortexResult<()> { + let array = buffer![1i32, 2, 3].into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::inexact(ScalarValue::from(0u64))); + + let result = array + .apply(&all_non_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(true, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_returns_null_for_inexact_nonzero_null_count_as_all_non_null() -> VortexResult<()> { + let array = + PrimitiveArray::from_option_iter([Some(1i32), None, Some(3), None]).into_array(); + array + .statistics() + .set(Stat::NullCount, Precision::inexact(ScalarValue::from(2u64))); + + let result = array + .apply(&all_non_null(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::null(DType::Bool(Nullability::Nullable)), 4).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_rejects_all_nan_for_non_float() -> VortexResult<()> { + let array = PrimitiveArray::empty::(Nullability::NonNullable).into_array(); + let mut ctx = SESSION.create_execution_ctx(); + + let result = array + .apply(&all_nan(root())) + .and_then(|array| array.execute::(&mut ctx)); + + assert!(result.is_err()); + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_nan_from_nan_count() -> VortexResult<()> { + let array = + PrimitiveArray::from_option_iter([Some(f32::NAN), Some(f32::NAN), Some(f32::NAN)]) + .into_array(); + array + .statistics() + .set(Stat::NaNCount, Precision::exact(ScalarValue::from(3u64))); + + let result = array + .apply(&all_nan(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(true, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_nan_false_from_inexact_low_nan_count() -> VortexResult<()> { + let array = + PrimitiveArray::from_option_iter([Some(f32::NAN), Some(1.0f32), Some(f32::NAN)]) + .into_array(); + array + .statistics() + .set(Stat::NaNCount, Precision::inexact(ScalarValue::from(2u64))); + + let result = array + .apply(&all_nan(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(false, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_returns_null_for_inexact_full_nan_count_as_all_nan() -> VortexResult<()> { + let array = + PrimitiveArray::from_option_iter([Some(f32::NAN), Some(1.0f32), Some(f32::NAN)]) + .into_array(); + array + .statistics() + .set(Stat::NaNCount, Precision::inexact(ScalarValue::from(3u64))); + + let result = array + .apply(&all_nan(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::null(DType::Bool(Nullability::Nullable)), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_all_non_nan_true_from_inexact_zero_nan_count() -> VortexResult<()> { + let array = buffer![1.0f32, 2.0, 3.0].into_array(); + array + .statistics() + .set(Stat::NaNCount, Precision::inexact(ScalarValue::from(0u64))); + + let result = array + .apply(&all_non_nan(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::bool(true, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_returns_null_for_inexact_nonzero_nan_count_as_all_non_nan() -> VortexResult<()> { + let array = PrimitiveArray::from_option_iter([Some(1.0f32), Some(f32::NAN), Some(3.0)]) + .into_array(); + array + .statistics() + .set(Stat::NaNCount, Precision::inexact(ScalarValue::from(1u64))); + + let result = array + .apply(&all_non_nan(root()))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + + let expected = + ConstantArray::new(Scalar::null(DType::Bool(Nullability::Nullable)), 3).into_array(); + assert_arrays_eq!(result, expected); + + Ok(()) + } + + #[test] + fn stat_expr_reads_cached_min_and_max() -> VortexResult<()> { + let array = buffer![3i32, 1, 2].into_array(); + array + .statistics() + .set(Stat::Min, Precision::exact(ScalarValue::from(1i32))); + array + .statistics() + .set(Stat::Max, Precision::exact(ScalarValue::from(3i32))); + + let min_result = array + .clone() + .apply(&stat( + root(), + Stat::Min + .aggregate_fn() + .vortex_expect("min should have an aggregate function"), + ))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + let expected_min = + ConstantArray::new(Scalar::primitive(1i32, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(min_result, expected_min); + + let max_result = array + .apply(&stat( + root(), + Stat::Max + .aggregate_fn() + .vortex_expect("max should have an aggregate function"), + ))? + .execute::(&mut SESSION.create_execution_ctx())? + .into_array(); + let expected_max = + ConstantArray::new(Scalar::primitive(3i32, Nullability::Nullable), 3).into_array(); + assert_arrays_eq!(max_result, expected_max); + + Ok(()) + } } diff --git a/vortex-array/src/stats/mod.rs b/vortex-array/src/stats/mod.rs index 1d2994d01ff..ceb085e0815 100644 --- a/vortex-array/src/stats/mod.rs +++ b/vortex-array/src/stats/mod.rs @@ -7,6 +7,10 @@ use arrow_buffer::BooleanBufferBuilder; use arrow_buffer::MutableBuffer; use arrow_buffer::bit_iterator::BitIterator; use enum_iterator::last; +pub use expr::all_nan; +pub use expr::all_non_nan; +pub use expr::all_non_null; +pub use expr::all_null; pub use expr::min_max; pub use expr::nan_count; pub use expr::null_count; diff --git a/vortex-array/src/stats/rewrite.rs b/vortex-array/src/stats/rewrite.rs index 0eacc2d6629..98c9c01f894 100644 --- a/vortex-array/src/stats/rewrite.rs +++ b/vortex-array/src/stats/rewrite.rs @@ -7,12 +7,14 @@ use std::fmt::Debug; use std::sync::Arc; use vortex_error::VortexResult; +use vortex_error::vortex_ensure; use vortex_session::VortexSession; +use crate::dtype::DType; use crate::expr::Expression; use crate::expr::or_collect; use crate::scalar_fn::ScalarFnId; -use crate::stats::session::StatsRewriteSessionExt; +use crate::stats::session::StatsSessionExt; /// Shared reference to a stats rewrite rule. pub(crate) type StatsRewriteRuleRef = Arc; @@ -54,12 +56,13 @@ pub(crate) trait StatsRewriteRule: Debug + Send + Sync + 'static { /// Context passed to stats rewrite rules. pub(crate) struct StatsRewriteCtx<'a> { session: &'a VortexSession, + scope: &'a DType, } impl<'a> StatsRewriteCtx<'a> { /// Create a rewrite context for `session`. - pub(crate) fn new(session: &'a VortexSession) -> Self { - Self { session } + pub(crate) fn new(session: &'a VortexSession, scope: &'a DType) -> Self { + Self { session, scope } } /// Returns the session that owns the rewrite registry. @@ -67,15 +70,31 @@ impl<'a> StatsRewriteCtx<'a> { self.session } + /// Return the dtype of `expr` within this rewrite scope. + pub(crate) fn return_dtype(&self, expr: &Expression) -> VortexResult { + expr.return_dtype(self.scope) + } + /// Rewrite `expr` into a stats-backed falsifier. pub(crate) fn falsify(&self, expr: &Expression) -> VortexResult> { + self.ensure_predicate(expr)?; rewrite(expr, self, StatsRewriteRule::falsify) } /// Rewrite `expr` into a stats-backed satisfier. pub(crate) fn satisfy(&self, expr: &Expression) -> VortexResult> { + self.ensure_predicate(expr)?; rewrite(expr, self, StatsRewriteRule::satisfy) } + + fn ensure_predicate(&self, expr: &Expression) -> VortexResult<()> { + let dtype = self.return_dtype(expr)?; + vortex_ensure!( + matches!(dtype, DType::Bool(_)), + "Stats rewrites require a boolean predicate, got {dtype}", + ); + Ok(()) + } } fn rewrite( @@ -89,8 +108,8 @@ fn rewrite( ) -> VortexResult> { let rules = ctx .session() - .stats_rewrites() - .rules_for(expr.scalar_fn().id()); + .stats() + .rewrite_rules_for(expr.scalar_fn().id()); let Some(rules) = rules else { return Ok(None); }; @@ -112,14 +131,17 @@ mod tests { use super::StatsRewriteCtx; use super::StatsRewriteRule; + use crate::dtype::DType; + use crate::dtype::Nullability; + use crate::dtype::PType; use crate::expr::Expression; use crate::expr::lit; use crate::expr::or; use crate::scalar_fn::ScalarFnId; use crate::scalar_fn::ScalarFnVTable; use crate::scalar_fn::fns::literal::Literal; - use crate::stats::session::StatsRewriteSession; - use crate::stats::session::StatsRewriteSessionExt; + use crate::stats::session::StatsSession; + use crate::stats::session::StatsSessionExt; #[derive(Debug)] struct StaticLiteralRule { @@ -151,42 +173,60 @@ mod tests { #[test] fn combines_multiple_falsifiers_with_or() -> VortexResult<()> { - let session = VortexSession::empty().with::(); - session.stats_rewrites().register(StaticLiteralRule { + let session = VortexSession::empty().with::(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + session.stats().register_rewrite(StaticLiteralRule { falsifier: Some(lit(false)), satisfier: None, }); - session.stats_rewrites().register(StaticLiteralRule { + session.stats().register_rewrite(StaticLiteralRule { falsifier: Some(lit(true)), satisfier: None, }); - assert_eq!(lit(7).falsify(&session)?, Some(or(lit(false), lit(true)))); + assert_eq!( + lit(true).falsify(&dtype, &session)?, + Some(or(lit(false), lit(true))) + ); Ok(()) } #[test] fn combines_multiple_satisfiers_with_or() -> VortexResult<()> { - let session = VortexSession::empty().with::(); - session.stats_rewrites().register(StaticLiteralRule { + let session = VortexSession::empty().with::(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + session.stats().register_rewrite(StaticLiteralRule { falsifier: None, satisfier: Some(lit(false)), }); - session.stats_rewrites().register(StaticLiteralRule { + session.stats().register_rewrite(StaticLiteralRule { falsifier: None, satisfier: Some(lit(true)), }); - assert_eq!(lit(7).satisfy(&session)?, Some(or(lit(false), lit(true)))); + assert_eq!( + lit(true).satisfy(&dtype, &session)?, + Some(or(lit(false), lit(true))) + ); Ok(()) } #[test] fn unregistered_expression_has_no_rewrite() -> VortexResult<()> { - let session = VortexSession::empty().with::(); + let session = VortexSession::empty().with::(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); - assert_eq!(lit(7).falsify(&session)?, None); - assert_eq!(lit(7).satisfy(&session)?, None); + assert_eq!(lit(true).falsify(&dtype, &session)?, None); + assert_eq!(lit(true).satisfy(&dtype, &session)?, None); Ok(()) } + + #[test] + fn non_predicate_expression_errors() { + let session = VortexSession::empty().with::(); + let dtype = DType::Primitive(PType::I32, Nullability::NonNullable); + + assert!(lit(7).falsify(&dtype, &session).is_err()); + assert!(lit(7).satisfy(&dtype, &session).is_err()); + } } diff --git a/vortex-array/src/stats/session.rs b/vortex-array/src/stats/session.rs index da9fe9dc786..8b1dc639441 100644 --- a/vortex-array/src/stats/session.rs +++ b/vortex-array/src/stats/session.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: Copyright the Vortex contributors -//! Session state for stats rewrite rules. +//! Session state for stats APIs. use std::any::Any; use std::sync::Arc; @@ -18,23 +18,23 @@ use crate::stats::rewrite::StatsRewriteRuleRef; type StatsRewriteRuleSet = Arc<[StatsRewriteRuleRef]>; -/// Session state for stats rewrite rules. +/// Session state for stats APIs. #[derive(Debug, Default)] -pub struct StatsRewriteSession { - rules: RwLock>, +pub struct StatsSession { + rewrite_rules: RwLock>, } -impl StatsRewriteSession { +impl StatsSession { /// Register a stats rewrite rule. #[allow(dead_code)] - pub(crate) fn register(&self, rule: R) { - self.register_ref(Arc::new(rule)); + pub(crate) fn register_rewrite(&self, rule: R) { + self.register_rewrite_ref(Arc::new(rule)); } /// Register a shared stats rewrite rule. #[allow(dead_code)] - pub(crate) fn register_ref(&self, rule: StatsRewriteRuleRef) { - let mut rules = self.rules.write(); + pub(crate) fn register_rewrite_ref(&self, rule: StatsRewriteRuleRef) { + let mut rules = self.rewrite_rules.write(); let rule_id = rule.scalar_fn_id(); let mut updated_rules = rules .get(&rule_id) @@ -45,12 +45,15 @@ impl StatsRewriteSession { } /// Return the rewrite rules registered for `scalar_fn_id`. - pub(crate) fn rules_for(&self, scalar_fn_id: ScalarFnId) -> Option { - self.rules.read().get(&scalar_fn_id).cloned() + pub(crate) fn rewrite_rules_for( + &self, + scalar_fn_id: ScalarFnId, + ) -> Option { + self.rewrite_rules.read().get(&scalar_fn_id).cloned() } } -impl SessionVar for StatsRewriteSession { +impl SessionVar for StatsSession { fn as_any(&self) -> &dyn Any { self } @@ -60,11 +63,11 @@ impl SessionVar for StatsRewriteSession { } } -/// Extension trait for accessing stats rewrite session data. -pub(crate) trait StatsRewriteSessionExt: SessionExt { - /// Returns the stats rewrite rule registry. - fn stats_rewrites(&self) -> Ref<'_, StatsRewriteSession> { - self.get::() +/// Extension trait for accessing stats session data. +pub(crate) trait StatsSessionExt: SessionExt { + /// Returns the stats session state. + fn stats(&self) -> Ref<'_, StatsSession> { + self.get::() } } -impl StatsRewriteSessionExt for S {} +impl StatsSessionExt for S {} diff --git a/vortex/src/lib.rs b/vortex/src/lib.rs index 3da75c68a3b..8668de339cb 100644 --- a/vortex/src/lib.rs +++ b/vortex/src/lib.rs @@ -16,7 +16,7 @@ use vortex_array::optimizer::kernels::ArrayKernels; pub use vortex_array::scalar_fn; use vortex_array::scalar_fn::session::ScalarFnSession; use vortex_array::session::ArraySession; -use vortex_array::stats::session::StatsRewriteSession; +use vortex_array::stats::session::StatsSession; use vortex_io::session::RuntimeSession; use vortex_layout::session::LayoutSession; use vortex_session::VortexSession; @@ -168,7 +168,7 @@ impl VortexSessionDefault for VortexSession { .with::() .with::() .with::() - .with::() + .with::() .with::() .with::() .with::();