LuciferYang opened a new pull request, #9561:
URL: https://github.com/apache/paimon/pull/9561

   ### Purpose
   
   close #9560
   
   `RowFileFormat.createReaderFactory` built one `NestedProjectedRow` and 
`RowFormatReaderFactory` handed that same instance to every reader it created. 
The iterator mutates the wrapper in place per row, and 
`NestedProjectedRow.replaceRow` returns `this`, so two readers from one factory 
hand out the same row object: reading from one overwrites the row whose 
consumer is still holding it. That breaks `RecordReader.readBatch`, which 
documents that the returned iterator and the objects in it may be held onto for 
some time and should not be reused. This creates the projection per reader 
instead.
   
   Any consumer that holds a row from one reader while advancing another reader 
of the same factory is affected. In this codebase that is merge-on-read: 
`KeyValueFileReaderFactory` caches one `FormatReaderMapping` per `(schemaId, 
formatIdentifier)`, `MergeTreeReaders` opens one reader per sorted run through 
it, and `SortMergeReaderWithMinHeap` and the loser tree hold each run's current 
`KeyValue` while advancing the others. That path is traced from the code and 
not reproduced here: it needs a primary-key table with `file.format = 'row'`, 
two overlapping sorted runs, and a column projection.
   
   The change also drops the `@Nullable` on `projectedRowType`. It was correct 
on the `NestedProjectedRow` field it replaced, since `create` returns null when 
the two schemas are equal, but not on a `RowType` that `create` dereferences; 
`FileFormat.createReaderFactory` declares only `filters` as nullable and all 
call sites pass a real `RowType`.
   
   ### Tests
   
   `RowFormatReadWriteTest.testInterleavedReadersDoNotShareProjectedRow` writes 
two single-row files, opens a reader for each from one factory, reads a row 
from A, then reads from B and checks that A's row is neither the same object as 
B's nor overwritten. The projection has to drop a column: with an identical 
schema `NestedProjectedRow.create` returns null, no wrapper is involved, and 
the test would pass against the old code too. The comment in the test says so.
   
   Against the pre-fix code it fails on `assertThat(rowA).isNotSameAs(rowB)` 
with `Expected not same: org.apache.paimon.utils.NestedProjectedRow@...`, which 
names the mechanism rather than just a wrong value. The final assertion is not 
redundant with it: two distinct wrappers over one shared underlying row would 
satisfy `isNotSameAs` and still fail the value check.
   
   `mvn -pl paimon-format test` on JDK 8: 597 tests, 0 failures. 
`spotless:check` and `checkstyle:check` are clean.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to