| 388 | template <typename Type> |
| 389 | struct ReplaceMaskChunked { |
| 390 | static Status Exec(KernelContext* ctx, const ExecBatch& batch, Datum* out) { |
| 391 | const Datum& mask = batch[1]; |
| 392 | const Datum& replacements = batch[2]; |
| 393 | |
| 394 | // TODO(wesm): these assertions that the arguments cannot be ChunkedArray |
| 395 | // should happen someplace more generic, not here |
| 396 | if (!mask.is_array() && !mask.is_scalar()) { |
| 397 | return Status::Invalid("Mask must be array or scalar, not ", batch[1].ToString()); |
| 398 | } |
| 399 | |
| 400 | if (!replacements.is_array() && !replacements.is_scalar()) { |
| 401 | return Status::Invalid("Replacements must be array or scalar, not ", |
| 402 | replacements.ToString()); |
| 403 | } |
| 404 | |
| 405 | const ChunkedArray& arr = *batch[0].chunked_array(); |
| 406 | |
| 407 | RETURN_NOT_OK(CheckReplaceMaskInputs(*arr.type(), arr.length(), GetExecValue(mask), |
| 408 | *replacements.type(), replacements.length(), |
| 409 | replacements.is_arraylike())); |
| 410 | |
| 411 | ExecValue replacements_val = GetExecValue(replacements); |
| 412 | |
| 413 | // Chunked array |
| 414 | ArrayVector output_chunks; |
| 415 | output_chunks.reserve(arr.num_chunks()); |
| 416 | |
| 417 | int64_t mask_offset = 0; |
| 418 | int64_t replacements_offset = 0; |
| 419 | for (const std::shared_ptr<Array>& chunk : arr.chunks()) { |
| 420 | if (chunk->length() == 0) continue; |
| 421 | // Allocate a new array |
| 422 | ExecResult chunk_result; |
| 423 | if (is_fixed_width(out->type()->id())) { |
| 424 | auto chunk_out = std::make_shared<ArrayData>(chunk->type(), chunk->length()); |
| 425 | chunk_out->buffers.resize(2); |
| 426 | ARROW_ASSIGN_OR_RAISE(chunk_out->buffers[0], |
| 427 | ctx->AllocateBitmap(chunk->length())); |
| 428 | const int64_t slot_width = out->type()->byte_width(); |
| 429 | ARROW_ASSIGN_OR_RAISE(chunk_out->buffers[1], |
| 430 | ctx->Allocate(slot_width * chunk->length())); |
| 431 | chunk_result.value = chunk_out; |
| 432 | } |
| 433 | if (batch[1].is_scalar()) { |
| 434 | ARROW_ASSIGN_OR_RAISE( |
| 435 | replacements_offset, |
| 436 | ReplaceMaskImpl<Type>::ExecScalarMask( |
| 437 | ctx, *chunk->data(), batch[1].scalar_as<BooleanScalar>(), |
| 438 | replacements_val, replacements_offset, &chunk_result)); |
| 439 | } else { |
| 440 | ARROW_ASSIGN_OR_RAISE(replacements_offset, |
| 441 | ReplaceMaskImpl<Type>::ExecArrayMask( |
| 442 | ctx, *chunk->data(), *batch[1].array(), mask_offset, |
| 443 | replacements_val, replacements_offset, &chunk_result)); |
| 444 | } |
| 445 | output_chunks.push_back(MakeArray(chunk_result.array_data())); |
| 446 | mask_offset += chunk->length(); |
| 447 | } |
nothing calls this directly
no test coverage detected