| 813 | |
| 814 | template <typename UnionArrayType> |
| 815 | Status WriteUnionBatch(const Array& array, int64_t orc_offset, |
| 816 | liborc::ColumnVectorBatch* column_vector_batch) { |
| 817 | auto union_array = checked_cast<const UnionArrayType*>(&array); |
| 818 | auto batch = checked_cast<liborc::UnionVectorBatch*>(column_vector_batch); |
| 819 | |
| 820 | // Union array itself does not have nulls. |
| 821 | batch->hasNulls = false; |
| 822 | |
| 823 | int64_t arrow_length = array.length(); |
| 824 | int64_t running_arrow_offset = 0, running_orc_offset = orc_offset; |
| 825 | |
| 826 | for (; running_arrow_offset < arrow_length; |
| 827 | running_orc_offset++, running_arrow_offset++) { |
| 828 | auto child_id = union_array->child_id(running_arrow_offset); |
| 829 | batch->tags[running_orc_offset] = static_cast<unsigned char>(child_id); |
| 830 | batch->notNull[running_orc_offset] = true; |
| 831 | |
| 832 | // Orc union batch is dense, so we need to find the previous row that has the same |
| 833 | // type code (or child_id) to calculate the offset. |
| 834 | batch->offsets[running_orc_offset] = 0; |
| 835 | for (int64_t row = running_orc_offset - 1; row >= 0; row--) { |
| 836 | if (batch->tags[row] == child_id) { |
| 837 | batch->offsets[running_orc_offset] = batch->offsets[row] + 1; |
| 838 | break; |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | // Fill child batch. |
| 843 | liborc::ColumnVectorBatch* child_batch = batch->children[child_id]; |
| 844 | int64_t child_array_orc_offset = batch->offsets[running_orc_offset]; |
| 845 | int64_t child_array_arrow_offset; |
| 846 | |
| 847 | if constexpr (std::is_same_v<UnionArrayType, DenseUnionArray>) { |
| 848 | child_array_arrow_offset = union_array->value_offset(running_arrow_offset); |
| 849 | } else { |
| 850 | static_assert(std::is_same_v<UnionArrayType, SparseUnionArray>); |
| 851 | child_array_arrow_offset = running_arrow_offset; |
| 852 | } |
| 853 | child_batch->resize(child_array_orc_offset + 1); |
| 854 | |
| 855 | std::shared_ptr<Array> child_array = union_array->field(child_id); |
| 856 | RETURN_NOT_OK(WriteBatch(*(child_array->Slice(child_array_arrow_offset, 1)), |
| 857 | child_array_orc_offset, child_batch)); |
| 858 | } |
| 859 | |
| 860 | return Status::OK(); |
| 861 | } |
| 862 | |
| 863 | Status WriteBatch(const Array& array, int64_t orc_offset, |
| 864 | liborc::ColumnVectorBatch* column_vector_batch) { |
nothing calls this directly
no test coverage detected