This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new eaeac0b93c [python] Fix bucket registration for dynamic bucket 
overflow (#9788)
eaeac0b93c is described below

commit eaeac0b93c499eb13798845f10591cb83e66eced
Author: QuakeWang <[email protected]>
AuthorDate: Mon Sep 14 10:52:10 2026 +0800

    [python] Fix bucket registration for dynamic bucket overflow (#9788)
---
 .../write/simple_hash_bucket_assigner_test.py      | 39 ++++++++++++++++++++++
 paimon-python/pypaimon/write/row_key_extractor.py  |  2 +-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git 
a/paimon-python/pypaimon/tests/write/simple_hash_bucket_assigner_test.py 
b/paimon-python/pypaimon/tests/write/simple_hash_bucket_assigner_test.py
index 8bc19fd084..6a7b78c2bd 100644
--- a/paimon-python/pypaimon/tests/write/simple_hash_bucket_assigner_test.py
+++ b/paimon-python/pypaimon/tests/write/simple_hash_bucket_assigner_test.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import unittest
+from unittest.mock import patch
 
 from pypaimon.write.row_key_extractor import SimpleHashBucketAssigner
 
@@ -55,6 +56,44 @@ class SimpleHashBucketAssignerTest(unittest.TestCase):
                 for b in buckets[100:]:
                     self.assertEqual(b, 0)
 
+    def test_register_each_bucket_once(self):
+        for num_assigners, assign_id, max_buckets, expected in [
+            (1, 0, 1, [0, 0, 0, 0, 0, 0]),
+            (1, 0, 3, [0, 0, 1, 1, 2, 2]),
+            (1, 0, -1, [0, 0, 1, 1, 2, 2]),
+            (2, 1, 6, [1, 1, 3, 3, 5, 5]),
+        ]:
+            with self.subTest(num_assigners=num_assigners, assign_id=assign_id,
+                              max_buckets=max_buckets):
+                assigner = SimpleHashBucketAssigner(num_assigners, assign_id, 
2, max_buckets)
+                for h, expected_bucket in enumerate(expected):
+                    self.assertEqual(assigner.assign((), h), expected_bucket)
+                    index = assigner._partition_index[()]
+                    self.assertCountEqual(index.bucket_list, 
index.bucket_information)
+
+    def test_overflow_uses_all_registered_buckets(self):
+        assigner = SimpleHashBucketAssigner(1, 0, 2, 3)
+        initial = [assigner.assign((), h) for h in range(6)]
+        self.assertEqual(initial, [0, 0, 1, 1, 2, 2])
+        index = assigner._partition_index[()]
+
+        with patch('pypaimon.write.row_key_extractor.random.choice') as choice:
+            for h, selected in enumerate([0, 1, 2, 0, 1, 2], start=6):
+                choice.return_value = selected
+                self.assertEqual(assigner.assign((), h), selected)
+                choice.assert_called_with([0, 1, 2])
+                self.assertCountEqual(index.bucket_list, [0, 1, 2])
+            self.assertEqual(choice.call_count, 6)
+            self.assertEqual(index.bucket_information, {0: 4, 1: 4, 2: 4})
+            self.assertEqual(assigner.max_bucket_id, 2)
+
+            choice.reset_mock()
+            repeated = [assigner.assign((), h) for h in range(12)]
+            self.assertEqual(repeated, initial + [0, 1, 2, 0, 1, 2])
+            choice.assert_not_called()
+            self.assertEqual(index.bucket_information, {0: 4, 1: 4, 2: 4})
+            self.assertCountEqual(index.bucket_list, [0, 1, 2])
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/paimon-python/pypaimon/write/row_key_extractor.py 
b/paimon-python/pypaimon/write/row_key_extractor.py
index 3313620d7d..827b9f08b2 100644
--- a/paimon-python/pypaimon/write/row_key_extractor.py
+++ b/paimon-python/pypaimon/write/row_key_extractor.py
@@ -353,7 +353,6 @@ class _SimplePartitionIndex:
             return assigned, max(max_bucket_id, assigned)
 
         if self.current_bucket not in self.bucket_information:
-            self.bucket_list.append(self.current_bucket)
             self.bucket_information[self.current_bucket] = 0
         num = self.bucket_information[self.current_bucket]
 
@@ -383,6 +382,7 @@ class _SimplePartitionIndex:
             ):
                 if max_buckets_num == -1 or i <= max_buckets_num - 1:
                     self.current_bucket = i
+                    self.bucket_list.append(i)
                     return
                 return
         raise RuntimeError(

Reply via email to