Repository: apache/arrow
File: cpp/src/arrow/acero/hash_join_node.cc (C++)

Code before:
          input_field_name + right_field_name_suffix, input_data_type, true /*nullable*/);
    }

    if (!match_found) {
      // insert right table field without suffix
      fields[left_size + i] =
          std::make_shared<Field>(input_field_name, input_data_type, true /*nullable*/);
    }
  }
  return std::make_shared<Schema>(std::move(fields));
}

Result<Expression> HashJoinSchema::BindFilter(Expression filter,
                                              const Schema& left_schema,
                                              const Schema& right_schema,
                                              ExecContext* exec_context) {
  if (filter.IsBound() || filter == literal(true)) {
    return filter;
  }
  // Step 1: Construct filter schema
  FieldVector fields;
  auto left_f_to_i =
      proj_maps[0].map(HashJoinProjection::FILTER, HashJoinProjection::INPUT);
  auto right_f_to_i =
      proj_maps[1].map(HashJoinProjection::FILTER, HashJoinProjection::INPUT);

  auto AppendFieldsInMap = [&fields](const SchemaProjectionMap& map,
                                     const Schema& schema) {
    for (int i = 0; i < map.num_cols; i++) {
      int input_idx = map.get(i);
      fields.push_back(schema.fields()[input_idx]);
    }
  };
  AppendFieldsInMap(left_f_to_i, left_schema);
  AppendFieldsInMap(right_f_to_i, right_schema);
  Schema filter_schema(fields);

  // Step 2: Rewrite expression to use filter schema
  auto left_i_to_f =
      proj_maps[0].map(HashJoinProjection::INPUT, HashJoinProjection::FILTER);
  auto right_i_to_f =
      proj_maps[1].map(HashJoinProjection::INPUT, HashJoinProjection::FILTER);
  filter = RewriteFilterToUseFilterSchema(left_f_to_i.num_cols, left_i_to_f, right_i_to_f,
                                          filter);

  // Step 3: Bind
  ARROW_ASSIGN_OR_RAISE(filter, filter.Bind(filter_schema, exec_context));
  if (filter.type()->id() != Type::BOOL) {
    return Status::TypeError("Filter expression must evaluate to bool, but ",
                             filter.ToString(), " evaluates to ",
                             filter.type()->ToString());

Review comment (suggestion):
`IsBound()` is implied by `literal(true)` so one check should suffice.

Code after:
          input_field_name + right_field_name_suffix, input_data_type, true /*nullable*/);
    }

    if (!match_found) {
      // insert right table field without suffix
      fields[left_size + i] =
          std::make_shared<Field>(input_field_name, input_data_type, true /*nullable*/);
    }
  }
  return std::make_shared<Schema>(std::move(fields));
}

Result<Expression> HashJoinSchema::BindFilter(Expression filter,
                                              const Schema& left_schema,
                                              const Schema& right_schema,
                                              ExecContext* exec_context) {
  auto ValidateFilterTypeAndReturn = [](Expression filter) -> Result<Expression> {
    if (filter.type()->id() != Type::BOOL) {
      return Status::TypeError("Filter expression must evaluate to bool, but ",
                               filter.ToString(), " evaluates to ",
                               filter.type()->ToString());
    }
    return filter;
  };

  if (filter.IsBound()) {
    return ValidateFilterTypeAndReturn(std::move(filter));
  }

  // Step 1: Construct filter schema
  FieldVector fields;
  auto left_f_to_i =
      proj_maps[0].map(HashJoinProjection::FILTER, HashJoinProjection::INPUT);
  auto right_f_to_i =
      proj_maps[1].map(HashJoinProjection::FILTER, HashJoinProjection::INPUT);

  auto AppendFieldsInMap = [&fields](const SchemaProjectionMap& map,
                                     const Schema& schema) {
    for (int i = 0; i < map.num_cols; i++) {
      int input_idx = map.get(i);
      fields.push_back(schema.fields()[input_idx]);
    }
  };
  AppendFieldsInMap(left_f_to_i, left_schema);
  AppendFieldsInMap(right_f_to_i, right_schema);
  Schema filter_schema(fields);

  // Step 2: Rewrite expression to use filter schema
  auto left_i_to_f =
      proj_maps[0].map(HashJoinProjection::INPUT, HashJoinProjection::FILTER);
  auto right_i_to_f =