branch-4.1:[feat](paimon) support paimon-rust reader on BE - #66227
Open
pzhdfy wants to merge 4 commits into
Open
branch-4.1:[feat](paimon) support paimon-rust reader on BE#66227pzhdfy wants to merge 4 commits into
pzhdfy wants to merge 4 commits into
Conversation
added 4 commits
July 29, 2026 14:24
Add PAIMON_RUST source tarball (paimon-rust-2fb5e49) and a build_paimon_rust
helper that builds paimon-c via cargo, generates the C header from the Rust
extern "C" surface via cbindgen (installed via cargo install when missing),
and installs libpaimon_c.a + paimon.h under ${TP_INSTALL_DIR}.
The build script writes a temporary cbindgen.toml at build time so we don't
have to patch the upstream tree, and pins Rust/Cargo to 1.91.0 (auto-installed
via rustup when available) so builds are reproducible across environments.
libpaimon_c.a (built from paimon-rust) brings in Rust compiler_builtins that would otherwise steal libm symbols. Place libm before it so the final linker resolves C math symbols from the system library first.
Add PaimonRustReader that reads Paimon splits on BE via the paimon-rust C
bindings (libpaimon_c), plumbed into the FORMAT_JNI paimon dispatch alongside
PaimonJniReader and PaimonCppReader.
Pipeline on BE:
catalog_create(warehouse) -> catalog_get_table(db, table)
-> read_builder -> projection -> filter
-> plan_from_split_bytes(FE split) -> read -> arrow record batch stream
FE emits PAIMON_RUST as the reader type when enable_paimon_rust_reader is set
(higher priority than enable_paimon_cpp_reader). Both native paimon readers
consume the same DataSplit binary wire format, so non-DataSplit inputs
transparently fall back to PAIMON_JNI. FE additionally ships db/table so BE
can open the paimon catalog.
The FE-planned split bytes are deserialized directly into a one-split plan
via paimon_plan_from_split_bytes so each scanner reads exactly the split it
was assigned rather than replanning the whole table.
Push-down conjuncts are converted to a paimon-rust filter predicate via
PaimonRustPredicateConverter after the table opens (paimon_predicate_*
functions need the live table handle to resolve fields from the schema).
Conjuncts that cannot be represented are dropped silently — the engine
still re-applies the full conjunct list.
Adds:
- BE: format/table/paimon_rust_reader.{h,cpp}
format/table/paimon_rust_predicate_converter.{h,cpp}
test/format/table/paimon_rust_reader_test.cpp
- FE: SessionVariable.enable_paimon_rust_reader (session var, fuzzy)
PaimonScanNode dispatch (RUST > CPP > JNI when native split)
- Thrift: TPaimonReaderType.PAIMON_RUST = 3
TQueryOptions.enable_paimon_rust_reader = 227
Remap common OSS/S3 hadoop-style credential keys (fs.oss.*, fs.s3a.*) to AWS_ACCESS_KEY / AWS_SECRET_KEY / AWS_ENDPOINT / ... in _build_options so OSS/S3-backed paimon tables can authenticate through the paimon-rust FileIO.
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
11 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Related PR: #65883 (for master)
we current will keep iterating on branch-4.1, because our internal doris forks from branch-4.1
and the pr for master will be closed later, becuase paimon-rust reader is based on scanner v1, and all the scanner v1 code will be removed, we will refactor paimon-rust reader to scanner v2 in the future, and open a new pull request.
Problem Summary:
Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the
paimon-rustC bindings (libpaimon_c.a, statically linked). Rust Reader is gated by the session variableenable_paimon_rust_reader(defaultfalse).attention:
when using enable_paimon_rust_reader=true, must set enable_file_scanner_v2=false;
because now will all route to scanner_v2 when enable_file_scanner_v2=true; after #66008
Compared with the existing readers:
deserialized in-process and rows arrive via the Arrow C Data Interface,
which shortens the scanner critical section and removes JNI copy cost.
(schema, DV, snapshots, predicates), so features/fixes propagate may be more fast and different.
Our goal is not to replace paimon-cpp, just give user a choice to switch at query time.
Architecture
FE (
PaimonScanNode): whenenable_paimon_rust_readeris on and the splitis a
DataSplit, encode it with paimon's native binary serialization(
PaimonUtil.encodeDataSplitToString), stamp the range withTPaimonReaderType.PAIMON_RUST, and attachdb_name/table_name/paimon_tableso BE can open the table through a catalog.BE (
FileScanner::_get_next_reader): dispatches onreader_type. OnPAIMON_RUSTit instantiatesPaimonRustReader, which:paimon_catalog_create({warehouse, metastore=filesystem, ...})/<db>.db/<table>(paimon FS convention).paimon_identifier_new(db, tbl)→paimon_catalog_get_tablepaimon_table_new_read_builder→ projection (case-insensitive) →optional filter from
PaimonRustPredicateConverter(translates Dorispush-down conjuncts into paimon-rust predicates, best-effort so any
non-representable conjunct is silently dropped and re-applied by the
engine).
paimon_plan_from_split_bytes(split_bytes)— one BE scanner readsexactly its FE-planned split (no re-planning).
paimon_table_read_to_arrow→ streamed arrow record batches → block.Partition columns are back-filled in
on_after_read_blockfromFE-provided
columns_from_path*, mirroringPaimonCppReader. OSS/S3hadoop-style credential keys (
fs.oss.*/fs.s3a.*) are remapped toAWS_ACCESS_KEY/AWS_ENDPOINT/ ... so paimon-rust's FileIO canauthenticate.
Thirdparty
paimon-rust-2fb5e49(built with Rust 1.91.0, featurepaimon/storage-hdfs,--locked).cbindgenand regenerates the C header from the Rustextern "C" surface via a locally-written
cbindgen.toml(
language=C, include_guard=PAIMON_C_H, pragma_once=true, cpp_compat=true),so the shipped
paimon.halways matches the built.a.Release note
Add
enable_paimon_rust_readersession variable. When enabled, Paimonnon-native reads on BE use the paimon-rust reader instead of paimon-jni /
paimon-cpp.
Check List (For Author)
Test
CREATE CATALOG paimon_fs PROPERTIES ("type"="paimon", "paimon.catalog.type"="filesystem", "warehouse"="file:///media/ssd1/test_paimon/warehouse/");when using "warehouse"="hdfs://.../warehouse/", add HADOOP_CONF_DIR=xx in be.confSET enable_paimon_rust_reader=true; SET force_jni_scanner=1;set enable_file_scanner_v2=0;SELECTfrom a partitioned/DV paimon table; results must matchenable_paimon_rust_reader=false and force_jni_scanner=0 and enable_file_scanner_v2=1.SELECT count(*)— should hit table-level row count push-down.WHERE a=1 AND b>2— BE INFO log should showpaimon-rust predicate pushdown: applied.Behavior changed:
enable_paimon_rust_reader(defaultfalse); when off, all paths are unchanged.Does this need documentation?
Check List (For Reviewer who merge this PR)