MCPcopy Create free account
hub / github.com/apache/arrow / CallTabularFunction

Function CallTabularFunction

python/pyarrow/src/arrow/python/udf.cc:646–704  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

644}
645
646Result<std::shared_ptr<RecordBatchReader>> CallTabularFunction(
647 const std::string& func_name, const std::vector<Datum>& args,
648 compute::FunctionRegistry* registry) {
649 if (args.size() != 0) {
650 return Status::NotImplemented("non-empty arguments to tabular function");
651 }
652 if (registry == NULLPTR) {
653 registry = compute::GetFunctionRegistry();
654 }
655 ARROW_ASSIGN_OR_RAISE(auto func, registry->GetFunction(func_name));
656 if (func->kind() != compute::Function::SCALAR) {
657 return Status::Invalid("tabular function of non-scalar kind");
658 }
659 auto arity = func->arity();
660 if (arity.num_args != 0 || arity.is_varargs) {
661 return Status::NotImplemented("tabular function of non-null arity");
662 }
663 auto kernels =
664 arrow::internal::checked_pointer_cast<compute::ScalarFunction>(func)->kernels();
665 if (kernels.size() != 1) {
666 return Status::NotImplemented("tabular function with non-single kernel");
667 }
668 const compute::ScalarKernel* kernel = kernels[0];
669 auto out_type = kernel->signature->out_type();
670 if (out_type.kind() != compute::OutputType::FIXED) {
671 return Status::Invalid("tabular kernel of non-fixed kind");
672 }
673 auto datatype = out_type.type();
674 if (datatype->id() != Type::type::STRUCT) {
675 return Status::Invalid("tabular kernel with non-struct output");
676 }
677 auto struct_type = arrow::internal::checked_cast<StructType*>(datatype.get());
678 auto schema = ::arrow::schema(struct_type->fields());
679 std::vector<TypeHolder> in_types;
680 ARROW_ASSIGN_OR_RAISE(auto func_exec,
681 GetFunctionExecutor(func_name, in_types, NULLPTR, registry));
682 auto next_func = [schema, func_exec = std::move(
683 func_exec)]() -> Result<std::shared_ptr<RecordBatch>> {
684 std::vector<Datum> args;
685 // passed_length of -1 or 0 with args.size() of 0 leads to an empty ExecSpanIterator
686 // in exec.cc and to never invoking the source function, so 1 is passed instead
687 // TODO: GH-33612: Support batch size in user-defined tabular functions
688 ARROW_ASSIGN_OR_RAISE(auto datum, func_exec->Execute(args, /*passed_length=*/1));
689 if (!datum.is_array()) {
690 return Status::Invalid("UDF result of non-array kind");
691 }
692 std::shared_ptr<Array> array = datum.make_array();
693 if (array->length() == 0) {
694 return IterationTraits<std::shared_ptr<RecordBatch>>::End();
695 }
696 ARROW_ASSIGN_OR_RAISE(auto batch, RecordBatch::FromStructArray(std::move(array)));
697 if (!schema->Equals(batch->schema())) {
698 return Status::Invalid("UDF result with shape not conforming to schema");
699 }
700 return std::move(batch);
701 };
702 return RecordBatchReader::MakeFromIterator(MakeFunctionIterator(std::move(next_func)),
703 schema);

Callers

nothing calls this directly

Calls 15

GetFunctionRegistryFunction · 0.85
MakeFunctionIteratorFunction · 0.85
kernelsMethod · 0.80
is_arrayMethod · 0.80
make_arrayMethod · 0.80
NotImplementedFunction · 0.50
InvalidFunction · 0.50
schemaFunction · 0.50
EndFunction · 0.50
sizeMethod · 0.45
kindMethod · 0.45
out_typeMethod · 0.45

Tested by

no test coverage detected