From 61a32cc351dec508ae87e29b9607ca98e939d947 Mon Sep 17 00:00:00 2001 From: Alexander Taepper Date: Thu, 22 Oct 2026 11:00:05 +0200 Subject: [PATCH] fix extension array variadic buffer detection --- cpp/src/arrow/array/array_test.cc | 20 ++++++++++++++++++++ cpp/src/arrow/array/data.cc | 9 +++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index 2cdf94bfab95..55ac106e6907 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -1139,6 +1139,26 @@ TEST_F(TestArray, TestBinaryViewAppendArraySlice) { AssertArraysEqual(*src, *dst); } +// GH-54924: ArraySpan::HasVariadicBuffers must look through extension types. +TEST_F(TestArray, TestBinaryViewExtensionArraySpanRoundtrip) { + auto storage = ArrayFromJSON( + binary_view(), + R"([null, "short", "long string that is not inlined", "another somewhat long string"])"); + auto extension_type = binary_view_extension_type(); + auto extension_array = ExtensionType::WrapArray(extension_type, storage); + ASSERT_OK(extension_array->ValidateFull()); + + ArraySpan span(*extension_array->data()); + ASSERT_TRUE(span.HasVariadicBuffers()); + ASSERT_EQ(span.GetVariadicBuffers().size(), storage->data()->buffers.size() - 2); + + auto roundtripped = span.ToArray(); + ASSERT_OK(roundtripped->ValidateFull()); + AssertArraysEqual(*extension_array, *roundtripped); + ASSERT_EQ(roundtripped->data()->buffers.size(), + extension_array->data()->buffers.size()); +} + TEST_F(TestArray, ValidateBuffersPrimitive) { auto empty_buffer = std::make_shared(""); auto null_buffer = Buffer::FromString("\xff"); diff --git a/cpp/src/arrow/array/data.cc b/cpp/src/arrow/array/data.cc index edeb1c311906..5e34758c0bcc 100644 --- a/cpp/src/arrow/array/data.cc +++ b/cpp/src/arrow/array/data.cc @@ -321,7 +321,7 @@ void ArraySpan::SetMembers(const ArrayData& data) { this->buffers[i] = {}; } - if (type_id == Type::STRING_VIEW || type_id == Type::BINARY_VIEW) { + if (HasVariadicBuffers()) { // store the span of data buffers in the third buffer this->buffers[2] = internal::PackVariadicBuffers(std::span(data.buffers).subspan(2)); } @@ -687,7 +687,12 @@ std::span> ArraySpan::GetVariadicBuffers() const { } bool ArraySpan::HasVariadicBuffers() const { - return type->id() == Type::BINARY_VIEW || type->id() == Type::STRING_VIEW; + Type::type type_id = type->id(); + if (type_id == Type::EXTENSION) { + const auto* ext_type = checked_cast(type); + type_id = ext_type->storage_type()->id(); + } + return type_id == Type::BINARY_VIEW || type_id == Type::STRING_VIEW; } std::shared_ptr ArraySpan::ToArray() const {