| 644 | } |
| 645 | |
| 646 | Result<ExecBatch> MakeExecBatch(const Schema& full_schema, const Datum& partial, |
| 647 | Expression guarantee) { |
| 648 | ExecBatch out; |
| 649 | |
| 650 | if (partial.kind() == Datum::RECORD_BATCH) { |
| 651 | const auto& partial_batch = *partial.record_batch(); |
| 652 | out.guarantee = std::move(guarantee); |
| 653 | out.length = partial_batch.num_rows(); |
| 654 | |
| 655 | ARROW_ASSIGN_OR_RAISE(auto known_field_values, |
| 656 | ExtractKnownFieldValues(out.guarantee)); |
| 657 | |
| 658 | for (const auto& field : full_schema.fields()) { |
| 659 | auto field_ref = FieldRef(field->name()); |
| 660 | |
| 661 | // If we know what the value must be from the guarantee, prefer to use that value |
| 662 | // than the data from the record batch (if it exists at all -- probably it doesn't), |
| 663 | // because this way it will be a scalar. |
| 664 | auto known_field_value = known_field_values.map.find(field_ref); |
| 665 | if (known_field_value != known_field_values.map.end()) { |
| 666 | out.values.emplace_back(known_field_value->second); |
| 667 | continue; |
| 668 | } |
| 669 | |
| 670 | ARROW_ASSIGN_OR_RAISE(auto column, field_ref.GetOneOrNone(partial_batch)); |
| 671 | if (column) { |
| 672 | if (!column->type()->Equals(field->type())) { |
| 673 | // Referenced field was present but didn't have the expected type. |
| 674 | // This *should* be handled by readers, and will just be an error in the future. |
| 675 | ARROW_ASSIGN_OR_RAISE( |
| 676 | auto converted, |
| 677 | compute::Cast(column, field->type(), compute::CastOptions::Safe())); |
| 678 | column = converted.make_array(); |
| 679 | } |
| 680 | out.values.emplace_back(std::move(column)); |
| 681 | } else { |
| 682 | out.values.emplace_back(MakeNullScalar(field->type())); |
| 683 | } |
| 684 | } |
| 685 | return out; |
| 686 | } |
| 687 | |
| 688 | // wasteful but useful for testing: |
| 689 | const auto& partial_type = partial.type(); |
| 690 | if (partial_type && partial_type->id() == Type::STRUCT) { |
| 691 | if (partial.is_array()) { |
| 692 | ARROW_ASSIGN_OR_RAISE(auto partial_batch, |
| 693 | RecordBatch::FromStructArray(partial.make_array())); |
| 694 | |
| 695 | return MakeExecBatch(full_schema, partial_batch, std::move(guarantee)); |
| 696 | } |
| 697 | |
| 698 | if (partial.is_scalar()) { |
| 699 | ARROW_ASSIGN_OR_RAISE(auto partial_array, |
| 700 | MakeArrayFromScalar(*partial.scalar(), 1)); |
| 701 | ARROW_ASSIGN_OR_RAISE( |
| 702 | auto out, MakeExecBatch(full_schema, partial_array, std::move(guarantee))); |
| 703 | |