Skip to content

fix(parquet): make column reader cleanup idempotent#924

Merged
zeroshade merged 6 commits into
apache:mainfrom
fallintoplace:fix/column-reader-close-idempotent
Jul 14, 2026
Merged

fix(parquet): make column reader cleanup idempotent#924
zeroshade merged 6 commits into
apache:mainfrom
fallintoplace:fix/column-reader-close-idempotent

Conversation

@fallintoplace

Copy link
Copy Markdown
Contributor

Column chunk cleanup retained both the current page and page reader after Close, so repeated cleanup could release or close the same resources twice. Page-reader replacement also discarded close errors and installed the replacement anyway.

This change detaches resources before cleanup, makes Close idempotent, returns and retains replacement cleanup errors, and uses the checked replacement path from the Arrow reader before continuing to seek or read.

Tests:

  • go test ./parquet/file -run 'TestPrimitiveReaderSuite|TestColumnChunkReader'
  • go test ./parquet/... -run '^$'

@fallintoplace fallintoplace requested a review from zeroshade as a code owner July 11, 2026 07:42

@zeroshade zeroshade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM in substance — detaching curPage/rdr before cleanup makes Close idempotent (no double-release/close), and making setPageReader return an error so replacement failures propagate through SeekToRow/nextRowGroup is the right call. Good targeted tests. Two nits inline.

Comment thread parquet/file/column_reader.go Outdated
return nil
}

// Close closes the page raeder and the page if set.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Typo: raeder -> reader.

func (c *columnChunkReader) setPageReader(rdr PageReader) {
c.Close()

func (c *columnChunkReader) setPageReader(rdr PageReader) error {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Optional: add a pqarrow-level test that a replacement close-error surfaces via LoadBatch/SeekToRow; the propagation is currently only covered at the primitive level.

@zeroshade zeroshade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The idempotent-cleanup change looks right. One resource leak on the error path to address — inline.

Comment thread parquet/pqarrow/column_readers.go Outdated
if !ok {
return errors.New("record reader does not support error-returning page reader replacement")
}
return rr.SetPageReaderWithError(pr)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If SetPageReaderWithError(pr) returns an error, the freshly acquired pr is neither installed nor closed. Both call sites (SeekToRow and nextRowGroup) obtain a new PageReader immediately before calling this helper, so a replacement failure leaks the reader and its buffers. Please close pr before returning the error here (or transfer ownership back and close it at each call site).

@zeroshade zeroshade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks — all prior review feedback is addressed. LGTM.

@zeroshade zeroshade merged commit adbc4cf into apache:main Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants