From 1de420f38f34d1d5ac76f54622ed7f80ca09f7cb Mon Sep 17 00:00:00 2001 From: Moemen Mahmoud Date: Tue, 21 Jul 2026 23:06:38 +0300 Subject: [PATCH 1/4] GH-50508: Support scalar values in AppendScalars --- cpp/src/arrow/array/array_run_end_test.cc | 81 ++++++++++++++++++++++- cpp/src/arrow/array/builder_run_end.cc | 12 ++-- 2 files changed, 88 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/array/array_run_end_test.cc b/cpp/src/arrow/array/array_run_end_test.cc index f2c493fb3a3b..4479b42f42e6 100644 --- a/cpp/src/arrow/array/array_run_end_test.cc +++ b/cpp/src/arrow/array/array_run_end_test.cc @@ -227,7 +227,7 @@ TEST_P(TestRunEndEncodedArray, LogicalRunEnds) { ASSERT_OK_AND_ASSIGN(logical_run_ends, ree_slice->LogicalRunEnds(pool)); ASSERT_ARRAYS_EQUAL(*logical_run_ends, *expected_run_ends); } - +//<---------------------------------------------------------------------------------> TEST_P(TestRunEndEncodedArray, Builder) { auto value_type = utf8(); auto ree_type = run_end_encoded(run_end_type, value_type); @@ -366,6 +366,85 @@ TEST_P(TestRunEndEncodedArray, Builder) { } } } +//<--------------------------------------------my function----------------------------------------------------> +TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsPrimitiveScalar) { + auto value_type = float32(); + auto ree_type = run_end_encoded(run_end_type, value_type); + + ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, + MakeBuilder(ree_type)); + + + ASSERT_OK_AND_ASSIGN(auto v1, MakeScalar(float32(), 1.0f)); + ASSERT_OK_AND_ASSIGN(auto v2, MakeScalar(float32(), 1.0f)); + ASSERT_OK_AND_ASSIGN(auto v3, MakeScalar(float32(), 2.0f)); + ASSERT_OK_AND_ASSIGN(auto v4, MakeScalar(float32(), 2.0f)); + ASSERT_OK_AND_ASSIGN(auto v5, MakeScalar(float32(), 3.0f)); + + ScalarVector scalars = {v1, v2, v3, v4, v5}; + + ASSERT_OK(builder->AppendScalars(scalars)); + + ASSERT_EQ(builder->length(), 5); + + ASSERT_OK_AND_ASSIGN(auto array, builder->Finish()); + + auto ree_array = std::dynamic_pointer_cast(array); + + ASSERT_NE(ree_array, NULLPTR); + + auto expected_run_ends = + ArrayFromJSON(run_end_type, "[2,4,5]"); + + auto expected_values = + ArrayFromJSON(float32(), "[1,2,3]"); + + ASSERT_ARRAYS_EQUAL(*expected_run_ends, + *ree_array->run_ends()); + + ASSERT_ARRAYS_EQUAL(*expected_values, + *ree_array->values()); +} + +TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsRunEndEncodedScalar) { + auto value_type = float32(); + auto ree_type = run_end_encoded(run_end_type, value_type); + + ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, + MakeBuilder(ree_type)); + + ASSERT_OK_AND_ASSIGN(auto s1, MakeScalar(ree_type, *MakeScalar(float32(), 1.0f))); + ASSERT_OK_AND_ASSIGN(auto s2,MakeScalar(ree_type, *MakeScalar(float32(), 1.0f))); + ASSERT_OK_AND_ASSIGN(auto s3,MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); + ASSERT_OK_AND_ASSIGN(auto s4,MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); + ASSERT_OK_AND_ASSIGN(auto s5, MakeScalar(ree_type, *MakeScalar(float32(), 3.0f))); + + ScalarVector scalars = {s1, s2, s3, s4, s5}; + + ASSERT_OK(builder->AppendScalars(scalars)); + + ASSERT_EQ(builder->length(), 5); + + ASSERT_OK_AND_ASSIGN(auto array, builder->Finish()); + + auto ree_array = + std::dynamic_pointer_cast(array); + + ASSERT_NE(ree_array, NULLPTR); + + auto expected_run_ends = + ArrayFromJSON(run_end_type, "[2,4,5]"); + + auto expected_values = + ArrayFromJSON(float32(), "[1,2,3]"); + + ASSERT_ARRAYS_EQUAL(*expected_run_ends, + *ree_array->run_ends()); + + ASSERT_ARRAYS_EQUAL(*expected_values, + *ree_array->values()); +} +//<-----------------------------------------------------------------------------------------------------> TEST_P(TestRunEndEncodedArray, BuilderReuseAfterFinish) { // GH-45532: RunEndEncodedBuilder should clear dimensions after a Finish() call diff --git a/cpp/src/arrow/array/builder_run_end.cc b/cpp/src/arrow/array/builder_run_end.cc index 9199b5ab498a..273ebb6f57ac 100644 --- a/cpp/src/arrow/array/builder_run_end.cc +++ b/cpp/src/arrow/array/builder_run_end.cc @@ -201,7 +201,6 @@ Status RunEndEncodedBuilder::AppendEmptyValues(int64_t length) { UpdateDimensions(committed_logical_length_, 0); return Status::OK(); } - Status RunEndEncodedBuilder::AppendScalar(const Scalar& scalar, int64_t n_repeats) { if (scalar.type->id() == Type::RUN_END_ENCODED) { return AppendScalar(*internal::checked_cast(scalar).value, @@ -212,11 +211,16 @@ Status RunEndEncodedBuilder::AppendScalar(const Scalar& scalar, int64_t n_repeat return Status::OK(); } +//<---------------------------------------------------------------------------------> Status RunEndEncodedBuilder::AppendScalars(const ScalarVector& scalars) { - RETURN_NOT_OK(this->ArrayBuilder::AppendScalars(scalars)); - UpdateDimensions(committed_logical_length_, value_run_builder_->open_run_length()); - return Status::OK(); + if(scalars.empty()) return Status::OK(); + for (const auto& scalar : scalars) { + RETURN_NOT_OK(AppendScalar(*scalar,1)); +} + UpdateDimensions(committed_logical_length_,value_run_builder_->open_run_length()); +return Status::OK(); } +//<---------------------------------------------------------------------------------> template Status RunEndEncodedBuilder::DoAppendArraySlice(const ArraySpan& array, int64_t offset, From 41745a9ae22b9ad5091206f9d6ea8be91fbdf1a4 Mon Sep 17 00:00:00 2001 From: Moemen Mahmoud Date: Tue, 21 Jul 2026 23:54:55 +0300 Subject: [PATCH 2/4] GH-50508: Clean up comments --- cpp/src/arrow/array/array_run_end_test.cc | 4 +--- cpp/src/arrow/array/builder_run_end.cc | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/cpp/src/arrow/array/array_run_end_test.cc b/cpp/src/arrow/array/array_run_end_test.cc index 4479b42f42e6..d0f8c60b4055 100644 --- a/cpp/src/arrow/array/array_run_end_test.cc +++ b/cpp/src/arrow/array/array_run_end_test.cc @@ -227,7 +227,6 @@ TEST_P(TestRunEndEncodedArray, LogicalRunEnds) { ASSERT_OK_AND_ASSIGN(logical_run_ends, ree_slice->LogicalRunEnds(pool)); ASSERT_ARRAYS_EQUAL(*logical_run_ends, *expected_run_ends); } -//<---------------------------------------------------------------------------------> TEST_P(TestRunEndEncodedArray, Builder) { auto value_type = utf8(); auto ree_type = run_end_encoded(run_end_type, value_type); @@ -366,7 +365,6 @@ TEST_P(TestRunEndEncodedArray, Builder) { } } } -//<--------------------------------------------my function----------------------------------------------------> TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsPrimitiveScalar) { auto value_type = float32(); auto ree_type = run_end_encoded(run_end_type, value_type); @@ -444,7 +442,7 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsRunEndEncodedScalar) { ASSERT_ARRAYS_EQUAL(*expected_values, *ree_array->values()); } -//<-----------------------------------------------------------------------------------------------------> + TEST_P(TestRunEndEncodedArray, BuilderReuseAfterFinish) { // GH-45532: RunEndEncodedBuilder should clear dimensions after a Finish() call diff --git a/cpp/src/arrow/array/builder_run_end.cc b/cpp/src/arrow/array/builder_run_end.cc index 273ebb6f57ac..696f2d38099b 100644 --- a/cpp/src/arrow/array/builder_run_end.cc +++ b/cpp/src/arrow/array/builder_run_end.cc @@ -211,7 +211,6 @@ Status RunEndEncodedBuilder::AppendScalar(const Scalar& scalar, int64_t n_repeat return Status::OK(); } -//<---------------------------------------------------------------------------------> Status RunEndEncodedBuilder::AppendScalars(const ScalarVector& scalars) { if(scalars.empty()) return Status::OK(); for (const auto& scalar : scalars) { @@ -220,7 +219,6 @@ Status RunEndEncodedBuilder::AppendScalars(const ScalarVector& scalars) { UpdateDimensions(committed_logical_length_,value_run_builder_->open_run_length()); return Status::OK(); } -//<---------------------------------------------------------------------------------> template Status RunEndEncodedBuilder::DoAppendArraySlice(const ArraySpan& array, int64_t offset, From cc8e4fddb1c6a4cf65718993656bba1988645998 Mon Sep 17 00:00:00 2001 From: Moemen Mahmoud Date: Wed, 22 Jul 2026 04:15:04 +0300 Subject: [PATCH 3/4] GH-50508: Apply clang-format --- cpp/src/arrow/array/array_run_end_test.cc | 51 +++++++++-------------- cpp/src/arrow/array/builder_run_end.cc | 12 +++--- 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/cpp/src/arrow/array/array_run_end_test.cc b/cpp/src/arrow/array/array_run_end_test.cc index d0f8c60b4055..b5c23807f034 100644 --- a/cpp/src/arrow/array/array_run_end_test.cc +++ b/cpp/src/arrow/array/array_run_end_test.cc @@ -369,15 +369,13 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsPrimitiveScalar) { auto value_type = float32(); auto ree_type = run_end_encoded(run_end_type, value_type); - ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, - MakeBuilder(ree_type)); - + ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, MakeBuilder(ree_type)); - ASSERT_OK_AND_ASSIGN(auto v1, MakeScalar(float32(), 1.0f)); - ASSERT_OK_AND_ASSIGN(auto v2, MakeScalar(float32(), 1.0f)); - ASSERT_OK_AND_ASSIGN(auto v3, MakeScalar(float32(), 2.0f)); - ASSERT_OK_AND_ASSIGN(auto v4, MakeScalar(float32(), 2.0f)); - ASSERT_OK_AND_ASSIGN(auto v5, MakeScalar(float32(), 3.0f)); + ASSERT_OK_AND_ASSIGN(auto v1, MakeScalar(float32(), 1.0f)); + ASSERT_OK_AND_ASSIGN(auto v2, MakeScalar(float32(), 1.0f)); + ASSERT_OK_AND_ASSIGN(auto v3, MakeScalar(float32(), 2.0f)); + ASSERT_OK_AND_ASSIGN(auto v4, MakeScalar(float32(), 2.0f)); + ASSERT_OK_AND_ASSIGN(auto v5, MakeScalar(float32(), 3.0f)); ScalarVector scalars = {v1, v2, v3, v4, v5}; @@ -391,30 +389,25 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsPrimitiveScalar) { ASSERT_NE(ree_array, NULLPTR); - auto expected_run_ends = - ArrayFromJSON(run_end_type, "[2,4,5]"); + auto expected_run_ends = ArrayFromJSON(run_end_type, "[2,4,5]"); - auto expected_values = - ArrayFromJSON(float32(), "[1,2,3]"); + auto expected_values = ArrayFromJSON(float32(), "[1,2,3]"); - ASSERT_ARRAYS_EQUAL(*expected_run_ends, - *ree_array->run_ends()); + ASSERT_ARRAYS_EQUAL(*expected_run_ends, *ree_array->run_ends()); - ASSERT_ARRAYS_EQUAL(*expected_values, - *ree_array->values()); + ASSERT_ARRAYS_EQUAL(*expected_values, *ree_array->values()); } TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsRunEndEncodedScalar) { auto value_type = float32(); auto ree_type = run_end_encoded(run_end_type, value_type); - ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, - MakeBuilder(ree_type)); + ASSERT_OK_AND_ASSIGN(std::shared_ptr builder, MakeBuilder(ree_type)); ASSERT_OK_AND_ASSIGN(auto s1, MakeScalar(ree_type, *MakeScalar(float32(), 1.0f))); - ASSERT_OK_AND_ASSIGN(auto s2,MakeScalar(ree_type, *MakeScalar(float32(), 1.0f))); - ASSERT_OK_AND_ASSIGN(auto s3,MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); - ASSERT_OK_AND_ASSIGN(auto s4,MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); + ASSERT_OK_AND_ASSIGN(auto s2, MakeScalar(ree_type, *MakeScalar(float32(), 1.0f))); + ASSERT_OK_AND_ASSIGN(auto s3, MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); + ASSERT_OK_AND_ASSIGN(auto s4, MakeScalar(ree_type, *MakeScalar(float32(), 2.0f))); ASSERT_OK_AND_ASSIGN(auto s5, MakeScalar(ree_type, *MakeScalar(float32(), 3.0f))); ScalarVector scalars = {s1, s2, s3, s4, s5}; @@ -425,25 +418,19 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsRunEndEncodedScalar) { ASSERT_OK_AND_ASSIGN(auto array, builder->Finish()); - auto ree_array = - std::dynamic_pointer_cast(array); + auto ree_array = std::dynamic_pointer_cast(array); ASSERT_NE(ree_array, NULLPTR); - auto expected_run_ends = - ArrayFromJSON(run_end_type, "[2,4,5]"); + auto expected_run_ends = ArrayFromJSON(run_end_type, "[2,4,5]"); - auto expected_values = - ArrayFromJSON(float32(), "[1,2,3]"); + auto expected_values = ArrayFromJSON(float32(), "[1,2,3]"); - ASSERT_ARRAYS_EQUAL(*expected_run_ends, - *ree_array->run_ends()); + ASSERT_ARRAYS_EQUAL(*expected_run_ends, *ree_array->run_ends()); - ASSERT_ARRAYS_EQUAL(*expected_values, - *ree_array->values()); + ASSERT_ARRAYS_EQUAL(*expected_values, *ree_array->values()); } - TEST_P(TestRunEndEncodedArray, BuilderReuseAfterFinish) { // GH-45532: RunEndEncodedBuilder should clear dimensions after a Finish() call auto ree_type = run_end_encoded(run_end_type, utf8()); diff --git a/cpp/src/arrow/array/builder_run_end.cc b/cpp/src/arrow/array/builder_run_end.cc index 696f2d38099b..e8b2161c0c03 100644 --- a/cpp/src/arrow/array/builder_run_end.cc +++ b/cpp/src/arrow/array/builder_run_end.cc @@ -212,12 +212,12 @@ Status RunEndEncodedBuilder::AppendScalar(const Scalar& scalar, int64_t n_repeat } Status RunEndEncodedBuilder::AppendScalars(const ScalarVector& scalars) { - if(scalars.empty()) return Status::OK(); - for (const auto& scalar : scalars) { - RETURN_NOT_OK(AppendScalar(*scalar,1)); -} - UpdateDimensions(committed_logical_length_,value_run_builder_->open_run_length()); -return Status::OK(); + if (scalars.empty()) return Status::OK(); + for (const auto& scalar : scalars) { + RETURN_NOT_OK(AppendScalar(*scalar, 1)); + } + UpdateDimensions(committed_logical_length_, value_run_builder_->open_run_length()); + return Status::OK(); } template From 64df56106f657ab59e21b5e01cbbf64f8791d856 Mon Sep 17 00:00:00 2001 From: Moemen Mahmoud Date: Wed, 22 Jul 2026 19:38:47 +0300 Subject: [PATCH 4/4] GH-50508: Address review comments --- cpp/src/arrow/array/array_run_end_test.cc | 2 ++ cpp/src/arrow/array/builder_run_end.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/cpp/src/arrow/array/array_run_end_test.cc b/cpp/src/arrow/array/array_run_end_test.cc index b5c23807f034..933748913522 100644 --- a/cpp/src/arrow/array/array_run_end_test.cc +++ b/cpp/src/arrow/array/array_run_end_test.cc @@ -384,6 +384,7 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsPrimitiveScalar) { ASSERT_EQ(builder->length(), 5); ASSERT_OK_AND_ASSIGN(auto array, builder->Finish()); + ASSERT_OK(array->ValidateFull()); auto ree_array = std::dynamic_pointer_cast(array); @@ -417,6 +418,7 @@ TEST_P(TestRunEndEncodedArray, BuilderAppendScalarsRunEndEncodedScalar) { ASSERT_EQ(builder->length(), 5); ASSERT_OK_AND_ASSIGN(auto array, builder->Finish()); + ASSERT_OK(array->ValidateFull()); auto ree_array = std::dynamic_pointer_cast(array); diff --git a/cpp/src/arrow/array/builder_run_end.cc b/cpp/src/arrow/array/builder_run_end.cc index e8b2161c0c03..2edeaff504d2 100644 --- a/cpp/src/arrow/array/builder_run_end.cc +++ b/cpp/src/arrow/array/builder_run_end.cc @@ -201,6 +201,7 @@ Status RunEndEncodedBuilder::AppendEmptyValues(int64_t length) { UpdateDimensions(committed_logical_length_, 0); return Status::OK(); } + Status RunEndEncodedBuilder::AppendScalar(const Scalar& scalar, int64_t n_repeats) { if (scalar.type->id() == Type::RUN_END_ENCODED) { return AppendScalar(*internal::checked_cast(scalar).value,