| 852 | // File reader implementation |
| 853 | |
| 854 | Status GetReader(const SchemaField& field, const std::shared_ptr<Field>& arrow_field, |
| 855 | const std::shared_ptr<ReaderContext>& ctx, |
| 856 | std::unique_ptr<ColumnReaderImpl>* out) { |
| 857 | BEGIN_PARQUET_CATCH_EXCEPTIONS |
| 858 | |
| 859 | auto type_id = arrow_field->type()->id(); |
| 860 | |
| 861 | if (type_id == ::arrow::Type::EXTENSION) { |
| 862 | auto storage_field = arrow_field->WithType( |
| 863 | checked_cast<const ExtensionType&>(*arrow_field->type()).storage_type()); |
| 864 | RETURN_NOT_OK(GetReader(field, storage_field, ctx, out)); |
| 865 | if (*out) { |
| 866 | auto storage_type = (*out)->field()->type(); |
| 867 | if (!storage_type->Equals(storage_field->type())) { |
| 868 | return Status::Invalid( |
| 869 | "Due to column pruning only part of an extension's storage type was loaded. " |
| 870 | "An extension type cannot be created without all of its fields"); |
| 871 | } |
| 872 | *out = std::make_unique<ExtensionReader>(arrow_field, std::move(*out)); |
| 873 | } |
| 874 | return Status::OK(); |
| 875 | } |
| 876 | |
| 877 | if (field.children.size() == 0) { |
| 878 | if (!field.is_leaf()) { |
| 879 | return Status::Invalid("Parquet non-leaf node has no children"); |
| 880 | } |
| 881 | if (!ctx->IncludesLeaf(field.column_index)) { |
| 882 | *out = nullptr; |
| 883 | return Status::OK(); |
| 884 | } |
| 885 | std::unique_ptr<FileColumnIterator> input( |
| 886 | ctx->iterator_factory(field.column_index, ctx->reader)); |
| 887 | *out = std::make_unique<LeafReader>(ctx, arrow_field, std::move(input), |
| 888 | field.level_info); |
| 889 | } else if (type_id == ::arrow::Type::LIST || type_id == ::arrow::Type::MAP || |
| 890 | type_id == ::arrow::Type::FIXED_SIZE_LIST || |
| 891 | type_id == ::arrow::Type::LARGE_LIST) { |
| 892 | auto list_field = arrow_field; |
| 893 | auto child = &field.children[0]; |
| 894 | std::unique_ptr<ColumnReaderImpl> child_reader; |
| 895 | RETURN_NOT_OK(GetReader(*child, ctx, &child_reader)); |
| 896 | if (child_reader == nullptr) { |
| 897 | *out = nullptr; |
| 898 | return Status::OK(); |
| 899 | } |
| 900 | |
| 901 | // These two types might not be equal if there is column pruning occurred. |
| 902 | // further down the stack. |
| 903 | const std::shared_ptr<DataType> reader_child_type = child_reader->field()->type(); |
| 904 | // This should really never happen but was raised as a question on the code |
| 905 | // review, this should be pretty cheap check so leave it in. |
| 906 | if (ARROW_PREDICT_FALSE(list_field->type()->num_fields() != 1)) { |
| 907 | return Status::Invalid("expected exactly one child field for: ", |
| 908 | list_field->ToString()); |
| 909 | } |
| 910 | const DataType& schema_child_type = *(list_field->type()->field(0)->type()); |
| 911 | if (type_id == ::arrow::Type::MAP) { |