@@ -6027,6 +6027,149 @@ def test_primary_key_managed_blob_requires_native_writer(self):
60276027 }, schema = pa_schema ))
60286028 writer .close ()
60296029
6030+ def test_postpone_fixed_bucket_pk_inline_blob_write_row_new_partition (self ):
6031+ from pypaimon import Schema
6032+ from pypaimon .table .row .blob import Blob , BlobDescriptor , BlobViewStruct
6033+ from pypaimon .table .row .generic_row import GenericRow
6034+
6035+ pk_pa_schema = pa .schema ([
6036+ pa .field ('pt' , pa .string (), nullable = False ),
6037+ pa .field ('id' , pa .int32 (), nullable = False ),
6038+ pa .field ('picture' , pa .large_binary ()),
6039+ ])
6040+ with self .subTest (field = 'blob-descriptor-field' ):
6041+ blob_file = os .path .join (self .temp_dir , 'postpone_pk_descriptor.bin' )
6042+ with open (blob_file , 'wb' ) as f :
6043+ f .write (b'postpone-desc-0postpone-desc-1' )
6044+ desc_0 = BlobDescriptor (blob_file , 0 , 15 )
6045+ desc_1 = BlobDescriptor (blob_file , 15 , 15 )
6046+
6047+ desc_schema = Schema .from_pyarrow_schema (
6048+ pk_pa_schema ,
6049+ primary_keys = ['pt' , 'id' ],
6050+ partition_keys = ['pt' ],
6051+ options = {
6052+ 'bucket' : '-2' ,
6053+ 'postpone.batch-write-fixed-bucket' : 'true' ,
6054+ 'blob-descriptor-field' : 'picture' ,
6055+ 'write.native.enabled' : 'false' ,
6056+ },
6057+ )
6058+ self .catalog .create_table ('test_db.pk_postpone_blob_descriptor' , desc_schema , False )
6059+ desc_table = self .catalog .get_table ('test_db.pk_postpone_blob_descriptor' )
6060+
6061+ desc_wb = desc_table .new_postpone_fixed_bucket_write_builder ()
6062+ desc_writer = desc_wb .new_write ()
6063+ try :
6064+ desc_writer .write_row (GenericRow (
6065+ [
6066+ 'p0' ,
6067+ 1 ,
6068+ Blob .from_descriptor_bytes (
6069+ desc_0 .serialize (), file_io = desc_table .file_io
6070+ ),
6071+ ],
6072+ desc_table .fields ,
6073+ ))
6074+ desc_writer .write_row (GenericRow (
6075+ [
6076+ 'p1' ,
6077+ 2 ,
6078+ Blob .from_descriptor_bytes (
6079+ desc_1 .serialize (), file_io = desc_table .file_io
6080+ ),
6081+ ],
6082+ desc_table .fields ,
6083+ ))
6084+ messages = desc_writer .prepare_commit ()
6085+ self .assertEqual ({message .partition for message in messages }, {('p0' ,), ('p1' ,)})
6086+ for message in messages :
6087+ self .assertEqual (message .total_buckets , 1 )
6088+ desc_wb .new_commit ().commit (messages )
6089+ finally :
6090+ desc_writer .close ()
6091+
6092+ desc_rb = desc_table .new_read_builder ()
6093+ desc_result = desc_rb .new_read ().to_arrow (
6094+ desc_rb .new_scan ().plan ().splits ()
6095+ ).sort_by ('id' )
6096+ self .assertEqual (desc_result .column ('pt' ).to_pylist (), ['p0' , 'p1' ])
6097+ self .assertEqual (desc_result .column ('id' ).to_pylist (), [1 , 2 ])
6098+ self .assertEqual (
6099+ desc_result .column ('picture' ).to_pylist (),
6100+ [b'postpone-desc-0' , b'postpone-desc-1' ],
6101+ )
6102+
6103+ with self .subTest (field = 'blob-view-field' ):
6104+ source_schema = pa .schema ([
6105+ ('id' , pa .int32 ()),
6106+ ('picture' , pa .large_binary ()),
6107+ ])
6108+ source = Schema .from_pyarrow_schema (
6109+ source_schema ,
6110+ options = {
6111+ 'row-tracking.enabled' : 'true' ,
6112+ 'data-evolution.enabled' : 'true' ,
6113+ },
6114+ )
6115+ self .catalog .create_table ('test_db.pk_postpone_view_source' , source , False )
6116+ source_table = self .catalog .get_table ('test_db.pk_postpone_view_source' )
6117+ src_wb = source_table .new_batch_write_builder ()
6118+ src_writer = src_wb .new_write ()
6119+ src_writer .write_arrow (pa .Table .from_pydict ({
6120+ 'id' : [10 , 20 ],
6121+ 'picture' : [b'postpone-view-0' , b'postpone-view-1' ],
6122+ }, schema = source_schema ))
6123+ src_wb .new_commit ().commit (src_writer .prepare_commit ())
6124+ src_writer .close ()
6125+
6126+ view_0 = BlobViewStruct .of ('test_db.pk_postpone_view_source' , source_table , 'picture' , 0 )
6127+ view_1 = BlobViewStruct .of ('test_db.pk_postpone_view_source' , source_table , 'picture' , 1 )
6128+
6129+ view_schema = Schema .from_pyarrow_schema (
6130+ pk_pa_schema ,
6131+ primary_keys = ['pt' , 'id' ],
6132+ partition_keys = ['pt' ],
6133+ options = {
6134+ 'bucket' : '-2' ,
6135+ 'postpone.batch-write-fixed-bucket' : 'true' ,
6136+ 'blob-view-field' : 'picture' ,
6137+ 'write.native.enabled' : 'false' ,
6138+ },
6139+ )
6140+ self .catalog .create_table ('test_db.pk_postpone_blob_view' , view_schema , False )
6141+ view_table = self .catalog .get_table ('test_db.pk_postpone_blob_view' )
6142+
6143+ view_wb = view_table .new_postpone_fixed_bucket_write_builder ()
6144+ view_writer = view_wb .new_write ()
6145+ try :
6146+ view_writer .write_row (GenericRow (
6147+ ['p0' , 1 , Blob .from_view (view_0 )],
6148+ view_table .fields ,
6149+ ))
6150+ view_writer .write_row (GenericRow (
6151+ ['p1' , 2 , Blob .from_view (view_1 )],
6152+ view_table .fields ,
6153+ ))
6154+ messages = view_writer .prepare_commit ()
6155+ self .assertEqual ({message .partition for message in messages }, {('p0' ,), ('p1' ,)})
6156+ for message in messages :
6157+ self .assertEqual (message .total_buckets , 1 )
6158+ view_wb .new_commit ().commit (messages )
6159+ finally :
6160+ view_writer .close ()
6161+
6162+ view_rb = view_table .new_read_builder ()
6163+ view_result = view_rb .new_read ().to_arrow (
6164+ view_rb .new_scan ().plan ().splits ()
6165+ ).sort_by ('id' )
6166+ self .assertEqual (view_result .column ('pt' ).to_pylist (), ['p0' , 'p1' ])
6167+ self .assertEqual (view_result .column ('id' ).to_pylist (), [1 , 2 ])
6168+ self .assertEqual (
6169+ view_result .column ('picture' ).to_pylist (),
6170+ [b'postpone-view-0' , b'postpone-view-1' ],
6171+ )
6172+
60306173
60316174class GetBlobTest (unittest .TestCase ):
60326175
0 commit comments