use vortex_array::ArrayRef;
use vortex_array::Canonical;
use vortex_array::aggregate_fn::fns::is_constant::is_constant;
use vortex_error::VortexResult;
use super::is_utf8_string;
use crate::CascadingCompressor;
use crate::builtins::StringConstantScheme;
use crate::builtins::constant::compress_constant_array_with_validity;
use crate::ctx::CompressorContext;
use crate::estimate::CompressionEstimate;
use crate::estimate::DeferredEstimate;
use crate::estimate::EstimateVerdict;
use crate::scheme::Scheme;
use crate::stats::ArrayAndStats;
impl Scheme for StringConstantScheme {
fn scheme_name(&self) -> &'static str {
"vortex.string.constant"
}
fn matches(&self, canonical: &Canonical) -> bool {
is_utf8_string(canonical)
}
fn expected_compression_ratio(
&self,
data: &mut ArrayAndStats,
ctx: CompressorContext,
) -> CompressionEstimate {
if ctx.is_sample() {
return CompressionEstimate::Verdict(EstimateVerdict::Skip);
}
let array_len = data.array().len();
let stats = data.string_stats();
if stats.value_count() == 0 {
debug_assert_eq!(stats.null_count() as usize, array_len);
return CompressionEstimate::Verdict(EstimateVerdict::AlwaysUse);
}
if stats.estimated_distinct_count().is_some_and(|c| c > 1) {
return CompressionEstimate::Verdict(EstimateVerdict::Skip);
}
CompressionEstimate::Deferred(DeferredEstimate::Callback(Box::new(
|compressor, data, _ctx| {
if is_constant(data.array(), &mut compressor.execution_ctx())? {
Ok(EstimateVerdict::AlwaysUse)
} else {
Ok(EstimateVerdict::Skip)
}
},
)))
}
fn compress(
&self,
_compressor: &CascadingCompressor,
data: &mut ArrayAndStats,
_ctx: CompressorContext,
) -> VortexResult<ArrayRef> {
compress_constant_array_with_validity(data.array())
}
}