| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #pragma once | |
| /// \file iceberg/file_reader.h | |
| /// Reader interface for file formats like Parquet, Avro and ORC. | |
| #include <cstdint> | |
| #include <functional> | |
| #include <memory> | |
| #include <optional> | |
| #include "iceberg/arrow_c_data.h" | |
| #include "iceberg/file_format.h" | |
| #include "iceberg/result.h" | |
| #include "iceberg/type_fwd.h" | |
| #include "iceberg/util/config.h" | |
| namespace iceberg { | |
| /// \brief Base reader class to read data from different file formats. | |
| class ICEBERG_EXPORT Reader { | |
| public: | |
| virtual ~Reader() = default; | |
| Reader() = default; | |
| Reader(const Reader&) = delete; | |
| Reader& operator=(const Reader&) = delete; | |
| /// \brief Open the reader. | |
| virtual Status Open(const ReaderOptions& options) = 0; | |
| /// \brief Close the reader. | |
| virtual Status Close() = 0; | |
| /// \brief Read next data from file. | |
| /// | |
| /// \return std::nullopt if the reader has no more data, otherwise `ArrowArray`. | |
| virtual Result<std::optional<ArrowArray>> Next() = 0; | |
| /// \brief Get the schema of the data. | |
| virtual Result<ArrowSchema> Schema() = 0; | |
| /// \brief Get the metadata of the file. | |
| virtual Result<std::unordered_map<std::string, std::string>> Metadata() = 0; | |
| }; | |
| /// \brief A split of the file to read. | |
| struct ICEBERG_EXPORT Split { | |
| /// \brief The offset of the split. | |
| size_t offset; | |
| /// \brief The length of the split. | |
| size_t length; | |
| }; | |
| class ICEBERG_EXPORT ReaderProperties : public ConfigBase<ReaderProperties> { | |
| public: | |
| template <typename T> | |
| using Entry = const ConfigBase<ReaderProperties>::Entry<T>; | |
| /// \brief The batch size to read. | |
| inline static Entry<int64_t> kBatchSize{"read.batch-size", 4096}; | |
| /// \brief Read list columns as Arrow large_list (64-bit offsets) instead of list. | |
| /// Only the Parquet reader honors this option; other readers ignore it. | |
| /// Default: false (use 32-bit offset list). | |
| inline static Entry<bool> kArrowUseLargeList{"read.arrow.use-large-list", false}; | |
| /// \brief Skip GenericDatum in Avro reader for better performance. | |
| /// When true, decode directly from Avro to Arrow without GenericDatum intermediate. | |
| /// Default: true (skip GenericDatum for better performance). | |
| inline static Entry<bool> kAvroSkipDatum{"read.avro.skip-datum", true}; | |
| /// \brief The buffer size used by Avro input stream. | |
| inline static Entry<int64_t> kAvroBufferSize{"read.avro.buffer-size", 1024 * 1024}; | |
| /// \brief Create a ReaderProperties instance from a map of key-value pairs. | |
| static ReaderProperties FromMap( | |
| const std::unordered_map<std::string, std::string>& properties); | |
| }; | |
| /// \brief Options for creating a reader. | |
| struct ICEBERG_EXPORT ReaderOptions { | |
| /// \brief The path to the file to read. | |
| std::string path; | |
| /// \brief The total length of the file. | |
| std::optional<size_t> length; | |
| /// \brief The split to read. | |
| std::optional<Split> split; | |
| /// \brief FileIO instance to open the file. | |
| std::shared_ptr<class FileIO> io; | |
| /// \brief The projection schema to read from the file. This field is required. | |
| std::shared_ptr<class Schema> projection; | |
| /// \brief The filter to apply to the data. Reader implementations may ignore this if | |
| /// the file format does not support filtering. | |
| std::shared_ptr<class Expression> filter; | |
| /// \brief Name mapping for schema evolution compatibility. Used when reading files | |
| /// that may have different field names than the current schema. | |
| std::shared_ptr<class NameMapping> name_mapping; | |
| /// \brief First row ID inherited by the data file, if assigned. | |
| std::optional<int64_t> first_row_id; | |
| /// \brief Data sequence number inherited by the manifest entry, if assigned. | |
| std::optional<int64_t> data_sequence_number; | |
| /// \brief Format-specific or implementation-specific properties. | |
| ReaderProperties properties; | |
| }; | |
| /// \brief Factory function to create a reader of a specific file format. | |
| using ReaderFactory = std::function<Result<std::unique_ptr<Reader>>()>; | |
| /// \brief Registry of reader factories for different file formats. | |
| struct ICEBERG_EXPORT ReaderFactoryRegistry { | |
| /// \brief Register a factory function for a specific file format. | |
| ReaderFactoryRegistry(FileFormatType format_type, ReaderFactory factory); | |
| /// \brief Get the factory function for a specific file format. | |
| static ReaderFactory& GetFactory(FileFormatType format_type); | |
| /// \brief Open a reader for a specific file format. | |
| static Result<std::unique_ptr<Reader>> Open(FileFormatType format_type, | |
| const ReaderOptions& options); | |
| }; | |
| } // namespace iceberg |