@@ -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+
19832025def 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
0 commit comments