You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by li...@apache.org on 2025/07/23 12:29:50 UTC

(iceberg-rust) branch main updated: feat: append action allows snapshot properties (#1534)

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

liurenjie1024 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new b3ea8d1f feat: append action allows snapshot properties (#1534)
b3ea8d1f is described below

commit b3ea8d1fca14ddc23154615862a62d3e3e56a769
Author: dentiny <de...@gmail.com>
AuthorDate: Wed Jul 23 05:29:45 2025 -0700

    feat: append action allows snapshot properties (#1534)
---
 crates/iceberg/src/transaction/append.rs   | 30 ++++++++++++++++++++++++++++++
 crates/iceberg/src/transaction/snapshot.rs | 25 +++++++++++++++++++++----
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/crates/iceberg/src/transaction/append.rs b/crates/iceberg/src/transaction/append.rs
index 6e719163..f248543d 100644
--- a/crates/iceberg/src/transaction/append.rs
+++ b/crates/iceberg/src/transaction/append.rs
@@ -208,6 +208,36 @@ mod tests {
         );
     }
 
+    #[tokio::test]
+    async fn test_append_snapshot_properties() {
+        let table = make_v2_minimal_table();
+        let tx = Transaction::new(&table);
+
+        let mut snapshot_properties = HashMap::new();
+        snapshot_properties.insert("key".to_string(), "val".to_string());
+
+        let action = tx
+            .fast_append()
+            .set_snapshot_properties(snapshot_properties);
+        let mut action_commit = Arc::new(action).commit(&table).await.unwrap();
+        let updates = action_commit.take_updates();
+
+        // Check customized properties is contained in snapshot summary properties.
+        let new_snapshot = if let TableUpdate::AddSnapshot { snapshot } = &updates[0] {
+            snapshot
+        } else {
+            unreachable!()
+        };
+        assert_eq!(
+            new_snapshot
+                .summary()
+                .additional_properties
+                .get("key")
+                .unwrap(),
+            "val"
+        );
+    }
+
     #[tokio::test]
     async fn test_fast_append_file_with_incompatible_partition_value() {
         let table = make_v2_minimal_table();
diff --git a/crates/iceberg/src/transaction/snapshot.rs b/crates/iceberg/src/transaction/snapshot.rs
index 092f9fb2..48dc2b5b 100644
--- a/crates/iceberg/src/transaction/snapshot.rs
+++ b/crates/iceberg/src/transaction/snapshot.rs
@@ -254,7 +254,7 @@ impl<'a> SnapshotProducer<'a> {
         if added_data_files.is_empty() {
             return Err(Error::new(
                 ErrorKind::PreconditionFailed,
-                "No added data files found when write a manifest file",
+                "No added data files found when write an added manifest file",
             ));
         }
 
@@ -284,13 +284,30 @@ impl<'a> SnapshotProducer<'a> {
         snapshot_produce_operation: &OP,
         manifest_process: &MP,
     ) -> Result<Vec<ManifestFile>> {
-        let added_manifest = self.write_added_manifest().await?;
+        // Assert current snapshot producer contains new content to add to new snapshot.
+        //
+        // TODO: Allowing snapshot property setup with no added data files is a workaround.
+        // We should clean it up after all necessary actions are supported.
+        // For details, please refer to https://github.com/apache/iceberg-rust/issues/1548
+        if self.added_data_files.is_empty() && self.snapshot_properties.is_empty() {
+            return Err(Error::new(
+                ErrorKind::PreconditionFailed,
+                "No added data files or added snapshot properties found when write a manifest file",
+            ));
+        }
+
         let existing_manifests = snapshot_produce_operation.existing_manifest(self).await?;
+        let mut manifest_files = existing_manifests;
+
+        // Process added entries.
+        if !self.added_data_files.is_empty() {
+            let added_manifest = self.write_added_manifest().await?;
+            manifest_files.push(added_manifest);
+        }
+
         // # TODO
         // Support process delete entries.
 
-        let mut manifest_files = vec![added_manifest];
-        manifest_files.extend(existing_manifests);
         let manifest_files = manifest_process.process_manifests(self, manifest_files);
         Ok(manifest_files)
     }