wangzhigang1999 opened a new issue, #9819:
URL: https://github.com/apache/paimon/issues/9819

   ### Search before asking
   
   - [x] I searched in the issues and found nothing similar.
   
   ### Paimon version
   
   Apache Paimon master, commit `c081ccd0d7003ceae2517c6b592a947e824acc25`.
   
   ### Compute Engine
   
   PyPaimon, Python 3.12.6, PyArrow 19.0.1.
   
   ### Minimal reproduce step
   
   A primary-key merge read fails when an input reader returns an empty batch 
after a non-empty batch. The following example uses the reader interfaces to 
reproduce the batch transition without external storage. Run it with 
`PYTHONPATH` pointing to `paimon-python`:
   
   ```python
   from pypaimon.read.reader.iface.record_iterator import RecordIterator
   from pypaimon.read.reader.iface.record_reader import RecordReader
   from pypaimon.read.reader.sort_merge_reader import SortMergeReaderWithMinHeap
   from pypaimon.schema.data_types import AtomicType, DataField
   from pypaimon.schema.table_schema import TableSchema
   from pypaimon.table.row.key_value import KeyValue
   from pypaimon.table.row.row_kind import RowKind
   
   
   class BatchIterator(RecordIterator):
       def __init__(self, rows):
           self.rows = iter(rows)
   
       def next(self):
           return next(self.rows, None)
   
   
   class BatchReader(RecordReader):
       def __init__(self, batches):
           self.batches = iter(batches)
   
       def read_batch(self):
           batch = next(self.batches, None)
           return None if batch is None else BatchIterator(batch)
   
       def close(self):
           pass
   
   
   def kv(key):
       return KeyValue(1, 1).replace((key, 1, RowKind.INSERT.value, key))
   
   
   schema = TableSchema(
       fields=[DataField(0, "id", AtomicType("INT"))], primary_keys=["id"])
   reader = SortMergeReaderWithMinHeap(
       [BatchReader([[kv(1)], [], [], [kv(2)], []])], schema)
   try:
       result = []
       while True:
           batch = reader.read_batch()
           if batch is None:
               break
           while True:
               record = batch.next()
               if record is None:
                   break
               result.append(record.key.get_field(0))
       assert result == [1, 2], result
       print(result)
   finally:
       reader.close()
   ```
   
   ### What doesn't meet your expectations?
   
   Expected: read both records and print `[1, 2]`. An empty batch should not 
end the reader; only `read_batch()` returning `None` indicates EOF.
   
   Actual: the second call to the merge iterator raises:
   
   ```text
     File "pypaimon/read/reader/sort_merge_reader.py", line 127, in _next_impl
       entry = HeapEntry(element.kv.key, element, self.key_comparator,
   AttributeError: 'NoneType' object has no attribute 'key'
   ```
   
   ### Anything else?
   
   In `Element.update()`, after exhausting the current batch, we read one more 
batch and assign its first record to `self.kv`. If that batch is empty, we 
assign `None` but return `True`. The caller then accesses `element.kv.key`.
   
   I also reproduced this through table writes, commits, and a filtered read 
using local files: a full scan returns 6,144 rows, while the filtered scan 
fails with the same exception. With the fix, the filtered scan returns the 
expected four rows and values.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!
   


-- 
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