-
Notifications
You must be signed in to change notification settings - Fork 344
feat(core): Add support for _file column
#1824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
crates/iceberg/src/scan/mod.rs
Outdated
| /// // Select regular columns along with the file path | ||
| /// let scan = table | ||
| /// .scan() | ||
| /// .select(["id", "name", RESERVED_COL_NAME_FILE]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we ask for _file column without having to explicitly list all the other columns? E.g. get me all columns + _file. There should be some shortcut for this.
_file column_file column
…erg-rust into feature/gb/file-column
liurenjie1024
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @gbrgr for this pr. But I think we need to rethink how to compute the _file, _pos metadata column. While it's somehow trivial to compute _file, it's non trivial to compute _pos efficient, since when we read parquet files, we have filtered out some row groups. I think the best way is to push reading these two columns to arrow-rs.
crates/iceberg/src/arrow/reader.rs
Outdated
| pub(crate) const RESERVED_FIELD_ID_FILE: i32 = 2147483646; | ||
|
|
||
| /// Column name for the file path metadata column per Iceberg spec | ||
| pub(crate) const RESERVED_COL_NAME_FILE: &str = "_file"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add a metadata_columns module similar to what java did: https://github.com/apache/iceberg/blob/bb32b90c4ad63f037f0bda197cc53fb08c886934/core/src/main/java/org/apache/iceberg/MetadataColumns.java#L2
@liurenjie1024 I agree for How do we go forward with rethinking this, what would be the action items for us? |
…erg-rust into feature/gb/file-column
liurenjie1024
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @gbrgr for this pr, I left some comments to improve.
crates/iceberg/src/scan/mod.rs
Outdated
| /// # Ok(()) | ||
| /// # } | ||
| /// ``` | ||
| pub const RESERVED_COL_NAME_FILE: &str = RESERVED_COL_NAME_FILE_INTERNAL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will have more metadata columns, so I would prefert to put these definition in sth like metadata_columns module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a new module
crates/iceberg/src/scan/mod.rs
Outdated
| if let Some(column_names) = self.column_names.as_ref() { | ||
| for column_name in column_names { | ||
| // Skip reserved columns that don't exist in the schema | ||
| if column_name == RESERVED_COL_NAME_FILE_INTERNAL { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have sth like is_metadata_column_name() in metadata_columns module, and useis_metadata_column_name so that we could avoid such changes when we add more metadata columns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in the new module
crates/iceberg/src/arrow/reader.rs
Outdated
|
|
||
| /// Helper function to add a `_file` column to a RecordBatch at a specific position. | ||
| /// Takes the array, field to add, and position where to insert. | ||
| fn create_file_field_at_position( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this approach is not extensible. I prefer what's similar in this pr:
- Add
constant_mapforArrowReader - Add another variant of
RecordBatchTransformerto handle constant field like_file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I sketched an approach in the record batch transformer, I took the path of the transformer just having a constant_map stored which can be populated by the reader.
Hi, @vustef I also agree that we should put |
| let vals: Vec<Option<f64>> = vec![None; num_rows]; | ||
| Arc::new(Float64Array::from(vals)) | ||
| } | ||
| (DataType::RunEndEncoded(_, _), Some(PrimitiveLiteral::String(value))) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we in general encode constant columns as REE? Or should we make this custom per field? For the file path it definitely makes sense to run-end encode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit random to me that only strings use REE in primitive_literal_to_arrow_type below. Yes, they might use the most memory otherwise, but other types also have similar kind of redundancy suitable for the REE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that is why I am pointing it out here. If the reviewers are fine with it, I'd go with REE everywhere.
vustef
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the new API with the with_constant. Curious to see what Renjie thinks.
| // This is a virtual field - add it with the constant value | ||
| return Ok(ColumnSource::Add { | ||
| value: Some(constant_value.clone()), | ||
| target_type: Self::primitive_literal_to_arrow_type(constant_value)?, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels a bit redundant to have to not only lookup constants_map twice, but call primitive_literal_to_arrow_type twice (once here and once in generate_batch_transform)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I store fields now instead of constants, the double lookup is not easily avoidable in the current grand scheme of things, and should not hurt.
| let vals: Vec<Option<f64>> = vec![None; num_rows]; | ||
| Arc::new(Float64Array::from(vals)) | ||
| } | ||
| (DataType::RunEndEncoded(_, _), Some(PrimitiveLiteral::String(value))) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit random to me that only strings use REE in primitive_literal_to_arrow_type below. Yes, they might use the most memory otherwise, but other types also have similar kind of redundancy suitable for the REE.
| /// The field ID of the metadata column, or an error if the column name is not recognized | ||
| pub fn get_metadata_field_id(column_name: &str) -> Result<i32> { | ||
| match column_name { | ||
| RESERVED_COL_NAME_FILE => Ok(RESERVED_FIELD_ID_FILE), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wish that we could somehow reuse the mapping from get_metadata_column_name, to form some bidirectional 1-1 mapping. Perhaps some macro magic or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possible, but I don't think it pays off for a hand full of fields.
Which issue does this PR close?
_filemetadata column #1766.What changes are included in this PR?
Integrates virtual field handling for the
_filemetadata column intoRecordBatchTransformerusing a pre-computed constants map, eliminating post-processing and duplicate lookups.Key Changes
New
metadata_columns.rsmodule: Centralized utilities for metadata columnsRESERVED_FIELD_ID_FILE,RESERVED_COL_NAME_FILEget_metadata_column_name(),get_metadata_field_id(),is_metadata_field(),is_metadata_column_name()Enhanced
RecordBatchTransformer:constant_fields: HashMap<i32, (DataType, PrimitiveLiteral)>- pre-computed during initializationwith_constant()method - computes Arrow type once during setupDataType::RunEndEncodedfor constant strings (memory efficient)Simplified
reader.rs:project_field_ids(including virtual) to RecordBatchTransformerwith_constant()call to register_filecolumnUpdated
scan/mod.rs:is_metadata_column_name()andget_metadata_field_id()instead of hardcoded checksAre these changes tested?
Yes, comprehensive tests have been added to verify the functionality:
New Tests (7 tests added)
Table Scan API Tests (7 tests)
test_select_with_file_column- Verifies basic functionality of selecting_filewith regular columnstest_select_file_column_position- Verifies column ordering is preservedtest_select_file_column_only- Tests selecting only the_filecolumntest_file_column_with_multiple_files- Tests multiple data files scenariotest_file_column_at_start- Tests_fileat position 0test_file_column_at_end- Tests_fileat the last positiontest_select_with_repeated_column_names- Tests repeated column selection