You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "Periecle (via GitHub)" <gi...@apache.org> on 2026/06/12 12:37:16 UTC

[PR] [C++][Compute] Support view arrays in selection kernels [arrow]

Periecle opened a new pull request, #50164:
URL: https://github.com/apache/arrow/pull/50164

   ### Rationale for this change
   
     `binary_view` and `string_view` arrays were not fully supported by selection kernels. This also blocked dictionary decoding for dictionaries with view-type values.
   
     ### What changes are included in this PR?
   
     - Add take/filter support for `BINARY_VIEW` and `STRING_VIEW`.
     - Preserve variadic payload buffers when taking view arrays.
     - Allow dictionary decode/cast from dictionaries with view-type values.
     - Add coverage for take, filter, drop null, scatter, and dictionary decode paths.
   
     ### Are these changes tested?
   
     Yes.
   
     - `pre-commit run cpp --files <changed files>`
     - `cmake --build cpp/build --target arrow-compute-vector-selection-test`
     - Focused compute tests for cast, selection, drop null, and scatter view-array paths
   
     ### Are there any user-facing changes?
   
     Yes. `binary_view` and `string_view` arrays are now supported by the affected selection and dictionary decode paths.
     
     Partially addresses GH-39634


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on PR #50164:
URL: https://github.com/apache/arrow/pull/50164#issuecomment-4709770402

   Also @zanmato1984 might be interested as well.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "Periecle (via GitHub)" <gi...@apache.org>.
Periecle commented on PR #50164:
URL: https://github.com/apache/arrow/pull/50164#issuecomment-6107564082

   @pitrou  and @zanmato1984. I fixed pitrou comments, can you take another look into that?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #50164:
URL: https://github.com/apache/arrow/pull/50164#discussion_r3414409113


##########
cpp/src/arrow/compute/kernels/vector_selection_take_internal.cc:
##########
@@ -488,6 +489,123 @@ Status FixedWidthTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
 
 namespace {
 
+template <typename IndexCType>
+Status VarBinaryViewTakeTyped(const ArraySpan& values, const ArraySpan& indices,
+                              BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                              int64_t* valid_count) {
+  const auto* source_views = values.GetValues<BinaryViewType::c_type>(1);
+  const auto* index_values = indices.GetValues<IndexCType>(1);
+
+  const bool values_may_have_nulls = values.MayHaveNulls();
+  const bool indices_may_have_nulls = indices.MayHaveNulls();
+
+  if (!values_may_have_nulls && !indices_may_have_nulls) {
+    for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+      out_views[out_i] = source_views[static_cast<int64_t>(index_values[out_i])];
+    }
+    *valid_count = indices.length;
+    return Status::OK();
+  }
+
+  for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+    if (indices_may_have_nulls &&
+        !bit_util::GetBit(indices.buffers[0].data, indices.offset + out_i)) {
+      continue;
+    }
+
+    const int64_t source_i = static_cast<int64_t>(index_values[out_i]);
+    const bool source_valid =
+        !values_may_have_nulls ||
+        bit_util::GetBit(values.buffers[0].data, values.offset + source_i);
+    if (!source_valid) {
+      continue;
+    }
+
+    out_views[out_i] = source_views[source_i];
+    if (out_validity != nullptr) {
+      bit_util::SetBit(out_validity, out_i);
+    }
+    ++(*valid_count);
+  }
+
+  return Status::OK();
+}
+
+Status VarBinaryViewTakeDispatch(const ArraySpan& values, const ArraySpan& indices,
+                                 BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                                 int64_t* valid_count) {
+  switch (indices.type->byte_width()) {
+    case 1:
+      return VarBinaryViewTakeTyped<uint8_t>(values, indices, out_views, out_validity,
+                                             valid_count);
+    case 2:
+      return VarBinaryViewTakeTyped<uint16_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+    case 4:
+      return VarBinaryViewTakeTyped<uint32_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+    default:
+      DCHECK_EQ(indices.type->byte_width(), 8);
+      return VarBinaryViewTakeTyped<uint64_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+  }
+}
+
+}  // namespace
+
+Status VarBinaryViewTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult* out) {
+  const ArraySpan& values = batch[0].array;
+  const ArraySpan& indices = batch[1].array;
+
+  if (TakeState::Get(ctx).boundscheck) {
+    RETURN_NOT_OK(CheckIndexBounds(indices, values.length));
+  }
+
+  const int64_t out_length = indices.length;
+  const bool may_have_nulls = values.MayHaveNulls() || indices.MayHaveNulls();
+  const auto data_buffers = values.GetVariadicBuffers();
+
+  ARROW_ASSIGN_OR_RAISE(
+      auto views_buf,
+      AllocateBuffer(out_length * static_cast<int64_t>(sizeof(BinaryViewType::c_type)),
+                     ctx->memory_pool()));
+  auto* out_views = reinterpret_cast<BinaryViewType::c_type*>(views_buf->mutable_data());
+  if (may_have_nulls && views_buf->size() > 0) {
+    std::memset(out_views, 0, views_buf->size());
+  }
+
+  std::shared_ptr<Buffer> validity_buf;
+  uint8_t* out_validity = nullptr;
+  if (may_have_nulls) {
+    ARROW_ASSIGN_OR_RAISE(validity_buf,
+                          AllocateEmptyBitmap(out_length, ctx->memory_pool()));
+    if (validity_buf->size() > 0) {
+      std::memset(validity_buf->mutable_data(), 0, validity_buf->size());
+    }

Review Comment:
   `AllocateEmptyBitmap` should ensure that the bitmap is already zero-filled, IIRC.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #50164:
URL: https://github.com/apache/arrow/pull/50164#discussion_r3414439819


##########
cpp/src/arrow/compute/kernels/vector_selection_take_internal.cc:
##########
@@ -488,6 +489,123 @@ Status FixedWidthTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
 
 namespace {
 
+template <typename IndexCType>
+Status VarBinaryViewTakeTyped(const ArraySpan& values, const ArraySpan& indices,
+                              BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                              int64_t* valid_count) {
+  const auto* source_views = values.GetValues<BinaryViewType::c_type>(1);
+  const auto* index_values = indices.GetValues<IndexCType>(1);
+
+  const bool values_may_have_nulls = values.MayHaveNulls();
+  const bool indices_may_have_nulls = indices.MayHaveNulls();
+
+  if (!values_may_have_nulls && !indices_may_have_nulls) {
+    for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+      out_views[out_i] = source_views[static_cast<int64_t>(index_values[out_i])];
+    }
+    *valid_count = indices.length;
+    return Status::OK();
+  }
+
+  for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+    if (indices_may_have_nulls &&
+        !bit_util::GetBit(indices.buffers[0].data, indices.offset + out_i)) {
+      continue;
+    }
+
+    const int64_t source_i = static_cast<int64_t>(index_values[out_i]);
+    const bool source_valid =
+        !values_may_have_nulls ||
+        bit_util::GetBit(values.buffers[0].data, values.offset + source_i);
+    if (!source_valid) {
+      continue;
+    }
+
+    out_views[out_i] = source_views[source_i];
+    if (out_validity != nullptr) {
+      bit_util::SetBit(out_validity, out_i);
+    }

Review Comment:
   `OptionalBitmapAnd` would probably be much more efficient that settings output validity bits individually.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #50164:
URL: https://github.com/apache/arrow/pull/50164#discussion_r3414439819


##########
cpp/src/arrow/compute/kernels/vector_selection_take_internal.cc:
##########
@@ -488,6 +489,123 @@ Status FixedWidthTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
 
 namespace {
 
+template <typename IndexCType>
+Status VarBinaryViewTakeTyped(const ArraySpan& values, const ArraySpan& indices,
+                              BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                              int64_t* valid_count) {
+  const auto* source_views = values.GetValues<BinaryViewType::c_type>(1);
+  const auto* index_values = indices.GetValues<IndexCType>(1);
+
+  const bool values_may_have_nulls = values.MayHaveNulls();
+  const bool indices_may_have_nulls = indices.MayHaveNulls();
+
+  if (!values_may_have_nulls && !indices_may_have_nulls) {
+    for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+      out_views[out_i] = source_views[static_cast<int64_t>(index_values[out_i])];
+    }
+    *valid_count = indices.length;
+    return Status::OK();
+  }
+
+  for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+    if (indices_may_have_nulls &&
+        !bit_util::GetBit(indices.buffers[0].data, indices.offset + out_i)) {
+      continue;
+    }
+
+    const int64_t source_i = static_cast<int64_t>(index_values[out_i]);
+    const bool source_valid =
+        !values_may_have_nulls ||
+        bit_util::GetBit(values.buffers[0].data, values.offset + source_i);
+    if (!source_valid) {
+      continue;
+    }
+
+    out_views[out_i] = source_views[source_i];
+    if (out_validity != nullptr) {
+      bit_util::SetBit(out_validity, out_i);
+    }

Review Comment:
   `OptionalBitmapAnd` would probably be much more efficient than settings output validity bits individually.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #50164:
URL: https://github.com/apache/arrow/pull/50164#issuecomment-4691319474

   <!--
     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.
   -->
   
   Thanks for opening a pull request!
   
   If this is not a [minor PR](https://github.com/apache/arrow/blob/main/CONTRIBUTING.md#Minor-Fixes). Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose
   
   Opening GitHub issues ahead of time contributes to the [Openness](http://theapacheway.com/open/#:~:text=Openness%20allows%20new%20users%20the,must%20happen%20in%20the%20open.) of the Apache Arrow project.
   
   Then could you also rename the pull request title in the following format?
   
       GH-${GITHUB_ISSUE_ID}: [${COMPONENT}] ${SUMMARY}
   
   or
   
       MINOR: [${COMPONENT}] ${SUMMARY}
   
   See also:
   
     * [Other pull requests](https://github.com/apache/arrow/pulls/)
     * [Contribution Guidelines - Contributing Overview](https://arrow.apache.org/docs/developers/overview.html)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "pitrou (via GitHub)" <gi...@apache.org>.
pitrou commented on code in PR #50164:
URL: https://github.com/apache/arrow/pull/50164#discussion_r3414394862


##########
cpp/src/arrow/compute/kernels/vector_selection_take_internal.cc:
##########
@@ -488,6 +489,123 @@ Status FixedWidthTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
 
 namespace {
 
+template <typename IndexCType>
+Status VarBinaryViewTakeTyped(const ArraySpan& values, const ArraySpan& indices,
+                              BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                              int64_t* valid_count) {
+  const auto* source_views = values.GetValues<BinaryViewType::c_type>(1);
+  const auto* index_values = indices.GetValues<IndexCType>(1);
+
+  const bool values_may_have_nulls = values.MayHaveNulls();
+  const bool indices_may_have_nulls = indices.MayHaveNulls();
+
+  if (!values_may_have_nulls && !indices_may_have_nulls) {
+    for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+      out_views[out_i] = source_views[static_cast<int64_t>(index_values[out_i])];
+    }
+    *valid_count = indices.length;
+    return Status::OK();
+  }
+
+  for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+    if (indices_may_have_nulls &&
+        !bit_util::GetBit(indices.buffers[0].data, indices.offset + out_i)) {

Review Comment:
   I think you can use `VisitTwoBitBlocksVoid` which will be more efficient than individual calls to `GetBit` for each item.



##########
cpp/src/arrow/compute/kernels/vector_selection_take_internal.cc:
##########
@@ -488,6 +489,123 @@ Status FixedWidthTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult*
 
 namespace {
 
+template <typename IndexCType>
+Status VarBinaryViewTakeTyped(const ArraySpan& values, const ArraySpan& indices,
+                              BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                              int64_t* valid_count) {
+  const auto* source_views = values.GetValues<BinaryViewType::c_type>(1);
+  const auto* index_values = indices.GetValues<IndexCType>(1);
+
+  const bool values_may_have_nulls = values.MayHaveNulls();
+  const bool indices_may_have_nulls = indices.MayHaveNulls();
+
+  if (!values_may_have_nulls && !indices_may_have_nulls) {
+    for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+      out_views[out_i] = source_views[static_cast<int64_t>(index_values[out_i])];
+    }
+    *valid_count = indices.length;
+    return Status::OK();
+  }
+
+  for (int64_t out_i = 0; out_i < indices.length; ++out_i) {
+    if (indices_may_have_nulls &&
+        !bit_util::GetBit(indices.buffers[0].data, indices.offset + out_i)) {
+      continue;
+    }
+
+    const int64_t source_i = static_cast<int64_t>(index_values[out_i]);
+    const bool source_valid =
+        !values_may_have_nulls ||
+        bit_util::GetBit(values.buffers[0].data, values.offset + source_i);
+    if (!source_valid) {
+      continue;
+    }
+
+    out_views[out_i] = source_views[source_i];
+    if (out_validity != nullptr) {
+      bit_util::SetBit(out_validity, out_i);
+    }
+    ++(*valid_count);
+  }
+
+  return Status::OK();
+}
+
+Status VarBinaryViewTakeDispatch(const ArraySpan& values, const ArraySpan& indices,
+                                 BinaryViewType::c_type* out_views, uint8_t* out_validity,
+                                 int64_t* valid_count) {
+  switch (indices.type->byte_width()) {
+    case 1:
+      return VarBinaryViewTakeTyped<uint8_t>(values, indices, out_views, out_validity,
+                                             valid_count);
+    case 2:
+      return VarBinaryViewTakeTyped<uint16_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+    case 4:
+      return VarBinaryViewTakeTyped<uint32_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+    default:
+      DCHECK_EQ(indices.type->byte_width(), 8);
+      return VarBinaryViewTakeTyped<uint64_t>(values, indices, out_views, out_validity,
+                                              valid_count);
+  }
+}
+
+}  // namespace
+
+Status VarBinaryViewTakeExec(KernelContext* ctx, const ExecSpan& batch, ExecResult* out) {
+  const ArraySpan& values = batch[0].array;
+  const ArraySpan& indices = batch[1].array;
+
+  if (TakeState::Get(ctx).boundscheck) {
+    RETURN_NOT_OK(CheckIndexBounds(indices, values.length));
+  }
+
+  const int64_t out_length = indices.length;
+  const bool may_have_nulls = values.MayHaveNulls() || indices.MayHaveNulls();
+  const auto data_buffers = values.GetVariadicBuffers();
+
+  ARROW_ASSIGN_OR_RAISE(
+      auto views_buf,
+      AllocateBuffer(out_length * static_cast<int64_t>(sizeof(BinaryViewType::c_type)),
+                     ctx->memory_pool()));
+  auto* out_views = reinterpret_cast<BinaryViewType::c_type*>(views_buf->mutable_data());
+  if (may_have_nulls && views_buf->size() > 0) {
+    std::memset(out_views, 0, views_buf->size());
+  }
+
+  std::shared_ptr<Buffer> validity_buf;
+  uint8_t* out_validity = nullptr;
+  if (may_have_nulls) {
+    ARROW_ASSIGN_OR_RAISE(validity_buf,
+                          AllocateEmptyBitmap(out_length, ctx->memory_pool()));
+    if (validity_buf->size() > 0) {
+      std::memset(validity_buf->mutable_data(), 0, validity_buf->size());
+    }
+    out_validity = validity_buf->mutable_data();
+  }
+
+  int64_t valid_count = 0;
+  RETURN_NOT_OK(
+      VarBinaryViewTakeDispatch(values, indices, out_views, out_validity, &valid_count));
+
+  const int64_t null_count = out_length - valid_count;
+  BufferVector buffers;
+  buffers.reserve(2 + data_buffers.size());
+  buffers.push_back(null_count == 0 ? nullptr : std::move(validity_buf));
+  buffers.push_back(std::move(views_buf));
+
+  for (const auto& data_buffer : data_buffers) {
+    buffers.push_back(data_buffer);
+  }

Review Comment:
   This is going to keep alive all data buffers from the input, but it would be nice to only keep alive those that are actually used by the output.
   
   Depending on the outcome from https://github.com/apache/arrow/issues/50172 we may replace the unused buffers with NULL slots, or with zero-sized buffers (or we can remap the buffer indices, which is going to be more costly).



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] GH-43010: [C++][Compute] Support view arrays in selection kernels [arrow]

Posted by "Periecle (via GitHub)" <gi...@apache.org>.
Periecle commented on PR #50164:
URL: https://github.com/apache/arrow/pull/50164#issuecomment-4692538577

   @github-actions crossbow submit -g cpp


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org