|
11 | 11 | use vortex_error::VortexResult; |
12 | 12 |
|
13 | 13 | use crate::aggregate_fn::AggregateFnRef; |
| 14 | +use crate::aggregate_fn::fns::all_nan::AllNan; |
| 15 | +use crate::aggregate_fn::fns::all_non_nan::AllNonNan; |
| 16 | +use crate::aggregate_fn::fns::all_non_null::AllNonNull; |
| 17 | +use crate::aggregate_fn::fns::all_null::AllNull; |
14 | 18 | use crate::dtype::DType; |
15 | 19 | use crate::expr::Expression; |
| 20 | +use crate::expr::eq; |
16 | 21 | use crate::expr::lit; |
17 | 22 | use crate::expr::stats::Stat; |
18 | 23 | use crate::expr::traversal::NodeExt; |
19 | 24 | use crate::expr::traversal::Transformed; |
20 | 25 | use crate::scalar::Scalar; |
| 26 | +use crate::scalar_fn::EmptyOptions; |
| 27 | +use crate::scalar_fn::ScalarFnVTableExt; |
21 | 28 | use crate::scalar_fn::fns::stat::StatFn; |
| 29 | +use crate::scalar_fn::internal::row_count::RowCount; |
22 | 30 |
|
23 | 31 | /// A target that can bind abstract statistics to concrete expressions. |
24 | 32 | pub trait StatBinder { |
@@ -56,12 +64,53 @@ pub trait StatBinder { |
56 | 64 | aggregate_fn: &AggregateFnRef, |
57 | 65 | stat_dtype: &DType, |
58 | 66 | ) -> VortexResult<Option<Expression>> { |
| 67 | + if aggregate_fn.is::<AllNan>() { |
| 68 | + let Some(nan_count) = self.bind_legacy_stat(input, Stat::NaNCount)? else { |
| 69 | + return Ok(None); |
| 70 | + }; |
| 71 | + return Ok(Some(eq(nan_count, RowCount.new_expr(EmptyOptions, [])))); |
| 72 | + } |
| 73 | + |
| 74 | + if aggregate_fn.is::<AllNonNan>() { |
| 75 | + let Some(nan_count) = self.bind_legacy_stat(input, Stat::NaNCount)? else { |
| 76 | + return Ok(None); |
| 77 | + }; |
| 78 | + return Ok(Some(eq(nan_count, lit(0u64)))); |
| 79 | + } |
| 80 | + |
| 81 | + if aggregate_fn.is::<AllNull>() { |
| 82 | + let Some(null_count) = self.bind_legacy_stat(input, Stat::NullCount)? else { |
| 83 | + return Ok(None); |
| 84 | + }; |
| 85 | + return Ok(Some(eq(null_count, RowCount.new_expr(EmptyOptions, [])))); |
| 86 | + } |
| 87 | + |
| 88 | + if aggregate_fn.is::<AllNonNull>() { |
| 89 | + let Some(null_count) = self.bind_legacy_stat(input, Stat::NullCount)? else { |
| 90 | + return Ok(None); |
| 91 | + }; |
| 92 | + return Ok(Some(eq(null_count, lit(0u64)))); |
| 93 | + } |
| 94 | + |
59 | 95 | let Some(stat) = Stat::from_aggregate_fn(aggregate_fn) else { |
60 | 96 | return Ok(None); |
61 | 97 | }; |
62 | 98 | self.bind_stat(input, stat, stat_dtype) |
63 | 99 | } |
64 | 100 |
|
| 101 | + /// Bind one of the legacy stat slots for `input`. |
| 102 | + fn bind_legacy_stat( |
| 103 | + &mut self, |
| 104 | + input: &Expression, |
| 105 | + stat: Stat, |
| 106 | + ) -> VortexResult<Option<Expression>> { |
| 107 | + let input_dtype = input.return_dtype(self.scope())?; |
| 108 | + let Some(stat_dtype) = stat.dtype(&input_dtype) else { |
| 109 | + return Ok(None); |
| 110 | + }; |
| 111 | + self.bind_stat(input, stat, &stat_dtype) |
| 112 | + } |
| 113 | + |
65 | 114 | /// Expression to use when a stat is unavailable. |
66 | 115 | /// |
67 | 116 | /// The default is a nullable null literal, which preserves three-valued |
|
0 commit comments