Repository navigation
Conversation
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
| } | ||
| identifier_ptr identifier(id_res.identifier); | ||
|
|
||
| paimon_result_get_table tbl_res = |
There was a problem hiding this comment.
BE should not reopen the catalog to obtain the table here. FE has already resolved and serialized the Paimon table in TFileScanRangeParams.serialized_table and planned the exact split; the JNI reader restores that table context and executes the split directly. Re-resolving it through paimon_catalog_get_table may observe different table/schema state and unnecessarily restricts this path to the derived filesystem-catalog layout. Please deserialize/restore the FE-provided table information for the Rust reader instead of doing a catalog lookup in BE.
There was a problem hiding this comment.
跟paimon_rust社区同学沟通回复(后面发布后 会切换table获取接口):
paimon-rust 将提供通用的 catalog-free 接口 paimon_table_from_schema_json。Doris FE 直接传递 table_path、完整的 TableSchema JSON、database/table_name、branch 和文件系统访问配置,Rust 侧直接构造 Table,不创建 Catalog,也不会重新加载
或覆盖 FE 已解析的 schema。branch 仅决定 schema/snapshot/tag 的读取路径,读取仍可使用 FE 生成的 splits;如需 Rust 侧 time travel,可继续使用现有的 read-builder options。POC 代码已推送到 JunRuiLee/paimon-rust 的 feat/resolved-table-c-api 分
支,commit 为 9c39365。
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
…nstruction
Add org.apache.paimon.table.TableDescriptor (paimon-api) and
TableDescriptorSerializer (paimon-core): a slim, versioned JSON wire form that
serializes a resolved FileStoreTable into {path, full TableSchema, options} so a
non-Java reader (e.g. paimon-rust / paimon-cpp) can rebuild the table for
scan/read without a catalog lookup or JVM-only state. Non-main branches are
carried verbatim so a reader can fail fast rather than silently read main.
Motivated by the Doris Paimon-external-table integration (apache/doris#65883),
where the compute node re-resolves the table through a catalog; this lets it
consume the FE-planned table instead.
|
@pzhdfy Thank you for the contibution! Just to clarify, paimon-cpp has already been donated from the Alibaba repository Alibaba repo to the Apache repo and is currently in the release process. It is now the official Paimon standard-format implementation under the Apache community, and we expect it to continue tracking the upstream standard as the Paimon community evolves. So, I’m not sure “bespoke C++ port” is a accurate wording here. Also, paimon-cpp has been widely used in production within Alibaba for about 2 years, with both stability and performance validated in large-scale scenarios. Given that Doris’s backend is implemented in C++, I wonder whether the C++ path might be a more natural fit to prioritize here. |
3.paimon-rust is 2x~3x faster than paimon-java when read MOR ,and close to doris native reader when read DV( only slow 10%,because arrow convert to doris block)
|
|
@pzhdfy Thanks for the reply. If
Looking forward to seeing more testing and results. |
Port two behaviors from paimon_cpp_reader to keep paimon-rust reader on feature parity with the cpp path: - Fill partition columns from FE-provided `columns_from_path*` in `on_before_init_reader` / `on_after_read_block` (defensive: paimon-rust arrow output may not carry partition columns). - 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.
Rebase onto master's connector refactor migrated the rust reader branch to
PaimonScanRange, but two things were dropped from the original
PaimonScanNode.setPaimonParams:
1. paimon_split for PAIMON_RUST / PAIMON_CPP must be the Paimon
native binary encoding (DataSplit.serialize) — not
InstantiationUtil.serializeObject — because paimon-rust decodes
with paimon_plan_from_split_bytes / paimon::table::DataSplit::Deserialize.
2. fileDesc.paimon_table (the table root location) was not set;
PaimonRustReader needs it to point paimon-rust at the correct table.
Add encodeDataSplitNative() (mirrors legacy PaimonUtil.encodeDataSplitToString)
and thread rustTableLocation through PaimonScanPlanProvider ->
PaimonScanRange.Builder -> populateRangeParams (fileDesc.setPaimonTable).
Non-DataSplit under rust flag falls back to plain JNI (matches legacy
PAIMON_CPP arm; native binary supports DataSplit only).
### What problem does this PR solve? Related PR: #65883 (for master , current closed) **this pr add paimon rust reader both in scanner v1 and v2. the scanner v1 code is just for legacy, will be removed later.** Problem Summary: Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the `paimon-rust` C bindings (`libpaimon_c.a`, statically linked). Rust Reader is gated by the session variable `enable_paimon_rust_reader` (default `false`). Compared with the existing readers: - **vs paimon-jni**: no JVM round-trip on the hot path — the split is deserialized in-process and rows arrive via the Arrow C Data Interface, which shortens the scanner critical section and removes JNI copy cost. **Architecture** FE (`PaimonScanNode`): when `enable_paimon_rust_reader` is on and the split is a `DataSplit`, encode it with paimon's native binary serialization (`PaimonUtil.encodeDataSplitToString`), stamp the range with `TPaimonReaderType.PAIMON_RUST`, and attach `db_name` / `table_name` / `paimon_table` so BE can open the table through a catalog. BE (`FileScanner::_get_next_reader`): dispatches on `reader_type`. On `PAIMON_RUST` it instantiates `PaimonRustReader`, which: 1. `paimon_catalog_create({warehouse, metastore=filesystem, ...})` - warehouse is derived from the table root path by stripping `/<db>.db/<table>` (paimon FS convention). 2. `paimon_identifier_new(db, tbl)` → `paimon_catalog_get_table` 3. `paimon_table_new_read_builder` → projection (case-insensitive) → optional filter from `PaimonRustPredicateConverter` (translates Doris push-down conjuncts into paimon-rust predicates, best-effort so any non-representable conjunct is silently dropped and re-applied by the engine). 4. `paimon_plan_from_split_bytes(split_bytes)` — one BE scanner reads exactly its FE-planned split (no re-planning). 5. `paimon_table_read_to_arrow` → streamed arrow record batches → block. Partition columns are back-filled in `on_after_read_block` from FE-provided `columns_from_path*`, mirroring `PaimonCppReader`. OSS/S3 hadoop-style credential keys (`fs.oss.*` / `fs.s3a.*`) are remapped to `AWS_ACCESS_KEY` / `AWS_ENDPOINT` / ... so paimon-rust's FileIO can authenticate. **Thirdparty** - Introduces `paimon-rust-2fb5e49` (built with Rust 1.91.0, feature `paimon/storage-hdfs`, `--locked`). - Auto-installs `cbindgen` and regenerates the C header from the Rust extern "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.h` always matches the built `.a`. ### Release note Add `enable_paimon_rust_reader` session variable. When enabled, Paimon non-native reads on BE use the paimon-rust reader instead of paimon-jni / paimon-cpp. ### Check List (For Author) - Test - [x] Unit Test - [x] Manual test (add detailed scripts or steps below) 1. `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.conf 2. `SET enable_paimon_rust_reader=true; SET force_jni_scanner=1` 3. `SELECT` from a partitioned/DV paimon table; results must match `enable_paimon_rust_reader=false and force_jni_scanner=0`. 4. `SELECT count(*)` — should hit table-level row count push-down. 5. `WHERE a=1 AND b>2` — BE INFO log should show `paimon-rust predicate pushdown: applied`. - [x] Regression test - [ ] No need to test or manual test. - Behavior changed: - [x] No. Guarded by `enable_paimon_rust_reader` (default `false`); when off, all paths are unchanged. - Does this need documentation? - [ ] No. - [x] Yes. <!-- Add doris-website PR link here for the new session variable --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --------- Co-authored-by: dengfangyuan <dengfangyuan@kuaishou.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Gabriel <gabrielleebuaa@gmail.com>
### What problem does this PR solve? Related PR: #65883 (for master , current closed) **this pr add paimon rust reader both in scanner v1 and v2. the scanner v1 code is just for legacy, will be removed later.** Problem Summary: Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the `paimon-rust` C bindings (`libpaimon_c.a`, statically linked). Rust Reader is gated by the session variable `enable_paimon_rust_reader` (default `false`). Compared with the existing readers: - **vs paimon-jni**: no JVM round-trip on the hot path — the split is deserialized in-process and rows arrive via the Arrow C Data Interface, which shortens the scanner critical section and removes JNI copy cost. **Architecture** FE (`PaimonScanNode`): when `enable_paimon_rust_reader` is on and the split is a `DataSplit`, encode it with paimon's native binary serialization (`PaimonUtil.encodeDataSplitToString`), stamp the range with `TPaimonReaderType.PAIMON_RUST`, and attach `db_name` / `table_name` / `paimon_table` so BE can open the table through a catalog. BE (`FileScanner::_get_next_reader`): dispatches on `reader_type`. On `PAIMON_RUST` it instantiates `PaimonRustReader`, which: 1. `paimon_catalog_create({warehouse, metastore=filesystem, ...})` - warehouse is derived from the table root path by stripping `/<db>.db/<table>` (paimon FS convention). 2. `paimon_identifier_new(db, tbl)` → `paimon_catalog_get_table` 3. `paimon_table_new_read_builder` → projection (case-insensitive) → optional filter from `PaimonRustPredicateConverter` (translates Doris push-down conjuncts into paimon-rust predicates, best-effort so any non-representable conjunct is silently dropped and re-applied by the engine). 4. `paimon_plan_from_split_bytes(split_bytes)` — one BE scanner reads exactly its FE-planned split (no re-planning). 5. `paimon_table_read_to_arrow` → streamed arrow record batches → block. Partition columns are back-filled in `on_after_read_block` from FE-provided `columns_from_path*`, mirroring `PaimonCppReader`. OSS/S3 hadoop-style credential keys (`fs.oss.*` / `fs.s3a.*`) are remapped to `AWS_ACCESS_KEY` / `AWS_ENDPOINT` / ... so paimon-rust's FileIO can authenticate. **Thirdparty** - Introduces `paimon-rust-2fb5e49` (built with Rust 1.91.0, feature `paimon/storage-hdfs`, `--locked`). - Auto-installs `cbindgen` and regenerates the C header from the Rust extern "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.h` always matches the built `.a`. ### Release note Add `enable_paimon_rust_reader` session variable. When enabled, Paimon non-native reads on BE use the paimon-rust reader instead of paimon-jni / paimon-cpp. ### Check List (For Author) - Test - [x] Unit Test - [x] Manual test (add detailed scripts or steps below) 1. `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.conf 2. `SET enable_paimon_rust_reader=true; SET force_jni_scanner=1` 3. `SELECT` from a partitioned/DV paimon table; results must match `enable_paimon_rust_reader=false and force_jni_scanner=0`. 4. `SELECT count(*)` — should hit table-level row count push-down. 5. `WHERE a=1 AND b>2` — BE INFO log should show `paimon-rust predicate pushdown: applied`. - [x] Regression test - [ ] No need to test or manual test. - Behavior changed: - [x] No. Guarded by `enable_paimon_rust_reader` (default `false`); when off, all paths are unchanged. - Does this need documentation? - [ ] No. - [x] Yes. <!-- Add doris-website PR link here for the new session variable --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --------- Co-authored-by: dengfangyuan <dengfangyuan@kuaishou.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Gabriel <gabrielleebuaa@gmail.com>
) Related PR: apache#65883 (for master , current closed) **this pr add paimon rust reader both in scanner v1 and v2. the scanner v1 code is just for legacy, will be removed later.** Problem Summary: Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the `paimon-rust` C bindings (`libpaimon_c.a`, statically linked). Rust Reader is gated by the session variable `enable_paimon_rust_reader` (default `false`). Compared with the existing readers: - **vs paimon-jni**: no JVM round-trip on the hot path — the split is deserialized in-process and rows arrive via the Arrow C Data Interface, which shortens the scanner critical section and removes JNI copy cost. **Architecture** FE (`PaimonScanNode`): when `enable_paimon_rust_reader` is on and the split is a `DataSplit`, encode it with paimon's native binary serialization (`PaimonUtil.encodeDataSplitToString`), stamp the range with `TPaimonReaderType.PAIMON_RUST`, and attach `db_name` / `table_name` / `paimon_table` so BE can open the table through a catalog. BE (`FileScanner::_get_next_reader`): dispatches on `reader_type`. On `PAIMON_RUST` it instantiates `PaimonRustReader`, which: 1. `paimon_catalog_create({warehouse, metastore=filesystem, ...})` - warehouse is derived from the table root path by stripping `/<db>.db/<table>` (paimon FS convention). 2. `paimon_identifier_new(db, tbl)` → `paimon_catalog_get_table` 3. `paimon_table_new_read_builder` → projection (case-insensitive) → optional filter from `PaimonRustPredicateConverter` (translates Doris push-down conjuncts into paimon-rust predicates, best-effort so any non-representable conjunct is silently dropped and re-applied by the engine). 4. `paimon_plan_from_split_bytes(split_bytes)` — one BE scanner reads exactly its FE-planned split (no re-planning). 5. `paimon_table_read_to_arrow` → streamed arrow record batches → block. Partition columns are back-filled in `on_after_read_block` from FE-provided `columns_from_path*`, mirroring `PaimonCppReader`. OSS/S3 hadoop-style credential keys (`fs.oss.*` / `fs.s3a.*`) are remapped to `AWS_ACCESS_KEY` / `AWS_ENDPOINT` / ... so paimon-rust's FileIO can authenticate. **Thirdparty** - Introduces `paimon-rust-2fb5e49` (built with Rust 1.91.0, feature `paimon/storage-hdfs`, `--locked`). - Auto-installs `cbindgen` and regenerates the C header from the Rust extern "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.h` always matches the built `.a`. ### Release note Add `enable_paimon_rust_reader` session variable. When enabled, Paimon non-native reads on BE use the paimon-rust reader instead of paimon-jni / paimon-cpp. ### Check List (For Author) - Test - [x] Unit Test - [x] Manual test (add detailed scripts or steps below) 1. `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.conf 2. `SET enable_paimon_rust_reader=true; SET force_jni_scanner=1` 3. `SELECT` from a partitioned/DV paimon table; results must match `enable_paimon_rust_reader=false and force_jni_scanner=0`. 4. `SELECT count(*)` — should hit table-level row count push-down. 5. `WHERE a=1 AND b>2` — BE INFO log should show `paimon-rust predicate pushdown: applied`. - [x] Regression test - [ ] No need to test or manual test. - Behavior changed: - [x] No. Guarded by `enable_paimon_rust_reader` (default `false`); when off, all paths are unchanged. - Does this need documentation? - [ ] No. - [x] Yes. <!-- Add doris-website PR link here for the new session variable --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --------- Co-authored-by: dengfangyuan <dengfangyuan@kuaishou.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Gabriel <gabrielleebuaa@gmail.com>
) Related PR: apache#65883 (for master , current closed) **this pr add paimon rust reader both in scanner v1 and v2. the scanner v1 code is just for legacy, will be removed later.** Problem Summary: Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the `paimon-rust` C bindings (`libpaimon_c.a`, statically linked). Rust Reader is gated by the session variable `enable_paimon_rust_reader` (default `false`). Compared with the existing readers: - **vs paimon-jni**: no JVM round-trip on the hot path — the split is deserialized in-process and rows arrive via the Arrow C Data Interface, which shortens the scanner critical section and removes JNI copy cost. **Architecture** FE (`PaimonScanNode`): when `enable_paimon_rust_reader` is on and the split is a `DataSplit`, encode it with paimon's native binary serialization (`PaimonUtil.encodeDataSplitToString`), stamp the range with `TPaimonReaderType.PAIMON_RUST`, and attach `db_name` / `table_name` / `paimon_table` so BE can open the table through a catalog. BE (`FileScanner::_get_next_reader`): dispatches on `reader_type`. On `PAIMON_RUST` it instantiates `PaimonRustReader`, which: 1. `paimon_catalog_create({warehouse, metastore=filesystem, ...})` - warehouse is derived from the table root path by stripping `/<db>.db/<table>` (paimon FS convention). 2. `paimon_identifier_new(db, tbl)` → `paimon_catalog_get_table` 3. `paimon_table_new_read_builder` → projection (case-insensitive) → optional filter from `PaimonRustPredicateConverter` (translates Doris push-down conjuncts into paimon-rust predicates, best-effort so any non-representable conjunct is silently dropped and re-applied by the engine). 4. `paimon_plan_from_split_bytes(split_bytes)` — one BE scanner reads exactly its FE-planned split (no re-planning). 5. `paimon_table_read_to_arrow` → streamed arrow record batches → block. Partition columns are back-filled in `on_after_read_block` from FE-provided `columns_from_path*`, mirroring `PaimonCppReader`. OSS/S3 hadoop-style credential keys (`fs.oss.*` / `fs.s3a.*`) are remapped to `AWS_ACCESS_KEY` / `AWS_ENDPOINT` / ... so paimon-rust's FileIO can authenticate. **Thirdparty** - Introduces `paimon-rust-2fb5e49` (built with Rust 1.91.0, feature `paimon/storage-hdfs`, `--locked`). - Auto-installs `cbindgen` and regenerates the C header from the Rust extern "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.h` always matches the built `.a`. ### Release note Add `enable_paimon_rust_reader` session variable. When enabled, Paimon non-native reads on BE use the paimon-rust reader instead of paimon-jni / paimon-cpp. ### Check List (For Author) - Test - [x] Unit Test - [x] Manual test (add detailed scripts or steps below) 1. `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.conf 2. `SET enable_paimon_rust_reader=true; SET force_jni_scanner=1` 3. `SELECT` from a partitioned/DV paimon table; results must match `enable_paimon_rust_reader=false and force_jni_scanner=0`. 4. `SELECT count(*)` — should hit table-level row count push-down. 5. `WHERE a=1 AND b>2` — BE INFO log should show `paimon-rust predicate pushdown: applied`. - [x] Regression test - [ ] No need to test or manual test. - Behavior changed: - [x] No. Guarded by `enable_paimon_rust_reader` (default `false`); when off, all paths are unchanged. - Does this need documentation? - [ ] No. - [x] Yes. <!-- Add doris-website PR link here for the new session variable --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --------- Co-authored-by: dengfangyuan <dengfangyuan@kuaishou.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Gabriel <gabrielleebuaa@gmail.com>
) Related PR: apache#65883 (for master , current closed) **this pr add paimon rust reader both in scanner v1 and v2. the scanner v1 code is just for legacy, will be removed later.** Problem Summary: Adds a third BE-side reader for Paimon FORMAT_JNI splits, backed by the `paimon-rust` C bindings (`libpaimon_c.a`, statically linked). Rust Reader is gated by the session variable `enable_paimon_rust_reader` (default `false`). Compared with the existing readers: - **vs paimon-jni**: no JVM round-trip on the hot path — the split is deserialized in-process and rows arrive via the Arrow C Data Interface, which shortens the scanner critical section and removes JNI copy cost. **Architecture** FE (`PaimonScanNode`): when `enable_paimon_rust_reader` is on and the split is a `DataSplit`, encode it with paimon's native binary serialization (`PaimonUtil.encodeDataSplitToString`), stamp the range with `TPaimonReaderType.PAIMON_RUST`, and attach `db_name` / `table_name` / `paimon_table` so BE can open the table through a catalog. BE (`FileScanner::_get_next_reader`): dispatches on `reader_type`. On `PAIMON_RUST` it instantiates `PaimonRustReader`, which: 1. `paimon_catalog_create({warehouse, metastore=filesystem, ...})` - warehouse is derived from the table root path by stripping `/<db>.db/<table>` (paimon FS convention). 2. `paimon_identifier_new(db, tbl)` → `paimon_catalog_get_table` 3. `paimon_table_new_read_builder` → projection (case-insensitive) → optional filter from `PaimonRustPredicateConverter` (translates Doris push-down conjuncts into paimon-rust predicates, best-effort so any non-representable conjunct is silently dropped and re-applied by the engine). 4. `paimon_plan_from_split_bytes(split_bytes)` — one BE scanner reads exactly its FE-planned split (no re-planning). 5. `paimon_table_read_to_arrow` → streamed arrow record batches → block. Partition columns are back-filled in `on_after_read_block` from FE-provided `columns_from_path*`, mirroring `PaimonCppReader`. OSS/S3 hadoop-style credential keys (`fs.oss.*` / `fs.s3a.*`) are remapped to `AWS_ACCESS_KEY` / `AWS_ENDPOINT` / ... so paimon-rust's FileIO can authenticate. **Thirdparty** - Introduces `paimon-rust-2fb5e49` (built with Rust 1.91.0, feature `paimon/storage-hdfs`, `--locked`). - Auto-installs `cbindgen` and regenerates the C header from the Rust extern "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.h` always matches the built `.a`. ### Release note Add `enable_paimon_rust_reader` session variable. When enabled, Paimon non-native reads on BE use the paimon-rust reader instead of paimon-jni / paimon-cpp. ### Check List (For Author) - Test - [x] Unit Test - [x] Manual test (add detailed scripts or steps below) 1. `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.conf 2. `SET enable_paimon_rust_reader=true; SET force_jni_scanner=1` 3. `SELECT` from a partitioned/DV paimon table; results must match `enable_paimon_rust_reader=false and force_jni_scanner=0`. 4. `SELECT count(*)` — should hit table-level row count push-down. 5. `WHERE a=1 AND b>2` — BE INFO log should show `paimon-rust predicate pushdown: applied`. - [x] Regression test - [ ] No need to test or manual test. - Behavior changed: - [x] No. Guarded by `enable_paimon_rust_reader` (default `false`); when off, all paths are unchanged. - Does this need documentation? - [ ] No. - [x] Yes. <!-- Add doris-website PR link here for the new session variable --> ### Check List (For Reviewer who merge this PR) - [ ] Confirm the release note - [ ] Confirm test cases - [ ] Confirm document - [ ] Add branch pick label --------- Co-authored-by: dengfangyuan <dengfangyuan@kuaishou.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Gabriel <gabrielleebuaa@gmail.com>
What problem does this PR solve?
Problem Summary:
this pr for master is just a prototype
becuase the current paimon-rust reader implementation 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.
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)