@@ -686,3 +686,76 @@ def test_table_rollback_to_nonexistent_tag(self):
686686 table .rollback_to ("no-such-tag" )
687687 self .assertIn ("no-such-tag" , str (context .exception ))
688688 self .assertIn ("doesn't exist" , str (context .exception ))
689+
690+ def test_table_rollback_to_timestamp (self ):
691+ """Test table-level rollback to a timestamp."""
692+ schema = Schema .from_pyarrow_schema (
693+ self .pa_schema ,
694+ primary_keys = ['pt' , 'k' ],
695+ partition_keys = ['pt' ],
696+ options = {'bucket' : '3' }
697+ )
698+ self .catalog .create_table ('default.test_rollback_ts' , schema , False )
699+ table = self .catalog .get_table ('default.test_rollback_ts' )
700+
701+ write_builder = table .new_batch_write_builder ()
702+
703+ # Write 5 commits
704+ for i in range (5 ):
705+ table_write = write_builder .new_write ()
706+ table_commit = write_builder .new_commit ()
707+ data = pa .Table .from_pydict ({
708+ 'pt' : [1 ],
709+ 'k' : [i ],
710+ 'v' : [i * 100 ]
711+ }, schema = self .pk_pa_schema )
712+ table_write .write_arrow (data )
713+ table_commit .commit (table_write .prepare_commit ())
714+ table_write .close ()
715+ table_commit .close ()
716+
717+ snapshot_mgr = table .snapshot_manager ()
718+ self .assertEqual (snapshot_mgr .get_latest_snapshot ().id , 5 )
719+
720+ # Get the timestamp of snapshot 3 and rollback to it
721+ snap3 = snapshot_mgr .get_snapshot_by_id (3 )
722+ table .rollback_to_timestamp (snap3 .time_millis )
723+
724+ self .assertEqual (snapshot_mgr .get_latest_snapshot ().id , 3 )
725+ self .assertIsNone (snapshot_mgr .get_snapshot_by_id (4 ))
726+ self .assertIsNone (snapshot_mgr .get_snapshot_by_id (5 ))
727+
728+ def test_table_rollback_to_timestamp_no_match (self ):
729+ """Test rollback_to_timestamp raises ValueError when no snapshot exists."""
730+ schema = Schema .from_pyarrow_schema (
731+ self .pa_schema ,
732+ primary_keys = ['pt' , 'k' ],
733+ partition_keys = ['pt' ],
734+ options = {'bucket' : '3' }
735+ )
736+ self .catalog .create_table ('default.test_rollback_ts_nomatch' , schema , False )
737+ table = self .catalog .get_table ('default.test_rollback_ts_nomatch' )
738+
739+ write_builder = table .new_batch_write_builder ()
740+
741+ # Write 1 commit
742+ table_write = write_builder .new_write ()
743+ table_commit = write_builder .new_commit ()
744+ data = pa .Table .from_pydict ({
745+ 'pt' : [1 ],
746+ 'k' : [0 ],
747+ 'v' : [100 ]
748+ }, schema = self .pk_pa_schema )
749+ table_write .write_arrow (data )
750+ table_commit .commit (table_write .prepare_commit ())
751+ table_write .close ()
752+ table_commit .close ()
753+
754+ # Use a timestamp before the first snapshot
755+ snapshot_mgr = table .snapshot_manager ()
756+ earliest = snapshot_mgr .try_get_earliest_snapshot ()
757+ before_earliest = earliest .time_millis - 1
758+
759+ with self .assertRaises (ValueError ) as context :
760+ table .rollback_to_timestamp (before_earliest )
761+ self .assertIn ("No snapshot found" , str (context .exception ))
0 commit comments