Skip to content

Commit e71c8d1

Browse files
committed
Test external single and packed deletion vector fixtures
1 parent 0e99544 commit e71c8d1

4 files changed

Lines changed: 67 additions & 0 deletions

File tree

‎tests/io/test_pyarrow.py‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,48 @@ def test_read_all_delete_files_keeps_multiple_dv_content_ranges_for_same_path(tm
19801980
assert sorted(delete.to_pylist() for delete in deletes[referenced_data_file]) == [[1, 3], [5]]
19811981

19821982

1983+
def test_read_all_delete_files_from_external_packed_deletion_vectors() -> None:
1984+
"""Read all DV ranges from an externally generated .bin file without losing entries to deduplication."""
1985+
fixture_path = Path(__file__).parents[1] / "table" / "deletion_vector" / "v1" / "packed-deletion-vectors.bin"
1986+
# (content_offset, content_size_in_bytes, expected deleted row positions)
1987+
# Ranges copied from the fixture's V3 manifest; each DV references a different ten-row data file.
1988+
content_ranges = [
1989+
(1, 46, [1, 4, 7]),
1990+
(47, 48, [0, 3, 6, 9]),
1991+
(95, 42, [0]),
1992+
(137, 50, [1, 3, 5, 7, 9]),
1993+
(187, 52, [0, 2, 4, 6, 8, 9]),
1994+
(239, 44, [0, 2]),
1995+
]
1996+
tasks = []
1997+
expected_deletes = {}
1998+
for index, (content_offset, content_size_in_bytes, expected_positions) in enumerate(content_ranges):
1999+
referenced_data_file = f"data-{index}.parquet"
2000+
dv = DataFile.from_args(
2001+
_table_format_version=3,
2002+
content=DataFileContent.POSITION_DELETES,
2003+
file_path=str(fixture_path),
2004+
file_format=FileFormat.PUFFIN,
2005+
record_count=len(expected_positions),
2006+
content_offset=content_offset,
2007+
content_size_in_bytes=content_size_in_bytes,
2008+
referenced_data_file=referenced_data_file,
2009+
)
2010+
data_file = DataFile.from_args(
2011+
content=DataFileContent.DATA,
2012+
file_path=referenced_data_file,
2013+
file_format=FileFormat.PARQUET,
2014+
record_count=10,
2015+
file_size_in_bytes=100,
2016+
)
2017+
tasks.append(FileScanTask(data_file=data_file, delete_files=[dv]))
2018+
expected_deletes[referenced_data_file] = [pa.chunked_array([expected_positions])]
2019+
2020+
deletes = _read_all_delete_files(PyArrowFileIO(), tasks)
2021+
2022+
assert deletes == expected_deletes
2023+
2024+
19832025
def test_delete(deletes_file: str, request: pytest.FixtureRequest, table_schema_simple: Schema) -> None:
19842026
# Determine file format from the file extension
19852027
file_format = FileFormat.PARQUET if deletes_file.endswith(".parquet") else FileFormat.ORC
47 Bytes
Binary file not shown.
283 Bytes
Binary file not shown.

‎tests/table/test_deletion_vector.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,19 @@
1717
import struct
1818
import zlib
1919
from os import path
20+
from pathlib import Path
2021

2122
import pytest
2223
from pyroaring import BitMap
2324

25+
from pyiceberg.io.pyarrow import PyArrowFileIO
2426
from pyiceberg.manifest import DataFile, DataFileContent, FileFormat
2527
from pyiceberg.table.deletion_vector import (
2628
_DV_BLOB_MAGIC_NUMBER,
2729
DeletionVector,
2830
_deserialize_dv_blob,
2931
has_deletion_vector_content_reference,
32+
read_deletion_vectors,
3033
)
3134

3235

@@ -101,6 +104,28 @@ def test_has_deletion_vector_content_reference() -> None:
101104
assert has_deletion_vector_content_reference(_data_file(referenced_data_file="data.parquet"))
102105

103106

107+
def test_read_external_deletion_vector_content_range() -> None:
108+
"""Read an externally generated Iceberg DV blob from a .bin content range."""
109+
fixture_path = Path(__file__).parent / "deletion_vector" / "v1" / "deletion-vector.bin"
110+
# The V3 manifest points past the one-byte file prefix to the complete DV blob.
111+
dv = DataFile.from_args(
112+
_table_format_version=3,
113+
content=DataFileContent.POSITION_DELETES,
114+
file_path=str(fixture_path),
115+
file_format=FileFormat.PUFFIN,
116+
record_count=3,
117+
content_offset=1,
118+
content_size_in_bytes=46,
119+
referenced_data_file="data.parquet",
120+
)
121+
122+
deletion_vectors = read_deletion_vectors(PyArrowFileIO(), dv)
123+
124+
assert len(deletion_vectors) == 1
125+
assert deletion_vectors[0].referenced_data_file == "data.parquet"
126+
assert deletion_vectors[0].to_vector().to_pylist() == [1, 4, 5]
127+
128+
104129
def test_map_empty() -> None:
105130
puffin = _open_file("64mapempty.bin")
106131

0 commit comments

Comments
 (0)