Project statistics according to this projection. For example, for a projection `SELECT a AS x, b + 1 AS y`, where `a` is at index 0 and `b` is at index 1, if the input statistics has column statistics for columns `a`, `b`, and `c`, the output statistics would have column statistics for columns `x` and `y`. # Example ```rust use arrow::datatypes::{DataType, Field, Schema}; use datafusion_common::
(
&self,
mut stats: Statistics,
output_schema: &Schema,
)
| 652 | /// } |
| 653 | /// ``` |
| 654 | pub fn project_statistics( |
| 655 | &self, |
| 656 | mut stats: Statistics, |
| 657 | output_schema: &Schema, |
| 658 | ) -> Result<Statistics> { |
| 659 | let mut column_statistics = Vec::with_capacity(self.exprs.len()); |
| 660 | |
| 661 | for proj_expr in self.exprs.iter() { |
| 662 | let expr = &proj_expr.expr; |
| 663 | let col_stats = if let Some(col) = expr.downcast_ref::<Column>() { |
| 664 | std::mem::take(&mut stats.column_statistics[col.index()]) |
| 665 | } else if let Some(literal) = expr.downcast_ref::<Literal>() { |
| 666 | // Handle literal expressions (constants) by calculating proper statistics |
| 667 | let data_type = expr.data_type(output_schema)?; |
| 668 | |
| 669 | if literal.value().is_null() { |
| 670 | let null_count = match stats.num_rows { |
| 671 | Precision::Exact(num_rows) => Precision::Exact(num_rows), |
| 672 | _ => Precision::Absent, |
| 673 | }; |
| 674 | |
| 675 | ColumnStatistics { |
| 676 | min_value: Precision::Exact(literal.value().clone()), |
| 677 | max_value: Precision::Exact(literal.value().clone()), |
| 678 | distinct_count: Precision::Exact(1), |
| 679 | null_count, |
| 680 | sum_value: Precision::Exact(literal.value().clone()), |
| 681 | byte_size: Precision::Exact(0), |
| 682 | } |
| 683 | } else { |
| 684 | let value = literal.value(); |
| 685 | let distinct_count = Precision::Exact(1); |
| 686 | let null_count = Precision::Exact(0); |
| 687 | |
| 688 | let byte_size = if let Some(byte_width) = data_type.primitive_width() |
| 689 | { |
| 690 | stats.num_rows.multiply(&Precision::Exact(byte_width)) |
| 691 | } else { |
| 692 | // Complex types depend on array encoding, so set to Absent |
| 693 | Precision::Absent |
| 694 | }; |
| 695 | |
| 696 | let widened_sum = Precision::Exact(value.clone()).cast_to_sum_type(); |
| 697 | let sum_value = widened_sum |
| 698 | .get_value() |
| 699 | .and_then(|sum| { |
| 700 | Precision::<ScalarValue>::from(stats.num_rows) |
| 701 | .cast_to(&sum.data_type()) |
| 702 | .ok() |
| 703 | }) |
| 704 | .map(|row_count| widened_sum.multiply(&row_count)) |
| 705 | .unwrap_or(Precision::Absent); |
| 706 | |
| 707 | ColumnStatistics { |
| 708 | min_value: Precision::Exact(value.clone()), |
| 709 | max_value: Precision::Exact(value.clone()), |
| 710 | distinct_count, |
| 711 | null_count, |