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

Function BindNonRecursive

cpp/src/arrow/compute/expression.cc:539–603  ·  view source on GitHub ↗

Produce a bound Expression from unbound Call and bound arguments.

Source from the content-addressed store, hash-verified

537
538// Produce a bound Expression from unbound Call and bound arguments.
539Result<Expression> BindNonRecursive(Expression::Call call, bool insert_implicit_casts,
540 compute::ExecContext* exec_context) {
541 DCHECK(std::all_of(call.arguments.begin(), call.arguments.end(),
542 [](const Expression& argument) { return argument.IsBound(); }));
543
544 std::vector<TypeHolder> types = GetTypes(call.arguments);
545 ARROW_ASSIGN_OR_RAISE(call.function, GetFunction(call, exec_context));
546
547 // First try and bind exactly
548 Result<const Kernel*> maybe_exact_match = call.function->DispatchExact(types);
549 if (maybe_exact_match.ok()) {
550 call.kernel = *maybe_exact_match;
551 } else {
552 if (!insert_implicit_casts) {
553 return maybe_exact_match.status();
554 }
555
556 // If exact binding fails, and we are allowed to cast, then prefer casting literals
557 // first. Since DispatchBest generally prefers up-casting the best way to do this is
558 // first down-cast the literals as much as possible
559 types = GetTypesWithSmallestLiteralRepresentation(call.arguments);
560 ARROW_ASSIGN_OR_RAISE(call.kernel, call.function->DispatchBest(&types));
561
562 for (size_t i = 0; i < types.size(); ++i) {
563 if (types[i] == call.arguments[i].type()) continue;
564
565 if (const Datum* lit = call.arguments[i].literal()) {
566 ARROW_ASSIGN_OR_RAISE(Datum new_lit,
567 compute::Cast(*lit, types[i].GetSharedPtr()));
568 call.arguments[i] = literal(std::move(new_lit));
569 continue;
570 }
571
572 // construct an implicit cast Expression with which to replace this argument
573 Expression::Call implicit_cast;
574 implicit_cast.function_name = "cast";
575 implicit_cast.arguments = {std::move(call.arguments[i])};
576
577 // TODO(wesm): Use TypeHolder in options
578 implicit_cast.options = std::make_shared<compute::CastOptions>(
579 compute::CastOptions::Safe(types[i].GetSharedPtr()));
580
581 ARROW_ASSIGN_OR_RAISE(
582 call.arguments[i],
583 BindNonRecursive(std::move(implicit_cast),
584 /*insert_implicit_casts=*/false, exec_context));
585 }
586 }
587
588 compute::KernelContext kernel_context(exec_context, call.kernel);
589 if (call.kernel->init) {
590 const FunctionOptions* options =
591 call.options ? call.options.get() : call.function->default_options();
592 ARROW_ASSIGN_OR_RAISE(
593 call.kernel_state,
594 call.kernel->init(&kernel_context, {call.kernel, types, options}));
595
596 kernel_context.SetState(call.kernel_state.get());

Callers 4

BindImplFunction · 0.85
HandleInconsistentTypesFunction · 0.85
CanonicalizeFunction · 0.85
simplified_toMethod · 0.85

Calls 15

SafeFunction · 0.85
IsBoundMethod · 0.80
literalMethod · 0.80
GetTypesFunction · 0.70
literalFunction · 0.70
ExpressionClass · 0.70
ARROW_ASSIGN_OR_RAISEFunction · 0.50
beginMethod · 0.45
endMethod · 0.45
DispatchExactMethod · 0.45
okMethod · 0.45

Tested by

no test coverage detected