lidavidm commented on a change in pull request #10806:
URL: https://github.com/apache/arrow/pull/10806#discussion_r691592498



##########
File path: cpp/src/arrow/compute/kernels/scalar_if_else.cc
##########
@@ -1413,6 +1417,588 @@ struct CaseWhenFunctor<NullType> {
   }
 };
 
+static Status ExecVarWidthScalarCaseWhen(KernelContext* ctx, const ExecBatch& 
batch,
+                                         Datum* out) {
+  const auto& conds = checked_cast<const 
StructScalar&>(*batch.values[0].scalar());
+  Datum result;
+  for (size_t i = 0; i < batch.values.size() - 1; i++) {
+    if (i < conds.value.size()) {
+      const Scalar& cond = *conds.value[i];
+      if (cond.is_valid && internal::UnboxScalar<BooleanType>::Unbox(cond)) {
+        result = batch[i + 1];
+        break;
+      }
+    } else {
+      // ELSE clause
+      result = batch[i + 1];
+      break;
+    }
+  }
+  if (out->is_scalar()) {
+    *out = result.is_scalar() ? result.scalar() : MakeNullScalar(out->type());
+    return Status::OK();
+  }
+  ArrayData* output = out->mutable_array();
+  if (!result.is_value()) {
+    // All conditions false, no 'else' argument
+    ARROW_ASSIGN_OR_RAISE(
+        auto array, MakeArrayOfNull(output->type, batch.length, 
ctx->memory_pool()));
+    *output = *array->data();
+  } else if (result.is_scalar()) {
+    ARROW_ASSIGN_OR_RAISE(auto array, MakeArrayFromScalar(*result.scalar(), 
batch.length,
+                                                          ctx->memory_pool()));
+    *output = *array->data();
+  } else {
+    *output = *result.array();
+  }
+  return Status::OK();
+}
+
+template <typename ReserveData, typename AppendScalar, typename AppendArray>
+static Status ExecVarWidthArrayCaseWhen(KernelContext* ctx, const ExecBatch& 
batch,
+                                        Datum* out, ReserveData reserve_data,
+                                        AppendScalar append_scalar,
+                                        AppendArray append_array) {
+  const auto& conds_array = *batch.values[0].array();
+  ArrayData* output = out->mutable_array();
+  const bool have_else_arg =
+      static_cast<size_t>(conds_array.type->num_fields()) < 
(batch.values.size() - 1);
+  std::unique_ptr<ArrayBuilder> raw_builder;
+  RETURN_NOT_OK(MakeBuilder(ctx->memory_pool(), out->type(), &raw_builder));
+  RETURN_NOT_OK(raw_builder->Reserve(batch.length));
+  RETURN_NOT_OK(reserve_data(raw_builder.get()));
+
+  for (int64_t row = 0; row < batch.length; row++) {
+    int64_t selected = have_else_arg ? 
static_cast<int64_t>(batch.values.size() - 1) : -1;
+    for (int64_t arg = 0; static_cast<size_t>(arg) < 
conds_array.child_data.size();
+         arg++) {
+      const ArrayData& cond_array = *conds_array.child_data[arg];
+      if ((!cond_array.buffers[0] ||
+           BitUtil::GetBit(cond_array.buffers[0]->data(),
+                           conds_array.offset + cond_array.offset + row)) &&
+          BitUtil::GetBit(cond_array.buffers[1]->data(),
+                          conds_array.offset + cond_array.offset + row)) {
+        selected = arg + 1;
+        break;
+      }
+    }
+    if (selected < 0) {
+      RETURN_NOT_OK(raw_builder->AppendNull());

Review comment:
       We'd have to make it public virtual instead of protected nonvirtual as 
it currently is. (It's public in concrete classes but not in the base class, so 
we could also template the function on the builder type…)




-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to