Skip to content

[PARQUET] Allow UNKNOWN logical type annotation on any physical type#9855

Merged
etseidl merged 4 commits into
apache:mainfrom
etseidl:logical_type_unknown
May 1, 2026
Merged

[PARQUET] Allow UNKNOWN logical type annotation on any physical type#9855
etseidl merged 4 commits into
apache:mainfrom
etseidl:logical_type_unknown

Conversation

@etseidl
Copy link
Copy Markdown
Contributor

@etseidl etseidl commented Apr 30, 2026

Which issue does this PR close?

Rationale for this change

Parquet writers for the most part only annotate INT32 columns with the UNKNOWN logical type annotation. This annotation is used to denote a column which contains only null values for which the actual physical type cannot be deduced. This crate assumes only INT32 columns can be so annotated, but there is no such requirement in the Parquet specification.

What changes are included in this PR?

Modifies Parquet schema parsing to allow UNKNOWN on any type, and ensures that when encountered, an arrow array reader for the Null datatype is used.

Are these changes tested?

Yes, unit test is added.

Are there any user-facing changes?

No API changes, just a behavior change.

@github-actions github-actions Bot added the parquet Changes to the parquet crate label Apr 30, 2026
@etseidl
Copy link
Copy Markdown
Contributor Author

etseidl commented Apr 30, 2026

Keeping as draft while awaiting a test file (see issue discussion).

@etseidl
Copy link
Copy Markdown
Contributor Author

etseidl commented Apr 30, 2026

Received confirmation that this fixes the downstream issue so marking as ready.

@cdelmonte-zg one thing this fix doesn't do is preserve the physical type upon write...it will revert to INT32 (UNKNOWN). If that's a requirement we'll need a follow-up.

@cdelmonte-zg
Copy link
Copy Markdown

Received confirmation that this fixes the downstream issue so marking as ready.

@cdelmonte-zg one thing this fix doesn't do is preserve the physical type upon write...it will revert to INT32 (UNKNOWN). If that's a requirement we'll need a follow-up.

Thanks @etseidl, no follow-up needed for the delta-kernel-rs side. The kernel strips void columns from the physical write schema before handing data to the parquet writer (it's a deliberate design choice from the Delta protocol, void columns are never materialized in data files). So kernel never writes a Null/UNKNOWN column; it only needs to read what other writers (Spark, in the DAT cases) produced. Read-side correctness is all that #9855 needs to provide.

Copy link
Copy Markdown
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me -- thank you @etseidl

// specification. Since this can only annotate an entirely null column, the data type
// used for the NullArrayReader should be irrelevant. It's just needed to read the
// repetition and definition level data.
if matches!(arrow_type, Some(DataType::Null)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pulling this up out of INT32 type makes sense to me

let batch = reader.next().unwrap().unwrap();

for col in batch.columns() {
assert_eq!(col.len(), 4);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably also assert the DataType of each column read in. In this case, I think they should all be DataType::Null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ecbeaf1

unit
)),
},
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#unknown-always-null
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reson this is removed is that it is now handled higher up in from_parquet 👍

@etseidl
Copy link
Copy Markdown
Contributor Author

etseidl commented May 1, 2026

Thanks for the review @alamb.

@etseidl etseidl merged commit 1ddb4d9 into apache:main May 1, 2026
16 checks passed
@etseidl etseidl deleted the logical_type_unknown branch May 1, 2026 22:04
Rich-T-kid pushed a commit to Rich-T-kid/arrow-rs that referenced this pull request Jun 2, 2026
apache#9855)

# Which issue does this PR close?

- Closes apache#9844.

# Rationale for this change

Parquet writers for the most part only annotate `INT32` columns with the
`UNKNOWN` logical type annotation. This annotation is used to denote a
column which contains only null values for which the actual physical
type cannot be deduced. This crate assumes _only_ INT32 columns can be
so annotated, but there is no such requirement in the Parquet
[specification](https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#unknown-always-null).

# What changes are included in this PR?

Modifies Parquet schema parsing to allow `UNKNOWN` on any type, and
ensures that when encountered, an arrow array reader for the `Null`
datatype is used.

# Are these changes tested?

Yes, unit test is added.

# Are there any user-facing changes?

No API changes, just a behavior change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parquet reader rejects canonical UNKNOWN logical type on BOOLEAN physical columns

3 participants