-
Notifications
You must be signed in to change notification settings - Fork 3.9k
branch-4.1: [feature](paimon) Support table writes via JNI and schema evolution #65868
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
Merged
yiguolei
merged 19 commits into
apache:branch-4.1
from
suxiaogang223:codex/backport-paimon-jni-write-4.1
Jul 30, 2026
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
cb590e4
[feature](paimon) Add Paimon write support via JNI
suxiaogang223 0996dc3
[feature](paimon) Support merge engines in Paimon writes
suxiaogang223 8fe04d7
fix paimon complex null conversion
suxiaogang223 a20b57c
[feature](paimon) Support changelog producers in writes
suxiaogang223 ea80c26
[feature](paimon) Support bucket modes in writes
suxiaogang223 9795e07
[test](paimon) Expand JNI write regression coverage
suxiaogang223 e573aec
[refactor](paimon) Remove vectorized writer prefix
suxiaogang223 dc5093f
[feature](paimon) Support external table schema evolution
suxiaogang223 b5231a0
[test](paimon) Cover HMS and REST catalog writes
suxiaogang223 594aabf
[fix](paimon) Use remote schema and typed partition metadata
suxiaogang223 72bc288
[fix](paimon) Apply defaults to omitted write fields
suxiaogang223 4008f51
[test](paimon) Extend write regression coverage
suxiaogang223 68f97ef
[improvement](paimon) Manage JNI writer memory
suxiaogang223 6fca2fb
[fix](paimon) Address write correctness edge cases
suxiaogang223 044c561
[fix](paimon) Handle ambiguous partition metadata
suxiaogang223 9c3ef49
[fix](paimon) Address write correctness review findings
suxiaogang223 7b2a7c6
[fix](paimon) harden write correctness and partition naming
suxiaogang223 96a7fb8
[fix](paimon) Fix rebase build compatibility
suxiaogang223 d3197e7
[fix](paimon) Address latest review findings
suxiaogang223 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| #include "exec/operator/paimon_table_sink_operator.h" | ||
|
|
||
| #include "common/logging.h" | ||
|
|
||
| namespace doris { | ||
|
|
||
| Status PaimonTableSinkLocalState::init(RuntimeState* state, LocalSinkStateInfo& info) { | ||
| return Base::init(state, info); | ||
| } | ||
|
|
||
| Status PaimonTableSinkOperatorX::sink_impl(RuntimeState* state, Block* in_block, bool eos) { | ||
| auto& local_state = get_local_state(state); | ||
| SCOPED_TIMER(local_state.exec_time_counter()); | ||
| COUNTER_UPDATE(local_state.rows_input_counter(), static_cast<int64_t>(in_block->rows())); | ||
|
|
||
| // Delegate to AsyncWriterSink → PaimonTableWriter for this pipeline instance. | ||
| // Each pipeline instance has its own writer session; partition and bucket | ||
| // routing is handled internally by the Paimon SDK inside IPaimonWriter::write(). | ||
| return local_state.sink(state, in_block, eos); | ||
| } | ||
|
|
||
| } // namespace doris |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <gen_cpp/DataSinks_types.h> | ||
|
|
||
| #include <memory> | ||
| #include <string> | ||
|
|
||
| #include "common/status.h" | ||
| #include "core/block/block.h" | ||
| #include "exec/operator/operator.h" | ||
| #include "exec/sink/writer/paimon/paimon_table_writer.h" | ||
| #include "runtime/runtime_state.h" | ||
|
|
||
| namespace doris { | ||
|
|
||
| /// Paimon table sink operator — simple pass-through to AsyncWriterSink. | ||
| /// | ||
| /// Each pipeline instance (LocalState) owns one PaimonTableWriter, which in | ||
| /// turn owns one IPaimonWriteBackend + IPaimonWriter. Pipeline parallelism | ||
| /// determines the number of concurrent Paimon writer sessions per table. | ||
| /// | ||
| /// Partition and bucket routing is performed internally by the Paimon SDK | ||
| /// (Java via JNI, or Rust via FFI). Doris does not compute partition values | ||
| /// or bucket ids; it passes complete Blocks through the backend to the SDK, | ||
| /// where each row is routed via getPartition(row) + getBucket(row). | ||
| /// | ||
| /// This mirrors Iceberg's approach: IcebergTableSinkOperatorX delegates to | ||
| /// AsyncWriterSink<VIcebergTableWriter>, with partition routing inside | ||
| /// VIcebergTableWriter::write(). | ||
| class PaimonTableSinkOperatorX; | ||
|
|
||
| class PaimonTableSinkLocalState final | ||
| : public AsyncWriterSink<PaimonTableWriter, PaimonTableSinkOperatorX> { | ||
| public: | ||
| using Base = AsyncWriterSink<PaimonTableWriter, PaimonTableSinkOperatorX>; | ||
| using Parent = PaimonTableSinkOperatorX; | ||
| ENABLE_FACTORY_CREATOR(PaimonTableSinkLocalState); | ||
| PaimonTableSinkLocalState(DataSinkOperatorXBase* parent, RuntimeState* state) | ||
| : Base(parent, state) {} | ||
| Status init(RuntimeState* state, LocalSinkStateInfo& info) override; | ||
| Status open(RuntimeState* state) override { | ||
| SCOPED_TIMER(exec_time_counter()); | ||
| SCOPED_TIMER(_open_timer); | ||
| return Base::open(state); | ||
| } | ||
|
|
||
| friend class PaimonTableSinkOperatorX; | ||
| }; | ||
|
|
||
| class PaimonTableSinkOperatorX final : public DataSinkOperatorX<PaimonTableSinkLocalState> { | ||
| public: | ||
| using Base = DataSinkOperatorX<PaimonTableSinkLocalState>; | ||
| PaimonTableSinkOperatorX(ObjectPool* pool, int operator_id, const RowDescriptor& row_desc, | ||
| const std::vector<TExpr>& t_output_expr) | ||
| : Base(operator_id, 0, 0), | ||
| _row_desc(row_desc), | ||
| _t_output_expr(t_output_expr), | ||
| _pool(pool) {} | ||
|
|
||
| Status init(const TDataSink& thrift_sink) override { | ||
| RETURN_IF_ERROR(Base::init(thrift_sink)); | ||
| DCHECK(thrift_sink.__isset.paimon_table_sink); | ||
| RETURN_IF_ERROR(VExpr::create_expr_trees(_t_output_expr, _output_vexpr_ctxs)); | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| Status prepare(RuntimeState* state) override { | ||
| RETURN_IF_ERROR(Base::prepare(state)); | ||
| RETURN_IF_ERROR(VExpr::prepare(_output_vexpr_ctxs, state, _row_desc)); | ||
| return VExpr::open(_output_vexpr_ctxs, state); | ||
| } | ||
|
|
||
| Status sink_impl(RuntimeState* state, Block* in_block, bool eos) override; | ||
|
|
||
| private: | ||
| friend class PaimonTableSinkLocalState; | ||
| template <typename Writer, typename Parent> | ||
| requires(std::is_base_of_v<AsyncResultWriter, Writer>) | ||
| friend class AsyncWriterSink; | ||
|
|
||
| const RowDescriptor& _row_desc; | ||
| VExprContextSPtrs _output_vexpr_ctxs; | ||
| const std::vector<TExpr>& _t_output_expr; | ||
| ObjectPool* _pool = nullptr; | ||
| }; | ||
|
|
||
| } // namespace doris |
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
34 changes: 34 additions & 0 deletions
34
be/src/exec/sink/writer/paimon/ffi_paimon_write_backend.cpp
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| #include "exec/sink/writer/paimon/ffi_paimon_write_backend.h" | ||
|
|
||
| namespace doris { | ||
|
|
||
| Status FfiPaimonWriteBackend::open(const TPaimonTableSink&, RuntimeState*, RuntimeProfile*) { | ||
| return Status::NotSupported("Paimon Rust FFI writer is not implemented"); | ||
| } | ||
|
|
||
| Status FfiPaimonWriteBackend::create_writer(std::unique_ptr<IPaimonWriter>*) { | ||
| return Status::NotSupported("Paimon Rust FFI writer is not implemented"); | ||
| } | ||
|
|
||
| Status FfiPaimonWriteBackend::close() { | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| } // namespace doris |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // Licensed to the Apache Software Foundation (ASF) under one | ||
| // or more contributor license agreements. See the NOTICE file | ||
| // distributed with this work for additional information | ||
| // regarding copyright ownership. The ASF licenses this file | ||
| // to you under the Apache License, Version 2.0 (the | ||
| // "License"); you may not use this file except in compliance | ||
| // with the License. You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, | ||
| // software distributed under the License is distributed on an | ||
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
| // KIND, either express or implied. See the License for the | ||
| // specific language governing permissions and limitations | ||
| // under the License. | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "exec/sink/writer/paimon/paimon_write_backend.h" | ||
|
|
||
| namespace doris { | ||
|
|
||
| /// Placeholder for the future paimon-rust writer implementation. Keeping this | ||
| /// backend in the factory makes the integration boundary explicit without | ||
| /// introducing a BE commit contract that the Rust writer will not own. | ||
| class FfiPaimonWriteBackend final : public IPaimonWriteBackend { | ||
| public: | ||
| Status open(const TPaimonTableSink& sink, RuntimeState* state, | ||
| RuntimeProfile* profile) override; | ||
| Status create_writer(std::unique_ptr<IPaimonWriter>* writer) override; | ||
| Status close() override; | ||
| PaimonBackendType type() const override { return PaimonBackendType::FFI; } | ||
| }; | ||
|
|
||
| } // namespace doris |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.