etseidl commented on code in PR #10842:
URL: https://github.com/apache/arrow-rs/pull/10842#discussion_r3867360751
##########
parquet/src/file/metadata/mod.rs:
##########
@@ -362,18 +283,460 @@ impl PageIndex {
/// Returns:
/// * `Some(&Vec<PageLocation>)` - Vector of page locations if offset
index exists
/// * `None` - Offset index not available
- pub fn page_locations(
+ fn page_locations(
&self,
row_group_idx: usize,
column_idx: usize,
) -> Option<&Vec<PageLocation>> {
- if let Some(offset_indexes) = self.offset_indexes.as_ref() {
- let rg = offset_indexes.get(row_group_idx)?;
- let off_idx = rg.get(column_idx)?.as_ref()?;
- Some(off_idx.page_locations())
+ Some(
+ self.offset_index(row_group_idx, column_idx)?
+ .page_locations(),
+ )
+ }
+
+ /// Returns a reference to the trait object as `&dyn Any` for downcasting
+ ///
+ /// This allows downcasting to concrete types when needed (e.g., for
serialization)
+ fn as_any(&self) -> &dyn std::any::Any;
+}
+
+/// Provides convenient access to page index data for a specific row group
+///
+/// This struct wraps a [`PageIndexProvider`] and automatically applies the
row group
+/// index, simplifying access to column and offset indexes for a single row
group.
+/// It is primarily used by readers to avoid repeatedly passing the row group
index
+/// when accessing page-level metadata.
+///
+/// # Example
+///
+/// ```
+/// use parquet::file::metadata::ParquetMetaData;
+/// # use parquet::errors::Result;
+///
+/// fn process_row_group_pages(metadata: &ParquetMetaData, row_group_idx:
usize) -> Result<()> {
+/// if let Some(page_index) = metadata.page_index() {
+/// // Create a row-group-specific view
+/// let rg_page_index =
parquet::file::metadata::RowGroupPageIndex::new(
+/// row_group_idx,
+/// metadata.page_index().cloned(),
+/// );
+///
+/// // Now access column indexes without specifying row_group_idx each
time
+/// for col_idx in
0..metadata.file_metadata().schema_descr().num_columns() {
+/// if let Some(col_idx_data) =
rg_page_index.column_index(col_idx) {
+/// println!("Column {} has {} pages", col_idx,
col_idx_data.num_pages());
+/// }
+/// }
+/// }
+/// Ok(())
+/// }
+/// ```
+#[derive(Debug)]
+pub struct RowGroupPageIndex {
+ row_group_idx: usize,
+ page_index: Option<Arc<dyn PageIndexProvider>>,
+}
+
+impl RowGroupPageIndex {
+ /// Creates a new [`RowGroupPageIndex`] for the specified row group
+ ///
+ /// # Arguments
+ ///
+ /// * `row_group_idx` - The index of the row group within the file
+ /// * `page_index` - Optional page index provider containing the index data
+ pub fn new(row_group_idx: usize, page_index: Option<Arc<dyn
PageIndexProvider>>) -> Self {
+ Self {
+ row_group_idx,
+ page_index,
+ }
+ }
+
+ /// Returns the column index for a specific column in this row group
+ ///
+ /// This is a convenience method that wraps
[`PageIndexProvider::column_index`],
+ /// automatically applying the row group index stored in this struct.
+ ///
+ /// # Returns
+ ///
+ /// * `Some(&ColumnIndexMetaData)` - Column index is available with
page-level statistics
+ /// * `None` - Index unavailable (no page index, column out of bounds, or
no statistics)
+ ///
+ /// # See Also
+ ///
+ /// * [`PageIndexProvider::column_index`] for more details on column
indexes
+ pub fn column_index(&self, column_idx: usize) ->
Option<&ColumnIndexMetaData> {
+ self.page_index
+ .as_ref()?
+ .column_index(self.row_group_idx, column_idx)
+ }
+
+ /// Returns the offset index for a specific column in this row group
+ ///
+ /// This is a convenience method that wraps
[`PageIndexProvider::offset_index`],
+ /// automatically applying the row group index stored in this struct.
+ ///
+ /// # Returns
+ ///
+ /// * `Some(&OffsetIndexMetaData)` - Offset index is available with page
locations
+ /// * `None` - Index unavailable (no page index, column out of bounds)
+ ///
+ /// # See Also
+ ///
+ /// * [`PageIndexProvider::offset_index`] for more details on offset
indexes
+ pub fn offset_index(&self, column_idx: usize) ->
Option<&OffsetIndexMetaData> {
+ self.page_index
+ .as_ref()?
+ .offset_index(self.row_group_idx, column_idx)
+ }
+
+ /// Returns the physical locations of all data pages for a specific column
in this row group
+ ///
+ /// This is a convenience method that wraps
[`PageIndexProvider::page_locations`],
+ /// automatically applying the row group index stored in this struct.
+ ///
+ /// This enables direct I/O to specific pages without reading the entire
column chunk.
+ ///
+ /// # Returns
+ ///
+ /// * `Some(&Vec<PageLocation>)` - Vector of page locations if offset
index exists
+ /// * `None` - Offset index not available for this column
+ ///
+ /// # See Also
+ ///
+ /// * [`PageIndexProvider::page_locations`] for more details on page
locations
+ pub fn page_locations(&self, column_idx: usize) ->
Option<&Vec<PageLocation>> {
+ Some(self.offset_index(column_idx)?.page_locations())
+ }
+
+ /// Returns the expected number of data pages for a specific column in
this row group
+ ///
+ /// This count includes only data pages, not dictionary pages or other
metadata pages.
+ ///
+ /// This is a convenience method that wraps
[`PageIndexProvider::num_data_pages`],
+ /// automatically applying the row group index stored in this struct.
+ ///
+ /// # Returns
+ ///
+ /// * `Some(usize)` - Number of data pages if any index is available
+ /// * `None` - No index information available for this column
+ ///
+ /// # See Also
+ ///
+ /// * [`PageIndexProvider::num_data_pages`] for more details
+ pub fn num_data_pages(&self, column_idx: usize) -> Option<usize> {
+ self.page_index
+ .as_ref()?
+ .num_data_pages(self.row_group_idx, column_idx)
+ }
+}
+
+/// Struct to encapsulate the Parquet [Page Index]
+///
+/// This struct provides a dense representation of the Page Index. It is
+/// used internally by this crate when assembling and writing the Page
+/// Index. It is also the default implmentation of the [`PageIndexProvider`]
+/// contained in the [`ParquetMetaData`].
+///
+/// # Example: Constructing a synthetic `PageIndex`
+///
+/// This example builds a [`ParquetMetaData`] for a file with a single row
+/// group containing a single `BYTE_ARRAY` column with one data page, and
+/// attaches a matching `PageIndex`, as might be done in tests that
+/// exercise page-level statistics handling.
+///
+/// ```
+/// # use std::sync::Arc;
+/// # use parquet::basic::{BoundaryOrder, Type as PhysicalType};
+/// # use parquet::file::metadata::{
+/// # ColumnChunkMetaData, ColumnIndexBuilder, FileMetaData,
OffsetIndexBuilder,
+/// # PageIndexBuilder, ParquetMetaData, RowGroupMetaData,
+/// # };
+/// # use parquet::schema::types::{SchemaDescriptor, Type};
+/// // Create metadata for a file with a single row group containing a
Review Comment:
done in
https://github.com/apache/arrow-rs/pull/10842/commits/9dff481e6ab49719a3b6e00f7078056a2fe165af
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]