Apache Parquet Java https://parquet.apache.org/
  • Java 97.5%
  • Shell 1.7%
  • Thrift 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Burak Yavuz e265ac7f57
Implementation for FileType (#3608)
* Introduce implementation for FileType

* address

* address comments and update spec

* update to spec

* Introduce self-reference reader/writer APIs

* Add threshold-driven inline vs self-reference storage for FILE values (#1)

* Add threshold-driven inline vs self-reference storage for FILE values

Writers hand FILE payloads to FileValueWriter, which decides from a
configured threshold whether to keep the bytes inline or store them out
of line as a self-reference. Both forms describe the same logical bytes,
so content_type and checksum are written identically either way and
consumers see no difference beyond which fields are set.

The payload is written eagerly, while the record is being written and
before the row group's column chunks are flushed. This is what makes the
offset knowable in time: offset and size are ordinary column values, and
once a value reaches a column writer it is encoded into a buffered page
and cannot be revised, so a placeholder could not be patched up later.
Writing at that point also leaves each column chunk contiguous on disk,
which the read path relies on when coalescing chunks into range reads.

Along the way, per parquet-format#603:

- Key the self-reference AAD on the file offset rather than a synthetic
  per-chunk counter. The spec defines AAD suffix field 6 as the offset,
  and the counter was not recoverable from the file: nothing stores it,
  so a reader had to walk preceding values to rebuild it, defeating the
  offset-based design that lets a value be resolved on its own. The
  ordinal parameter is gone from five signatures as a result.
- Decompress into a dynamically sized buffer, supporting every codec.
  The previous stream-drain loop was broken for all codecs, not just
  unframed ones: NonBlockedDecompressorStream throws rather than
  returning -1 once its block is consumed.
- Enforce the 2 GiB encrypted-module limit on write, directing oversized
  values to external references.
- Require inline whenever offset is declared. uri is optional per value,
  so a uri+offset+size schema still permits self-references, and one
  emitted without an inline column chunk has no reference point to
  inherit compression and encryption from.

Tests cover threshold routing, offset-keyed AAD round-trips in both GCM
and CTR modes, tamper detection when an offset is altered, and payloads
spanning several buffer doublings across SNAPPY, GZIP, ZSTD and LZ4_RAW.

Co-authored-by: Isaac

* Fix ZSTD resolution, revert schema tightening, fix test imports

Verified the change by building and running the suites locally, which
turned up three things:

ZSTD self-references could not be resolved at all. ZstandardCodec
returns null from createDecompressor because it decompresses only
through its stream, so driving the Decompressor directly failed with
"Could not obtain a decompressor". Such codecs are framed and report
end-of-input properly, so drain the stream for them and keep
grow-and-retry for the rest. Four tests were failing on this.

Reverted requiring `inline` whenever `offset` is declared, back to
requiring it only when `uri` is absent. Two existing tests
(testFileLogicalTypeExternalRangedReferenceWithoutInline,
testFileLogicalTypeOffsetWithSize) assert that a uri+offset+size schema
without `inline` is valid, so the stricter rule contradicted the
author's documented intent. The concern is real -- `uri` is optional per
value, so such a schema can still emit a self-reference with no
reference point -- but it belongs on the write path, and the FILE group
declaring `uri` is now documented as needing an always-inline threshold.

Fixed two pre-existing test compile errors that blocked the module:
TestParquetMetadataConverter used assertEquals/assertTrue with no JUnit
import (switched to the AssertJ style used throughout that file), and
TestSelfReferenceFileWrite was missing the ParquetReadOptions import.
Both fail on the base commit independently of these changes.

Also applied spotless formatting.

Local results: parquet-column 679/679 pass, parquet-hadoop 761/762. The
one failure, testEnumEquivalence on Encoding.ALP, is an artifact of the
local workaround for FileType being unreleased -- parquet.thrift was
substituted from parquet-format master, which defines an ALP encoding
the Java enum does not yet have. It is unrelated to these changes and
will not occur once a parquet-format release carries FileType.

Co-authored-by: Isaac

* remove self reference

* Add FILE value writer validation

* Added FileValueWriters and FileConverters for writes and reads

* save

* fix lint

* Prevent partial FILE projections

* Fix FILE projection formatting

* Harden FILE type validation

* Validate FILE schema replacements and expand reader coverage

Revalidate FILE fields in GroupType.withNewFields and cover duplicate names, invalid annotations, generic projections, converter lifecycle, and persisted reader/writer behavior. Apply the repository's Spotless formatting to the FILE changes.

* Address FILE logical type review feedback

---------

Co-authored-by: Alkis Evlogimenos <alkis@evlogimenos.com>
2026-11-05 13:59:22 +01:00
.github
.mvn/wrapper
agents/docs
dev
doc/dremel_paper
parquet-arrow
parquet-avro
parquet-benchmarks
parquet-cli
parquet-column Implementation for FileType (#3608) 2026-11-05 13:59:22 +01:00
parquet-common
parquet-encoding
parquet-format-structures Implementation for FileType (#3608) 2026-11-05 13:59:22 +01:00
parquet-generator
parquet-hadoop Implementation for FileType (#3608) 2026-11-05 13:59:22 +01:00
parquet-hadoop-bundle
parquet-jackson
parquet-plugins
parquet-protobuf
parquet-thrift
parquet-variant
release MINOR: Set the POM SCM tag when preparing and publishing releases (#3933) 2026-11-05 10:20:48 +08:00
src
.asf.yaml
.editorconfig
.gitattributes
.gitignore
AGENTS.md
changelog.sh
CHANGES.md Fix typo 'dependancy' to 'dependency' in CHANGES.md (#3932) 2026-11-05 09:54:23 +08:00
LICENSE
mvnw
mvnw.cmd
NOTICE
pom.xml
PoweredBy.md
README.md
SECURITY.md

Parquet Java (formerly Parquet MR) CI Hadoop 3

This repository contains a Java implementation of Apache Parquet

Apache Parquet is an open source, column-oriented data file format designed for efficient data storage and retrieval. It provides high performance compression and encoding schemes to handle complex data in bulk and is supported in many programming languages and analytics tools.

The parquet-format repository contains the file format specification.

Parquet uses the record shredding and assembly algorithm described in the Dremel paper to represent nested structures. You can find additional details about the format and intended use cases in our Hadoop Summit 2013 presentation

Building

Parquet-Java requires Java 17 or higher and uses Maven to build. It also depends on the thrift compiler (protoc is now managed by maven plugin).

Install Thrift

To build and install the thrift compiler, run:

wget -nv https://archive.apache.org/dist/thrift/0.25.0/thrift-0.25.0.tar.gz
tar xzf thrift-0.25.0.tar.gz
cd thrift-0.25.0
chmod +x ./configure
./configure --disable-libs
sudo make install -j

Note: if you wish to verify the signature and checksum of a release:

  1. The GPG and sha checksums can be found under https://archive.apache.org/dist/thrift/0.25.0/
  2. Validate the signature of the artifact against the Thrift committer KEYS.

If you're on OSX and use homebrew, you can instead install Thrift 0.25.0 with brew and ensure that it comes first in your PATH.

brew install thrift
export PATH="$(brew --prefix thrift)/bin:$PATH"

Update Parquet Thrift Definitions

Parquet-Java uses an inlined version of the parquet.thrift IDL, located at parquet-format-structures/src/main/thrift. To update this definition to include changes from the canonical definition in parquet-format, you can use:

# Update to a parquet-format release
> ./dev/update-parquet-thrift.sh apache-parquet-format-2.13.0

# Update to an arbitrary parquet-format commit (can be unreleased)
> ./dev/update-parquet-thrift.sh <commit hash>

# Update to a commit from a parquet-format fork (e.g. for a reference implementation of an in-progress spec change)
> PARQUET_FORMAT_REPO="https://github.com/divjotarora/parquet-format" ./dev/update-parquet-thrift.sh <commit hash>

Build Parquet with Maven

Once protobuf and thrift are available in your path, you can build the project by running:

LC_ALL=C ./mvnw clean install

Features

Parquet is an active project, and new features are being added quickly. Here are a few features:

  • Type-specific encoding
  • Hive integration (deprecated)
  • Pig integration (deprecated)
  • Cascading integration (deprecated)
  • Crunch integration
  • Apache Arrow integration
  • Scrooge integration (deprecated)
  • Impala integration (non-nested)
  • Java Map/Reduce API
  • Native Avro support
  • Native Thrift support
  • Native Protocol Buffers support
  • Complex structure support
  • Run-length encoding (RLE)
  • Bit Packing
  • Adaptive dictionary encoding
  • Predicate pushdown
  • Column stats
  • Delta encoding
  • Index pages
  • Scala DSL (deprecated)
  • Java Vector API support (experimental)

Java Vector API support

The feature is experimental and is currently not part of the parquet distribution.

Parquet-Java has supported Java Vector API to speed up reading, to enable this feature:

  • Java 17+, 64-bit
  • Requiring the CPU to support instruction sets:
    • avx512vbmi
    • avx512_vbmi2
  • To build the jars: ./mvnw clean package -P vector-plugins
  • For Apache Spark to enable this feature:
    • Build parquet and replace the parquet-encoding-{VERSION}.jar on the spark jars folder
    • Build parquet-encoding-vector and copy parquet-encoding-vector-{VERSION}.jar to the spark jars folder
    • Edit spark class#VectorizedRleValuesReader, function#readNextGroup refer to parquet class#ParquetReadRouter, function#readBatchUsing512Vector
    • Build spark with maven and replace spark-sql_2.12-{VERSION}.jar on the spark jars folder

Map/Reduce integration

Input and Output formats. Note that to use an Input or Output format, you need to implement a WriteSupport or ReadSupport class, which will implement the conversion of your object to and from a Parquet schema.

We've implemented this for 2 popular data formats to provide a clean migration path as well:

Thrift

Thrift integration is provided by the parquet-thrift sub-project.

Avro

Avro conversion is implemented via the parquet-avro sub-project.

Protobuf

Protobuf conversion is implemented via the parquet-protobuf sub-project.

Create your own objects

  • The ParquetOutputFormat can be provided a WriteSupport to write your own objects to an event based RecordConsumer.
  • The ParquetInputFormat can be provided a ReadSupport to materialize your own objects by implementing a RecordMaterializer

See the APIs:

Hive integration

Hive integration is now deprecated within the Parquet project. It is now maintained by Apache Hive.

Build

To run the unit tests: ./mvnw test

To build the jars: ./mvnw package

The build runs in GitHub Actions: Build Status

Add Parquet as a dependency in Maven

The current release is version 1.18.1.

  <dependencies>
    <dependency>
      <groupId>org.apache.parquet</groupId>
      <artifactId>parquet-common</artifactId>
      <version>1.18.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.parquet</groupId>
      <artifactId>parquet-encoding</artifactId>
      <version>1.18.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.parquet</groupId>
      <artifactId>parquet-column</artifactId>
      <version>1.18.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.parquet</groupId>
      <artifactId>parquet-hadoop</artifactId>
      <version>1.18.1</version>
    </dependency>
  </dependencies>

How To Contribute

We prefer to receive contributions in the form of GitHub pull requests. Please send pull requests against the parquet-java Git repository. If you've previously forked Parquet from its old location, you will need to add a remote or update your origin remote to https://github.com/apache/parquet-java.git.

If you are looking for some ideas on what to contribute, check out GitHub issues for labeled Good first issue. Comment on the issue and/or contact dev@parquet.apache.org with your questions and ideas.

If you’d like to report a bug but don’t have time to fix it, you can still raise an issue on GitHub, or email the mailing list dev@parquet.apache.org.

To contribute a patch:

  1. Break your work into small, single-purpose patches if possible. It’s much harder to merge in a large change with a lot of disjoint features.
  2. Create an issue for your patch on the GitHub issues.
  3. Submit the patch as a GitHub pull request against the master branch. For a tutorial, see the GitHub guides on forking a repo and sending a pull request. Prefix your pull request name with the issue (ex: https://github.com/apache/parquet-java/pull/3260).
  4. Make sure that your code passes the unit tests. You can run the tests with ./mvnw test in the root directory.
  5. Add new unit tests for your code.

We tend to do fairly close readings of pull requests, and you may get a lot of comments. Some common issues that are not code structure related, but still important:

  • Use 2 spaces for whitespace. Not tabs, not 4 spaces. The number of the spacing shall be 2.
  • Give your operators some room. Not a+b but a + b and not foo(int a,int b) but foo(int a, int b).
  • Generally speaking, stick to the Sun Java Code Conventions
  • Make sure tests pass!

Thank you for getting involved!

Authors and contributors

Code of Conduct

We hold ourselves and the Parquet developer community to two codes of conduct:

  1. The Apache Software Foundation Code of Conduct
  2. The Twitter OSS Code of Conduct

Discussions

License

Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0