| 885 | // File reader implementation |
| 886 | |
| 887 | Status GetReader(const SchemaField& field, const std::shared_ptr<Field>& arrow_field, |
| 888 | const std::shared_ptr<ReaderContext>& ctx, |
| 889 | std::unique_ptr<ColumnReaderImpl>* out) { |
| 890 | BEGIN_PARQUET_CATCH_EXCEPTIONS |
| 891 | |
| 892 | auto type_id = arrow_field->type()->id(); |
| 893 | |
| 894 | if (type_id == ::arrow::Type::EXTENSION) { |
| 895 | auto storage_field = arrow_field->WithType( |
| 896 | checked_cast<const ExtensionType&>(*arrow_field->type()).storage_type()); |
| 897 | RETURN_NOT_OK(GetReader(field, storage_field, ctx, out)); |
| 898 | if (*out) { |
| 899 | auto storage_type = (*out)->field()->type(); |
| 900 | if (!storage_type->Equals(storage_field->type())) { |
| 901 | return Status::Invalid( |
| 902 | "Due to column pruning only part of an extension's storage type was loaded. " |
| 903 | "An extension type cannot be created without all of its fields"); |
| 904 | } |
| 905 | *out = std::make_unique<ExtensionReader>(arrow_field, std::move(*out)); |
| 906 | } |
| 907 | return Status::OK(); |
| 908 | } |
| 909 | |
| 910 | if (field.children.size() == 0) { |
| 911 | if (!field.is_leaf()) { |
| 912 | return Status::Invalid("Parquet non-leaf node has no children"); |
| 913 | } |
| 914 | if (!ctx->IncludesLeaf(field.column_index)) { |
| 915 | *out = nullptr; |
| 916 | return Status::OK(); |
| 917 | } |
| 918 | std::unique_ptr<FileColumnIterator> input( |
| 919 | ctx->iterator_factory(field.column_index, ctx->reader)); |
| 920 | *out = std::make_unique<LeafReader>(ctx, arrow_field, std::move(input), |
| 921 | field.level_info); |
| 922 | } else if (type_id == ::arrow::Type::LIST || type_id == ::arrow::Type::MAP || |
| 923 | type_id == ::arrow::Type::FIXED_SIZE_LIST || |
| 924 | type_id == ::arrow::Type::LARGE_LIST || |
| 925 | type_id == ::arrow::Type::LIST_VIEW || |
| 926 | type_id == ::arrow::Type::LARGE_LIST_VIEW) { |
| 927 | auto list_field = arrow_field; |
| 928 | auto child = &field.children[0]; |
| 929 | std::unique_ptr<ColumnReaderImpl> child_reader; |
| 930 | RETURN_NOT_OK(GetReader(*child, ctx, &child_reader)); |
| 931 | if (child_reader == nullptr) { |
| 932 | *out = nullptr; |
| 933 | return Status::OK(); |
| 934 | } |
| 935 | |
| 936 | // These two types might not be equal if there is column pruning occurred. |
| 937 | // further down the stack. |
| 938 | const std::shared_ptr<DataType> reader_child_type = child_reader->field()->type(); |
| 939 | // This should really never happen but was raised as a question on the code |
| 940 | // review, this should be pretty cheap check so leave it in. |
| 941 | if (ARROW_PREDICT_FALSE(list_field->type()->num_fields() != 1)) { |
| 942 | return Status::Invalid("expected exactly one child field for: ", |
| 943 | list_field->ToString()); |
| 944 | } |