(
projected_sort_order: &LexOrdering, // Sort order with respect to projected schema
projected_schema: &SchemaRef, // Projected schema
projection: Option<&[usize]>, // In
| 67 | } |
| 68 | |
| 69 | pub fn new_from_files<'a>( |
| 70 | projected_sort_order: &LexOrdering, // Sort order with respect to projected schema |
| 71 | projected_schema: &SchemaRef, // Projected schema |
| 72 | projection: Option<&[usize]>, // Indices of projection in full table schema (None = all columns) |
| 73 | files: impl IntoIterator<Item = &'a PartitionedFile>, |
| 74 | ) -> Result<Self> { |
| 75 | let Some(statistics_and_partition_values) = files |
| 76 | .into_iter() |
| 77 | .map(|file| { |
| 78 | file.statistics |
| 79 | .as_ref() |
| 80 | .zip(Some(file.partition_values.as_slice())) |
| 81 | }) |
| 82 | .collect::<Option<Vec<_>>>() |
| 83 | else { |
| 84 | return plan_err!("Parquet file missing statistics"); |
| 85 | }; |
| 86 | |
| 87 | // Helper function to get min/max statistics for a given column of projected_schema |
| 88 | let get_min_max = |i: usize| -> Result<(Vec<ScalarValue>, Vec<ScalarValue>)> { |
| 89 | Ok(statistics_and_partition_values |
| 90 | .iter() |
| 91 | .map(|(s, pv)| { |
| 92 | if i < s.column_statistics.len() { |
| 93 | s.column_statistics[i] |
| 94 | .min_value |
| 95 | .get_value() |
| 96 | .cloned() |
| 97 | .zip(s.column_statistics[i].max_value.get_value().cloned()) |
| 98 | .ok_or_else(|| plan_datafusion_err!("statistics not found")) |
| 99 | } else { |
| 100 | let partition_value = &pv[i - s.column_statistics.len()]; |
| 101 | Ok((partition_value.clone(), partition_value.clone())) |
| 102 | } |
| 103 | }) |
| 104 | .collect::<Result<Vec<_>>>()? |
| 105 | .into_iter() |
| 106 | .unzip()) |
| 107 | }; |
| 108 | |
| 109 | let Some(sort_columns) = |
| 110 | sort_columns_from_physical_sort_exprs(projected_sort_order) |
| 111 | else { |
| 112 | return plan_err!("sort expression must be on column"); |
| 113 | }; |
| 114 | |
| 115 | // Project the schema & sort order down to just the relevant columns |
| 116 | let min_max_schema = Arc::new( |
| 117 | projected_schema |
| 118 | .project(&(sort_columns.iter().map(|c| c.index()).collect::<Vec<_>>()))?, |
| 119 | ); |
| 120 | |
| 121 | let min_max_sort_order = projected_sort_order |
| 122 | .iter() |
| 123 | .zip(sort_columns.iter()) |
| 124 | .enumerate() |
| 125 | .map(|(idx, (sort_expr, col))| { |
| 126 | let expr = Arc::new(Column::new(col.name(), idx)); |
nothing calls this directly
no test coverage detected