[python] Add Split.to_dict() to expose planned split contents#455
[python] Add Split.to_dict() to expose planned split contents#455XiaoHongbo-Hope wants to merge 4 commits into
Conversation
a1c8b00 to
becb6aa
Compare
Let a non-Rust reader (e.g. pypaimon) rebuild its own DataSplit from a Rust-planned split and read the files directly, without re-running its own scan planning. to_dict() exposes bucket / bucket_path / total_buckets / partition / raw_convertible and, per data file, the fully-resolved file_path plus scalar metadata (schema_id, level, sequence numbers, first_row_id, write_cols, creation_time, ...) and aligned per-file deletion files. partition is the serialized BinaryRow, byte-identical to a manifest _PARTITION. Planning-only statistics (key/value stats, min/max key) are omitted since planning already happened. Tested via test_split_to_dict_exposes_fields and test_split_to_dict_partition_and_reads.
becb6aa to
2b534b3
Compare
|
Thanks @XiaoHongbo-Hope! A question on necessity first. The direction of the read effort (#413) is to let pypaimon run its DataFrame read on the Rust core — initially as a basic, opt-in path behind a config flag, not a wholesale replacement, so it can mature alongside the pure-Python path. In that model Rust both plans and reads: PR3 already exposes
So: what's the use case for exposing split internals? If it's for a Rust-plans / Python-reads path, I think we should align on that direction first — otherwise it risks pulling us away from the opt-in Rust read path we're building toward. |
Thanks, Junrui. Got your concern, will discuss with Jingsong and then back to you. |
|
@JunRuiLee Thanks Junrui. My view: the read side can be handled by adding more workers in production, but plan runs on the driver. And It's additive and opt-in — no storage-format change — and it doesn't block #413; once full-Rust read lands, this just becomes an alternate/interim path. |
JingsongLi
left a comment
There was a problem hiding this comment.
Do you need to use Python? Should we directly let AI see how to design cross language calls? For example, designing a cross language binary format for Split?
… binary) Expose a planned split as the standard Java DataSplit#serialize (version 8) binary instead of a Python-only dict, so any Paimon reader (pypaimon, Java) can rebuild it without re-planning. DataSplit::serialize() writes the v8 framing plus each DataFileMeta as a BinaryRow (nested SimpleStats, string arrays, inline-compact fields). Verified byte-identical to Paimon's compatibility/datasplit-v8 fixture (testdata/datasplit_v8.bin).
…writeUTF serialize() now errors instead of silently dropping row ranges: a split from a row-id / global-index / vector plan has no v8 representation, so serializing would widen it and read extra rows. write_java_utf now emits true Java modified UTF-8 (NUL -> C0 80, supplementary chars via surrogate pairs) with a 65535-byte length check, matching DataOutput#writeUTF, instead of raw UTF-8 that could silently corrupt or wrap.
|
Let's create an unified protocol: apache/paimon#8482 |
…h path Add serialize() to datafusion.pyi so type checkers and stub users see the new API. Add a unit test for the BinaryArray var-length (element > 7 bytes) branch, which the datasplit-v8 fixture (all elements inline) does not exercise.
Purpose
Add Split.to_dict() to the Python bindings so a non-Rust reader (e.g. pypaimon) can rebuild its own split from a Rust-planned split and read the files directly — planning runs in Rust (the serial, driver-side bottleneck), reading stays in the existing reader, no re-planning.
Brief change log
PySplit::to_dict() exposes a planned split as a plain dict — bucket / paths / partition plus per-file metadata (file_path, schema_id, first_row_id, write_cols, …) and deletion files. Planning-only stats omitted.
Tests
test_split_to_dict_exposes_fields, test_split_to_dict_partition_and_reads.API and Format
Additive — new Split.to_dict() Python method. No storage-format change.
Documentation
Covered by the method docstring.