Skip to content

GH-54533: [C++][Parquet] Avoid emitting empty data pages and advance past empty pages in reader - #54582

Open
ShivanshhhG wants to merge 1 commit into
apache:mainfrom
ShivanshhhG:fix-54533-parquet-empty-data-page
Open

ShivanshhhG wants to merge 1 commit into
apache:mainfrom
ShivanshhhG:fix-54533-parquet-empty-data-page

Conversation

@ShivanshhhG

@ShivanshhhG ShivanshhhG commented Oct 19, 2026 •

Copy link
Copy Markdown

Rationale for this change

When writing repeated columns with single records or small data_page_size, empty encoders (such as RleBooleanEncoder) return small non-zero estimated sizes, causing AddDataPage() to emit an empty data page (num_values = 0). On read, ColumnReaderImplBase::HasNextInternal() returned false on empty data pages, prematurely terminating reading and dropping subsequent rows in the row group.

What changes are included in this PR?

  • Writer: Guard CommitWriteAndCheckPageLimit and AddDataPage to require num_buffered_values_ > 0 before writing data pages.
  • Reader: In ColumnReaderImplBase::HasNextInternal, loop past empty data pages (num_buffered_values_ == 0) to maintain backward compatibility with existing files.
  • Tests: Added unit tests in arrow_reader_writer_test.cc for repeated columns with small page sizes and dictionary encoding.

Are these changes tested?

Yes, unit tests added to arrow_reader_writer_test.cc.

Are there any user-facing changes?

No breaking changes. Fixes potential data omission when reading files with empty data pages.

Closes #54533.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #54533 has been automatically assigned in GitHub to PR creator.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #54533 has no components, please add labels for components.

…vance past empty pages in reader

When writing a repeated column with a single record batch or a small data_page_size, the writer could check page limits when num_buffered_values_ is zero. Because empty encoders (such as RleBooleanEncoder or DictionaryEncoder) estimate a small non-zero encoded size, the writer previously emitted an empty first data page (num_values = 0). On read, HasNextInternal returned false upon encountering the empty page, prematurely truncating the column chunk and silently dropping the row group's rows.

This commit:
1. In CommitWriteAndCheckPageLimit, ensures num_buffered_values_ > 0 before triggering AddDataPage().
2. In ColumnWriterImpl::AddDataPage(), guards against adding empty pages when num_buffered_values_ == 0.
3. In ColumnReaderImplBase::HasNextInternal(), loops across any data page with zero buffered values rather than treating it as end of column chunk, ensuring robust backward compatibility with existing Parquet files.
4. Adds unit tests in arrow_reader_writer_test.cc verifying repeated columns with small page sizes, V2 pages, dictionary encoding, and multi-column schemas.

Closes: apache#54533
Signed-off-by: SHIVANSH-ux-ys <singaser78@gmail.com>
@ShivanshhhG
ShivanshhhG force-pushed the fix-54533-parquet-empty-data-page branch from 262bda4 to ffb6e89 Compare October 26, 2026 12:10
@pitrou

pitrou commented Oct 27, 2026

Copy link
Copy Markdown
Member

This looks good to me. @wgtmac @adamreeve @HuaHuaY Do you think we should add a file with an empty data page in parquet-testing?

@ShivanshhhG The PR description looks AI-generated and is quite verbose, can you trim it down for human consumption?

@ShivanshhhG

Copy link
Copy Markdown
Author

Thanks for the review @pitrou! I have trimmed down the PR description to be concise and straight to the point.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #54533 has been automatically assigned in GitHub to PR creator.

@adamreeve adamreeve left a comment

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.

This change also looks correct to me, thanks for the fix @ShivanshhhG.

This looks good to me. @wgtmac @adamreeve @HuaHuaY Do you think we should add a file with an empty data page in parquet-testing?

Yes, as far as I can tell, an empty page is valid according to the spec. Although not when an offset index is used and the empty page isn't the last one. While it makes sense to avoid writing an empty page, it's a good edge case to include in parquet-testing. Maybe there should be a bad_data example with the offset index included, and a valid file without it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C++][Parquet] Writer emits an empty first data page for a repeated column when data_page_size is small, and the reader then drops the row group's rows

3 participants