镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

[client-v2] Keep row buffers across Native blocks so rows at a block boundary are not lost - #3294

Open
piyush15102003 wants to merge 1 commit into
ClickHouse:mainfrom
piyush15102003:fix/native-block-boundary-rows
Open

piyush15102003 wants to merge 1 commit into
ClickHouse:mainfrom
piyush15102003:fix/native-block-boundary-rows

Conversation

@piyush15102003

@piyush15102003 piyush15102003 commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Reading a Native result that spans more than one block lost two rows at every block boundary: the last row of a block and the first row of the next were returned as all-null rows, with the row count unchanged and no error.

AbstractBinaryFormatReader reads one row ahead. When the read-ahead starts a new block, NativeFormatReader.readBlock() calls setSchema(), which replaced both row buffers. The read-ahead then wrote the new block's first row into the old nextRecord array, and next() wrapped the freshly allocated, empty currentRecord.

Changes:

  • setSchema() allocates currentRecord / nextRecord only when they are null or the column count differs, so the first call (constructor, RowBinaryWithNamesAndTypes header) still allocates them.
  • next() takes the record reference before the read-ahead, so the returned row does not depend on what the read-ahead does to the fields.

Closes #3151

Checklist


Note

Medium Risk
Touches core Native/binary row iteration where incorrect behavior silently corrupted values; the fix is narrow and covered by new regression tests.

Overview
Fixes silent data loss when reading multi-block Native query results in client-v2: at every block boundary the last row of one block and the first row of the next were replaced by all-null rows while the row count stayed the same.

The reader read-aheads one row; starting the next block re-publishes the schema via setSchema(), which used to always allocate new currentRecord / nextRecord buffers and left next() wrapping empty arrays after the read-ahead. setSchema() now reuses those buffers when the column count is unchanged, and next() captures the row array reference before readNextRecord() so returned rows are not tied to buffer swaps during read-ahead.

Adds NativeFormatReaderBlockBoundaryTest (multi-block and 1-row blocks, via next() and typed getters) and a changelog note for #3151.

Reviewed by Cursor Bugbot for commit ed0e317. Bugbot is set up for automated code reviews on this repo. Configure here.

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.

[client-v2] Native format: two rows are silently lost and returned as all-null at every block boundary

1 participant