This is an automated email from the ASF dual-hosted git repository.
pitrou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new f9eee02fd19 GH-54924: [C++] HasVariadicBuffers should respect
extension types (#54925)
f9eee02fd19 is described below
commit f9eee02fd19564c12ae58999fba6ac731be80836
Author: Alexander Taepper <[email protected]>
AuthorDate: Mon Oct 26 16:10:07 2026 +0100
GH-54924: [C++] HasVariadicBuffers should respect extension types (#54925)
### Rationale for this change
This fixes #54924. An extension array would not round-trip correctly
through ArraySpans as a test demonstrates.
### What changes are included in this PR?
This fixes the `HasVariadicBuffers` implementation to correctly handle
extension types. A test demonstrating the fix is also included.
The fix follows the implementation of `ArraySpan::SetMembers`, where the
same additional case for extension types is included
### Are these changes tested?
Yes. By the existing test suite plus an additional test.
### Are there any user-facing changes?
None other than the bug fix.
### Was AI used for this PR?
In accordance to the [AI generation
guidelines](https://arrow.apache.org/docs/dev/developers/overview.html#ai-generated-code),
please disclose below whether and how AI was used in this PR.
**PR code and description written by:**
- [X] Human
- [ ] AI
**Reviewed before submission by:**
- [X] Human
- [X] AI
- [ ] Not reviewed
An LLM suggested the second fix for
```
if (type_id == Type::STRING_VIEW || type_id == Type::BINARY_VIEW) {
```
in `ArraySpan::SetMembers`, which does look correct to me.
* GitHub Issue: #54924
Authored-by: Alexander Taepper <[email protected]>
Signed-off-by: Antoine Pitrou <[email protected]>
---
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 2cdf94bfab9..55ac106e690 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<Buffer>("");
auto null_buffer = Buffer::FromString("\xff");
diff --git a/cpp/src/arrow/array/data.cc b/cpp/src/arrow/array/data.cc
index edeb1c31190..5e34758c0bc 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<const std::shared_ptr<Buffer>>
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<const ExtensionType*>(type);
+ type_id = ext_type->storage_type()->id();
+ }
+ return type_id == Type::BINARY_VIEW || type_id == Type::STRING_VIEW;
}
std::shared_ptr<Array> ArraySpan::ToArray() const {