This is an automated email from the ASF dual-hosted git repository.
Gabriel39 pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new f0e00809c81 branch-4.1:[chore](thirdparty) Upgrade Apache Arrow to
24.0.0(#66221) (#66480)
f0e00809c81 is described below
commit f0e00809c812ae6d10fa70a9188a953424063626
Author: daidai <[email protected]>
AuthorDate: Thu Aug 6 21:50:34 2026 +0800
branch-4.1:[chore](thirdparty) Upgrade Apache Arrow to 24.0.0(#66221)
(#66480)
### What problem does this PR solve?
bp #66221
Problem Summary: Doris used Apache Arrow 17.0.0, which blocked consuming
newer Arrow fixes and APIs. Upgrade the C++ third-party dependency to
24.0.0, align xsimd with Arrow 24, port the Paimon row-group, INT96, and
Parquet LZO compatibility patches, add Arrow Compute to the static
dependency graph, and migrate removed Arrow and Parquet APIs while
preserving Decimal128 semantics.
### Release note
None
### Check List (For Author)
- Test <!-- At least one of them must be included. -->
- [ ] Regression test
- [ ] Unit Test
- [ ] Manual test (add detailed scripts or steps below)
- [X] No need to test or manual test. Explain why:
- [ ] This is a refactor/code format and no logic has been changed.
- [x] Previous test can cover this change.
- [ ] No code files have been changed.
- [ ] Other reason <!-- Add your reason? -->
- Behavior changed:
- [x] No.
- [ ] Yes. <!-- Explain the behavior change -->
- Does this need documentation?
- [x] No.
- [ ] Yes. <!-- Add document PR link here. eg:
https://github.com/apache/doris-website/pull/1214 -->
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label <!-- Add branch pick label that this PR
should merge into -->
---
.github/workflows/be-ut-mac.yml | 50 ++-
.github/workflows/build-thirdparty.yml | 38 +-
be/CMakeLists.txt | 2 +-
be/cmake/thirdparty.cmake | 1 +
be/src/format/table/iceberg/arrow_schema_util.cpp | 2 +-
.../data_type_serde_decimal_test.cpp | 4 +-
be/test/format/parquet/parquet_expr_test.cpp | 2 +-
be/test/format_v2/parquet/parquet_reader_test.cpp | 58 ++-
.../format_v2/table/remote_doris_reader_test.cpp | 2 +-
build.sh | 75 +++-
docker/compilation/Dockerfile.gcc10 | 3 +-
docker/compilation/Dockerfile.gcc7 | 119 -----
docker/compilation/arm/Dockerfile | 12 +
.../iceberg/write/test_iceberg_write_stats2.out | 2 +-
.../iceberg/iceberg_schema_change_ddl.groovy | 2 +-
run-be-ut.sh | 25 ++
thirdparty/arrow-paimon-vars.sh | 408 +++++++++++++++++
thirdparty/build-thirdparty.sh | 16 +-
thirdparty/download-thirdparty.sh | 64 ++-
thirdparty/paimon-cpp-cache.cmake | 3 +-
...rrow-24.0.0-force-write-int96-timestamps.patch} | 42 +-
...0.0-lzo.patch => apache-arrow-24.0.0-lzo.patch} | 72 ++-
...imon.patch => apache-arrow-24.0.0-paimon.patch} | 116 ++---
.../paimon-cpp-arrow-24-compatibility.patch | 64 +++
.../patches/paimon-cpp-arrow-24-compute.patch | 44 ++
thirdparty/test/arrow-paimon-lifecycle-test.sh | 492 +++++++++++++++++++++
thirdparty/vars.sh | 31 +-
27 files changed, 1442 insertions(+), 307 deletions(-)
diff --git a/.github/workflows/be-ut-mac.yml b/.github/workflows/be-ut-mac.yml
index 4f3db038dba..c64dc52e0de 100644
--- a/.github/workflows/be-ut-mac.yml
+++ b/.github/workflows/be-ut-mac.yml
@@ -47,9 +47,23 @@ jobs:
- 'be/**'
- 'gensrc/proto/**'
- 'gensrc/thrift/**'
+ arrow_paimon_changes:
+ - '.github/workflows/be-ut-mac.yml'
+ - 'build.sh'
+ - 'env.sh'
+ - 'thirdparty/arrow-paimon-vars.sh'
+ - 'thirdparty/vars.sh'
+ - 'thirdparty/download-thirdparty.sh'
+ - 'thirdparty/build-thirdparty.sh'
+ - 'thirdparty/paimon-cpp-cache.cmake'
+ - 'thirdparty/patches/apache-arrow-*.patch'
+ - 'thirdparty/patches/paimon-cpp-*.patch'
- name: Ccache ${{ github.ref }}
- if: ${{ github.event_name == 'schedule' ||
steps.filter.outputs.be_changes == 'true' }}
+ if: |
+ github.event_name == 'schedule' ||
+ steps.filter.outputs.be_changes == 'true' ||
+ steps.filter.outputs.arrow_paimon_changes == 'true'
uses: ./.github/actions/ccache-action
with:
key: BE-UT-macOS
@@ -57,7 +71,10 @@ jobs:
restore-keys: BE-UT-macOS-
- name: Run UT ${{ github.ref }}
- if: ${{ github.event_name == 'schedule' ||
steps.filter.outputs.be_changes == 'true' }}
+ if: |
+ github.event_name == 'schedule' ||
+ steps.filter.outputs.be_changes == 'true' ||
+ steps.filter.outputs.arrow_paimon_changes == 'true'
run: |
cellars=(
'm4'
@@ -84,6 +101,15 @@ jobs:
)
brew install "${cellars[@]}" || true
+ # Paimon's bundled dependencies still require pre-CMake-4 policy
+ # compatibility. Match the supported version used by the full
+ # thirdparty jobs instead of relying on Homebrew's latest CMake.
+ brew unlink cmake || true
+ wget
https://github.com/Kitware/CMake/releases/download/v3.25.3/cmake-3.25.3-macos-universal.tar.gz
+ tar -xzf cmake-3.25.3-macos-universal.tar.gz
+ sudo cp -r cmake-3.25.3-macos-universal/CMake.app/Contents/*
/usr/local/
+ export CUSTOM_CMAKE=/usr/local/bin/cmake
+ "${CUSTOM_CMAKE}" --version
pushd thirdparty
branch="${{ github.base_ref }}"
if [[ -z "${branch}" ]] || [[ "${branch}" == 'master' ]]; then
@@ -94,6 +120,26 @@ jobs:
-o doris-thirdparty-prebuilt-darwin-x86_64.tar.xz
fi
tar -xvf doris-thirdparty-prebuilt-darwin-x86_64.tar.xz
+
+ # Rebuild the Arrow/Paimon stack when its inputs change or the shared
+ # prebuilt predates the selected Arrow version/component closure.
+ # The artifact check also covers scheduled and later BE-only builds,
+ # where Paths Filter is skipped or reports no Arrow/Paimon changes.
+ # shellcheck source=thirdparty/arrow-paimon-vars.sh
+ . ./arrow-paimon-vars.sh
+ arrow_paimon_prebuilt_is_valid=false
+ if arrow_paimon_prebuilt_valid installed; then
+ arrow_paimon_prebuilt_is_valid=true
+ fi
+ if [[ "${{ steps.filter.outputs.arrow_paimon_changes }}" == "true" ||
+ "${arrow_paimon_prebuilt_is_valid}" != "true" ]]; then
+ curl -L
https://github.com/apache/doris-thirdparty/releases/download/automation/doris-thirdparty-source.tgz
\
+ -o doris-thirdparty-source.tgz
+ tar -zxvf doris-thirdparty-source.tgz
+ ./download-thirdparty.sh arrow paimon_cpp xsimd brotli
+ export MACOSX_DEPLOYMENT_TARGET=12.0
+ ./build-thirdparty.sh -j "$(nproc)" arrow paimon_cpp
+ fi
popd
export JAVA_HOME="${JAVA_HOME_17_X64%\/}"
diff --git a/.github/workflows/build-thirdparty.yml
b/.github/workflows/build-thirdparty.yml
index cc707cf516b..7144cfe8425 100644
--- a/.github/workflows/build-thirdparty.yml
+++ b/.github/workflows/build-thirdparty.yml
@@ -39,6 +39,7 @@ jobs:
github.event.issue.user.login == 'github-actions[bot]')
outputs:
thirdparty_changes: ${{ steps.filter.outputs.thirdparty_changes }}
+ arrow_paimon_lifecycle_changes: ${{
steps.filter.outputs.arrow_paimon_lifecycle_changes }}
steps:
- name: Checkout ${{ github.ref }}
uses: actions/checkout@v4
@@ -54,6 +55,30 @@ jobs:
thirdparty_changes:
- 'thirdparty/**'
- 'env.sh'
+ arrow_paimon_lifecycle_changes:
+ - 'build.sh'
+ - 'env.sh'
+ - 'thirdparty/arrow-paimon-vars.sh'
+ - 'thirdparty/vars.sh'
+ - 'thirdparty/build-thirdparty.sh'
+ - 'thirdparty/download-thirdparty.sh'
+ - 'thirdparty/paimon-cpp-cache.cmake'
+ - 'thirdparty/patches/apache-arrow-*.patch'
+ - 'thirdparty/patches/paimon-cpp-*.patch'
+ - 'thirdparty/test/arrow-paimon-lifecycle-test.sh'
+ - '.github/workflows/build-thirdparty.yml'
+
+ arrow_paimon_lifecycle_test:
+ name: Arrow/Paimon Lifecycle Test
+ needs: changes
+ if: ${{ needs.changes.outputs.arrow_paimon_lifecycle_changes == 'true' }}
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout ${{ github.ref }}
+ uses: actions/checkout@v4
+
+ - name: Test focused thirdparty lifecycle
+ run: thirdparty/test/arrow-paimon-lifecycle-test.sh
build_linux:
name: Build Third Party Libraries (Linux)
@@ -195,9 +220,9 @@ jobs:
# Install specific version of cmake
brew unlink cmake || true
- wget
https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-macos-universal.tar.gz
- tar -xzf cmake-3.22.1-macos-universal.tar.gz
- sudo cp -r cmake-3.22.1-macos-universal/CMake.app/Contents/*
/usr/local/
+ wget
https://github.com/Kitware/CMake/releases/download/v3.25.3/cmake-3.25.3-macos-universal.tar.gz
+ tar -xzf cmake-3.25.3-macos-universal.tar.gz
+ sudo cp -r cmake-3.25.3-macos-universal/CMake.app/Contents/*
/usr/local/
cmake --version
- name: Build
@@ -260,9 +285,9 @@ jobs:
# Install specific version of cmake
brew unlink cmake || true
- wget
https://github.com/Kitware/CMake/releases/download/v3.22.1/cmake-3.22.1-macos-universal.tar.gz
- tar -xzf cmake-3.22.1-macos-universal.tar.gz
- sudo cp -r cmake-3.22.1-macos-universal/CMake.app/Contents/*
/usr/local/
+ wget
https://github.com/Kitware/CMake/releases/download/v3.25.3/cmake-3.25.3-macos-universal.tar.gz
+ tar -xzf cmake-3.25.3-macos-universal.tar.gz
+ sudo cp -r cmake-3.25.3-macos-universal/CMake.app/Contents/*
/usr/local/
cmake --version
- name: Build
@@ -278,4 +303,3 @@ jobs:
cd thirdparty
#./build-thirdparty.sh -j "$(nproc)"
./build-thirdparty.sh -j 2
-
diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt
index f3c6aa3379a..05bdc796351 100644
--- a/be/CMakeLists.txt
+++ b/be/CMakeLists.txt
@@ -653,7 +653,7 @@ endif()
set(PAIMON_FACTORY_REGISTRY_LIBS)
if (ENABLE_PAIMON_CPP)
# Plan B: Doris Arrow is now built with COMPUTE/DATASET/ACERO/FILESYSTEM,
- # so arrow, arrow_dataset, arrow_acero are all in COMMON_THIRDPARTY via
+ # so arrow, arrow_compute, arrow_dataset, arrow_acero are all in
COMMON_THIRDPARTY via
# thirdparty.cmake. paimon-cpp reuses the same Arrow (no paimon_deps).
# No dual-stack selection needed — single Arrow for everything.
diff --git a/be/cmake/thirdparty.cmake b/be/cmake/thirdparty.cmake
index 91e3e40dd39..eed1823515f 100644
--- a/be/cmake/thirdparty.cmake
+++ b/be/cmake/thirdparty.cmake
@@ -105,6 +105,7 @@ add_thirdparty(brotlidec LIB64)
add_thirdparty(brotlienc LIB64)
add_thirdparty(zstd LIB64)
add_thirdparty(arrow LIB64)
+add_thirdparty(arrow_compute LIB64)
add_thirdparty(arrow_flight LIB64)
add_thirdparty(arrow_flight_sql LIB64)
add_thirdparty(arrow_dataset LIB64)
diff --git a/be/src/format/table/iceberg/arrow_schema_util.cpp
b/be/src/format/table/iceberg/arrow_schema_util.cpp
index d53faf0062b..77989a64812 100644
--- a/be/src/format/table/iceberg/arrow_schema_util.cpp
+++ b/be/src/format/table/iceberg/arrow_schema_util.cpp
@@ -98,7 +98,7 @@ Status ArrowSchemaUtil::convert_to(const
iceberg::NestedField& field,
case iceberg::TypeID::DECIMAL: {
auto* dt = dynamic_cast<DecimalType*>(field.field_type());
- arrow_type = arrow::decimal(dt->get_precision(), dt->get_scale());
+ arrow_type = arrow::decimal128(dt->get_precision(), dt->get_scale());
break;
}
diff --git a/be/test/core/data_type_serde/data_type_serde_decimal_test.cpp
b/be/test/core/data_type_serde/data_type_serde_decimal_test.cpp
index 4394f012b7c..fab8453a816 100644
--- a/be/test/core/data_type_serde/data_type_serde_decimal_test.cpp
+++ b/be/test/core/data_type_serde/data_type_serde_decimal_test.cpp
@@ -292,7 +292,7 @@ TEST_F(DataTypeDecimalSerDeTest, serdes) {
// Run with UBSan enabled to catch misalignment errors.
TEST_F(DataTypeDecimalSerDeTest, ArrowMemNotAligned) {
// 1.Prepare the data.
- arrow::Decimal128Builder builder(arrow::decimal(38, 30));
+ arrow::Decimal128Builder builder(arrow::decimal128(38, 30));
std::vector<std::string> decimal_strings = {"12345.67", "89.10",
"1112.13", "1415.16",
"1718.19"};
@@ -318,7 +318,7 @@ TEST_F(DataTypeDecimalSerDeTest, ArrowMemNotAligned) {
// 4. Create Arrow array with unaligned memory
auto unaligned_buffer = arrow::Buffer::Wrap(unaligned_data, num_elements *
element_size);
- auto arr = std::make_shared<arrow::DecimalArray>(arrow::decimal(38, 30),
num_elements,
+ auto arr = std::make_shared<arrow::DecimalArray>(arrow::decimal128(38,
30), num_elements,
unaligned_buffer);
const auto* raw_values_ptr = arr->raw_values();
diff --git a/be/test/format/parquet/parquet_expr_test.cpp
b/be/test/format/parquet/parquet_expr_test.cpp
index 0e1774fa634..d8cfb8765b6 100644
--- a/be/test/format/parquet/parquet_expr_test.cpp
+++ b/be/test/format/parquet/parquet_expr_test.cpp
@@ -339,7 +339,7 @@ public:
outfile = std::move(result_file).ValueUnsafe();
::parquet::WriterProperties::Builder builder;
- builder.version(::parquet::ParquetVersion::PARQUET_2_0);
+ builder.version(::parquet::ParquetVersion::PARQUET_2_6);
builder.data_page_version(::parquet::ParquetDataPageVersion::V2);
builder.enable_write_page_index();
builder.compression(::parquet::Compression::SNAPPY);
diff --git a/be/test/format_v2/parquet/parquet_reader_test.cpp
b/be/test/format_v2/parquet/parquet_reader_test.cpp
index abc67839d2d..fca95c06177 100644
--- a/be/test/format_v2/parquet/parquet_reader_test.cpp
+++ b/be/test/format_v2/parquet/parquet_reader_test.cpp
@@ -1004,16 +1004,25 @@ void write_sparse_filter_nested_parquet_file(const
std::string& file_path) {
::parquet::WriterProperties::Builder builder;
builder.version(::parquet::ParquetVersion::PARQUET_2_6);
- // V2 and page-index writers preserve record boundaries, so use V1 here to
produce the
- // continuation pages that the reader must still handle correctly.
+ // Arrow 24 enables page indexes by default. V2 and page-index writers
preserve record
+ // boundaries, so use V1 without a page index to produce the continuation
pages that the
+ // reader must still handle correctly.
builder.data_page_version(::parquet::ParquetDataPageVersion::V1);
+ builder.disable_write_page_index();
builder.compression(::parquet::Compression::UNCOMPRESSED);
builder.disable_dictionary();
builder.write_batch_size(8);
- builder.data_pagesize(64);
+ // Arrow 24 checks repeated-column page limits only at record or
WriteBatch boundaries.
+ // A one-byte target deterministically flushes at every eligible boundary,
including the
+ // deliberately split wide record below.
+ builder.data_pagesize(1);
auto writer = ::parquet::ParquetFileWriter::Open(out, schema,
builder.build());
auto* row_group = writer->AppendRowGroup();
+ // Split each wide record across WriteBatch calls. The first half flushes
at the one-byte page
+ // limit, so the second call deterministically creates a page whose first
repetition level is 1.
+ constexpr int64_t SPANNING_BATCH_VALUES = SPANNING_NESTED_VALUES / 2;
+
auto* id_writer =
static_cast<::parquet::Int32Writer*>(row_group->NextColumn());
const int32_t ids[] = {1, 2, 3, 4, 5, 6};
EXPECT_EQ(id_writer->WriteBatch(6, nullptr, nullptr, ids), 6);
@@ -1042,16 +1051,32 @@ void write_sparse_filter_nested_parquet_file(const
std::string& file_path) {
map_keys.push_back(6000);
auto* map_key_writer =
static_cast<::parquet::Int32Writer*>(row_group->NextColumn());
-
EXPECT_EQ(map_key_writer->WriteBatch(static_cast<int64_t>(map_repetition_levels.size()),
- map_key_definition_levels.data(),
+ constexpr int64_t MAP_PREFIX_LEVELS = 4;
+ constexpr int64_t MAP_KEY_PREFIX_VALUES = 2;
+ constexpr int64_t MAP_SPLIT_LEVELS = MAP_PREFIX_LEVELS +
SPANNING_BATCH_VALUES;
+ constexpr int64_t MAP_KEY_SPLIT_VALUES = MAP_KEY_PREFIX_VALUES +
SPANNING_BATCH_VALUES;
+ EXPECT_EQ(map_key_writer->WriteBatch(MAP_SPLIT_LEVELS,
map_key_definition_levels.data(),
map_repetition_levels.data(),
map_keys.data()),
- static_cast<int64_t>(map_keys.size()));
+ MAP_KEY_SPLIT_VALUES);
+ EXPECT_EQ(map_key_writer->WriteBatch(
+ static_cast<int64_t>(map_repetition_levels.size()) -
MAP_SPLIT_LEVELS,
+ map_key_definition_levels.data() + MAP_SPLIT_LEVELS,
+ map_repetition_levels.data() + MAP_SPLIT_LEVELS,
+ map_keys.data() + MAP_KEY_SPLIT_VALUES),
+ static_cast<int64_t>(map_keys.size()) - MAP_KEY_SPLIT_VALUES);
map_key_writer->Close();
auto* map_value_writer =
static_cast<::parquet::ByteArrayWriter*>(row_group->NextColumn());
-
EXPECT_EQ(map_value_writer->WriteBatch(static_cast<int64_t>(map_repetition_levels.size()),
- map_value_definition_levels.data(),
+ constexpr int64_t MAP_VALUE_PREFIX_VALUES = 1;
+ constexpr int64_t MAP_VALUE_SPLIT_VALUES = MAP_VALUE_PREFIX_VALUES +
SPANNING_BATCH_VALUES;
+ EXPECT_EQ(map_value_writer->WriteBatch(MAP_SPLIT_LEVELS,
map_value_definition_levels.data(),
map_repetition_levels.data(),
map_values.data()),
- static_cast<int64_t>(map_values.size()));
+ MAP_VALUE_SPLIT_VALUES);
+ EXPECT_EQ(map_value_writer->WriteBatch(
+ static_cast<int64_t>(map_repetition_levels.size()) -
MAP_SPLIT_LEVELS,
+ map_value_definition_levels.data() + MAP_SPLIT_LEVELS,
+ map_repetition_levels.data() + MAP_SPLIT_LEVELS,
+ map_values.data() + MAP_VALUE_SPLIT_VALUES),
+ static_cast<int64_t>(map_values.size()) -
MAP_VALUE_SPLIT_VALUES);
map_value_writer->Close();
std::vector<int16_t> element_repetition_levels {0, 0, 0, 1, 0};
@@ -1069,10 +1094,19 @@ void write_sparse_filter_nested_parquet_file(const
std::string& file_path) {
element_definition_levels.push_back(3);
auto* element_writer =
static_cast<::parquet::Int32Writer*>(row_group->NextColumn());
-
EXPECT_EQ(element_writer->WriteBatch(static_cast<int64_t>(element_repetition_levels.size()),
- element_definition_levels.data(),
+ constexpr int64_t ELEMENT_PREFIX_LEVELS = 5;
+ constexpr int64_t ELEMENT_PREFIX_VALUES = 2;
+ constexpr int64_t ELEMENT_SPLIT_LEVELS = ELEMENT_PREFIX_LEVELS +
SPANNING_BATCH_VALUES;
+ constexpr int64_t ELEMENT_SPLIT_VALUES = ELEMENT_PREFIX_VALUES +
SPANNING_BATCH_VALUES;
+ EXPECT_EQ(element_writer->WriteBatch(ELEMENT_SPLIT_LEVELS,
element_definition_levels.data(),
element_repetition_levels.data(),
element_values.data()),
- static_cast<int64_t>(element_values.size()));
+ ELEMENT_SPLIT_VALUES);
+ EXPECT_EQ(element_writer->WriteBatch(
+ static_cast<int64_t>(element_repetition_levels.size()) -
ELEMENT_SPLIT_LEVELS,
+ element_definition_levels.data() + ELEMENT_SPLIT_LEVELS,
+ element_repetition_levels.data() + ELEMENT_SPLIT_LEVELS,
+ element_values.data() + ELEMENT_SPLIT_VALUES),
+ static_cast<int64_t>(element_values.size()) -
ELEMENT_SPLIT_VALUES);
element_writer->Close();
auto* marker_writer =
static_cast<::parquet::Int32Writer*>(row_group->NextColumn());
const int16_t marker_definition_levels[] = {1, 0, 1, 1, 1, 1};
diff --git a/be/test/format_v2/table/remote_doris_reader_test.cpp
b/be/test/format_v2/table/remote_doris_reader_test.cpp
index a8affbde311..ad8149c9d05 100644
--- a/be/test/format_v2/table/remote_doris_reader_test.cpp
+++ b/be/test/format_v2/table/remote_doris_reader_test.cpp
@@ -213,7 +213,7 @@ TFileRangeDesc remote_doris_range(const
BlockingFlightServer& server) {
auto range = remote_doris_range();
auto& params = range.table_format_params.remote_doris_params;
params.__set_location_uri("grpc://localhost:" +
std::to_string(server.port()));
- arrow::flight::Ticket ticket {.ticket = "ticket"};
+ arrow::flight::Ticket ticket {"ticket"};
params.__set_ticket(ticket.SerializeToString().ValueOrDie());
return range;
}
diff --git a/build.sh b/build.sh
index 70673a15e49..2200aa1c71d 100755
--- a/build.sh
+++ b/build.sh
@@ -432,22 +432,74 @@ fi
if [[ "${HELP}" -eq 1 ]]; then
usage
fi
+
+if [[ "${CLEAN}" -eq 1 && "${BUILD_BE}" -eq 0 && "${BUILD_FE}" -eq 0 &&
${BUILD_CLOUD} -eq 0 ]]; then
+ clean_gensrc
+ clean_be
+ clean_fe
+ exit 0
+fi
+
# build thirdparty libraries if necessary. check last thirdparty lib
installation
if [[ "${TARGET_SYSTEM}" == 'Darwin' ]]; then
LAST_THIRDPARTY_LIB='libbrotlienc.a'
else
LAST_THIRDPARTY_LIB='hadoop_hdfs/native/libhdfs.a'
fi
-if [[ ! -f "${DORIS_THIRDPARTY}/installed/lib/${LAST_THIRDPARTY_LIB}" ]]; then
- echo "Thirdparty libraries need to be build ..."
- # need remove all installed pkgs because some lib like lz4 will throw
error if its lib alreay exists
- rm -rf "${DORIS_THIRDPARTY}/installed"
- if [[ "${CLEAN}" -eq 0 ]]; then
- "${DORIS_THIRDPARTY}/build-thirdparty.sh" -j "${PARALLEL}"
- else
- "${DORIS_THIRDPARTY}/build-thirdparty.sh" -j "${PARALLEL}" --clean
+# The final-library sentinel only proves that some third-party build
completed. It cannot
+# distinguish an older prebuilt whose Arrow/Paimon closure predates the
selected sources.
+# shellcheck source=thirdparty/arrow-paimon-vars.sh
+. "${DORIS_HOME}/thirdparty/arrow-paimon-vars.sh"
+NEED_ARROW_PAIMON_THIRDPARTY=false
+if [[ "${BUILD_BE}" -eq 1 || "${BUILD_CLOUD}" -eq 1 ||
+ "${BUILD_META_TOOL}" == "ON" || "${BUILD_FILE_CACHE_MICROBENCH_TOOL}" ==
"ON" ||
+ "${BUILD_INDEX_TOOL}" == "ON" ]]; then
+ NEED_ARROW_PAIMON_THIRDPARTY=true
+fi
+
+rebuild_thirdparty_libraries() {
+ local remove_installed="$1"
+ shift
+ local build_script="${DORIS_THIRDPARTY}/build-thirdparty.sh"
+ local build_args=(-j "${PARALLEL}")
+ local selected_thirdparty_root
+ local checkout_thirdparty_root
+
+ if [[ ! -f "${build_script}" ]]; then
+ echo "Cannot rebuild thirdparty libraries: ${build_script} is
missing." >&2
+ echo "DORIS_THIRDPARTY=${DORIS_THIRDPARTY} is an install-only or
incomplete prefix. Use a matching compilation image/prebuilt, or unset
DORIS_THIRDPARTY to rebuild with this checkout's thirdparty tree." >&2
+ exit 1
+ fi
+ selected_thirdparty_root="$(cd "${DORIS_THIRDPARTY}" && pwd -P)"
+ checkout_thirdparty_root="$(cd "${DORIS_HOME}/thirdparty" && pwd -P)"
+ if [[ "${selected_thirdparty_root}" != "${checkout_thirdparty_root}" ]];
then
+ echo "Cannot rebuild thirdparty libraries with an external source
tree: ${selected_thirdparty_root}." >&2
+ echo "Unset DORIS_THIRDPARTY to rebuild with this checkout's
thirdparty tree, then use the resulting version-matched installation." >&2
+ exit 1
fi
+ build_script="${checkout_thirdparty_root}/build-thirdparty.sh"
+ if [[ "${remove_installed}" == "true" ]]; then
+ # Some libraries, such as lz4, fail when an earlier installation
remains.
+ rm -rf "${DORIS_THIRDPARTY}/installed"
+ fi
+ if [[ "${CLEAN}" -eq 1 ]]; then
+ build_args+=(--clean)
+ fi
+ bash "${build_script}" "${build_args[@]}" "$@"
+ if ! arrow_paimon_prebuilt_valid "${DORIS_THIRDPARTY}/installed"; then
+ echo "Rebuilt Arrow/Paimon artifacts do not match this checkout's
selected inputs." >&2
+ exit 1
+ fi
+}
+
+if [[ ! -f "${DORIS_THIRDPARTY}/installed/lib/${LAST_THIRDPARTY_LIB}" ]]; then
+ echo "Thirdparty libraries need to be build ..."
+ rebuild_thirdparty_libraries true
+elif [[ "${NEED_ARROW_PAIMON_THIRDPARTY}" == "true" ]] &&
+ ! arrow_paimon_prebuilt_valid "${DORIS_THIRDPARTY}/installed"; then
+ echo "Arrow/Paimon thirdparty libraries need to be rebuilt ..."
+ rebuild_thirdparty_libraries false "${ARROW_PAIMON_BUILD_PACKAGES[@]}"
fi
update_submodule() {
@@ -486,13 +538,6 @@ update_submodule() {
fi
}
-if [[ "${CLEAN}" -eq 1 && "${BUILD_BE}" -eq 0 && "${BUILD_FE}" -eq 0 &&
${BUILD_CLOUD} -eq 0 ]]; then
- clean_gensrc
- clean_be
- clean_fe
- exit 0
-fi
-
if [[ -z "${GLIBC_COMPATIBILITY}" ]]; then
if [[ "${TARGET_SYSTEM}" != 'Darwin' ]]; then
GLIBC_COMPATIBILITY='ON'
diff --git a/docker/compilation/Dockerfile.gcc10
b/docker/compilation/Dockerfile.gcc10
index e0026ce5f59..f066fd3af1b 100644
--- a/docker/compilation/Dockerfile.gcc10
+++ b/docker/compilation/Dockerfile.gcc10
@@ -26,7 +26,7 @@ RUN yum makecache && yum -y update && yum -y groupinstall
'Development Tools' &&
devtoolset-10-libasan-devel
# build cmake
-ARG CMAKE_VERSION=3.22.1
+ARG CMAKE_VERSION=3.25.3
ARG
CMAKE_BASE_URL=https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}
RUN wget ${CMAKE_BASE_URL}/cmake-${CMAKE_VERSION}-Linux-x86_64.sh -q -O
/tmp/cmake-install.sh && \
chmod u+x /tmp/cmake-install.sh && \
@@ -121,4 +121,3 @@ ENV JAVA_HOME="/usr/lib/jvm/java-11" \
WORKDIR /root
CMD ["/bin/bash"]
-
diff --git a/docker/compilation/Dockerfile.gcc7
b/docker/compilation/Dockerfile.gcc7
deleted file mode 100644
index 7ca1fb321b4..00000000000
--- a/docker/compilation/Dockerfile.gcc7
+++ /dev/null
@@ -1,119 +0,0 @@
-# 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.
-
-FROM centos:centos7.5.1804 AS builder
-
-LABEL maintainer=tangxiaoqing214445
-
-ENV DEFAULT_DIR /var/local
-
-ARG GCC_VERSION=7.3.0
-ARG GCC_URL=https://mirrors.ustc.edu.cn/gnu/gcc/gcc-${GCC_VERSION}
-
-# install dependencies and build gcc
-RUN yum install -y bzip2 wget git gcc-c++ libstdc++-static byacc flex automake
libtool binutils-devel bison ncurses-devel make mlocate unzip patch which
vim-common redhat-lsb-core zip libcurl-devel libasan-static libtsan-static \
- && updatedb \
- && yum -y clean all \
- && rm -rf /var/cache/yum \
- && mkdir -p /var/local/gcc \
- && curl -fsSL -o /tmp/node-v14.16.0-linux-x64.tar.xz
https://nodejs.org/dist/v14.16.0/node-v14.16.0-linux-x64.tar.xz \
- && tar xf /tmp/node-v14.16.0-linux-x64.tar.xz -C ${DEFAULT_DIR}/ \
- && rm /tmp/node-v14.16.0-linux-x64.tar.xz \
- && curl -fsSL -o /tmp/gcc.tar.gz ${GCC_URL}/gcc-${GCC_VERSION}.tar.gz \
- && tar -xzf /tmp/gcc.tar.gz -C /var/local/gcc --strip-components=1 \
- && cd /var/local/gcc \
- && sed -i
's/ftp:\/\/gcc.gnu.org\/pub\/gcc\/infrastructure\//http:\/\/mirror.linux-ia64.org\/gnu\/gcc\/infrastructure\//g'
contrib/download_prerequisites \
- && ./contrib/download_prerequisites \
- && ./configure --disable-multilib --enable-languages=c,c++ --prefix=/usr \
- && make -j$[$(nproc)/4+1] && make install \
- && rm -rf /var/local/gcc \
- && rm -f /tmp/gcc.tar.gz
-
-ENV PATH ${DEFAULT_DIR}/node-v14.16.0-linux-x64/bin:$PATH
-
-# build cmake
-ARG CMAKE_VERSION=3.12.3
-ARG
CMAKE_DOWNLOAD_URL=https://cmake.org/files/v3.12/cmake-${CMAKE_VERSION}.tar.gz
-RUN mkdir -p /tmp/cmake && curl -fsSL -o /tmp/cmake.tar.gz
${CMAKE_DOWNLOAD_URL} \
- && tar -zxf /tmp/cmake.tar.gz -C /tmp/cmake --strip-components=1 \
- && cd /tmp/cmake \
- && ./bootstrap --system-curl \
- && gmake -j$[$(nproc)/4+1] \
- && gmake install \
- && rm -rf /tmp/cmake.tar.gz \
- && rm -rf /tmp/cmake
-
-# install jdk
-COPY ./jdk.rpm ./
-RUN wget --no-cookies --no-check-certificate --header "Cookie:
oraclelicense=accept-securebackup-cookie"
https://javadl.oracle.com/webapps/download/GetFile/1.8.0_281-b09/89d678f2be164786b292527658ca1605/linux-i586/jdk-8u281-linux-x64.rpm
-O jdk.rpm \
- && touch ${DEFAULT_DIR}/install_jdk.sh \
- && echo '#!/bin/bash' >> ${DEFAULT_DIR}/install_jdk.sh \
- && echo 'rpm -Uvh jdk.rpm > /dev/null 2>&1' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'mv /usr/java/jdk* /usr/java/jdk' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'export JAVA_HOME=/usr/java/jdk' >> ${DEFAULT_DIR}/install_jdk.sh
\
- && echo 'echo "export JAVA_HOME=/usr/java/jdk" >> /etc/environment' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'export JRE_HOME=/usr/java/jdk/jre' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'echo "export JRE_HOME=/usr/java/jdk/jre" >> /etc/environment' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'ls /usr/java/jdk > /dev/null 2>&1' >>
${DEFAULT_DIR}/install_jdk.sh \
- && echo 'echo "export JAVA_HOME=/usr/java/jdk" >> /root/.bashrc' >>
${DEFAULT_DIR}/install_jdk.sh \
- && chmod 777 ${DEFAULT_DIR}/install_jdk.sh \
- && /bin/bash ${DEFAULT_DIR}/install_jdk.sh \
- && rm -rf *.rpm \
- && rm ${DEFAULT_DIR}/install_jdk.sh
-
-ENV JAVA_HOME /usr/java/jdk
-
-# install maven 3.6.3
-ARG
SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0
-ARG
MAVEN_URL=http://mirror.bit.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
-
-RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
- && curl -fsSL -o /tmp/apache-maven.tar.gz ${MAVEN_URL} \
- && echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \
- && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven
--strip-components=1 \
- && rm -f /tmp/apache-maven.tar.gz \
- && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
-
-ENV MAVEN_HOME /usr/share/maven
-
-# build environment
-WORKDIR ${DEFAULT_DIR}
-
-# there is a repo which is included all of thirdparty
-ENV REPOSITORY_URL=https://doris-thirdparty-repo.bj.bcebos.com/thirdparty
-
-# clone lastest source code, download and build third party
-COPY doris ${DEFAULT_DIR}/doris
-RUN cd ${DEFAULT_DIR}/doris && /bin/bash thirdparty/build-thirdparty.sh \
- && rm -rf ${DEFAULT_DIR}/doris/thirdparty/src \
- && rm -rf ${DEFAULT_DIR}/doris-thirdparty.tar.gz \
- && rm -rf ${DEFAULT_DIR}/doris-thirdparty \
- && mkdir -p ${DEFAULT_DIR}/thirdparty \
- && mv ${DEFAULT_DIR}/doris/thirdparty/installed ${DEFAULT_DIR}/thirdparty/
\
- && rm -rf ${DEFAULT_DIR}/doris
-
-FROM scratch
-COPY --from=builder / /
-
-ENV DEFAULT_DIR /var/local
-ENV PATH ${DEFAULT_DIR}/node-v14.8.0-linux-x64/bin:$PATH
-ENV JAVA_HOME /usr/java/jdk
-ENV MAVEN_HOME /usr/share/maven
-ENV DORIS_THIRDPARTY /var/local/thirdparty
-WORKDIR /root
-CMD ["/bin/bash"]
-
diff --git a/docker/compilation/arm/Dockerfile
b/docker/compilation/arm/Dockerfile
index aa0ce5eea4d..656ee43d39a 100644
--- a/docker/compilation/arm/Dockerfile
+++ b/docker/compilation/arm/Dockerfile
@@ -47,10 +47,21 @@ RUN wget
https://github.com/amosbird/ldb_toolchain_gen/releases/download/v0.9.1/
&& sh /tmp/ldb_toolchain_gen.aarch64.sh /var/local/ldb-toolchain/ \
&& rm /tmp/ldb_toolchain_gen.aarch64.sh
+# Arrow 24 requires CMake 3.25 or newer. The bundled ldb toolchain only
+# provides CMake 3.22, so install and select a compatible native build.
+ARG CMAKE_VERSION=3.25.3
+ARG
CMAKE_BASE_URL=https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}
+RUN wget ${CMAKE_BASE_URL}/cmake-${CMAKE_VERSION}-Linux-aarch64.sh \
+ -q -O /tmp/cmake-install.sh \
+ && chmod u+x /tmp/cmake-install.sh \
+ && /tmp/cmake-install.sh --skip-license --prefix=/usr --exclude-subdir \
+ && rm /tmp/cmake-install.sh
+
# there is a repo which is included all of thirdparty
ENV REPOSITORY_URL="https://doris-thirdparty-repo.bj.bcebos.com/thirdparty/" \
DEFAULT_DIR="/var/local" \
JAVA_HOME="/usr/lib/jvm/java-11" \
+ CUSTOM_CMAKE="/usr/bin/cmake" \
PATH="/var/local/ldb-toolchain/bin/:$PATH"
# disable auto enable ccache
@@ -76,6 +87,7 @@ ENV JAVA_HOME="/usr/lib/jvm/java-11" \
MAVEN_HOME="/usr/share/maven" \
REPOSITORY_URL="" \
DEFAULT_DIR="/var/local" \
+ CUSTOM_CMAKE="/usr/bin/cmake" \
PATH="/var/local/ldb-toolchain/bin/:/var/local/thirdparty/installed/bin/:$PATH"
\
DORIS_THIRDPARTY="/var/local/thirdparty"
WORKDIR /root
diff --git
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
index 48765f6c4dd..0094b0f105f 100644
---
a/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
+++
b/regression-test/data/external_table_p0/iceberg/write/test_iceberg_write_stats2.out
@@ -7,7 +7,7 @@ true 11 111 1.1 1.1 1111 1234.5678
1234.567890 123456789012345678.123456789012 a
0 PARQUET 2 {1:2, 2:2, 3:2, 4:2, 5:2, 6:2, 7:2, 8:2, 9:2, 10:2,
11:2, 12:2} {1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0}
{1:0x00, 2:0x0B000000, 3:0x6F00000000000000, 4:0xCDCC8C3F,
5:0x9A9999999999F13F, 6:0x00000457, 7:0x00BC614E, 8:0x00000000499602D2,
9:0x000000018EE90FF6C373E0393713FA14, 10:0x616161, 11:0x9E4B0000,
12:0x005CE70F33F10500} {1:0x01, 2:0x16000000, 3:0xDE00000000000000,
4:0xCDCC0C40, 5:0x9A99999999990140, 6:0x000008AE, 7:0x05397FB1,
8:0x000000020A75E124, 9 [...]
-- !sql_2 --
-{"bigint_col":{"column_size":118, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":111, "upper_bound":222},
"boolean_col":{"column_size":49, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":0, "upper_bound":1},
"date_col":{"column_size":94, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":"2023-01-01",
"upper_bound":"2023-06-15"}, "datetime_col1":{"column_size":118,
"value_count":2, "null_value_count":0, [...]
+{"bigint_col":{"column_size":74, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":111, "upper_bound":222},
"boolean_col":{"column_size":33, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":0, "upper_bound":1},
"date_col":{"column_size":66, "value_count":2, "null_value_count":0,
"nan_value_count":null, "lower_bound":"2023-01-01",
"upper_bound":"2023-06-15"}, "datetime_col1":{"column_size":74,
"value_count":2, "null_value_count":0, "n [...]
-- !sql_3 --
false 22 222 2.2 2.2 2222 8765.4321 8765.432100
987654321098765432.987654321099 bbb 2023-06-15 2023-06-15T23:45:01
diff --git
a/regression-test/suites/external_table_p0/iceberg/iceberg_schema_change_ddl.groovy
b/regression-test/suites/external_table_p0/iceberg/iceberg_schema_change_ddl.groovy
index c197e3f372c..d40c1eb29c9 100644
---
a/regression-test/suites/external_table_p0/iceberg/iceberg_schema_change_ddl.groovy
+++
b/regression-test/suites/external_table_p0/iceberg/iceberg_schema_change_ddl.groovy
@@ -204,7 +204,7 @@ suite("iceberg_schema_change_ddl",
"p0,external,doris,external_docker,external_d
// Add test columns for type conversion tests
sql """ ALTER TABLE ${table_name} ADD COLUMN test_float FLOAT """
sql """ ALTER TABLE ${table_name} ADD COLUMN test_decimal DECIMAL(5,2) """
- sql """ INSERT INTO ${table_name} (id, test_float, test_decimal) VALUES
(7, 3.14, 123.45) """
+ sql """ INSERT INTO ${table_name} (id, grade, test_float, test_decimal)
VALUES (7, 0, 3.14, 123.45) """
// Positive case: float -> double
sql """ ALTER TABLE ${table_name} MODIFY COLUMN test_float DOUBLE """
diff --git a/run-be-ut.sh b/run-be-ut.sh
index 65d1ff68558..97e5759a9a4 100755
--- a/run-be-ut.sh
+++ b/run-be-ut.sh
@@ -48,6 +48,29 @@ export TP_INCLUDE_DIR="${DORIS_THIRDPARTY}/installed/include"
export TP_INSTALLED_DIR="${DORIS_THIRDPARTY}/installed"
export TP_LIB_DIR="${DORIS_THIRDPARTY}/installed/lib"
. "${DORIS_HOME}/env.sh"
+# shellcheck source=thirdparty/arrow-paimon-vars.sh
+. "${DORIS_HOME}/thirdparty/arrow-paimon-vars.sh"
+
+prepare_build_image_arrow_paimon_prebuilt() {
+ local selected_thirdparty_root
+ local checkout_thirdparty_root
+
+ selected_thirdparty_root="$(cd "${DORIS_THIRDPARTY}" && pwd -P)"
+ checkout_thirdparty_root="$(cd "${DORIS_HOME}/thirdparty" && pwd -P)"
+ if [[ "${selected_thirdparty_root}" == "${checkout_thirdparty_root}" ]];
then
+ return 0
+ fi
+
+ # The official Linux x86_64 build image carries an install-only thirdparty
+ # tree. Refresh it from the shared automation asset when the image predates
+ # the Arrow/Paimon closure selected by this checkout.
+ if [[ "${selected_thirdparty_root}" != "/var/local/thirdparty" ||
+ "$(uname -s)" != "Linux" || "$(uname -m)" != "x86_64" ]]; then
+ return 0
+ fi
+ ensure_arrow_paimon_prebuilt_from_url "${selected_thirdparty_root}" \
+ "${ARROW_PAIMON_SHARED_PREBUILT_LINUX_X86_64_URL}"
+}
trim_whitespace() {
local value="$1"
@@ -228,6 +251,8 @@ echo "Get params:
"
echo "Build Backend UT"
+prepare_build_image_arrow_paimon_prebuilt
+
update_submodule() {
local submodule_path=$1
local submodule_name=$2
diff --git a/thirdparty/arrow-paimon-vars.sh b/thirdparty/arrow-paimon-vars.sh
new file mode 100644
index 00000000000..b5c6d6955c6
--- /dev/null
+++ b/thirdparty/arrow-paimon-vars.sh
@@ -0,0 +1,408 @@
+#!/bin/bash
+# shellcheck disable=2034
+
+# 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.
+
+# Keep the Arrow/Paimon source closure in a dedicated file so targeted CI can
+# distinguish this stack from unrelated thirdparty changes.
+
+# arrow
+ARROW_VERSION="24.0.0"
+ARROW_DOWNLOAD="https://github.com/apache/arrow/archive/refs/tags/apache-arrow-${ARROW_VERSION}.tar.gz"
+ARROW_NAME="apache-arrow-${ARROW_VERSION}.tar.gz"
+ARROW_SOURCE="arrow-apache-arrow-${ARROW_VERSION}"
+ARROW_MD5SUM="66c53bd00baa79034bd2ca167beea436"
+
+# Arrow bundled dependencies
+BROTLI_DOWNLOAD="https://github.com/google/brotli/archive/v1.0.9.tar.gz"
+BROTLI_NAME="brotli-1.0.9.tar.gz"
+BROTLI_SOURCE="brotli-1.0.9"
+BROTLI_MD5SUM="c2274f0c7af8470ad514637c35bcee7d"
+
+XSIMD_DOWNLOAD="https://github.com/xtensor-stack/xsimd/archive/refs/tags/14.0.0.tar.gz"
+XSIMD_NAME="14.0.0.tar.gz"
+XSIMD_SOURCE=xsimd-14.0.0
+XSIMD_MD5SUM="75c0d34cf7011924ba19978076c76dc1"
+
+# paimon-cpp
+PAIMON_CPP_DOWNLOAD="https://github.com/apache/doris-thirdparty/archive/refs/tags/paimon-cpp-0a4f4e2.tar.gz"
+PAIMON_CPP_NAME="paimon-cpp-0a4f4e2.tar.gz"
+PAIMON_CPP_SOURCE="doris-thirdparty-paimon-cpp-0a4f4e2"
+PAIMON_CPP_MD5SUM="b8599a0421dbf1ec05e2f1a481d64e87"
+
+ARROW_PAIMON_SHARED_PREBUILT_LINUX_X86_64_URL="${ARROW_PAIMON_SHARED_PREBUILT_LINUX_X86_64_URL:-https://github.com/apache/doris-thirdparty/releases/download/automation/doris-thirdparty-prebuilt-linux-x86_64.tar.xz}"
+
+# Bump the corresponding schema version whenever output-affecting build
options or
+# helper behavior in build_arrow() or build_paimon_cpp() changes. The
fingerprints
+# below intentionally describe only this component stack so master and release
+# branches can reuse the same shared prebuilt when their semantic inputs match.
+ARROW_BUILD_SCHEMA_VERSION="1"
+PAIMON_BUILD_SCHEMA_VERSION="1"
+
+# The current shared automation prebuilt was published from master with the
former
+# whole-script fingerprint. Keep these exact markers during the schema
transition;
+# version and complete artifact validation are still mandatory before reuse.
+ARROW_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT="ab79ab0bbfbf93f9860050fb751b20fee9e40d96"
+PAIMON_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT="cb82e41ba46f534e611cdd52e66b53c227d49bf8"
+ARROW_LEGACY_BUILD_FINGERPRINTS=(
+ 9d03645dd1cded5184a8126f5c7f4a6eb9b92b53
+)
+PAIMON_LEGACY_BUILD_FINGERPRINTS=(
+ dbb6ca6e243cb3aa783b7a8011f97afda9e7ea28
+)
+
+# Arrow consumes xsimd and Brotli as bundled source archives, but neither is a
+# build target in the focused Arrow/Paimon recovery path.
+ARROW_PAIMON_BUILD_PACKAGES=(arrow paimon_cpp)
+ARROW_BUNDLED_SOURCE_PACKAGES=(xsimd brotli)
+ARROW_PAIMON_DOWNLOAD_PACKAGES=()
+
+prepare_arrow_paimon_download_packages() {
+ ARROW_PAIMON_DOWNLOAD_PACKAGES=("$@")
+
+ local package
+ local source_package
+ local arrow_requested=false
+ local source_requested
+ for package in "$@"; do
+ if [[ "${package}" == "arrow" ]]; then
+ arrow_requested=true
+ break
+ fi
+ done
+ if [[ "${arrow_requested}" != "true" ]]; then
+ return
+ fi
+
+ for source_package in "${ARROW_BUNDLED_SOURCE_PACKAGES[@]}"; do
+ source_requested=false
+ for package in "${ARROW_PAIMON_DOWNLOAD_PACKAGES[@]}"; do
+ if [[ "${package}" == "${source_package}" ]]; then
+ source_requested=true
+ break
+ fi
+ done
+ if [[ "${source_requested}" != "true" ]]; then
+ ARROW_PAIMON_DOWNLOAD_PACKAGES+=("${source_package}")
+ fi
+ done
+}
+
+# Print stable path-and-content records for fingerprint inputs. Including the
path
+# makes patch selection and ordering part of the contract, not only file
contents.
+arrow_paimon_fingerprint_files() {
+ local file
+ local blob
+ while IFS= read -r file; do
+ blob="$(git hash-object "${file}")" || return 1
+ printf 'file=%s\n' "${file}"
+ printf 'blob=%s\n' "${blob}"
+ done < <(printf '%s\n' "$@" | LC_ALL=C sort)
+}
+
+# Identify only the source, patch, and explicit build-schema inputs selected
for
+# Arrow. Arrow and Paimon publish separate installed markers so a package-only
+# build cannot certify a component that it did not rebuild.
+arrow_build_fingerprint() {
+ local vars_dir
+ vars_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ (
+ set -o pipefail
+ cd "${vars_dir}" || return 1
+ {
+ printf 'schema=%s\n' "${ARROW_BUILD_SCHEMA_VERSION}"
+ printf 'ARROW_VERSION=%s\n' "${ARROW_VERSION}"
+ printf 'ARROW_NAME=%s\n' "${ARROW_NAME}"
+ printf 'ARROW_SOURCE=%s\n' "${ARROW_SOURCE}"
+ printf 'ARROW_MD5SUM=%s\n' "${ARROW_MD5SUM}"
+ printf 'BROTLI_NAME=%s\n' "${BROTLI_NAME}"
+ printf 'BROTLI_SOURCE=%s\n' "${BROTLI_SOURCE}"
+ printf 'BROTLI_MD5SUM=%s\n' "${BROTLI_MD5SUM}"
+ printf 'XSIMD_NAME=%s\n' "${XSIMD_NAME}"
+ printf 'XSIMD_SOURCE=%s\n' "${XSIMD_SOURCE}"
+ printf 'XSIMD_MD5SUM=%s\n' "${XSIMD_MD5SUM}"
+ arrow_paimon_fingerprint_files \
+ patches/apache-arrow-"${ARROW_VERSION}"-*.patch
+ } | git hash-object --stdin
+ )
+}
+
+paimon_build_fingerprint() {
+ local vars_dir
+ vars_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ (
+ set -o pipefail
+ cd "${vars_dir}" || return 1
+ {
+ arrow_build_fingerprint
+ printf 'schema=%s\n' "${PAIMON_BUILD_SCHEMA_VERSION}"
+ printf 'PAIMON_CPP_NAME=%s\n' "${PAIMON_CPP_NAME}"
+ printf 'PAIMON_CPP_SOURCE=%s\n' "${PAIMON_CPP_SOURCE}"
+ printf 'PAIMON_CPP_MD5SUM=%s\n' "${PAIMON_CPP_MD5SUM}"
+ arrow_paimon_fingerprint_files \
+ paimon-cpp-cache.cmake \
+ patches/paimon-cpp-*.patch
+ } | git hash-object --stdin
+ )
+}
+
+# Source patch markers use a combined value because either component's inputs
+# may change the external-Arrow contract applied to both source trees.
+arrow_paimon_build_fingerprint() {
+ {
+ arrow_build_fingerprint
+ paimon_build_fingerprint
+ } | git hash-object --stdin
+}
+
+arrow_paimon_fingerprint_matches() {
+ local installed_fingerprint="$1"
+ local expected_fingerprint="$2"
+ local legacy_compatible_expected_fingerprint="$3"
+ shift 3
+ local compatible_fingerprint
+
+ if [[ "${installed_fingerprint}" == "${expected_fingerprint}" ]]; then
+ return 0
+ fi
+ if [[ "${expected_fingerprint}" !=
"${legacy_compatible_expected_fingerprint}" ]]; then
+ return 1
+ fi
+ for compatible_fingerprint in "$@"; do
+ if [[ "${installed_fingerprint}" == "${compatible_fingerprint}" ]];
then
+ return 0
+ fi
+ done
+ return 1
+}
+
+ARROW_REQUIRED_LIBRARIES=(
+ libbrotlicommon.a
+ libbrotlidec.a
+ libbrotlienc.a
+ libarrow.a
+ libarrow_compute.a
+ libarrow_flight.a
+ libarrow_flight_sql.a
+ libarrow_dataset.a
+ libarrow_acero.a
+ libarrow_bundled_dependencies.a
+ libparquet.a
+)
+
+PAIMON_REQUIRED_LIBRARIES=(
+ libpaimon.a
+ libpaimon_parquet_file_format.a
+ libpaimon_orc_file_format.a
+ libpaimon_blob_file_format.a
+ libpaimon_local_file_system.a
+ libpaimon_file_index.a
+ libpaimon_global_index.a
+ libroaring_bitmap_paimon.a
+ libxxhash_paimon.a
+ libfmt_paimon.a
+ libtbb_paimon.a
+)
+
+ARROW_PAIMON_REQUIRED_LIBRARIES=(
+ "${ARROW_REQUIRED_LIBRARIES[@]}"
+ "${PAIMON_REQUIRED_LIBRARIES[@]}"
+)
+
+arrow_artifacts_valid() {
+ local install_dir="$1"
+ local installed_arrow_version
+ local library
+
+ if [[ ! -f "${install_dir}/include/arrow/util/config.h" ]]; then
+ echo "Missing installed Arrow version header" >&2
+ return 1
+ fi
+ installed_arrow_version="$(
+ awk '$1 == "#define" && $2 == "ARROW_VERSION_STRING" {
+ gsub(/"/, "", $3); print $3; exit
+ }' "${install_dir}/include/arrow/util/config.h"
+ )"
+ if [[ "${installed_arrow_version}" != "${ARROW_VERSION}" ]]; then
+ echo "Installed Arrow version ${installed_arrow_version} does not
match ${ARROW_VERSION}" >&2
+ return 1
+ fi
+
+ for library in "${ARROW_REQUIRED_LIBRARIES[@]}"; do
+ if [[ ! -f "${install_dir}/lib64/${library}" ]]; then
+ echo "Missing Arrow library: ${library}" >&2
+ return 1
+ fi
+ done
+ return 0
+}
+
+paimon_artifacts_valid() {
+ local install_dir="$1"
+ local library
+
+ for library in "${PAIMON_REQUIRED_LIBRARIES[@]}"; do
+ if [[ ! -f "${install_dir}/lib64/${library}" ]]; then
+ echo "Missing Paimon library: ${library}" >&2
+ return 1
+ fi
+ done
+ return 0
+}
+
+arrow_prebuilt_valid() {
+ local install_dir="$1"
+ local arrow_fingerprint_mark="${install_dir}/arrow-build-fingerprint.txt"
+ local expected_fingerprint
+ local installed_fingerprint
+
+ if [[ ! -f "${arrow_fingerprint_mark}" ]]; then
+ echo "Missing Arrow build fingerprint: ${arrow_fingerprint_mark}" >&2
+ return 1
+ fi
+ expected_fingerprint="$(arrow_build_fingerprint)"
+ installed_fingerprint="$(<"${arrow_fingerprint_mark}")"
+ if ! arrow_paimon_fingerprint_matches "${installed_fingerprint}" \
+ "${expected_fingerprint}"
"${ARROW_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT}" \
+ "${ARROW_LEGACY_BUILD_FINGERPRINTS[@]}"; then
+ echo "Arrow build fingerprint does not match selected inputs" >&2
+ return 1
+ fi
+ arrow_artifacts_valid "${install_dir}"
+}
+
+paimon_prebuilt_valid() {
+ local install_dir="$1"
+ local paimon_fingerprint_mark="${install_dir}/paimon-build-fingerprint.txt"
+ local expected_fingerprint
+ local installed_fingerprint
+
+ if [[ ! -f "${paimon_fingerprint_mark}" ]]; then
+ echo "Missing Paimon build fingerprint: ${paimon_fingerprint_mark}" >&2
+ return 1
+ fi
+ expected_fingerprint="$(paimon_build_fingerprint)"
+ installed_fingerprint="$(<"${paimon_fingerprint_mark}")"
+ if ! arrow_paimon_fingerprint_matches "${installed_fingerprint}" \
+ "${expected_fingerprint}"
"${PAIMON_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT}" \
+ "${PAIMON_LEGACY_BUILD_FINGERPRINTS[@]}"; then
+ echo "Paimon build fingerprint does not match selected inputs" >&2
+ return 1
+ fi
+ paimon_artifacts_valid "${install_dir}"
+}
+
+arrow_paimon_prebuilt_valid() {
+ local install_dir="$1"
+ arrow_prebuilt_valid "${install_dir}" && paimon_prebuilt_valid
"${install_dir}"
+}
+
+# Validate an extracted candidate before replacing the selected thirdparty
+# installation. This keeps an older build image usable when a download is
+# incomplete or contains an incompatible Arrow/Paimon closure.
+install_arrow_paimon_prebuilt_archive() {
+ local archive="$1"
+ local thirdparty_root="$2"
+ local staging_dir
+ local had_previous_installed=false
+
+ staging_dir="$(mktemp -d
"${thirdparty_root}/.arrow-paimon-install.XXXXXX")"
+ mkdir -p "${staging_dir}/candidate"
+ if ! tar -xf "${archive}" -C "${staging_dir}/candidate"; then
+ rm -rf "${staging_dir}"
+ return 1
+ fi
+ if ! arrow_paimon_prebuilt_valid "${staging_dir}/candidate/installed"; then
+ rm -rf "${staging_dir}"
+ return 1
+ fi
+
+ if [[ -e "${thirdparty_root}/installed" || -L
"${thirdparty_root}/installed" ]]; then
+ if ! mv "${thirdparty_root}/installed"
"${staging_dir}/previous-installed"; then
+ rm -rf "${staging_dir}"
+ return 1
+ fi
+ had_previous_installed=true
+ fi
+ if ! mv "${staging_dir}/candidate/installed"
"${thirdparty_root}/installed"; then
+ if [[ "${had_previous_installed}" == "true" ]]; then
+ mv "${staging_dir}/previous-installed"
"${thirdparty_root}/installed"
+ fi
+ rm -rf "${staging_dir}"
+ return 1
+ fi
+ rm -rf "${staging_dir}"
+}
+
+ensure_arrow_paimon_prebuilt_from_url() {
+ local thirdparty_root="$1"
+ local prebuilt_url="$2"
+ local download_dir
+ local archive
+
+ if arrow_paimon_prebuilt_valid "${thirdparty_root}/installed"; then
+ return 0
+ fi
+
+ echo "Refreshing Arrow/Paimon thirdparty libraries from ${prebuilt_url}"
+ download_dir="$(mktemp -d
"${thirdparty_root}/.arrow-paimon-download.XXXXXX")"
+ archive="${download_dir}/doris-thirdparty-prebuilt.tar.xz"
+ if ! curl --fail --location --retry 3 --show-error \
+ --output "${archive}" "${prebuilt_url}"; then
+ rm -rf "${download_dir}"
+ return 1
+ fi
+ if ! install_arrow_paimon_prebuilt_archive "${archive}"
"${thirdparty_root}"; then
+ rm -rf "${download_dir}"
+ return 1
+ fi
+ rm -rf "${download_dir}"
+ arrow_paimon_prebuilt_valid "${thirdparty_root}/installed"
+}
+
+invalidate_arrow_prebuilt_marker() {
+ local install_dir="$1"
+ rm -f "${install_dir}/arrow-build-fingerprint.txt" \
+ "${install_dir}/arrow-paimon-build-fingerprint.txt"
+}
+
+publish_arrow_prebuilt_marker() {
+ local install_dir="$1"
+ arrow_artifacts_valid "${install_dir}"
+ arrow_build_fingerprint >"${install_dir}/arrow-build-fingerprint.txt"
+}
+
+invalidate_paimon_prebuilt_marker() {
+ local install_dir="$1"
+ rm -f "${install_dir}/paimon-build-fingerprint.txt" \
+ "${install_dir}/arrow-paimon-build-fingerprint.txt"
+}
+
+publish_paimon_prebuilt_marker() {
+ local install_dir="$1"
+ paimon_artifacts_valid "${install_dir}"
+ paimon_build_fingerprint >"${install_dir}/paimon-build-fingerprint.txt"
+}
+
+require_arrow_prebuilt_for_paimon() {
+ local install_dir="$1"
+ if ! arrow_prebuilt_valid "${install_dir}"; then
+ echo "Paimon requires Arrow to be built from the currently selected
inputs first" >&2
+ return 1
+ fi
+}
diff --git a/thirdparty/build-thirdparty.sh b/thirdparty/build-thirdparty.sh
index 7e460ade7d8..35437afcdf1 100755
--- a/thirdparty/build-thirdparty.sh
+++ b/thirdparty/build-thirdparty.sh
@@ -155,7 +155,8 @@ if [[ "${CLEAN}" -eq 1 ]] && [[ -d "${TP_SOURCE_DIR}" ]];
then
fi
# Download thirdparties.
-eval "${TP_DIR}/download-thirdparty.sh ${packages[*]}"
+prepare_arrow_paimon_download_packages "${packages[@]}"
+bash "${TP_DIR}/download-thirdparty.sh" "${ARROW_PAIMON_DOWNLOAD_PACKAGES[@]}"
export LD_LIBRARY_PATH="${TP_DIR}/installed/lib:${LD_LIBRARY_PATH}"
@@ -1064,6 +1065,7 @@ build_grpc() {
# arrow
build_arrow() {
check_if_source_exist "${ARROW_SOURCE}"
+ invalidate_arrow_prebuilt_marker "${TP_INSTALL_DIR}"
cd "${TP_SOURCE_DIR}/${ARROW_SOURCE}/cpp"
mkdir -p release
@@ -1088,9 +1090,7 @@ build_arrow() {
ldflags="-L${TP_LIB_DIR}"
fi
- CPPFLAGS="-I${TP_INCLUDE_DIR}" \
- CXXFLAGS="-I${TP_INCLUDE_DIR}" \
- LDFLAGS="${ldflags}" \
+ LDFLAGS="${ldflags}" \
"${CMAKE_CMD}" -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_CXX_STANDARD="${TP_CXX_STANDARD}" \
-G "${GENERATOR}" -DARROW_PARQUET=ON -DARROW_IPC=ON
-DARROW_BUILD_SHARED=OFF \
@@ -1125,6 +1125,7 @@ build_arrow() {
-Dxsimd_SOURCE=BUNDLED \
-DBrotli_SOURCE=BUNDLED \
-DARROW_LZ4_USE_SHARED=OFF \
+ -DLZ4_ROOT="${TP_INSTALL_DIR};${TP_INSTALL_DIR}/include/lz4" \
-DLZ4_LIB="${TP_INSTALL_DIR}/lib/liblz4.a"
-DLZ4_INCLUDE_DIR="${TP_INSTALL_DIR}/include/lz4" \
-DLz4_SOURCE=SYSTEM \
-DARROW_ZSTD_USE_SHARED=OFF \
@@ -1147,9 +1148,12 @@ build_arrow() {
cp -rf ./brotli_ep/src/brotli_ep-install/lib/libbrotlidec-static.a
"${TP_INSTALL_DIR}/lib64/libbrotlidec.a"
cp -rf ./brotli_ep/src/brotli_ep-install/lib/libbrotlicommon-static.a
"${TP_INSTALL_DIR}/lib64/libbrotlicommon.a"
strip_lib libarrow.a
+ strip_lib libarrow_compute.a
strip_lib libparquet.a
strip_lib libarrow_dataset.a
strip_lib libarrow_acero.a
+
+ publish_arrow_prebuilt_marker "${TP_INSTALL_DIR}"
}
# abseil
@@ -2042,6 +2046,8 @@ build_pugixml() {
# paimon-cpp
build_paimon_cpp() {
check_if_source_exist "${PAIMON_CPP_SOURCE}"
+ require_arrow_prebuilt_for_paimon "${TP_INSTALL_DIR}"
+ invalidate_paimon_prebuilt_marker "${TP_INSTALL_DIR}"
cd "${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}"
rm -rf "${BUILD_DIR}"
@@ -2088,6 +2094,7 @@ build_paimon_cpp() {
mkdir -p "${paimon_deps_dir}"
for paimon_arrow_dep in \
libarrow.a \
+ libarrow_compute.a \
libarrow_filesystem.a \
libarrow_dataset.a \
libarrow_acero.a \
@@ -2121,6 +2128,7 @@ build_paimon_cpp() {
fi
echo "Paimon-cpp internal dependencies installed successfully"
+ publish_paimon_prebuilt_marker "${TP_INSTALL_DIR}"
}
# lance-c
diff --git a/thirdparty/download-thirdparty.sh
b/thirdparty/download-thirdparty.sh
index c278b15c6f7..87eae93eaf4 100755
--- a/thirdparty/download-thirdparty.sh
+++ b/thirdparty/download-thirdparty.sh
@@ -334,6 +334,20 @@ echo "===== Patching thirdparty archives..."
# This is to avoid duplicated patch.
###################################################################################
PATCHED_MARK="patched_mark"
+ARROW_PAIMON_PATCH_FINGERPRINT_MARK="patched_mark_arrow_paimon_fingerprint"
+ARROW_PAIMON_BUILD_FINGERPRINT=""
+if [[ " ${TP_ARCHIVES[*]} " =~ " ARROW " ||
+ " ${TP_ARCHIVES[*]} " =~ " PAIMON_CPP " ]]; then
+ ARROW_PAIMON_BUILD_FINGERPRINT="$(arrow_paimon_build_fingerprint)"
+fi
+
+reset_arrow_paimon_source() {
+ local archive_name="$1"
+ local source_name="$2"
+ echo "Resetting ${source_name} because its patch state is incomplete or
stale"
+ rm -rf "${TP_SOURCE_DIR:?}/${source_name}"
+ "${TAR_CMD}" xzf "${TP_SOURCE_DIR}/${archive_name}" -C "${TP_SOURCE_DIR}/"
+}
# glog patch
if [[ " ${TP_ARCHIVES[*]} " =~ " GLOG " ]]; then
@@ -438,22 +452,28 @@ if [[ " ${TP_ARCHIVES[*]} " =~ " ARROW " ]]; then
fi
cd -
fi
- if [[ "${ARROW_SOURCE}" == "arrow-apache-arrow-17.0.0" ]]; then
- cd "${TP_SOURCE_DIR}/${ARROW_SOURCE}"
- if [[ ! -f "${PATCHED_MARK}" ]]; then
+ if [[ "${ARROW_SOURCE}" == "arrow-apache-arrow-24.0.0" ]]; then
+
arrow_fingerprint_mark="${TP_SOURCE_DIR}/${ARROW_SOURCE}/${ARROW_PAIMON_PATCH_FINGERPRINT_MARK}"
+ if ! [[ -f "${TP_SOURCE_DIR}/${ARROW_SOURCE}/${PATCHED_MARK}" &&
+ -f "${arrow_fingerprint_mark}" ]] ||
+ [[ "$(<"${arrow_fingerprint_mark}")" !=
"${ARROW_PAIMON_BUILD_FINGERPRINT}" ]]; then
+ reset_arrow_paimon_source "${ARROW_NAME}" "${ARROW_SOURCE}"
+ cd "${TP_SOURCE_DIR}/${ARROW_SOURCE}"
# Paimon-cpp parquet patches: row-group-aware batch reader,
max_row_group_size,
# GetBufferedSize(), int96 NANO guard, and Thrift_VERSION empty
fix.
- patch -p1 <"${TP_PATCH_DIR}/apache-arrow-17.0.0-paimon.patch"
+ patch -p1 <"${TP_PATCH_DIR}/apache-arrow-24.0.0-paimon.patch"
- # apache-arrow-17.0.0-force-write-int96-timestamps.patch :
- # Introducing the parameter that forces writing int96 timestampes
for compatibility with Paimon cpp.
- patch -p1
<"${TP_PATCH_DIR}/apache-arrow-17.0.0-force-write-int96-timestamps.patch"
+ # Introducing the parameter that forces writing INT96 timestamps
for
+ # compatibility with the Doris Parquet writer.
+ patch -p1
<"${TP_PATCH_DIR}/apache-arrow-24.0.0-force-write-int96-timestamps.patch"
# Add Parquet LZO page decompression support used by file scanner
v2.
- patch -p1 <"${TP_PATCH_DIR}/apache-arrow-17.0.0-lzo.patch"
+ patch -p1 <"${TP_PATCH_DIR}/apache-arrow-24.0.0-lzo.patch"
touch "${PATCHED_MARK}"
+ printf '%s\n' "${ARROW_PAIMON_BUILD_FINGERPRINT}" \
+ >"${ARROW_PAIMON_PATCH_FINGERPRINT_MARK}"
+ cd -
fi
- cd -
fi
echo "Finished patching ${ARROW_SOURCE}"
fi
@@ -731,16 +751,26 @@ fi
# patch paimon-cpp
if [[ " ${TP_ARCHIVES[*]} " =~ " PAIMON_CPP " ]]; then
- cd "${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}"
- if [[ ! -f "${PATCHED_MARK}" ]]; then
- if patch -p1 -N --batch --dry-run
<"${TP_PATCH_DIR}/paimon-cpp-buildutils-static-deps.patch" >/dev/null 2>&1; then
- patch -p1 -N --batch
<"${TP_PATCH_DIR}/paimon-cpp-buildutils-static-deps.patch"
- else
- echo "Skip paimon-cpp patch: already applied or not applicable for
current source"
- fi
+ PAIMON_CPP_ARROW_24_PATCHED_MARK="patched_mark_arrow_24"
+ PAIMON_CPP_ARROW_24_COMPUTE_PATCHED_MARK="patched_mark_arrow_24_compute"
+
paimon_fingerprint_mark="${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}/${ARROW_PAIMON_PATCH_FINGERPRINT_MARK}"
+ if ! [[ -f "${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}/${PATCHED_MARK}" &&
+ -f
"${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}/${PAIMON_CPP_ARROW_24_PATCHED_MARK}" &&
+ -f
"${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}/${PAIMON_CPP_ARROW_24_COMPUTE_PATCHED_MARK}"
&&
+ -f "${paimon_fingerprint_mark}" ]] ||
+ [[ "$(<"${paimon_fingerprint_mark}")" !=
"${ARROW_PAIMON_BUILD_FINGERPRINT}" ]]; then
+ reset_arrow_paimon_source "${PAIMON_CPP_NAME}" "${PAIMON_CPP_SOURCE}"
+ cd "${TP_SOURCE_DIR}/${PAIMON_CPP_SOURCE}"
+ patch -p1 <"${TP_PATCH_DIR}/paimon-cpp-buildutils-static-deps.patch"
+ patch -p1 <"${TP_PATCH_DIR}/paimon-cpp-arrow-24-compatibility.patch"
+ patch -p1 <"${TP_PATCH_DIR}/paimon-cpp-arrow-24-compute.patch"
touch "${PATCHED_MARK}"
+ touch "${PAIMON_CPP_ARROW_24_PATCHED_MARK}"
+ touch "${PAIMON_CPP_ARROW_24_COMPUTE_PATCHED_MARK}"
+ printf '%s\n' "${ARROW_PAIMON_BUILD_FINGERPRINT}" \
+ >"${ARROW_PAIMON_PATCH_FINGERPRINT_MARK}"
+ cd -
fi
- cd -
echo "Finished patching ${PAIMON_CPP_SOURCE}"
fi
diff --git a/thirdparty/paimon-cpp-cache.cmake
b/thirdparty/paimon-cpp-cache.cmake
index dbebd94a0cc..6ab6049c59b 100644
--- a/thirdparty/paimon-cpp-cache.cmake
+++ b/thirdparty/paimon-cpp-cache.cmake
@@ -65,7 +65,7 @@ set(LZ4_INCLUDE_DIR "${DORIS_INCLUDE_DIR}" CACHE PATH "LZ4
include directory")
# ============================================================================
# Arrow - Reuse from Doris (Doris Arrow now includes
COMPUTE/DATASET/ACERO/FILESYSTEM)
-# Doris's Arrow 17.0.0 is built with the full module set that paimon-cpp
+# Doris's Arrow 24.0.0 is built with the full module set that paimon-cpp
# needs, so we skip paimon-cpp's internal externalproject_add(arrow_ep ...).
# ============================================================================
set(PAIMON_USE_EXTERNAL_ARROW ON CACHE BOOL "Use pre-built Arrow from Doris
instead of building from source")
@@ -74,6 +74,7 @@ set(DORIS_LIB64_DIR "${DORIS_THIRDPARTY_DIR}/lib64" CACHE
PATH "Doris lib64 dire
set(PAIMON_EXTERNAL_ARROW_INCLUDE_DIR "${DORIS_INCLUDE_DIR}" CACHE PATH "Arrow
include directory")
set(PAIMON_EXTERNAL_ARROW_LIB "${DORIS_LIB64_DIR}/libarrow.a" CACHE FILEPATH
"Arrow core library")
+set(PAIMON_EXTERNAL_ARROW_COMPUTE_LIB "${DORIS_LIB64_DIR}/libarrow_compute.a"
CACHE FILEPATH "Arrow Compute library")
set(PAIMON_EXTERNAL_ARROW_DATASET_LIB "${DORIS_LIB64_DIR}/libarrow_dataset.a"
CACHE FILEPATH "Arrow Dataset library")
set(PAIMON_EXTERNAL_ARROW_ACERO_LIB "${DORIS_LIB64_DIR}/libarrow_acero.a"
CACHE FILEPATH "Arrow Acero library")
set(PAIMON_EXTERNAL_PARQUET_LIB "${DORIS_LIB64_DIR}/libparquet.a" CACHE
FILEPATH "Parquet library")
diff --git
a/thirdparty/patches/apache-arrow-17.0.0-force-write-int96-timestamps.patch
b/thirdparty/patches/apache-arrow-24.0.0-force-write-int96-timestamps.patch
similarity index 74%
rename from
thirdparty/patches/apache-arrow-17.0.0-force-write-int96-timestamps.patch
rename to
thirdparty/patches/apache-arrow-24.0.0-force-write-int96-timestamps.patch
index 5a754247566..1847a50694f 100644
--- a/thirdparty/patches/apache-arrow-17.0.0-force-write-int96-timestamps.patch
+++ b/thirdparty/patches/apache-arrow-24.0.0-force-write-int96-timestamps.patch
@@ -1,20 +1,20 @@
-diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/arrow/schema.cc
arrow-apache-arrow-17.0.0/cpp/src/parquet/arrow/schema.cc
---- arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/arrow/schema.cc
2026-03-27 01:23:23.651831424 +0800
-+++ arrow-apache-arrow-17.0.0/cpp/src/parquet/arrow/schema.cc 2026-03-27
01:28:36.855281965 +0800
-@@ -178,7 +178,8 @@
+--- a/cpp/src/parquet/arrow/schema.cc
++++ b/cpp/src/parquet/arrow/schema.cc
+@@ -215,8 +215,9 @@
// The user is explicitly asking for Impala int96 encoding, there is no
// logical type.
-- if (arrow_properties.support_deprecated_int96_timestamps() && target_unit
== ::arrow::TimeUnit::NANO) {
+- if (arrow_properties.support_deprecated_int96_timestamps() &&
+- target_unit == ::arrow::TimeUnit::NANO) {
+ if (arrow_properties.force_write_int96_timestamps() ||
-+ (arrow_properties.support_deprecated_int96_timestamps() && target_unit
== ::arrow::TimeUnit::NANO)) {
++ (arrow_properties.support_deprecated_int96_timestamps() &&
++ target_unit == ::arrow::TimeUnit::NANO)) {
*physical_type = ParquetType::INT96;
return Status::OK();
}
-diff -ruN arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h
arrow-apache-arrow-17.0.0/cpp/src/parquet/properties.h
---- arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h
2026-03-27 01:23:23.643831362 +0800
-+++ arrow-apache-arrow-17.0.0/cpp/src/parquet/properties.h 2026-03-27
01:27:47.717897537 +0800
-@@ -980,6 +980,7 @@
+--- a/cpp/src/parquet/properties.h
++++ b/cpp/src/parquet/properties.h
+@@ -1309,6 +1309,7 @@
public:
Builder()
: write_timestamps_as_int96_(false),
@@ -22,7 +22,7 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
coerce_timestamps_enabled_(false),
coerce_timestamps_unit_(::arrow::TimeUnit::SECOND),
truncated_timestamps_allowed_(false),
-@@ -1005,6 +1006,21 @@
+@@ -1334,6 +1335,21 @@
return this;
}
@@ -44,7 +44,7 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
/// \brief Coerce all timestamps to the specified time unit.
/// \param unit time unit to truncate to.
/// For Parquet versions 1.0 and 2.4, nanoseconds are casted to
microseconds.
-@@ -1085,7 +1101,8 @@
+@@ -1423,7 +1439,8 @@
/// Create the final properties.
std::shared_ptr<ArrowWriterProperties> build() {
return std::shared_ptr<ArrowWriterProperties>(new ArrowWriterProperties(
@@ -52,9 +52,9 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
+ write_timestamps_as_int96_, force_write_int96_timestamps_,
+ coerce_timestamps_enabled_, coerce_timestamps_unit_,
truncated_timestamps_allowed_, store_schema_,
compliant_nested_types_,
- engine_version_, use_threads_, executor_));
+ engine_version_, use_threads_, executor_,
write_time_adjusted_to_utc_));
}
-@@ -1093,6 +1110,8 @@
+@@ -1431,6 +1448,8 @@
private:
bool write_timestamps_as_int96_;
@@ -63,7 +63,7 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
bool coerce_timestamps_enabled_;
::arrow::TimeUnit::type coerce_timestamps_unit_;
bool truncated_timestamps_allowed_;
-@@ -1107,6 +1126,8 @@
+@@ -1447,6 +1466,8 @@
bool support_deprecated_int96_timestamps() const { return
write_timestamps_as_int96_; }
@@ -72,7 +72,7 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
bool coerce_timestamps_enabled() const { return coerce_timestamps_enabled_;
}
::arrow::TimeUnit::type coerce_timestamps_unit() const {
return coerce_timestamps_unit_;
-@@ -1138,6 +1159,7 @@
+@@ -1483,6 +1504,7 @@
private:
explicit ArrowWriterProperties(bool write_nanos_as_int96,
@@ -80,16 +80,16 @@ diff -ruN
arrow-apache-arrow-17.0.0-after-paimon/cpp/src/parquet/properties.h ar
bool coerce_timestamps_enabled,
::arrow::TimeUnit::type
coerce_timestamps_unit,
bool truncated_timestamps_allowed, bool
store_schema,
-@@ -1145,6 +1167,7 @@
- EngineVersion engine_version, bool
use_threads,
- ::arrow::internal::Executor* executor)
+@@ -1491,6 +1513,7 @@
+ ::arrow::internal::Executor* executor,
+ bool write_time_adjusted_to_utc)
: write_timestamps_as_int96_(write_nanos_as_int96),
+ force_write_int96_timestamps_(force_write_int96_timestamps),
coerce_timestamps_enabled_(coerce_timestamps_enabled),
coerce_timestamps_unit_(coerce_timestamps_unit),
truncated_timestamps_allowed_(truncated_timestamps_allowed),
-@@ -1155,6 +1178,7 @@
- executor_(executor) {}
+@@ -1502,6 +1525,7 @@
+ write_time_adjusted_to_utc_(write_time_adjusted_to_utc) {}
const bool write_timestamps_as_int96_;
+ const bool force_write_int96_timestamps_;
diff --git a/thirdparty/patches/apache-arrow-17.0.0-lzo.patch
b/thirdparty/patches/apache-arrow-24.0.0-lzo.patch
similarity index 55%
rename from thirdparty/patches/apache-arrow-17.0.0-lzo.patch
rename to thirdparty/patches/apache-arrow-24.0.0-lzo.patch
index a983818413a..d7076509756 100644
--- a/thirdparty/patches/apache-arrow-17.0.0-lzo.patch
+++ b/thirdparty/patches/apache-arrow-24.0.0-lzo.patch
@@ -1,11 +1,26 @@
--- a/cpp/src/parquet/column_reader.cc
+++ b/cpp/src/parquet/column_reader.cc
-@@ -30,0 +31,2 @@
-+
+@@ -29,6 +29,8 @@
+ #include <utility>
+ #include <vector>
+
+#include <lzo/lzo1x.h>
-@@ -268,0 +269 @@
++
+ #include "arrow/array.h"
+ #include "arrow/array/array_binary.h"
+ #include "arrow/array/builder_binary.h"
+@@ -228,6 +230,7 @@
+ const CryptoContext* crypto_ctx, bool
always_compressed)
+ : properties_(properties),
+ stream_(std::move(stream)),
+ compression_codec_(codec),
-@@ -279 +282,7 @@
+ decompression_buffer_(AllocateBuffer(properties_.memory_pool(), 0)),
+ page_ordinal_(0),
+ seen_num_values_(0),
+@@ -237,7 +240,13 @@
+ InitDecryption();
+ }
+ max_page_header_size_ = kDefaultMaxPageHeaderSize;
- decompressor_ = GetCodec(codec);
+ if (compression_codec_ == Compression::LZO) {
+ if (lzo_init() != LZO_E_OK) {
@@ -14,12 +29,30 @@
+ } else {
+ decompressor_ = GetCodec(codec);
+ }
-@@ -315,0 +325 @@
+ always_compressed_ = always_compressed;
+ }
+
+@@ -271,6 +280,7 @@
+ format::PageHeader current_page_header_;
+
+ // Compression codec to use.
+ Compression::type compression_codec_;
-@@ -585 +595 @@
+ std::unique_ptr<::arrow::util::Codec> decompressor_;
+ std::shared_ptr<ResizableBuffer> decompression_buffer_;
+
+@@ -548,7 +558,7 @@
+ std::shared_ptr<Buffer> SerializedPageReader::DecompressIfNeeded(
+ std::shared_ptr<Buffer> page_buffer, int compressed_len, int
uncompressed_len,
+ int levels_byte_len) {
- if (decompressor_ == nullptr) {
+ if (decompressor_ == nullptr && compression_codec_ != Compression::LZO) {
-@@ -601,0 +612,61 @@
+ return page_buffer;
+ }
+ if (compressed_len < levels_byte_len || uncompressed_len < levels_byte_len)
{
+@@ -565,6 +575,74 @@
+ memcpy(decompressed, page_buffer->data(), levels_byte_len);
+ }
+
+ if (compression_codec_ == Compression::LZO) {
+ const uint8_t* input = page_buffer->data() + levels_byte_len;
+ const uint8_t* const input_end = page_buffer->data() + compressed_len;
@@ -34,7 +67,8 @@
+
+ while (input < input_end) {
+ if (input_end - input < 4) {
-+ throw ParquetException("LZO page decompression failed: truncated
large block length");
++ throw ParquetException(
++ "LZO page decompression failed: truncated large block length");
+ }
+
+ uint32_t large_block_uncompressed_len = load_big_endian_u32(input);
@@ -45,13 +79,15 @@
+
+ while (large_block_uncompressed_len > 0) {
+ if (input_end - input < 4) {
-+ throw ParquetException("LZO page decompression failed: truncated
small block length");
++ throw ParquetException(
++ "LZO page decompression failed: truncated small block length");
+ }
+
+ uint32_t small_block_compressed_len = load_big_endian_u32(input);
+ input += 4;
+ if (static_cast<size_t>(input_end - input) <
small_block_compressed_len) {
-+ throw ParquetException("LZO page decompression failed: truncated
small block data");
++ throw ParquetException(
++ "LZO page decompression failed: truncated small block data");
+ }
+
+ auto small_block_uncompressed_len =
@@ -64,7 +100,8 @@
+ std::to_string(result));
+ }
+ if (small_block_uncompressed_len > large_block_uncompressed_len) {
-+ throw ParquetException("LZO page decompression failed: invalid
small block size");
++ throw ParquetException(
++ "LZO page decompression failed: invalid small block size");
+ }
+
+ input += small_block_compressed_len;
@@ -73,12 +110,17 @@
+ }
+ }
+ if (output != output_end) {
-+ throw ParquetException("Page didn't decompress to expected size,
expected: " +
-+ std::to_string(uncompressed_len -
levels_byte_len) + ", but got:" +
-+ std::to_string(output -
(decompression_buffer_->mutable_data() +
-+ levels_byte_len)));
++ throw ParquetException(
++ "Page didn't decompress to expected size, expected: " +
++ std::to_string(uncompressed_len - levels_byte_len) +
++ ", but got:" +
++ std::to_string(
++ output - (decompression_buffer_->mutable_data() +
levels_byte_len)));
+ }
+
+ return decompression_buffer_;
+ }
+
+ // GH-31992: DataPageV2 may store only levels and no values when all
+ // values are null. In this case, Parquet java is known to produce a
+ // 0-len compressed area (which is invalid compressed input).
diff --git a/thirdparty/patches/apache-arrow-17.0.0-paimon.patch
b/thirdparty/patches/apache-arrow-24.0.0-paimon.patch
similarity index 68%
rename from thirdparty/patches/apache-arrow-17.0.0-paimon.patch
rename to thirdparty/patches/apache-arrow-24.0.0-paimon.patch
index 4e53117b79b..583f85b4400 100644
--- a/thirdparty/patches/apache-arrow-17.0.0-paimon.patch
+++ b/thirdparty/patches/apache-arrow-24.0.0-paimon.patch
@@ -1,23 +1,19 @@
-diff --git a/cpp/src/parquet/arrow/schema.cc b/cpp/src/parquet/arrow/schema.cc
-index ec3890a41f..943f69bb6c 100644
--- a/cpp/src/parquet/arrow/schema.cc
+++ b/cpp/src/parquet/arrow/schema.cc
-@@ -178,7 +178,7 @@ static Status GetTimestampMetadata(const
::arrow::TimestampType& type,
+@@ -215,7 +215,8 @@
// The user is explicitly asking for Impala int96 encoding, there is no
// logical type.
- if (arrow_properties.support_deprecated_int96_timestamps()) {
-+ if (arrow_properties.support_deprecated_int96_timestamps() && target_unit
== ::arrow::TimeUnit::NANO) {
++ if (arrow_properties.support_deprecated_int96_timestamps() &&
++ target_unit == ::arrow::TimeUnit::NANO) {
*physical_type = ParquetType::INT96;
return Status::OK();
}
-
-diff --git a/cpp/src/parquet/arrow/reader.cc b/cpp/src/parquet/arrow/reader.cc
-index 285e2a5973..aa6f92f077 100644
--- a/cpp/src/parquet/arrow/reader.cc
+++ b/cpp/src/parquet/arrow/reader.cc
-@@ -1013,25 +1013,32 @@ Status FileReaderImpl::GetRecordBatchReader(const
std::vector<int>& row_groups,
- return Status::OK();
+@@ -1041,25 +1041,32 @@
+ ::arrow::MakeVectorIterator(std::move(batches)),
std::move(batch_schema));
}
- int64_t num_rows = 0;
@@ -28,7 +24,7 @@ index 285e2a5973..aa6f92f077 100644
}
using ::arrow::RecordBatchIterator;
-+ int row_group_idx = 0;
++ size_t row_group_idx = 0;
// NB: This lambda will be invoked outside the scope of this call to
// `GetRecordBatchReader()`, so it must capture `readers` and
`batch_schema` by value.
@@ -40,26 +36,23 @@ index 285e2a5973..aa6f92f077 100644
this]() mutable -> ::arrow::Result<RecordBatchIterator> {
::arrow::ChunkedArrayVector columns(readers.size());
-- // don't reserve more rows than necessary
+ // don't reserve more rows than necessary
- int64_t batch_size = std::min(properties().batch_size(), num_rows);
- num_rows -= batch_size;
+ int64_t batch_size = 0;
+ if (!num_rows.empty()) {
-+ // don't reserve more rows than necessary
+ batch_size = std::min(properties().batch_size(),
num_rows[row_group_idx]);
+ num_rows[row_group_idx] -= batch_size;
-+ if (num_rows[row_group_idx] == 0 && (num_rows.size() - 1) !=
row_group_idx) {
-+ row_group_idx++;
++ if (num_rows[row_group_idx] == 0 && row_group_idx + 1 <
num_rows.size()) {
++ ++row_group_idx;
+ }
+ }
RETURN_NOT_OK(::arrow::internal::OptionalParallelFor(
reader_properties_.use_threads(),
static_cast<int>(readers.size()),
-diff --git a/cpp/src/parquet/arrow/writer.cc b/cpp/src/parquet/arrow/writer.cc
-index 4fd7ef1b47..87326a54f1 100644
--- a/cpp/src/parquet/arrow/writer.cc
+++ b/cpp/src/parquet/arrow/writer.cc
-@@ -314,6 +314,14 @@ class FileWriterImpl : public FileWriter {
+@@ -341,6 +341,14 @@
return Status::OK();
}
@@ -68,13 +61,13 @@ index 4fd7ef1b47..87326a54f1 100644
+ return 0;
+ }
+ return row_group_writer_->total_compressed_bytes() +
-+ row_group_writer_->total_compressed_bytes_written();
++ row_group_writer_->total_compressed_bytes_written();
+ }
+
Status Close() override {
if (!closed_) {
// Make idempotent
-@@ -418,10 +426,13 @@ class FileWriterImpl : public FileWriter {
+@@ -444,10 +452,14 @@
// Max number of rows allowed in a row group.
const int64_t max_row_group_length =
this->properties().max_row_group_length();
@@ -84,16 +77,15 @@ index 4fd7ef1b47..87326a54f1 100644
if (row_group_writer_ == nullptr || !row_group_writer_->buffered() ||
- row_group_writer_->num_rows() >= max_row_group_length) {
+ row_group_writer_->num_rows() >= max_row_group_length ||
-+ (row_group_writer_->total_compressed_bytes_written() +
-+ row_group_writer_->total_compressed_bytes() >= max_row_group_size)) {
++ row_group_writer_->total_compressed_bytes_written() +
++ row_group_writer_->total_compressed_bytes() >=
++ max_row_group_size) {
RETURN_NOT_OK(NewBufferedRowGroup());
}
-diff --git a/cpp/src/parquet/arrow/writer.h b/cpp/src/parquet/arrow/writer.h
-index 4a1a033a7b..0f13d05e44 100644
--- a/cpp/src/parquet/arrow/writer.h
+++ b/cpp/src/parquet/arrow/writer.h
-@@ -138,6 +138,9 @@ class PARQUET_EXPORT FileWriter {
+@@ -124,6 +124,9 @@
/// option in this case.
virtual ::arrow::Status WriteRecordBatch(const ::arrow::RecordBatch& batch)
= 0;
@@ -103,11 +95,9 @@ index 4a1a033a7b..0f13d05e44 100644
/// \brief Write the footer and close the file.
virtual ::arrow::Status Close() = 0;
virtual ~FileWriter();
-diff --git a/cpp/src/parquet/properties.h b/cpp/src/parquet/properties.h
-index 4d3acb491e..3906ff3c59 100644
--- a/cpp/src/parquet/properties.h
+++ b/cpp/src/parquet/properties.h
-@@ -139,6 +139,7 @@ static constexpr bool DEFAULT_IS_DICTIONARY_ENABLED = true;
+@@ -160,6 +160,7 @@
static constexpr int64_t DEFAULT_DICTIONARY_PAGE_SIZE_LIMIT =
kDefaultDataPageSize;
static constexpr int64_t DEFAULT_WRITE_BATCH_SIZE = 1024;
static constexpr int64_t DEFAULT_MAX_ROW_GROUP_LENGTH = 1024 * 1024;
@@ -115,28 +105,28 @@ index 4d3acb491e..3906ff3c59 100644
static constexpr bool DEFAULT_ARE_STATISTICS_ENABLED = true;
static constexpr int64_t DEFAULT_MAX_STATISTICS_SIZE = 4096;
static constexpr Encoding::type DEFAULT_ENCODING = Encoding::UNKNOWN;
-@@ -232,6 +233,7 @@ class PARQUET_EXPORT WriterProperties {
+@@ -343,6 +344,7 @@
dictionary_pagesize_limit_(DEFAULT_DICTIONARY_PAGE_SIZE_LIMIT),
write_batch_size_(DEFAULT_WRITE_BATCH_SIZE),
max_row_group_length_(DEFAULT_MAX_ROW_GROUP_LENGTH),
+ max_row_group_size_(DEFAULT_MAX_ROW_GROUP_SIZE),
pagesize_(kDefaultDataPageSize),
+ max_rows_per_page_(kDefaultMaxRowsPerPage),
version_(ParquetVersion::PARQUET_2_6),
- data_page_version_(ParquetDataPageVersion::V1),
-@@ -244,6 +246,7 @@ class PARQUET_EXPORT WriterProperties {
+@@ -359,6 +361,7 @@
dictionary_pagesize_limit_(properties.dictionary_pagesize_limit()),
write_batch_size_(properties.write_batch_size()),
max_row_group_length_(properties.max_row_group_length()),
+ max_row_group_size_(properties.max_row_group_size()),
pagesize_(properties.data_pagesize()),
+ max_rows_per_page_(properties.max_rows_per_page()),
version_(properties.version()),
- data_page_version_(properties.data_page_version()),
-@@ -321,6 +324,13 @@ class PARQUET_EXPORT WriterProperties {
+@@ -468,6 +471,13 @@
return this;
}
+ /// Specify the max bytes size to put in a single row group.
-+ /// Default 128 M.
++ /// Default 128MB.
+ Builder* max_row_group_size(int64_t max_row_group_size) {
+ max_row_group_size_ = max_row_group_size;
+ return this;
@@ -145,24 +135,33 @@ index 4d3acb491e..3906ff3c59 100644
/// Specify the data page size.
/// Default 1MB.
Builder* data_pagesize(int64_t pg_size) {
-@@ -664,7 +674,7 @@ class PARQUET_EXPORT WriterProperties {
+@@ -867,11 +877,12 @@
return std::shared_ptr<WriterProperties>(new WriterProperties(
pool_, dictionary_pagesize_limit_, write_batch_size_,
max_row_group_length_,
-- pagesize_, version_, created_by_, page_checksum_enabled_,
-+ max_row_group_size_, pagesize_, version_, created_by_,
page_checksum_enabled_,
- std::move(file_encryption_properties_), default_column_properties_,
- column_properties, data_page_version_, store_decimal_as_integer_,
- std::move(sorting_columns_)));
-@@ -675,6 +685,7 @@ class PARQUET_EXPORT WriterProperties {
+- pagesize_, max_rows_per_page_, version_, created_by_,
page_checksum_enabled_,
+- size_statistics_level_, std::move(file_encryption_properties_),
+- default_column_properties_, column_properties, data_page_version_,
+- store_decimal_as_integer_, std::move(sorting_columns_),
+- content_defined_chunking_enabled_,
content_defined_chunking_options_));
++ max_row_group_size_, pagesize_, max_rows_per_page_, version_,
created_by_,
++ page_checksum_enabled_, size_statistics_level_,
++ std::move(file_encryption_properties_), default_column_properties_,
++ column_properties, data_page_version_, store_decimal_as_integer_,
++ std::move(sorting_columns_), content_defined_chunking_enabled_,
++ content_defined_chunking_options_));
+ }
+
+ private:
+@@ -881,6 +892,7 @@
int64_t dictionary_pagesize_limit_;
int64_t write_batch_size_;
int64_t max_row_group_length_;
+ int64_t max_row_group_size_;
int64_t pagesize_;
+ int64_t max_rows_per_page_;
ParquetVersion::type version_;
- ParquetDataPageVersion data_page_version_;
-@@ -705,6 +716,8 @@ class PARQUET_EXPORT WriterProperties {
+@@ -917,6 +929,8 @@
inline int64_t max_row_group_length() const { return max_row_group_length_;
}
@@ -170,40 +169,43 @@ index 4d3acb491e..3906ff3c59 100644
+
inline int64_t data_pagesize() const { return pagesize_; }
- inline ParquetDataPageVersion data_page_version() const {
-@@ -810,7 +823,7 @@ class PARQUET_EXPORT WriterProperties {
+ inline int64_t max_rows_per_page() const { return max_rows_per_page_; }
+@@ -1046,9 +1060,10 @@
private:
explicit WriterProperties(
MemoryPool* pool, int64_t dictionary_pagesize_limit, int64_t
write_batch_size,
-- int64_t max_row_group_length, int64_t pagesize, ParquetVersion::type
version,
-+ int64_t max_row_group_length, int64_t max_row_group_size, int64_t
pagesize, ParquetVersion::type version,
- const std::string& created_by, bool page_write_checksum_enabled,
+- int64_t max_row_group_length, int64_t pagesize, int64_t
max_rows_per_page,
+- ParquetVersion::type version, const std::string& created_by,
+- bool page_write_checksum_enabled, SizeStatisticsLevel
size_statistics_level,
++ int64_t max_row_group_length, int64_t max_row_group_size, int64_t
pagesize,
++ int64_t max_rows_per_page, ParquetVersion::type version,
++ const std::string& created_by, bool page_write_checksum_enabled,
++ SizeStatisticsLevel size_statistics_level,
std::shared_ptr<FileEncryptionProperties> file_encryption_properties,
const ColumnProperties& default_column_properties,
-@@ -821,6 +834,7 @@ class PARQUET_EXPORT WriterProperties {
+ const std::unordered_map<std::string, ColumnProperties>&
column_properties,
+@@ -1059,6 +1074,7 @@
dictionary_pagesize_limit_(dictionary_pagesize_limit),
write_batch_size_(write_batch_size),
max_row_group_length_(max_row_group_length),
+ max_row_group_size_(max_row_group_size),
pagesize_(pagesize),
+ max_rows_per_page_(max_rows_per_page),
parquet_data_page_version_(data_page_version),
- parquet_version_(version),
-@@ -836,6 +850,7 @@ class PARQUET_EXPORT WriterProperties {
+@@ -1078,6 +1094,7 @@
int64_t dictionary_pagesize_limit_;
int64_t write_batch_size_;
int64_t max_row_group_length_;
+ int64_t max_row_group_size_;
int64_t pagesize_;
+ int64_t max_rows_per_page_;
ParquetDataPageVersion parquet_data_page_version_;
- ParquetVersion::type parquet_version_;
-diff --git a/cpp/cmake_modules/ThirdpartyToolchain.cmake
b/cpp/cmake_modules/ThirdpartyToolchain.cmake
-index 9df922afa2..5c8b3d4d07 100644
--- a/cpp/cmake_modules/ThirdpartyToolchain.cmake
+++ b/cpp/cmake_modules/ThirdpartyToolchain.cmake
-@@ -1789,7 +1789,20 @@ if(ARROW_WITH_THRIFT)
- REQUIRED_VERSION
- 0.11.0)
-
+@@ -1884,7 +1884,20 @@
+ REQUIRED_VERSION
+ 0.11.0)
+
- string(REPLACE "." ";" Thrift_VERSION_LIST ${Thrift_VERSION})
+ if(NOT Thrift_VERSION)
+ if(DEFINED thrift_PC_VERSION AND thrift_PC_VERSION)
diff --git a/thirdparty/patches/paimon-cpp-arrow-24-compatibility.patch
b/thirdparty/patches/paimon-cpp-arrow-24-compatibility.patch
new file mode 100644
index 00000000000..d0e723a34d9
--- /dev/null
+++ b/thirdparty/patches/paimon-cpp-arrow-24-compatibility.patch
@@ -0,0 +1,64 @@
+diff --git a/include/paimon/status.h b/include/paimon/status.h
+--- a/include/paimon/status.h
++++ b/include/paimon/status.h
+@@ -458,9 +458,4 @@
+ } \
+ } while (false)
+
+-// This is an internal-use macro and should not be used in public headers.
+-#ifndef RETURN_NOT_OK
+-#define RETURN_NOT_OK(s) PAIMON_RETURN_NOT_OK(s)
+-#endif
+-
+ } // namespace paimon
+diff --git a/src/paimon/format/parquet/parquet_input_stream_impl.cpp
b/src/paimon/format/parquet/parquet_input_stream_impl.cpp
+--- a/src/paimon/format/parquet/parquet_input_stream_impl.cpp
++++ b/src/paimon/format/parquet/parquet_input_stream_impl.cpp
+@@ -59,7 +59,7 @@ arrow::Result<std::shared_ptr<arrow::Buffer>>
ParquetInputStreamImpl::Read(int64
+ arrow::AllocateResizableBuffer(nbytes,
pool_.get()));
+ ARROW_ASSIGN_OR_RAISE(int64_t read_bytes, Read(nbytes,
buffer->mutable_data()));
+ if (read_bytes < nbytes) {
+- RETURN_NOT_OK(buffer->Resize(read_bytes));
++ ARROW_RETURN_NOT_OK(buffer->Resize(read_bytes));
+ }
+ return std::shared_ptr<arrow::Buffer>(std::move(buffer));
+ }
+@@ -78,7 +78,7 @@ arrow::Result<std::shared_ptr<arrow::Buffer>>
ParquetInputStreamImpl::ReadAt(int
+ arrow::AllocateResizableBuffer(nbytes,
pool_.get()));
+ ARROW_ASSIGN_OR_RAISE(int64_t read_bytes, ReadAt(position, nbytes,
buffer->mutable_data()));
+ if (read_bytes < nbytes) {
+- RETURN_NOT_OK(buffer->Resize(read_bytes));
++ ARROW_RETURN_NOT_OK(buffer->Resize(read_bytes));
+ }
+ return std::shared_ptr<arrow::Buffer>(std::move(buffer));
+ }
+diff --git a/src/paimon/format/parquet/file_reader_wrapper.cpp
b/src/paimon/format/parquet/file_reader_wrapper.cpp
+--- a/src/paimon/format/parquet/file_reader_wrapper.cpp
++++ b/src/paimon/format/parquet/file_reader_wrapper.cpp
+@@ -81,8 +81,9 @@ Status FileReaderWrapper::SeekToRow(uint64_t row_number) {
+ PAIMON_ASSIGN_OR_RAISE(int32_t row_group_id,
GetRowGroupId(target_row_groups_[j]));
+ target_row_group_indices.push_back(row_group_id);
+ }
+-
PAIMON_RETURN_NOT_OK_FROM_ARROW(file_reader_->GetRecordBatchReader(
+- target_row_group_indices, target_column_indices_,
&batch_reader_));
++ PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(
++ batch_reader_,
file_reader_->GetRecordBatchReader(target_row_group_indices,
++
target_column_indices_));
+ return Status::OK();
+ }
+ }
+@@ -152,9 +153,11 @@ Status FileReaderWrapper::PrepareForReading(
+ std::vector<std::pair<uint64_t, uint64_t>> target_row_groups;
+ PAIMON_ASSIGN_OR_RAISE(target_row_groups,
GetRowGroupRanges(target_row_group_indices));
+ std::unique_ptr<arrow::RecordBatchReader> batch_reader;
+- PAIMON_RETURN_NOT_OK_FROM_ARROW(file_reader_->GetRecordBatchReader(
+- std::vector<int32_t>(target_row_group_indices.begin(),
target_row_group_indices.end()),
+- column_indices, &batch_reader));
++ PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(
++ batch_reader,
++ file_reader_->GetRecordBatchReader(
++ std::vector<int32_t>(target_row_group_indices.begin(),
target_row_group_indices.end()),
++ column_indices));
+ target_row_groups_ = target_row_groups;
+ target_column_indices_ = column_indices;
+ batch_reader_ = std::move(batch_reader);
diff --git a/thirdparty/patches/paimon-cpp-arrow-24-compute.patch
b/thirdparty/patches/paimon-cpp-arrow-24-compute.patch
new file mode 100644
index 00000000000..1b581b8f93e
--- /dev/null
+++ b/thirdparty/patches/paimon-cpp-arrow-24-compute.patch
@@ -0,0 +1,44 @@
+diff --git a/cmake_modules/ThirdpartyToolchain.cmake
b/cmake_modules/ThirdpartyToolchain.cmake
+--- a/cmake_modules/ThirdpartyToolchain.cmake
++++ b/cmake_modules/ThirdpartyToolchain.cmake
+@@ -38,6 +38,8 @@
+ set(PAIMON_EXTERNAL_ARROW_INCLUDE_DIR "" CACHE PATH
+ "Include directory for external Arrow/Parquet headers")
+ set(PAIMON_EXTERNAL_ARROW_LIB "" CACHE FILEPATH "Path to external libarrow.a")
++set(PAIMON_EXTERNAL_ARROW_COMPUTE_LIB "" CACHE FILEPATH
++ "Path to external libarrow_compute.a")
+ set(PAIMON_EXTERNAL_ARROW_DATASET_LIB "" CACHE FILEPATH "Path to external
libarrow_dataset.a")
+ set(PAIMON_EXTERNAL_ARROW_ACERO_LIB "" CACHE FILEPATH "Path to external
libarrow_acero.a")
+ set(PAIMON_EXTERNAL_PARQUET_LIB "" CACHE FILEPATH "Path to external
libparquet.a")
+@@ -1008,6 +1010,7 @@
+
+ foreach(_paimon_external_lib
+ IN ITEMS PAIMON_EXTERNAL_ARROW_LIB
++ PAIMON_EXTERNAL_ARROW_COMPUTE_LIB
+ PAIMON_EXTERNAL_ARROW_DATASET_LIB
+ PAIMON_EXTERNAL_ARROW_ACERO_LIB
+ PAIMON_EXTERNAL_PARQUET_LIB
+@@ -1028,6 +1031,13 @@
+ INTERFACE_INCLUDE_DIRECTORIES
+ "${ARROW_INCLUDE_DIR}")
+
++ add_library(arrow_compute STATIC IMPORTED)
++ set_target_properties(arrow_compute
++ PROPERTIES IMPORTED_LOCATION
++
"${PAIMON_EXTERNAL_ARROW_COMPUTE_LIB}"
++ INTERFACE_INCLUDE_DIRECTORIES
++ "${ARROW_INCLUDE_DIR}")
++
+ add_library(arrow_dataset STATIC IMPORTED)
+ set_target_properties(arrow_dataset
+ PROPERTIES IMPORTED_LOCATION
+@@ -1055,7 +1065,9 @@
+ INTERFACE_INCLUDE_DIRECTORIES
+ "${ARROW_INCLUDE_DIR}")
+
+- target_link_libraries(arrow_acero INTERFACE arrow)
++ target_link_libraries(arrow_compute INTERFACE arrow)
++
++ target_link_libraries(arrow_acero INTERFACE arrow_compute)
+
+ target_link_libraries(arrow_dataset INTERFACE arrow_acero)
diff --git a/thirdparty/test/arrow-paimon-lifecycle-test.sh
b/thirdparty/test/arrow-paimon-lifecycle-test.sh
new file mode 100755
index 00000000000..9873218a40a
--- /dev/null
+++ b/thirdparty/test/arrow-paimon-lifecycle-test.sh
@@ -0,0 +1,492 @@
+#!/usr/bin/env bash
+# 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.
+
+set -eo pipefail
+
+ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)"
+
+fail() {
+ echo "FAIL: $*" >&2
+ exit 1
+}
+
+tmpdir="$(mktemp -d)"
+trap 'rm -rf "${tmpdir}"' EXIT
+
+create_fingerprint_fixture() {
+ local destination="$1"
+
+ mkdir -p "${destination}/patches"
+ cp "${ROOT}/arrow-paimon-vars.sh" "${destination}/arrow-paimon-vars.sh"
+ cp "${ROOT}/paimon-cpp-cache.cmake" "${destination}/paimon-cpp-cache.cmake"
+ cp "${ROOT}"/patches/apache-arrow-24.0.0-*.patch "${destination}/patches/"
+ cp "${ROOT}"/patches/paimon-cpp-*.patch "${destination}/patches/"
+}
+
+fingerprint_from_fixture() {
+ local fixture="$1"
+ local component="$2"
+ local result_variable="$3"
+ local fingerprint
+
+ fingerprint="$(
+ set -e
+ # shellcheck source=/dev/null
+ . "${fixture}/arrow-paimon-vars.sh"
+ "${component}_build_fingerprint"
+ )"
+ printf -v "${result_variable}" '%s' "${fingerprint}"
+}
+
+exercise_semantic_fingerprints() {
+ local first_fixture="${tmpdir}/fingerprint-first"
+ local second_fixture="${tmpdir}/fingerprint-second"
+ local first_arrow
+ local first_paimon
+ local second_arrow
+ local second_paimon
+ local changed_arrow
+ local changed_paimon
+
+ create_fingerprint_fixture "${first_fixture}"
+ create_fingerprint_fixture "${second_fixture}"
+
+ printf '%s\n' first-env >"${first_fixture}/env.sh"
+ printf '%s\n' second-env >"${second_fixture}/env.sh"
+ printf '%s\n' first-vars >"${first_fixture}/vars.sh"
+ printf '%s\n' second-vars >"${second_fixture}/vars.sh"
+ printf '%s\n' first-download >"${first_fixture}/download-thirdparty.sh"
+ printf '%s\n' second-download >"${second_fixture}/download-thirdparty.sh"
+ printf '%s\n' first-build >"${first_fixture}/build-thirdparty.sh"
+ printf '%s\n' second-build >"${second_fixture}/build-thirdparty.sh"
+ printf '%s\n' '# release-branch-only comment'
>>"${second_fixture}/arrow-paimon-vars.sh"
+
+ fingerprint_from_fixture "${first_fixture}" arrow first_arrow
+ fingerprint_from_fixture "${first_fixture}" paimon first_paimon
+ [[ "${first_arrow}" == "${ARROW_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT}"
]] ||
+ fail "the Arrow legacy marker migration target is stale"
+ [[ "${first_paimon}" == "${PAIMON_LEGACY_COMPATIBLE_SEMANTIC_FINGERPRINT}"
]] ||
+ fail "the Paimon legacy marker migration target is stale"
+ fingerprint_from_fixture "${second_fixture}" arrow second_arrow
+ fingerprint_from_fixture "${second_fixture}" paimon second_paimon
+ [[ "${first_arrow}" == "${second_arrow}" ]] ||
+ fail "unrelated branch scripts changed the Arrow fingerprint"
+ [[ "${first_paimon}" == "${second_paimon}" ]] ||
+ fail "unrelated branch scripts changed the Paimon fingerprint"
+
+ printf '%s\n' semantic-change \
+ >>"${second_fixture}/patches/apache-arrow-24.0.0-lzo.patch"
+ fingerprint_from_fixture "${second_fixture}" arrow changed_arrow
+ fingerprint_from_fixture "${second_fixture}" paimon changed_paimon
+ [[ "${changed_arrow}" != "${first_arrow}" ]] ||
+ fail "an Arrow patch change did not change the Arrow fingerprint"
+ [[ "${changed_paimon}" != "${first_paimon}" ]] ||
+ fail "an Arrow patch change did not change the Paimon fingerprint"
+
+ cp "${first_fixture}/patches/apache-arrow-24.0.0-lzo.patch" \
+ "${second_fixture}/patches/apache-arrow-24.0.0-lzo.patch"
+ printf '%s\n' semantic-change >>"${second_fixture}/paimon-cpp-cache.cmake"
+ fingerprint_from_fixture "${second_fixture}" arrow second_arrow
+ fingerprint_from_fixture "${second_fixture}" paimon changed_paimon
+ [[ "${second_arrow}" == "${first_arrow}" ]] ||
+ fail "a Paimon-only cache change changed the Arrow fingerprint"
+ [[ "${changed_paimon}" != "${first_paimon}" ]] ||
+ fail "a Paimon cache change did not change the Paimon fingerprint"
+
+ changed_arrow="$(
+ set -e
+ # shellcheck source=/dev/null
+ . "${first_fixture}/arrow-paimon-vars.sh"
+ ARROW_BUILD_SCHEMA_VERSION="${ARROW_BUILD_SCHEMA_VERSION}-changed"
+ arrow_build_fingerprint
+ )"
+ [[ "${changed_arrow}" != "${first_arrow}" ]] ||
+ fail "an Arrow build-schema change did not change its fingerprint"
+}
+
+# shellcheck source=../arrow-paimon-vars.sh
+. "${ROOT}/arrow-paimon-vars.sh"
+exercise_semantic_fingerprints
+
+harness="${tmpdir}/harness"
+mkdir -p "${harness}/src" "${harness}/patches" "${harness}/installed"
+cp "${ROOT}/download-thirdparty.sh" "${harness}/download-thirdparty.sh"
+
+create_patch() {
+ local patch_file="$1"
+ local source_file="$2"
+ {
+ printf '%s\n' "--- a/${source_file}"
+ printf '%s\n' "+++ b/${source_file}"
+ printf '%s\n' '@@ -1 +1 @@'
+ printf '%s\n' '-original'
+ printf '%s\n' '+patched'
+ } >"${patch_file}"
+}
+
+create_archive() {
+ local source_name="$1"
+ local archive_name="$2"
+ local prefix="$3"
+ local index
+
+ mkdir -p "${harness}/src/${source_name}"
+ for index in 1 2 3; do
+ printf '%s\n' original
>"${harness}/src/${source_name}/${prefix}-${index}.txt"
+ done
+ tar -czf "${harness}/src/${archive_name}" -C "${harness}/src"
"${source_name}"
+ rm -rf "${harness}/src/${source_name}"
+}
+
+arrow_source="arrow-apache-arrow-24.0.0"
+arrow_archive="apache-arrow-24.0.0.tar.gz"
+paimon_source="doris-thirdparty-paimon-cpp-0a4f4e2"
+paimon_archive="paimon-cpp-0a4f4e2.tar.gz"
+
+create_archive "${arrow_source}" "${arrow_archive}" arrow
+create_archive "${paimon_source}" "${paimon_archive}" paimon
+
+arrow_patches=(
+ apache-arrow-24.0.0-paimon.patch
+ apache-arrow-24.0.0-force-write-int96-timestamps.patch
+ apache-arrow-24.0.0-lzo.patch
+)
+paimon_patches=(
+ paimon-cpp-buildutils-static-deps.patch
+ paimon-cpp-arrow-24-compatibility.patch
+ paimon-cpp-arrow-24-compute.patch
+)
+
+for index in 0 1 2; do
+ create_patch "${harness}/patches/${arrow_patches[${index}]}"
"arrow-$((index + 1)).txt"
+ create_patch "${harness}/patches/${paimon_patches[${index}]}"
"paimon-$((index + 1)).txt"
+done
+
+arrow_md5="$(md5sum "${harness}/src/${arrow_archive}" | awk '{print $1}')"
+paimon_md5="$(md5sum "${harness}/src/${paimon_archive}" | awk '{print $1}')"
+{
+ printf 'TP_SOURCE_DIR="%s"\n' "${harness}/src"
+ printf 'TP_INSTALL_DIR="%s"\n' "${harness}/installed"
+ printf 'TP_PATCH_DIR="%s"\n' "${harness}/patches"
+ printf '%s\n' 'TP_ARCHIVES=(ARROW PAIMON_CPP)'
+ printf 'ARROW_NAME="%s"\n' "${arrow_archive}"
+ printf 'ARROW_SOURCE="%s"\n' "${arrow_source}"
+ printf 'ARROW_MD5SUM="%s"\n' "${arrow_md5}"
+ printf '%s\n' 'ARROW_DOWNLOAD="unused"'
+ printf 'PAIMON_CPP_NAME="%s"\n' "${paimon_archive}"
+ printf 'PAIMON_CPP_SOURCE="%s"\n' "${paimon_source}"
+ printf 'PAIMON_CPP_MD5SUM="%s"\n' "${paimon_md5}"
+ printf '%s\n' 'PAIMON_CPP_DOWNLOAD="unused"'
+ printf '%s\n' 'arrow_paimon_build_fingerprint() { printf "%s\n"
test-fingerprint; }'
+} >"${harness}/vars.sh"
+
+exercise_interrupted_patch_set() {
+ local package="$1"
+ local source_name="$2"
+ local archive_name="$3"
+ local prefix="$4"
+ shift 4
+ local patches=("$@")
+ local applied
+ local index
+
+ for applied in 1 2 3; do
+ rm -rf "${harness}/src/${source_name}"
+ tar -xzf "${harness}/src/${archive_name}" -C "${harness}/src"
+ for ((index = 0; index < applied; ++index)); do
+ (
+ cd "${harness}/src/${source_name}"
+ patch -s -p1 <"${harness}/patches/${patches[${index}]}"
+ )
+ done
+
+ TP_DIR="${harness}" DORIS_HOME="${tmpdir}" \
+ bash "${harness}/download-thirdparty.sh" "${package}" >/dev/null
+
+ for index in 1 2 3; do
+ [[ "$(<"${harness}/src/${source_name}/${prefix}-${index}.txt")" ==
"patched" ]] ||
+ fail "${package} did not recover after interruption boundary
${applied}"
+ done
+ [[
"$(<"${harness}/src/${source_name}/patched_mark_arrow_paimon_fingerprint")" ==
"test-fingerprint" ]] ||
+ fail "${package} fingerprint marker is missing"
+
+ touch "${harness}/src/${source_name}/idempotence-sentinel"
+ TP_DIR="${harness}" DORIS_HOME="${tmpdir}" \
+ bash "${harness}/download-thirdparty.sh" "${package}" >/dev/null
+ [[ -f "${harness}/src/${source_name}/idempotence-sentinel" ]] ||
+ fail "${package} reset a completely patched source tree"
+ done
+}
+
+exercise_interrupted_patch_set ARROW "${arrow_source}" "${arrow_archive}"
arrow \
+ "${arrow_patches[@]}"
+exercise_interrupted_patch_set PAIMON_CPP "${paimon_source}"
"${paimon_archive}" paimon \
+ "${paimon_patches[@]}"
+
+exercise_generic_recovery_dispatch() {
+ local generic="${tmpdir}/generic-recovery"
+ local thirdparty_dir="${generic}/thirdparty"
+ local external_thirdparty_dir="${generic}/external-thirdparty"
+ local args_file="${generic}/build-args.txt"
+ local output_file="${generic}/build-output.txt"
+ local external_builder_called="${generic}/external-builder-called"
+ local fake_mvn="${generic}/fake-mvn"
+ local non_native_status=79
+ local non_native_target
+ local status
+ local flag
+ local parallel
+ local clean
+ local package1
+ local package2
+ local extra
+
+ mkdir -p "${thirdparty_dir}/installed/lib/hadoop_hdfs/native" \
+ "${external_thirdparty_dir}/installed/lib/hadoop_hdfs/native" \
+ "${generic}/gensrc" "${generic}/fe" "${generic}/be/build_Release" \
+ "${generic}/be/output"
+ cp "${ROOT}/../build.sh" "${generic}/build.sh"
+ cp "${ROOT}/arrow-paimon-vars.sh" "${thirdparty_dir}/arrow-paimon-vars.sh"
+ touch "${thirdparty_dir}/installed/lib/hadoop_hdfs/native/libhdfs.a"
+ touch
"${external_thirdparty_dir}/installed/lib/hadoop_hdfs/native/libhdfs.a"
+ printf '%s\n' 'clean: ; @:' >"${generic}/gensrc/Makefile"
+ # shellcheck disable=SC2016
+ printf '%s\n' '#!/usr/bin/env bash' '[[ "$1" == "clean" ]]' >"${fake_mvn}"
+ chmod +x "${fake_mvn}"
+ {
+ printf '%s\n' '#!/usr/bin/env bash'
+ printf 'exit %q\n' "${non_native_status}"
+ } >"${generic}/generated-source.sh"
+ chmod +x "${generic}/generated-source.sh"
+ {
+ printf '%s\n' 'DORIS_BUILD_PROFILE=0'
+ printf '%s\n' 'TARGET_SYSTEM=Linux'
+ printf 'MVN_CMD=%q\n' "${fake_mvn}"
+ } >"${generic}/env.sh"
+ {
+ printf '%s\n' '#!/usr/bin/env bash'
+ # RECOVERY_ARGS_FILE is expanded when the generated builder runs.
+ # shellcheck disable=SC2016
+ printf '%s\n' 'printf "%s\n" "$*" >"${RECOVERY_ARGS_FILE:?}"'
+ # shellcheck disable=SC2016
+ printf '%s\n' 'exit "${RECOVERY_EXIT_STATUS:-73}"'
+ } >"${thirdparty_dir}/build-thirdparty.sh"
+
+ DORIS_THIRDPARTY="${thirdparty_dir}" RECOVERY_ARGS_FILE="${args_file}" \
+ bash "${generic}/build.sh" --clean >"${output_file}" 2>&1 ||
+ fail "bare clean failed before reaching its clean-only exit"
+ [[ ! -e "${args_file}" ]] || fail "bare clean invoked the thirdparty
builder"
+ [[ ! -d "${generic}/be/build_Release" && ! -d "${generic}/be/output" ]] ||
+ fail "bare clean did not remove BE build outputs"
+
+ for non_native_target in --fe --hive-udf; do
+ if DORIS_THIRDPARTY="${thirdparty_dir}"
RECOVERY_ARGS_FILE="${args_file}" \
+ bash "${generic}/build.sh" "${non_native_target}"
>"${output_file}" 2>&1; then
+ fail "${non_native_target} did not reach the generated-source
sentinel"
+ else
+ status=$?
+ fi
+ [[ "${status}" -eq "${non_native_status}" ]] ||
+ fail "${non_native_target} failed before the generated-source
sentinel"
+ [[ ! -e "${args_file}" ]] ||
+ fail "${non_native_target} invoked the native Arrow/Paimon builder"
+ done
+
+ if DORIS_THIRDPARTY="${thirdparty_dir}" RECOVERY_ARGS_FILE="${args_file}" \
+ bash "${generic}/build.sh" --fe --clean >"${output_file}" 2>&1; then
+ fail "--fe --clean did not reach the generated-source sentinel"
+ else
+ status=$?
+ fi
+ [[ "${status}" -eq "${non_native_status}" ]] ||
+ fail "--fe --clean failed before the generated-source sentinel"
+ [[ ! -e "${args_file}" ]] ||
+ fail "--fe --clean invoked the native Arrow/Paimon builder"
+
+ if DORIS_THIRDPARTY="${thirdparty_dir}" RECOVERY_ARGS_FILE="${args_file}" \
+ bash "${generic}/build.sh" --be >"${output_file}" 2>&1; then
+ fail "generic stale-prebuilt recovery did not invoke the focused
builder"
+ else
+ status=$?
+ fi
+ [[ "${status}" -eq 73 ]] || fail "generic recovery failed before invoking
its builder"
+ read -r flag parallel package1 package2 extra <"${args_file}"
+ [[ "${flag}" == "-j" && "${parallel}" =~ ^[0-9]+$ &&
+ "${package1}" == "arrow" && "${package2}" == "paimon_cpp" && -z
"${extra}" ]] ||
+ fail "generic recovery dispatched the wrong build package set"
+
+ if DORIS_THIRDPARTY="${thirdparty_dir}" RECOVERY_ARGS_FILE="${args_file}" \
+ bash "${generic}/build.sh" --be --clean >"${output_file}" 2>&1; then
+ fail "generic clean recovery did not invoke the focused builder"
+ else
+ status=$?
+ fi
+ [[ "${status}" -eq 73 ]] || fail "generic clean recovery failed before
invoking its builder"
+ read -r flag parallel clean package1 package2 extra <"${args_file}"
+ [[ "${flag}" == "-j" && "${parallel}" =~ ^[0-9]+$ && "${clean}" ==
"--clean" &&
+ "${package1}" == "arrow" && "${package2}" == "paimon_cpp" && -z
"${extra}" ]] ||
+ fail "generic clean recovery dispatched the wrong build package set"
+
+ if DORIS_THIRDPARTY="${thirdparty_dir}" RECOVERY_ARGS_FILE="${args_file}" \
+ RECOVERY_EXIT_STATUS=0 bash "${generic}/build.sh" --be
>"${output_file}" 2>&1; then
+ fail "generic recovery accepted artifacts that failed current-checkout
validation"
+ fi
+ grep -Fq "Rebuilt Arrow/Paimon artifacts do not match this checkout's
selected inputs" \
+ "${output_file}" || fail "generic recovery did not validate artifacts
after its builder returned"
+
+ if DORIS_THIRDPARTY="${external_thirdparty_dir}" \
+ bash "${generic}/build.sh" --be >"${output_file}" 2>&1; then
+ fail "generic recovery accepted an invalid install-only thirdparty
prefix"
+ fi
+ grep -Fq "is an install-only or incomplete prefix" "${output_file}" ||
+ fail "generic recovery did not explain how to refresh an install-only
prebuilt"
+
+ {
+ printf '%s\n' '#!/usr/bin/env bash'
+ # EXTERNAL_BUILDER_CALLED is expanded when the generated builder runs.
+ # shellcheck disable=SC2016
+ printf '%s\n' 'touch "${EXTERNAL_BUILDER_CALLED:?}"'
+ } >"${external_thirdparty_dir}/build-thirdparty.sh"
+ if DORIS_THIRDPARTY="${external_thirdparty_dir}" \
+ EXTERNAL_BUILDER_CALLED="${external_builder_called}" \
+ bash "${generic}/build.sh" --be >"${output_file}" 2>&1; then
+ fail "generic recovery accepted an external thirdparty source tree"
+ fi
+ grep -Fq "Cannot rebuild thirdparty libraries with an external source
tree" "${output_file}" ||
+ fail "generic recovery did not reject an external thirdparty source
tree"
+ [[ ! -e "${external_builder_called}" ]] ||
+ fail "generic recovery invoked an external thirdparty builder"
+}
+
+exercise_generic_recovery_dispatch
+
+# A Paimon-only build may publish only its own fingerprint. It must not make a
+# stale Arrow installation pass the shared prebuilt validation.
+prebuilt="${tmpdir}/prebuilt"
+mkdir -p "${prebuilt}/include/arrow/util" "${prebuilt}/lib64"
+printf '#define ARROW_VERSION_STRING "%s"\n' "${ARROW_VERSION}" \
+ >"${prebuilt}/include/arrow/util/config.h"
+for library in "${ARROW_PAIMON_REQUIRED_LIBRARIES[@]}"; do
+ touch "${prebuilt}/lib64/${library}"
+done
+
+prepare_arrow_paimon_download_packages "${ARROW_PAIMON_BUILD_PACKAGES[@]}"
+[[ "${ARROW_PAIMON_BUILD_PACKAGES[*]}" == "arrow paimon_cpp" ]] ||
+ fail "focused recovery dispatches a bundled source package as a build
target"
+[[ "${ARROW_PAIMON_DOWNLOAD_PACKAGES[*]}" == "arrow paimon_cpp xsimd brotli"
]] ||
+ fail "focused recovery does not download the complete Arrow source closure"
+
+# A legacy prebuilt may have the old combined marker but no component markers.
+# Generic build.sh consumers must reject it before importing Arrow Compute.
+arrow_paimon_build_fingerprint
>"${prebuilt}/arrow-paimon-build-fingerprint.txt"
+if arrow_paimon_prebuilt_valid "${prebuilt}" >/dev/null 2>&1; then
+ fail "legacy combined marker certified an unversioned component closure"
+fi
+
+printf '%s\n' "${ARROW_LEGACY_BUILD_FINGERPRINTS[0]}" \
+ >"${prebuilt}/arrow-build-fingerprint.txt"
+printf '%s\n' "${PAIMON_LEGACY_BUILD_FINGERPRINTS[0]}" \
+ >"${prebuilt}/paimon-build-fingerprint.txt"
+arrow_paimon_prebuilt_valid "${prebuilt}" ||
+ fail "the complete shared prebuilt was rejected during fingerprint
migration"
+if (
+ ARROW_BUILD_SCHEMA_VERSION="${ARROW_BUILD_SCHEMA_VERSION}-changed"
+ arrow_prebuilt_valid "${prebuilt}"
+) >/dev/null 2>&1; then
+ fail "the legacy Arrow marker survived a semantic fingerprint change"
+fi
+if (
+ PAIMON_BUILD_SCHEMA_VERSION="${PAIMON_BUILD_SCHEMA_VERSION}-changed"
+ paimon_prebuilt_valid "${prebuilt}"
+) >/dev/null 2>&1; then
+ fail "the legacy Paimon marker survived a semantic fingerprint change"
+fi
+
+prebuilt_archive_root="${tmpdir}/prebuilt-archive-root"
+prebuilt_archive="${tmpdir}/prebuilt.tar.xz"
+mkdir -p "${prebuilt_archive_root}/installed"
+cp -a "${prebuilt}/." "${prebuilt_archive_root}/installed/"
+tar -C "${prebuilt_archive_root}" -cJf "${prebuilt_archive}" installed
+
+external_thirdparty="${tmpdir}/external-thirdparty"
+mkdir -p "${external_thirdparty}/installed"
+touch "${external_thirdparty}/installed/old-image-artifact"
+ensure_arrow_paimon_prebuilt_from_url "${external_thirdparty}" \
+ "file://${prebuilt_archive}" >/dev/null 2>&1 ||
+ fail "BE UT could not refresh an outdated build-image prebuilt"
+arrow_paimon_prebuilt_valid "${external_thirdparty}/installed" ||
+ fail "BE UT installed an invalid build-image prebuilt"
+[[ ! -e "${external_thirdparty}/installed/old-image-artifact" ]] ||
+ fail "BE UT kept files from the outdated build-image prebuilt"
+ensure_arrow_paimon_prebuilt_from_url "${external_thirdparty}" \
+ "file://${tmpdir}/missing-prebuilt.tar.xz" >/dev/null 2>&1 ||
+ fail "BE UT tried to download over a valid build-image prebuilt"
+
+invalid_archive_root="${tmpdir}/invalid-prebuilt-archive-root"
+invalid_archive="${tmpdir}/invalid-prebuilt.tar.xz"
+mkdir -p "${invalid_archive_root}/installed"
+cp -a "${prebuilt}/." "${invalid_archive_root}/installed/"
+rm "${invalid_archive_root}/installed/lib64/libarrow_compute.a"
+tar -C "${invalid_archive_root}" -cJf "${invalid_archive}" installed
+
+invalid_external_thirdparty="${tmpdir}/invalid-external-thirdparty"
+mkdir -p "${invalid_external_thirdparty}/installed"
+touch
"${invalid_external_thirdparty}/installed/preserved-after-invalid-download"
+if ensure_arrow_paimon_prebuilt_from_url "${invalid_external_thirdparty}" \
+ "file://${invalid_archive}" >/dev/null 2>&1; then
+ fail "BE UT accepted a downloaded prebuilt without Arrow Compute"
+fi
+[[ -e
"${invalid_external_thirdparty}/installed/preserved-after-invalid-download" ]]
||
+ fail "BE UT replaced the build-image prebuilt before validating its
download"
+
+publish_arrow_prebuilt_marker "${prebuilt}"
+publish_paimon_prebuilt_marker "${prebuilt}"
+rm "${prebuilt}/lib64/libarrow_compute.a"
+if arrow_paimon_prebuilt_valid "${prebuilt}" >/dev/null 2>&1; then
+ fail "prebuilt validation accepted a missing Arrow Compute archive"
+fi
+touch "${prebuilt}/lib64/libarrow_compute.a"
+
+printf '%s\n' stale-arrow >"${prebuilt}/arrow-build-fingerprint.txt"
+if arrow_paimon_prebuilt_valid "${prebuilt}" >/dev/null 2>&1; then
+ fail "Paimon-only marker update certified a stale Arrow build"
+fi
+if require_arrow_prebuilt_for_paimon "${prebuilt}" >/dev/null 2>&1; then
+ fail "Paimon build accepted a stale installed Arrow"
+fi
+
+publish_arrow_prebuilt_marker "${prebuilt}"
+require_arrow_prebuilt_for_paimon "${prebuilt}" ||
+ fail "Paimon build rejected the selected installed Arrow"
+arrow_paimon_prebuilt_valid "${prebuilt}" || fail "matching component markers
were rejected"
+
+invalidate_paimon_prebuilt_marker "${prebuilt}"
+if arrow_paimon_prebuilt_valid "${prebuilt}" >/dev/null 2>&1; then
+ fail "an interrupted Paimon rebuild left its old marker valid"
+fi
+publish_paimon_prebuilt_marker "${prebuilt}"
+
+invalidate_arrow_prebuilt_marker "${prebuilt}"
+if require_arrow_prebuilt_for_paimon "${prebuilt}" >/dev/null 2>&1; then
+ fail "an interrupted Arrow rebuild left its old marker valid"
+fi
+publish_arrow_prebuilt_marker "${prebuilt}"
+arrow_paimon_prebuilt_valid "${prebuilt}" ||
+ fail "republished component markers were rejected"
+
+echo "PASS"
diff --git a/thirdparty/vars.sh b/thirdparty/vars.sh
index c941548c05c..47c6f04b61f 100644
--- a/thirdparty/vars.sh
+++ b/thirdparty/vars.sh
@@ -50,6 +50,10 @@ export TP_JAR_DIR="${TP_INSTALL_DIR}/lib/jar"
# export REPOSITORY_URL=
DORIS_THIRDPARTY_REPOSITORY_URL="${DORIS_THIRDPARTY_REPOSITORY_URL:-https://doris-thirdparty-repo.bj.bcebos.com/thirdparty}"
+DORIS_THIRDPARTY_VARS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=arrow-paimon-vars.sh
+. "${DORIS_THIRDPARTY_VARS_DIR}/arrow-paimon-vars.sh"
+
#####################################################
# Download url, filename and unpaced filename
# of all thirdparties
@@ -235,12 +239,6 @@ ZSTD_NAME=zstd-1.5.7.tar.gz
ZSTD_SOURCE=zstd-1.5.7
ZSTD_MD5SUM="780fc1896922b1bc52a4e90980cdda48"
-# brotli
-BROTLI_DOWNLOAD="https://github.com/google/brotli/archive/v1.0.9.tar.gz"
-BROTLI_NAME="brotli-1.0.9.tar.gz"
-BROTLI_SOURCE="brotli-1.0.9"
-BROTLI_MD5SUM="c2274f0c7af8470ad514637c35bcee7d"
-
# flatbuffers
FLATBUFFERS_DOWNLOAD="https://github.com/google/flatbuffers/archive/v23.5.26.tar.gz"
FLATBUFFERS_NAME=flatbuffers-23.5.26.tar.gz
@@ -260,14 +258,6 @@ GRPC_NAME="grpc-v1.54.3.tar.gz"
GRPC_SOURCE=grpc-1.54.3
GRPC_MD5SUM="af00a2edeae0f02bb25917cc3473b7de"
-# arrow
-# Arrow 19.0.1 will MacOS compile error and decimal type error when convert to
Parquet.
-# https://github.com/apache/doris/pull/51217
-ARROW_DOWNLOAD="https://github.com/apache/arrow/archive/refs/tags/apache-arrow-17.0.0.tar.gz"
-ARROW_NAME="apache-arrow-17.0.0.tar.gz"
-ARROW_SOURCE="arrow-apache-arrow-17.0.0"
-ARROW_MD5SUM="ba18bf83e2164abd34b9ac4cb164f0f0"
-
# Abseil
ABSEIL_DOWNLOAD="https://github.com/abseil/abseil-cpp/releases/download/20250512.1/abseil-cpp-20250512.1.tar.gz"
ABSEIL_NAME="abseil-cpp-20250512.1.tar.gz"
@@ -428,13 +418,6 @@ BENCHMARK_NAME=benchmark-v1.8.0.tar.gz
BENCHMARK_SOURCE=benchmark-1.8.0
BENCHMARK_MD5SUM="8ddf8571d3f6198d37852bcbd964f817"
-# xsimd
-# for arrow-17.0.0, if arrow upgrade, this version may also need to be changed
-XSIMD_DOWNLOAD="https://github.com/xtensor-stack/xsimd/archive/refs/tags/13.0.0.tar.gz"
-XSIMD_NAME="13.0.0.tar.gz"
-XSIMD_SOURCE=xsimd-13.0.0
-XSIMD_MD5SUM="c661deb91836e82d3070f81032014fe6"
-
# simdjson
SIMDJSON_DOWNLOAD="https://github.com/simdjson/simdjson/archive/refs/tags/v3.11.6.tar.gz"
SIMDJSON_NAME=simdjson-3.11.6.tar.gz
@@ -568,12 +551,6 @@ PUGIXML_NAME=pugixml-1.15.tar.gz
PUGIXML_SOURCE=pugixml-1.15
PUGIXML_MD5SUM="3b894c29455eb33a40b165c6e2de5895"
-# paimon-cpp
-PAIMON_CPP_DOWNLOAD="https://github.com/apache/doris-thirdparty/archive/refs/tags/paimon-cpp-0a4f4e2.tar.gz"
-PAIMON_CPP_NAME="paimon-cpp-0a4f4e2.tar.gz"
-PAIMON_CPP_SOURCE="doris-thirdparty-paimon-cpp-0a4f4e2"
-PAIMON_CPP_MD5SUM="b8599a0421dbf1ec05e2f1a481d64e87"
-
# lance-c
LANCE_C_DOWNLOAD="https://github.com/lance-format/lance-c/archive/refs/tags/v0.1.2.tar.gz"
LANCE_C_NAME="lance-c-v0.1.2.tar.gz"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]