| 206 | /// Rewrite affected files and produce CommitMessages. |
| 207 | #[must_use = "commit messages must be passed to TableCommit"] |
| 208 | pub async fn prepare_commit(self) -> Result<Vec<CommitMessage>> { |
| 209 | if self.affected_files.is_empty() { |
| 210 | return Ok(Vec::new()); |
| 211 | } |
| 212 | |
| 213 | let schema = self.table.schema(); |
| 214 | let core_options = CoreOptions::new(schema.options()); |
| 215 | let partition_keys: Vec<String> = schema.partition_keys().to_vec(); |
| 216 | let partition_computer = PartitionComputer::new( |
| 217 | &partition_keys, |
| 218 | schema.fields(), |
| 219 | core_options.partition_default_name(), |
| 220 | core_options.legacy_partition_name(), |
| 221 | )?; |
| 222 | |
| 223 | let target_file_size = core_options.target_file_size(); |
| 224 | let file_compression = core_options.file_compression().to_string(); |
| 225 | let file_compression_zstd_level = core_options.file_compression_zstd_level(); |
| 226 | let write_buffer_size = core_options.write_parquet_buffer_size(); |
| 227 | let file_format = core_options.file_format().to_string(); |
| 228 | let schema_id = schema.id(); |
| 229 | |
| 230 | let update_columns = &self.update_columns; |
| 231 | let update_batches = &self.update_batches; |
| 232 | let file_index = &self.file_index; |
| 233 | let table = &self.table; |
| 234 | let partition_keys = &partition_keys; |
| 235 | let partition_computer = &partition_computer; |
| 236 | let file_compression = file_compression.as_str(); |
| 237 | let file_format = file_format.as_str(); |
| 238 | |
| 239 | // Process each affected file in parallel |
| 240 | let rewrite_futures: Vec<_> = self |
| 241 | .affected_files |
| 242 | .iter() |
| 243 | .map(|(&file_idx, operations)| async move { |
| 244 | let file_info = &file_index[file_idx]; |
| 245 | |
| 246 | // Read the entire file |
| 247 | let single_split = DataSplitBuilder::new() |
| 248 | .with_snapshot(file_info.snapshot_id) |
| 249 | .with_partition(BinaryRow::from_serialized_bytes(&file_info.partition)?) |
| 250 | .with_bucket(file_info.bucket) |
| 251 | .with_bucket_path(file_info.bucket_path.clone()) |
| 252 | .with_total_buckets(file_info.total_buckets) |
| 253 | .with_data_files(vec![file_info.file_meta.clone()]) |
| 254 | .build()?; |
| 255 | |
| 256 | let read = table.new_read_builder().new_read()?; |
| 257 | let original_batches: Vec<RecordBatch> = |
| 258 | read.to_arrow(&[single_split])?.try_collect().await?; |
| 259 | |
| 260 | if original_batches.is_empty() { |
| 261 | return Ok::<_, crate::Error>(None); |
| 262 | } |
| 263 | |
| 264 | let original = if original_batches.len() == 1 { |
| 265 | original_batches.into_iter().next().unwrap() |