From daac36e88b57eefefabe0160097ec4f9ce4d509e Mon Sep 17 00:00:00 2001 From: Ebraam Date: Tue, 3 Mar 2026 23:20:01 +0200 Subject: [PATCH 01/10] GH-49410: [C++] Add regression test for if_else with sliced BaseBinary chunks --- .../compute/kernels/scalar_if_else_test.cc | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index 85d152aa8cd2..086b122d5090 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -3778,5 +3778,36 @@ TEST(TestChooseKernel, Errors) { {ArrayFromJSON(int64(), "[-1]"), ArrayFromJSON(int32(), "[0]")})); } +TEST_F(TestIfElseKernel, IfElseBaseBinarySlicedChunk) { + for (auto type : {utf8(), binary(), large_utf8(), large_binary()}) { + auto full_arr = ArrayFromJSON(type, R"([null, "x", "x", null, "x", "x"])"); + auto chunk0 = full_arr->Slice(0, 3); + auto chunk1 = full_arr->Slice(3); + + auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); + ASSERT_OK_AND_ASSIGN(auto result_asa, + CallFunction("if_else", {cond_asa, MakeNullScalar(type), chunk1})); + ASSERT_OK(result_asa.make_array()->ValidateFull()); + AssertArraysEqual(*ArrayFromJSON(type, R"([null, "x", "x"])"), + *result_asa.make_array(), true); + + auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); + ASSERT_OK_AND_ASSIGN(auto result_aas, + CallFunction("if_else", {cond_aas, chunk1, MakeNullScalar(type)})); + ASSERT_OK(result_aas.make_array()->ValidateFull()); + AssertArraysEqual(*ArrayFromJSON(type, R"([null, "x", "x"])"), + *result_aas.make_array(), true); + + auto arr1 = std::make_shared(ArrayVector{chunk0, chunk1}); + auto mask = *CallFunction("is_null", {arr1}); + ASSERT_OK_AND_ASSIGN(auto arr2_datum, + CallFunction("if_else", {Datum(true), *Concatenate(arr1->chunks()), arr1})); + ASSERT_OK(arr2_datum.chunked_array()->ValidateFull()); + ASSERT_OK_AND_ASSIGN(auto arr3_datum, + CallFunction("if_else", {mask, MakeNullScalar(type), arr2_datum})); + ASSERT_OK(arr3_datum.chunked_array()->ValidateFull()); + AssertDatumsEqual(Datum(arr1), arr3_datum); + } +} } // namespace compute } // namespace arrow From 95b8bf8ed5818eede6633f913c29204339b0d79a Mon Sep 17 00:00:00 2001 From: Ebraam Date: Wed, 4 Mar 2026 21:13:50 +0200 Subject: [PATCH 02/10] GH-49410: [C++] Use TYPED_TEST and remove chunked array test --- .../compute/kernels/scalar_if_else_test.cc | 53 ++++++++----------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index 086b122d5090..f93303538030 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -608,6 +608,28 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinaryRand) { CheckIfElseOutput(cond, left, right, expected_data); } +TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { + auto type = TypeTraits::type_singleton(); + + auto full_arr = ArrayFromJSON(type, R"([null, "x", "x", null, "x", "x"])"); + auto sliced = full_arr->Slice(3); + + auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); + ASSERT_OK_AND_ASSIGN( + auto result_asa, + CallFunction("if_else", {cond_asa, MakeNullScalar(type), sliced})); + ASSERT_OK(result_asa.make_array()->ValidateFull()); + auto expected = ArrayFromJSON(type, R"([null, "x", "x"])"); + AssertArraysEqual(*expected, *result_asa.make_array(),true); + + auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); + ASSERT_OK_AND_ASSIGN( + auto result_aas, + CallFunction("if_else", {cond_aas, sliced, MakeNullScalar(type)})); + ASSERT_OK(result_aas.make_array()->ValidateFull()); + AssertArraysEqual(*expected, *result_aas.make_array(),true); +} + TEST_F(TestIfElseKernel, IfElseFSBinary) { auto type = fixed_size_binary(4); @@ -3778,36 +3800,5 @@ TEST(TestChooseKernel, Errors) { {ArrayFromJSON(int64(), "[-1]"), ArrayFromJSON(int32(), "[0]")})); } -TEST_F(TestIfElseKernel, IfElseBaseBinarySlicedChunk) { - for (auto type : {utf8(), binary(), large_utf8(), large_binary()}) { - auto full_arr = ArrayFromJSON(type, R"([null, "x", "x", null, "x", "x"])"); - auto chunk0 = full_arr->Slice(0, 3); - auto chunk1 = full_arr->Slice(3); - - auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); - ASSERT_OK_AND_ASSIGN(auto result_asa, - CallFunction("if_else", {cond_asa, MakeNullScalar(type), chunk1})); - ASSERT_OK(result_asa.make_array()->ValidateFull()); - AssertArraysEqual(*ArrayFromJSON(type, R"([null, "x", "x"])"), - *result_asa.make_array(), true); - - auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); - ASSERT_OK_AND_ASSIGN(auto result_aas, - CallFunction("if_else", {cond_aas, chunk1, MakeNullScalar(type)})); - ASSERT_OK(result_aas.make_array()->ValidateFull()); - AssertArraysEqual(*ArrayFromJSON(type, R"([null, "x", "x"])"), - *result_aas.make_array(), true); - - auto arr1 = std::make_shared(ArrayVector{chunk0, chunk1}); - auto mask = *CallFunction("is_null", {arr1}); - ASSERT_OK_AND_ASSIGN(auto arr2_datum, - CallFunction("if_else", {Datum(true), *Concatenate(arr1->chunks()), arr1})); - ASSERT_OK(arr2_datum.chunked_array()->ValidateFull()); - ASSERT_OK_AND_ASSIGN(auto arr3_datum, - CallFunction("if_else", {mask, MakeNullScalar(type), arr2_datum})); - ASSERT_OK(arr3_datum.chunked_array()->ValidateFull()); - AssertDatumsEqual(Datum(arr1), arr3_datum); - } -} } // namespace compute } // namespace arrow From 9f2edbc6d03bc93b601bb610dbd8b6173df3e097 Mon Sep 17 00:00:00 2001 From: Ebraam Date: Thu, 5 Mar 2026 16:57:32 +0200 Subject: [PATCH 03/10] GH-49410: [C++] Fix if_else null-scalar fast paths for sliced BaseBinary arrays --- .../arrow/compute/kernels/scalar_if_else.cc | 24 +++++++++++++++---- .../compute/kernels/scalar_if_else_test.cc | 4 ++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc b/cpp/src/arrow/compute/kernels/scalar_if_else.cc index d32070f5c0fa..cf24d6ae855c 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc @@ -745,9 +745,17 @@ struct IfElseFunctor> { ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); std::memcpy(out_data->buffers[1]->mutable_data(), right_offsets, offset_length); - auto right_data_length = right_offsets[right.length] - right_offsets[0]; + OffsetType base = right_offsets[0]; + auto* out_offsets = reinterpret_cast( + out_data->buffers[1]->mutable_data()); + for (int64_t i = 0; i <= cond.length; ++i) { + out_offsets[i] = right_offsets[i] - base; + } + + auto right_data_length = right_offsets[right.length] - base; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(right_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), right_data, right_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), right_data + base, + right_data_length); return Status::OK(); } @@ -785,9 +793,17 @@ struct IfElseFunctor> { ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); std::memcpy(out_data->buffers[1]->mutable_data(), left_offsets, offset_length); - auto left_data_length = left_offsets[left.length] - left_offsets[0]; + OffsetType base = left_offsets[0]; + auto* out_offsets = reinterpret_cast( + out_data->buffers[1]->mutable_data()); + for (int64_t i = 0; i <= cond.length; ++i) { + out_offsets[i] = left_offsets[i] - base; + } + + auto left_data_length = left_offsets[left.length] - base; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(left_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), left_data, left_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), left_data + base, + left_data_length); return Status::OK(); } diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index f93303538030..cd035c7c8779 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -611,8 +611,8 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinaryRand) { TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { auto type = TypeTraits::type_singleton(); - auto full_arr = ArrayFromJSON(type, R"([null, "x", "x", null, "x", "x"])"); - auto sliced = full_arr->Slice(3); + auto full_arr = ArrayFromJSON(type, R"(["not used", null, "x", "x"])"); + auto sliced = full_arr->Slice(1); auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); ASSERT_OK_AND_ASSIGN( From a8b051532b5dcbf250a0f06c89b5f191a59914d6 Mon Sep 17 00:00:00 2001 From: Ebraam Date: Sat, 7 Mar 2026 09:23:36 +0200 Subject: [PATCH 04/10] GH-49410: [C++] Fix clang-format style --- cpp/src/arrow/compute/kernels/scalar_if_else.cc | 8 ++++---- .../arrow/compute/kernels/scalar_if_else_test.cc | 14 ++++++-------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc b/cpp/src/arrow/compute/kernels/scalar_if_else.cc index cf24d6ae855c..1475cf97185a 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc @@ -746,8 +746,8 @@ struct IfElseFunctor> { std::memcpy(out_data->buffers[1]->mutable_data(), right_offsets, offset_length); OffsetType base = right_offsets[0]; - auto* out_offsets = reinterpret_cast( - out_data->buffers[1]->mutable_data()); + auto* out_offsets = + reinterpret_cast(out_data->buffers[1]->mutable_data()); for (int64_t i = 0; i <= cond.length; ++i) { out_offsets[i] = right_offsets[i] - base; } @@ -794,8 +794,8 @@ struct IfElseFunctor> { std::memcpy(out_data->buffers[1]->mutable_data(), left_offsets, offset_length); OffsetType base = left_offsets[0]; - auto* out_offsets = reinterpret_cast( - out_data->buffers[1]->mutable_data()); + auto* out_offsets = + reinterpret_cast(out_data->buffers[1]->mutable_data()); for (int64_t i = 0; i <= cond.length; ++i) { out_offsets[i] = left_offsets[i] - base; } diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index cd035c7c8779..460020cb463b 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -615,19 +615,17 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { auto sliced = full_arr->Slice(1); auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); - ASSERT_OK_AND_ASSIGN( - auto result_asa, - CallFunction("if_else", {cond_asa, MakeNullScalar(type), sliced})); + ASSERT_OK_AND_ASSIGN(auto result_asa, + CallFunction("if_else", {cond_asa, MakeNullScalar(type), sliced})); ASSERT_OK(result_asa.make_array()->ValidateFull()); auto expected = ArrayFromJSON(type, R"([null, "x", "x"])"); - AssertArraysEqual(*expected, *result_asa.make_array(),true); + AssertArraysEqual(*expected, *result_asa.make_array(), true); auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); - ASSERT_OK_AND_ASSIGN( - auto result_aas, - CallFunction("if_else", {cond_aas, sliced, MakeNullScalar(type)})); + ASSERT_OK_AND_ASSIGN(auto result_aas, + CallFunction("if_else", {cond_aas, sliced, MakeNullScalar(type)})); ASSERT_OK(result_aas.make_array()->ValidateFull()); - AssertArraysEqual(*expected, *result_aas.make_array(),true); + AssertArraysEqual(*expected, *result_aas.make_array(), true); } TEST_F(TestIfElseKernel, IfElseFSBinary) { From 9c88e00770e8d525c652829e5a85695883cad526 Mon Sep 17 00:00:00 2001 From: Ebraam Date: Sun, 8 Mar 2026 16:15:50 +0200 Subject: [PATCH 05/10] GH-49410: [C++] optimize offset handling --- .../arrow/compute/kernels/scalar_if_else.cc | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc b/cpp/src/arrow/compute/kernels/scalar_if_else.cc index 1475cf97185a..29031ae7c7a3 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc @@ -743,19 +743,22 @@ struct IfElseFunctor> { auto* out_data = out->array_data().get(); auto offset_length = (cond.length + 1) * sizeof(OffsetType); ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); - std::memcpy(out_data->buffers[1]->mutable_data(), right_offsets, offset_length); - OffsetType base = right_offsets[0]; - auto* out_offsets = - reinterpret_cast(out_data->buffers[1]->mutable_data()); - for (int64_t i = 0; i <= cond.length; ++i) { - out_offsets[i] = right_offsets[i] - base; + if (right.offset == 0) { + std::memcpy(out_data->buffers[1]->mutable_data(), right_offsets, offset_length); + } else { + OffsetType base = right_offsets[0]; + auto* out_offsets = + reinterpret_cast(out_data->buffers[1]->mutable_data()); + for (int64_t i = 0; i <= cond.length; ++i) { + out_offsets[i] = right_offsets[i] - base; + } } - auto right_data_length = right_offsets[right.length] - base; + auto right_data_length = right_offsets[right.length] - right_offsets[0]; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(right_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), right_data + base, - right_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), + right_data + right_offsets[0], right_data_length); return Status::OK(); } @@ -791,19 +794,22 @@ struct IfElseFunctor> { auto* out_data = out->array_data().get(); auto offset_length = (cond.length + 1) * sizeof(OffsetType); ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); - std::memcpy(out_data->buffers[1]->mutable_data(), left_offsets, offset_length); - OffsetType base = left_offsets[0]; - auto* out_offsets = - reinterpret_cast(out_data->buffers[1]->mutable_data()); - for (int64_t i = 0; i <= cond.length; ++i) { - out_offsets[i] = left_offsets[i] - base; + if (left.offset == 0) { + std::memcpy(out_data->buffers[1]->mutable_data(), left_offsets, offset_length); + } else { + OffsetType base = left_offsets[0]; + auto* out_offsets = + reinterpret_cast(out_data->buffers[1]->mutable_data()); + for (int64_t i = 0; i <= cond.length; ++i) { + out_offsets[i] = left_offsets[i] - base; + } } - auto left_data_length = left_offsets[left.length] - base; + auto left_data_length = left_offsets[left.length] - left_offsets[0]; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(left_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), left_data + base, - left_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), + left_data + left_offsets[0], left_data_length); return Status::OK(); } From 5979e54e0db5d0523df8a3ee597353d8ef3c1c9c Mon Sep 17 00:00:00 2001 From: Ebraam Date: Sun, 8 Mar 2026 16:22:23 +0200 Subject: [PATCH 06/10] GH-49410: [C++] [C++] Fix clang-format style --- cpp/src/arrow/compute/kernels/scalar_if_else.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc b/cpp/src/arrow/compute/kernels/scalar_if_else.cc index 29031ae7c7a3..70b281af3eb6 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc @@ -757,8 +757,8 @@ struct IfElseFunctor> { auto right_data_length = right_offsets[right.length] - right_offsets[0]; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(right_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), - right_data + right_offsets[0], right_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), right_data + right_offsets[0], + right_data_length); return Status::OK(); } @@ -808,8 +808,8 @@ struct IfElseFunctor> { auto left_data_length = left_offsets[left.length] - left_offsets[0]; ARROW_ASSIGN_OR_RAISE(out_data->buffers[2], ctx->Allocate(left_data_length)); - std::memcpy(out_data->buffers[2]->mutable_data(), - left_data + left_offsets[0], left_data_length); + std::memcpy(out_data->buffers[2]->mutable_data(), left_data + left_offsets[0], + left_data_length); return Status::OK(); } From f31b8c06d417d3e8695f997320455efe7c74c83e Mon Sep 17 00:00:00 2001 From: Ebraam Date: Mon, 9 Mar 2026 13:16:31 +0200 Subject: [PATCH 07/10] GH-49410: [C++] Key offset branch on offsets[0] instead of array offset --- cpp/src/arrow/compute/kernels/scalar_if_else.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else.cc b/cpp/src/arrow/compute/kernels/scalar_if_else.cc index 70b281af3eb6..8efcf6cb8341 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else.cc @@ -744,7 +744,7 @@ struct IfElseFunctor> { auto offset_length = (cond.length + 1) * sizeof(OffsetType); ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); - if (right.offset == 0) { + if (right_offsets[0] == 0) { std::memcpy(out_data->buffers[1]->mutable_data(), right_offsets, offset_length); } else { OffsetType base = right_offsets[0]; @@ -795,7 +795,7 @@ struct IfElseFunctor> { auto offset_length = (cond.length + 1) * sizeof(OffsetType); ARROW_ASSIGN_OR_RAISE(out_data->buffers[1], ctx->Allocate(offset_length)); - if (left.offset == 0) { + if (left_offsets[0] == 0) { std::memcpy(out_data->buffers[1]->mutable_data(), left_offsets, offset_length); } else { OffsetType base = left_offsets[0]; From 4303c72aa89804d7930ee37600c0b4997a372a97 Mon Sep 17 00:00:00 2001 From: Ebraam Date: Tue, 10 Mar 2026 11:20:45 +0200 Subject: [PATCH 08/10] GH-49410: [C++] add edge case test for offset=0 with non-zero first offset --- .../compute/kernels/scalar_if_else_test.cc | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index 460020cb463b..76e49cc43d5e 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -26,6 +26,7 @@ #include "arrow/compute/kernels/test_util_internal.h" #include "arrow/compute/registry.h" #include "arrow/testing/gtest_util.h" +#include "arrow/util/bitmap_builders.h" #include "arrow/util/checked_cast.h" namespace arrow { @@ -626,6 +627,28 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { CallFunction("if_else", {cond_aas, sliced, MakeNullScalar(type)})); ASSERT_OK(result_aas.make_array()->ValidateFull()); AssertArraysEqual(*expected, *result_aas.make_array(), true); + + // edge case: offset=0 but offsets[0] != 0 (spec-valid, manually constructed) + using OffsetType = typename TypeTraits::OffsetType::c_type; + std::vector raw_offsets = {8, 8, 9, 10}; + std::string raw_data(8, 'x'); + raw_data += "xx"; + auto offsets_buf = Buffer::Wrap(raw_offsets.data(), raw_offsets.size()); + auto data_buf = + std::make_shared(reinterpret_cast(raw_data.data()), + static_cast(raw_data.size())); + auto array_data = ArrayData::Make(type, /*length=*/3, {nullptr, offsets_buf, data_buf}, + /*null_count=*/1, /*offset=*/0); + std::vector validity_bytes = {0, 1, 1}; + ASSERT_OK_AND_ASSIGN( + array_data->buffers[0], + arrow::internal::BytesToBits(validity_bytes, arrow::default_memory_pool())); + auto arr = MakeArray(array_data); + ASSERT_OK(arr->ValidateFull()); + ASSERT_OK_AND_ASSIGN(auto result_nonzero, + CallFunction("if_else", {cond_asa, MakeNullScalar(type), arr})); + ASSERT_OK(result_nonzero.make_array()->ValidateFull()); + AssertArraysEqual(*expected, *result_nonzero.make_array(), true); } TEST_F(TestIfElseKernel, IfElseFSBinary) { From 3ec98d2b002b03b38922b514c83dcad235b425b5 Mon Sep 17 00:00:00 2001 From: Ebraam Date: Wed, 11 Mar 2026 11:11:25 +0200 Subject: [PATCH 09/10] GH-49410: [C++] Split non-sliced offset edge case into separate test --- .../compute/kernels/scalar_if_else_test.cc | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index a4a7df8fd5d9..324c3f8a2db0 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -615,12 +615,12 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { auto full_arr = ArrayFromJSON(type, R"(["not used", null, "x", "x"])"); auto sliced = full_arr->Slice(1); + auto expected = ArrayFromJSON(type, R"([null, "x", "x"])"); auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); ASSERT_OK_AND_ASSIGN(auto result_asa, CallFunction("if_else", {cond_asa, MakeNullScalar(type), sliced})); ASSERT_OK(result_asa.make_array()->ValidateFull()); - auto expected = ArrayFromJSON(type, R"([null, "x", "x"])"); AssertArraysEqual(*expected, *result_asa.make_array(), true); auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); @@ -628,28 +628,38 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinarySliced) { CallFunction("if_else", {cond_aas, sliced, MakeNullScalar(type)})); ASSERT_OK(result_aas.make_array()->ValidateFull()); AssertArraysEqual(*expected, *result_aas.make_array(), true); +} - // edge case: offset=0 but offsets[0] != 0 (spec-valid, manually constructed) +// array offset=0 but offsets[0] != 0 +TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinaryNonZeroFirst) { + auto type = TypeTraits::type_singleton(); using OffsetType = typename TypeTraits::OffsetType::c_type; + std::vector raw_offsets = {8, 8, 9, 10}; - std::string raw_data(8, 'x'); - raw_data += "xx"; + std::string raw_data(8, 'p'); + raw_data += "ab"; auto offsets_buf = Buffer::Wrap(raw_offsets.data(), raw_offsets.size()); - auto data_buf = - std::make_shared(reinterpret_cast(raw_data.data()), - static_cast(raw_data.size())); + auto data_buf = Buffer::Wrap(raw_data.data(), raw_data.size()); auto array_data = ArrayData::Make(type, /*length=*/3, {nullptr, offsets_buf, data_buf}, /*null_count=*/1, /*offset=*/0); std::vector validity_bytes = {0, 1, 1}; - ASSERT_OK_AND_ASSIGN( - array_data->buffers[0], - arrow::internal::BytesToBits(validity_bytes, arrow::default_memory_pool())); + ASSERT_OK_AND_ASSIGN(array_data->buffers[0], + internal::BytesToBits(validity_bytes, default_memory_pool())); auto arr = MakeArray(array_data); ASSERT_OK(arr->ValidateFull()); - ASSERT_OK_AND_ASSIGN(auto result_nonzero, + auto expected = ArrayFromJSON(type, R"([null, "a", "b"])"); + + auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); + ASSERT_OK_AND_ASSIGN(auto result_asa, CallFunction("if_else", {cond_asa, MakeNullScalar(type), arr})); - ASSERT_OK(result_nonzero.make_array()->ValidateFull()); - AssertArraysEqual(*expected, *result_nonzero.make_array(), true); + ASSERT_OK(result_asa.make_array()->ValidateFull()); + AssertArraysEqual(*expected, *result_asa.make_array(), true); + + auto cond_aas = ArrayFromJSON(boolean(), "[false, true, true]"); + ASSERT_OK_AND_ASSIGN(auto result_aas, + CallFunction("if_else", {cond_aas, arr, MakeNullScalar(type)})); + ASSERT_OK(result_aas.make_array()->ValidateFull()); + AssertArraysEqual(*expected, *result_aas.make_array(), true); } Result> MakeBinaryArrayWithData( From 9dd0db0a989a10985b41e7ab9cf6bb623b6ddf11 Mon Sep 17 00:00:00 2001 From: Ibraam-Ashraf <168275494+Ibraam-Ashraf@users.noreply.github.com> Date: Thu, 12 Mar 2026 08:47:55 +0200 Subject: [PATCH 10/10] GH-49410: [C++] Fix format --- cpp/src/arrow/compute/kernels/scalar_if_else_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc index 324c3f8a2db0..6fdcff8d9703 100644 --- a/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_if_else_test.cc @@ -648,7 +648,7 @@ TYPED_TEST(TestIfElseBaseBinary, IfElseBaseBinaryNonZeroFirst) { auto arr = MakeArray(array_data); ASSERT_OK(arr->ValidateFull()); auto expected = ArrayFromJSON(type, R"([null, "a", "b"])"); - + auto cond_asa = ArrayFromJSON(boolean(), "[true, false, false]"); ASSERT_OK_AND_ASSIGN(auto result_asa, CallFunction("if_else", {cond_asa, MakeNullScalar(type), arr}));