| 667 | } |
| 668 | |
| 669 | arrow::Status CallRScalarUDF(arrow::compute::KernelContext* context, |
| 670 | const arrow::compute::ExecSpan& span, |
| 671 | arrow::compute::ExecResult* result) { |
| 672 | if (result->is_array_span()) { |
| 673 | return arrow::Status::NotImplemented("ArraySpan result from R scalar UDF"); |
| 674 | } |
| 675 | |
| 676 | return SafeCallIntoRVoid( |
| 677 | [&]() { |
| 678 | auto kernel = |
| 679 | reinterpret_cast<const arrow::compute::ScalarKernel*>(context->kernel()); |
| 680 | auto state = std::dynamic_pointer_cast<RScalarUDFKernelState>(kernel->data); |
| 681 | |
| 682 | cpp11::writable::list args_sexp(span.num_values()); |
| 683 | |
| 684 | for (int i = 0; i < span.num_values(); i++) { |
| 685 | const arrow::compute::ExecValue& exec_val = span[i]; |
| 686 | if (exec_val.is_array()) { |
| 687 | args_sexp[i] = cpp11::to_r6<arrow::Array>(exec_val.array.ToArray()); |
| 688 | } else if (exec_val.is_scalar()) { |
| 689 | args_sexp[i] = cpp11::to_r6<arrow::Scalar>(exec_val.scalar->GetSharedPtr()); |
| 690 | } |
| 691 | } |
| 692 | |
| 693 | cpp11::sexp batch_length_sexp = cpp11::as_sexp(static_cast<double>(span.length)); |
| 694 | |
| 695 | std::shared_ptr<arrow::DataType> output_type = result->type()->GetSharedPtr(); |
| 696 | cpp11::sexp output_type_sexp = cpp11::to_r6<arrow::DataType>(output_type); |
| 697 | cpp11::writable::list udf_context = {batch_length_sexp, output_type_sexp}; |
| 698 | udf_context.names() = {"batch_length", "output_type"}; |
| 699 | |
| 700 | cpp11::sexp func_result_sexp = |
| 701 | cpp11::function(state->exec_func_)(udf_context, args_sexp); |
| 702 | |
| 703 | if (Rf_inherits(func_result_sexp, "Array")) { |
| 704 | auto array = cpp11::as_cpp<std::shared_ptr<arrow::Array>>(func_result_sexp); |
| 705 | |
| 706 | // Error for an Array result of the wrong type |
| 707 | if (!result->type()->Equals(array->type())) { |
| 708 | return cpp11::stop( |
| 709 | "Expected return Array or Scalar with type '%s' from user-defined " |
| 710 | "function but got Array with type '%s'", |
| 711 | result->type()->ToString().c_str(), array->type()->ToString().c_str()); |
| 712 | } |
| 713 | |
| 714 | result->value = std::move(array->data()); |
| 715 | } else if (Rf_inherits(func_result_sexp, "Scalar")) { |
| 716 | auto scalar = cpp11::as_cpp<std::shared_ptr<arrow::Scalar>>(func_result_sexp); |
| 717 | |
| 718 | // handle a Scalar result of the wrong type |
| 719 | if (!result->type()->Equals(scalar->type)) { |
| 720 | return cpp11::stop( |
| 721 | "Expected return Array or Scalar with type '%s' from user-defined " |
| 722 | "function but got Scalar with type '%s'", |
| 723 | result->type()->ToString().c_str(), scalar->type->ToString().c_str()); |
| 724 | } |
| 725 | |
| 726 | auto array = ValueOrStop( |
nothing calls this directly
no test coverage detected