From 88e681baf28bbb691b60c30045ec62d5ef1b8d94 Mon Sep 17 00:00:00 2001 From: jackylee-ch Date: Mon, 28 Sep 2026 22:18:08 +0800 Subject: [PATCH] fix(spec): default PartitionStatistics totalBuckets when absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `PartitionStatistics::total_buckets` had no serde default, so deserializing statistics that omit `totalBuckets` — e.g. produced by an older Paimon version that predates the field, which a REST catalog may still return — failed with a missing-field error instead of reading the rest of the record. Java treats the field as `@JsonProperty` on a primitive `int` and documents that it "defaults to 0 if absent (older Paimon version)". Add `#[serde(default)]` so the field falls back to 0, matching Java. --- .../paimon/src/spec/partition_statistics.rs | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/crates/paimon/src/spec/partition_statistics.rs b/crates/paimon/src/spec/partition_statistics.rs index ff82f3144..6f91fee0b 100644 --- a/crates/paimon/src/spec/partition_statistics.rs +++ b/crates/paimon/src/spec/partition_statistics.rs @@ -34,5 +34,44 @@ pub struct PartitionStatistics { pub file_size_in_bytes: i64, pub file_count: i64, pub last_file_creation_time: i64, + /// Defaults to 0 when absent, e.g. statistics serialized by an older Paimon + /// version that predates this field (matches Java `PartitionStatistics`). + #[serde(default)] pub total_buckets: i32, } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deserializes_without_total_buckets() { + // Statistics written by an older Paimon version omit `totalBuckets`; it + // must default to 0 rather than failing to deserialize. + let json = r#"{ + "spec": {"dt": "2024-01-01"}, + "recordCount": 10, + "fileSizeInBytes": 2048, + "fileCount": 3, + "lastFileCreationTime": 1700000000000 + }"#; + let stats: PartitionStatistics = serde_json::from_str(json).unwrap(); + assert_eq!(stats.total_buckets, 0); + assert_eq!(stats.record_count, 10); + assert_eq!(stats.file_count, 3); + } + + #[test] + fn deserializes_with_total_buckets() { + let json = r#"{ + "spec": {}, + "recordCount": 1, + "fileSizeInBytes": 1, + "fileCount": 1, + "lastFileCreationTime": 0, + "totalBuckets": 8 + }"#; + let stats: PartitionStatistics = serde_json::from_str(json).unwrap(); + assert_eq!(stats.total_buckets, 8); + } +}