Commit 48e710d
authored
fix: preserve manifest min sequence number of 0 (#3660)
# Rationale for this change
`ManifestWriter.to_manifest_file()` computed the manifest's minimum data
sequence number with a truthiness fallback:
```python
min_sequence_number = self._min_sequence_number or UNASSIGNED_SEQ
```
A data sequence number of `0` is a legitimate minimum for a live file
(files
from a v1 table, or the initial commit of a v2 table). Because `0` is
falsy,
`or` collapses it to `UNASSIGNED_SEQ` (`-1`), i.e. it treats a real `0`
the same
as "unset".
This diverges from the Java reference implementation, which falls back
to
`UNASSIGNED_SEQ` only when the value is actually unset:
```java
// ManifestWriter#toManifestFile (apache/iceberg)
long minSeqNumber = minDataSequenceNumber != null ? minDataSequenceNumber : UNASSIGNED_SEQ;
```
The `-1` is not harmless. When the manifest is produced by a
merge/compaction
(so its `added_snapshot_id` equals the current commit snapshot id),
`ManifestListWriter.prepare_manifest()` treats `min_sequence_number ==
UNASSIGNED_SEQ` as "no file had an assigned sequence number" and
overwrites it
with the current, higher commit sequence number
(`pyiceberg/manifest.py`, the `if
wrapped_manifest_file.min_sequence_number ==
UNASSIGNED_SEQ:` branch). The manifest's minimum data sequence number is
thereby
silently raised, which affects sequence-number-based delete-file
application and
scans.
The fix uses an explicit `None` check instead of a truthiness fallback,
mirroring the Java writer:
```python
min_sequence_number = self._min_sequence_number if self._min_sequence_number is not None else UNASSIGNED_SEQ
```
## Are these changes tested?
Yes. A new parametrized regression test,
`tests/utils/test_manifest.py::test_write_manifest_min_sequence_number_zero`
(format versions 1 and 2), drives a live `EXISTING` entry with
`sequence_number=0` through `ManifestWriter.existing()` and asserts that
`to_manifest_file().min_sequence_number == 0`.
The test fails before the fix (`assert -1 == 0`) and passes after it.
This path
had no prior coverage: no existing test drove a live sequence-0 entry
through
`to_manifest_file()`, which is why the defect was not caught.
Local runs (unit tests):
- `pytest tests/utils/test_manifest.py -q` -> passes.
- `pytest tests/table/test_snapshots.py
tests/table/test_manage_snapshots.py -q`
-> passes.
- `make lint` (ruff, ruff-format, mypy, pydocstyle, codespell) -> clean
on the
changed files.
The merge/compaction integration path exercised by `prepare_manifest()`
is
covered by the integration suite, which requires Docker and Spark; those
were
not run locally. The new unit test exercises the same
`to_manifest_file()` write
path that feeds it.
## Are there any user-facing changes?
No API changes. It is a correctness fix: manifests written for live
files whose
minimum data sequence number is `0` now record `0` instead of `-1`, so a
subsequent merge/compaction no longer silently raises the manifest's
minimum
data sequence number.
Signed-off-by: Anas Khan <83116240+anxkhn@users.noreply.github.com>1 parent 8a31e79 commit 48e710d
2 files changed
Lines changed: 45 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1145 | 1145 | | |
1146 | 1146 | | |
1147 | 1147 | | |
1148 | | - | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
1149 | 1151 | | |
1150 | 1152 | | |
1151 | 1153 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
938 | 938 | | |
939 | 939 | | |
940 | 940 | | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
941 | 983 | | |
942 | 984 | | |
943 | 985 | | |
| |||
0 commit comments