5151 write_manifest_list ,
5252)
5353from pyiceberg .partitioning import PartitionSpec
54- from pyiceberg .schema import Schema
5554from pyiceberg .table .refs import MAIN_BRANCH , SnapshotRefType
5655from pyiceberg .table .snapshots import (
5756 Operation ,
7473 UpdatesAndRequirements ,
7574 UpdateTableMetadata ,
7675)
77- from pyiceberg .typedef import EMPTY_DICT , KeyDefaultDict , Record
76+ from pyiceberg .typedef import EMPTY_DICT , KeyDefaultDict
7877from pyiceberg .utils .bin_packing import ListPacker
7978from pyiceberg .utils .concurrent import ExecutorFactory
8079from pyiceberg .utils .datetime import datetime_to_millis
@@ -229,8 +228,13 @@ def _process_manifests(self, manifests: list[ManifestFile]) -> list[ManifestFile
229228 def _manifests (self ) -> list [ManifestFile ]:
230229 def _write_added_manifest () -> list [ManifestFile ]:
231230 if self ._added_data_files :
232- with self .new_manifest_writer (
231+ with write_manifest (
232+ format_version = self ._transaction .table_metadata .format_version ,
233233 spec = self ._transaction .table_metadata .spec (),
234+ schema = self ._transaction .table_metadata .schema (),
235+ output_file = self .new_manifest_output (),
236+ snapshot_id = self ._snapshot_id ,
237+ avro_compression = self ._compression ,
234238 ) as writer :
235239 for data_file in self ._added_data_files :
236240 writer .add (
@@ -255,17 +259,21 @@ def _write_delete_manifest() -> list[ManifestFile]:
255259 for deleted_entry in deleted_entries :
256260 partition_groups [deleted_entry .data_file .spec_id ].append (deleted_entry )
257261 for spec_id , entries in partition_groups .items ():
258- with self .new_manifest_writer (self .spec (spec_id )) as writer :
262+ with write_manifest (
263+ format_version = self ._transaction .table_metadata .format_version ,
264+ spec = self ._transaction .table_metadata .specs ()[spec_id ],
265+ schema = self ._transaction .table_metadata .schema (),
266+ output_file = self .new_manifest_output (),
267+ snapshot_id = self ._snapshot_id ,
268+ avro_compression = self ._compression ,
269+ ) as writer :
259270 for entry in entries :
260271 writer .add_entry (entry )
261272 deleted_manifests .append (writer .to_manifest_file ())
262273 return deleted_manifests
263274 else :
264275 return []
265276
266- # Updates self._predicate with computed partition predicate for manifest pruning
267- self ._build_delete_files_partition_predicate ()
268-
269277 executor = ExecutorFactory .get_or_create ()
270278
271279 added_manifests = executor .submit (_write_added_manifest )
@@ -385,17 +393,14 @@ def _commit(self) -> UpdatesAndRequirements:
385393 def snapshot_id (self ) -> int :
386394 return self ._snapshot_id
387395
388- def schema (self ) -> Schema :
389- return self ._transaction .table_metadata .schema ()
390-
391396 def spec (self , spec_id : int ) -> PartitionSpec :
392397 return self ._transaction .table_metadata .specs ()[spec_id ]
393398
394399 def new_manifest_writer (self , spec : PartitionSpec ) -> ManifestWriter :
395400 return write_manifest (
396401 format_version = self ._transaction .table_metadata .format_version ,
397402 spec = spec ,
398- schema = self .schema (),
403+ schema = self ._transaction . table_metadata . schema (),
399404 output_file = self .new_manifest_output (),
400405 snapshot_id = self ._snapshot_id ,
401406 avro_compression = self ._compression ,
@@ -506,35 +511,22 @@ def _validate_concurrency(self) -> None:
506511 )
507512
508513 def _build_partition_projection (self , spec_id : int ) -> BooleanExpression :
509- project = inclusive_projection (self .schema (), self .spec (spec_id ), self ._case_sensitive )
514+ schema = self ._transaction .table_metadata .schema ()
515+ project = inclusive_projection (schema , self .spec (spec_id ), self ._case_sensitive )
510516 return project (self ._predicate )
511517
512518 @cached_property
513519 def partition_filters (self ) -> KeyDefaultDict [int , BooleanExpression ]:
514520 return KeyDefaultDict (self ._build_partition_projection )
515521
516522 def _build_manifest_evaluator (self , spec_id : int ) -> Callable [[ManifestFile ], bool ]:
517- return manifest_evaluator (self .spec (spec_id ), self .schema (), self .partition_filters [spec_id ], self ._case_sensitive )
523+ schema = self ._transaction .table_metadata .schema ()
524+ return manifest_evaluator (self .spec (spec_id ), schema , self .partition_filters [spec_id ], self ._case_sensitive )
518525
519526 def delete_by_predicate (self , predicate : BooleanExpression , case_sensitive : bool = True ) -> None :
520527 self ._predicate = Or (self ._predicate , predicate )
521528 self ._case_sensitive = case_sensitive
522529
523- def _build_delete_files_partition_predicate (self ) -> None :
524- """Build BooleanExpression based on deleted data files partitions."""
525- partition_to_overwrite : dict [int , set [Record ]] = {}
526- for data_file in self ._deleted_data_files :
527- group = partition_to_overwrite .setdefault (data_file .spec_id , set ())
528- group .add (data_file .partition )
529-
530- for spec_id , partition_records in partition_to_overwrite .items ():
531- self .delete_by_predicate (
532- self ._transaction ._build_partition_predicate (
533- partition_records = partition_records , schema = self .schema (), spec = self .spec (spec_id )
534- ),
535- self ._case_sensitive ,
536- )
537-
538530
539531class _DeleteFiles (_SnapshotProducer ["_DeleteFiles" ]):
540532 """Will delete manifest entries from the current snapshot based on the predicate.
@@ -637,7 +629,14 @@ def _copy_with_new_status(entry: ManifestEntry, status: ManifestEntryStatus) ->
637629
638630 # Rewrite the manifest
639631 if len (existing_entries ) > 0 :
640- with self .new_manifest_writer (spec = self .spec (manifest_file .partition_spec_id )) as writer :
632+ with write_manifest (
633+ format_version = self ._transaction .table_metadata .format_version ,
634+ spec = self ._transaction .table_metadata .specs ()[manifest_file .partition_spec_id ],
635+ schema = self ._transaction .table_metadata .schema (),
636+ output_file = self .new_manifest_output (),
637+ snapshot_id = self ._snapshot_id ,
638+ avro_compression = self ._compression ,
639+ ) as writer :
641640 for existing_entry in existing_entries :
642641 writer .add_entry (existing_entry )
643642 existing_manifests .append (writer .to_manifest_file ())
@@ -772,46 +771,36 @@ def _existing_manifests(self) -> list[ManifestFile]:
772771 """Determine if there are any existing manifest files."""
773772 existing_files = []
774773
775- manifest_evaluators : dict [int , Callable [[ManifestFile ], bool ]] = KeyDefaultDict (self ._build_manifest_evaluator )
776774 if snapshot := self ._transaction .table_metadata .snapshot_by_name (name = self ._target_branch ):
777775 for manifest_file in snapshot .manifests (io = self ._io ):
778- # Manifest does not contain rows that match the files to delete partitions
779- if not manifest_evaluators [manifest_file .partition_spec_id ](manifest_file ):
780- existing_files .append (manifest_file )
781- continue
782-
783- entries_to_write : set [ManifestEntry ] = set ()
784- found_deleted_entries : set [ManifestEntry ] = set ()
776+ entries = manifest_file .fetch_manifest_entry (io = self ._io , discard_deleted = True )
777+ found_deleted_data_files = [entry .data_file for entry in entries if entry .data_file in self ._deleted_data_files ]
785778
786- for entry in manifest_file .fetch_manifest_entry (io = self ._io , discard_deleted = True ):
787- if entry .data_file in self ._deleted_data_files :
788- found_deleted_entries .add (entry )
789- else :
790- entries_to_write .add (entry )
791-
792- # Is the intercept the empty set?
793- if len (found_deleted_entries ) == 0 :
779+ if len (found_deleted_data_files ) == 0 :
794780 existing_files .append (manifest_file )
795- continue
796-
797- # Delete all files from manifest
798- if len (entries_to_write ) == 0 :
799- continue
800-
801- # We have to rewrite the manifest file without the deleted data files
802- with self .new_manifest_writer (self .spec (manifest_file .partition_spec_id )) as writer :
803- for entry in entries_to_write :
804- writer .add_entry (
805- ManifestEntry .from_args (
806- status = ManifestEntryStatus .EXISTING ,
807- snapshot_id = entry .snapshot_id ,
808- sequence_number = entry .sequence_number ,
809- file_sequence_number = entry .file_sequence_number ,
810- data_file = entry .data_file ,
811- )
812- )
813- existing_files .append (writer .to_manifest_file ())
814-
781+ else :
782+ # We have to rewrite the manifest file without the deleted data files
783+ if any (entry .data_file not in found_deleted_data_files for entry in entries ):
784+ with write_manifest (
785+ format_version = self ._transaction .table_metadata .format_version ,
786+ spec = self ._transaction .table_metadata .specs ()[manifest_file .partition_spec_id ],
787+ schema = self ._transaction .table_metadata .schema (),
788+ output_file = self .new_manifest_output (),
789+ snapshot_id = self ._snapshot_id ,
790+ avro_compression = self ._compression ,
791+ ) as writer :
792+ for entry in entries :
793+ if entry .data_file not in found_deleted_data_files :
794+ writer .add_entry (
795+ ManifestEntry .from_args (
796+ status = ManifestEntryStatus .EXISTING ,
797+ snapshot_id = entry .snapshot_id ,
798+ sequence_number = entry .sequence_number ,
799+ file_sequence_number = entry .file_sequence_number ,
800+ data_file = entry .data_file ,
801+ )
802+ )
803+ existing_files .append (writer .to_manifest_file ())
815804 return existing_files
816805
817806 def _deleted_entries (self ) -> list [ManifestEntry ]:
@@ -828,12 +817,8 @@ def _deleted_entries(self) -> list[ManifestEntry]:
828817 raise ValueError (f"Could not find the previous snapshot: { self ._parent_snapshot_id } " )
829818
830819 executor = ExecutorFactory .get_or_create ()
831- manifest_evaluators : dict [int , Callable [[ManifestFile ], bool ]] = KeyDefaultDict (self ._build_manifest_evaluator )
832820
833821 def _get_entries (manifest : ManifestFile ) -> list [ManifestEntry ]:
834- if not manifest_evaluators [manifest .partition_spec_id ](manifest ):
835- return []
836-
837822 return [
838823 ManifestEntry .from_args (
839824 status = ManifestEntryStatus .DELETED ,
0 commit comments