parquet/lib.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//!
19//! This crate contains the official Native Rust implementation of
20//! [Apache Parquet](https://parquet.apache.org/), part of
21//! the [Apache Arrow](https://arrow.apache.org/) project.
22//! The crate provides a number of APIs to read and write Parquet files,
23//! covering a range of use cases.
24//!
25//! Please see the [parquet crates.io](https://crates.io/crates/parquet)
26//! page for feature flags and tips to improve performance.
27//!
28//! # Format Overview
29//!
30//! Parquet is a columnar format, which means that unlike row formats like [CSV], values are
31//! iterated along columns instead of rows. Parquet is similar in spirit to [Arrow], but
32//! focuses on storage efficiency whereas Arrow prioritizes compute efficiency.
33//!
34//! Parquet files are partitioned for scalability. Each file contains metadata,
35//! along with zero or more "row groups", each row group containing one or
36//! more columns. The APIs in this crate reflect this structure.
37//!
38//! Data in Parquet files is strongly typed and differentiates between logical
39//! and physical types (see [`schema`]). In addition, Parquet files may contain
40//! other metadata, such as statistics, which can be used to optimize reading
41//! (see [`file::metadata`]).
42//! For more details about the Parquet format itself, see the [Parquet spec]
43//!
44//! [Parquet spec]: https://github.com/apache/parquet-format/blob/master/README.md#file-format
45//!
46//! # APIs
47//!
48//! This crate exposes a number of APIs for different use-cases.
49//!
50//! ## Metadata and Schema
51//!
52//! The [`schema`] module provides APIs to work with Parquet schemas. The
53//! [`file::metadata`] module provides APIs to work with Parquet metadata.
54//!
55//! ## Reading and Writing Arrow (`arrow` feature)
56//!
57//! The [`arrow`] module supports reading and writing Parquet data to/from
58//! Arrow [`RecordBatch`]es. Using Arrow is simple and performant, and allows workloads
59//! to leverage the wide range of data transforms provided by the [arrow] crate, and by the
60//! ecosystem of [Arrow] compatible systems.
61//!
62//! Most users will use [`ArrowWriter`] for writing and [`ParquetRecordBatchReaderBuilder`] for
63//! reading from synchronous IO sources such as files or in-memory buffers.
64//!
65//! Lower level APIs include
66//! * [`ParquetPushDecoder`] for file grained control over interleaving of IO and CPU.
67//! * [`ArrowColumnWriter`] for writing using multiple threads,
68//! * [`RowFilter`] to apply filters during decode
69//!
70//! ### EXPERIMENTAL: Content-Defined Chunking
71//!
72//! [`ArrowWriter`] supports content-defined chunking (CDC), which creates data page
73//! boundaries based on content rather than fixed sizes. CDC enables efficient
74//! deduplication in content-addressable storage (CAS) systems: when the same data
75//! appears in successive file versions, it will produce identical byte sequences that
76//! CAS backends can deduplicate.
77//!
78//! Enable CDC via [`WriterProperties`]:
79//!
80//! ```rust
81//! # use parquet::file::properties::{WriterProperties, CdcOptions};
82//! let props = WriterProperties::builder()
83//! .set_content_defined_chunking(Some(CdcOptions::default()))
84//! .build();
85//! ```
86//!
87//! See [`CdcOptions`] for chunk size and normalization parameters.
88//!
89//! [`WriterProperties`]: file::properties::WriterProperties
90//! [`CdcOptions`]: file::properties::CdcOptions
91//!
92//! [`ArrowWriter`]: arrow::arrow_writer::ArrowWriter
93//! [`ParquetRecordBatchReaderBuilder`]: arrow::arrow_reader::ParquetRecordBatchReaderBuilder
94//! [`ParquetPushDecoder`]: arrow::push_decoder::ParquetPushDecoder
95//! [`ArrowColumnWriter`]: arrow::arrow_writer::ArrowColumnWriter
96//! [`RowFilter`]: arrow::arrow_reader::RowFilter
97//!
98//! ## `async` Reading and Writing Arrow (`arrow` feature + `async` feature)
99//!
100//! The [`async_reader`] and [`async_writer`] modules provide async APIs to
101//! read and write [`RecordBatch`]es asynchronously.
102//!
103//! Most users will use [`AsyncArrowWriter`] for writing and [`ParquetRecordBatchStreamBuilder`]
104//! for reading, automatically optimizing IO based on any predicates or projections provided.
105//! Object storage services such as S3 can be integrated by implementing
106//! [`AsyncFileReader`] on top of a client such as the [object_store] crate,
107//! or by passing a writer implementing [`AsyncWrite`] (such as
108//! `object_store::buffered::BufWriter`) to [`AsyncArrowWriter`].
109//!
110//! [`async_reader`]: arrow::async_reader
111//! [`async_writer`]: arrow::async_writer
112//! [`AsyncArrowWriter`]: arrow::async_writer::AsyncArrowWriter
113//! [`AsyncFileReader`]: arrow::async_reader::AsyncFileReader
114//! [`AsyncWrite`]: https://docs.rs/tokio/latest/tokio/io/trait.AsyncWrite.html
115//! [`ParquetRecordBatchStreamBuilder`]: arrow::async_reader::ParquetRecordBatchStreamBuilder
116//!
117//! ## Variant Logical Type (`variant_experimental` feature)
118//!
119//! The [`variant`] module supports reading and writing Parquet files
120//! with the [Variant Binary Encoding] logical type, which can represent
121//! semi-structured data such as JSON efficiently.
122//!
123//! [Variant Binary Encoding]: https://github.com/apache/parquet-format/blob/master/VariantEncoding.md
124//!
125//! ## Read/Write Parquet Directly
126//!
127//! Workloads needing finer-grained control, or to avoid a dependence on arrow,
128//! can use the APIs in [`mod@file`] directly. These APIs are harder to use
129//! as they directly use the underlying Parquet data model, and require knowledge
130//! of the Parquet format, including the details of [Dremel] record shredding
131//! and [Logical Types].
132//!
133//! [arrow]: https://docs.rs/arrow/latest/arrow/index.html
134//! [Arrow]: https://arrow.apache.org/
135//! [`RecordBatch`]: https://docs.rs/arrow/latest/arrow/array/struct.RecordBatch.html
136//! [CSV]: https://en.wikipedia.org/wiki/Comma-separated_values
137//! [Dremel]: https://research.google/pubs/pub36632/
138//! [Logical Types]: https://github.com/apache/parquet-format/blob/master/LogicalTypes.md
139//! [object_store]: https://docs.rs/object_store/latest/object_store/
140//!
141//! # Platform Support
142//!
143//! Only little-endian platforms are officially supported and tested in CI.
144//! Big-endian platforms are not tested in CI and may not work correctly.
145//! Fixes for big-endian platforms are welcome and handled on a best-effort basis,
146//! but compatibility is not guaranteed.
147
148#![doc(
149 html_logo_url = "https://raw.githubusercontent.com/apache/parquet-format/25f05e73d8cd7f5c83532ce51cb4f4de8ba5f2a2/logo/parquet-logos_1.svg",
150 html_favicon_url = "https://raw.githubusercontent.com/apache/parquet-format/25f05e73d8cd7f5c83532ce51cb4f4de8ba5f2a2/logo/parquet-logos_1.svg"
151)]
152#![cfg_attr(docsrs, feature(doc_cfg))]
153#![warn(missing_docs)]
154#[cfg(all(
155 feature = "flate2",
156 not(any(feature = "flate2-zlib-rs", feature = "flate2-rust_backend"))
157))]
158compile_error!(
159 "When enabling `flate2` you must enable one of the features: `flate2-zlib-rs` or `flate2-rust_backend`."
160);
161
162#[macro_use]
163pub mod errors;
164pub mod basic;
165
166#[macro_use]
167pub mod data_type;
168
169use std::fmt::Debug;
170use std::ops::Range;
171// Exported for external use, such as benchmarks
172#[cfg(feature = "experimental")]
173#[doc(hidden)]
174pub use self::encodings::{decoding, encoding};
175
176// Keep these module declarations explicit: rustfmt does not discover modules declared by macros.
177// See https://github.com/rust-lang/rustfmt/issues/3253
178#[cfg(feature = "experimental")]
179#[doc(hidden)]
180#[macro_use]
181pub mod util;
182#[cfg(not(feature = "experimental"))]
183#[macro_use]
184mod util;
185
186pub use util::utf8;
187
188#[cfg(feature = "arrow")]
189pub mod arrow;
190pub mod bloom_filter;
191pub mod column;
192#[cfg(feature = "experimental")]
193#[doc(hidden)]
194pub mod compression;
195#[cfg(not(feature = "experimental"))]
196mod compression;
197#[cfg(feature = "experimental")]
198#[doc(hidden)]
199pub mod encodings;
200#[cfg(not(feature = "experimental"))]
201mod encodings;
202
203#[cfg(feature = "encryption")]
204#[cfg_attr(feature = "experimental", doc(hidden))]
205pub mod encryption;
206
207pub mod file;
208pub mod record;
209pub mod schema;
210
211mod parquet_macros;
212mod parquet_thrift;
213
214/// What data is needed to read the next item from a decoder.
215///
216/// This is used to communicate between the decoder and the caller
217/// to indicate what data is needed next, or what the result of decoding is.
218#[derive(Debug)]
219pub enum DecodeResult<T: Debug> {
220 /// The ranges of data necessary to proceed
221 // TODO: distinguish between minimum needed to make progress and what could be used?
222 NeedsData(Vec<Range<u64>>),
223 /// The decoder produced an output item
224 Data(T),
225 /// The decoder finished processing
226 Finished,
227}
228
229#[cfg_attr(feature = "experimental", doc(hidden))]
230pub mod geospatial;
231#[cfg(feature = "variant_experimental")]
232pub mod variant;