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 609b792e feat: re-export name mapping (#1116)
609b792e is described below
commit 609b792e3f85c835bc9f0898f2ea5ee5eba215e9
Author: Jack <[email protected]>
AuthorDate: Fri Apr 18 14:36:26 2025 +0100
feat: re-export name mapping (#1116)
## Which issue does this PR close?
Likely helps towards https://github.com/apache/iceberg-rust/issues/919
and this was also discussed in
[Slack](https://apache-iceberg.slack.com/archives/C05HTENMJG4/p1742385647684059).
## What changes are included in this PR?
This publicly re-exports the `name_mapping` module to `iceberg::spec`.
Prior to this, it is private and inaccessible outside of this crate.
## Are these changes tested?
The main changes here are not functional changes except to visibility.
The additional fields to the `NameMapping` structure have test coverage
and are covered by prior tests, it is expected that these internal
fields do **not** show up in the serialised `NameMapping` output, hence
they are marked with the `serde(skip)` attribute - this is upheld with
prior tests.
---------
Co-authored-by: Renjie Liu <[email protected]>
---
crates/iceberg/src/spec/mod.rs | 1 +
.../spec/{name_mapping.rs => name_mapping/mod.rs} | 89 +++++++++++++++++-----
2 files changed, 73 insertions(+), 17 deletions(-)
diff --git a/crates/iceberg/src/spec/mod.rs b/crates/iceberg/src/spec/mod.rs
index 5cf2afa1..10a47574 100644
--- a/crates/iceberg/src/spec/mod.rs
+++ b/crates/iceberg/src/spec/mod.rs
@@ -38,6 +38,7 @@ mod view_version;
pub use datatypes::*;
pub use manifest::*;
pub use manifest_list::*;
+pub use name_mapping::*;
pub use partition::*;
pub use schema::*;
pub use snapshot::*;
diff --git a/crates/iceberg/src/spec/name_mapping.rs
b/crates/iceberg/src/spec/name_mapping/mod.rs
similarity index 83%
rename from crates/iceberg/src/spec/name_mapping.rs
rename to crates/iceberg/src/spec/name_mapping/mod.rs
index 53d190b4..af18e05b 100644
--- a/crates/iceberg/src/spec/name_mapping.rs
+++ b/crates/iceberg/src/spec/name_mapping/mod.rs
@@ -17,14 +17,31 @@
//! Iceberg name mapping.
+use std::sync::Arc;
+
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DefaultOnNull};
+/// Property name for name mapping.
+pub const DEFAULT_SCHEMA_NAME_MAPPING: &str = "schema.name-mapping.default";
+
/// Iceberg fallback field name to ID mapping.
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[serde(transparent)]
pub struct NameMapping {
- pub root: Vec<MappedField>,
+ root: Vec<MappedField>,
+}
+
+impl NameMapping {
+ /// Create a new [`NameMapping`] given a collection of mapped fields.
+ pub fn new(fields: Vec<MappedField>) -> Self {
+ Self { root: fields }
+ }
+
+ /// Get a reference to fields which are to be mapped from name to field ID.
+ pub fn fields(&self) -> &[MappedField] {
+ &self.root
+ }
}
/// Maps field names to IDs.
@@ -33,12 +50,38 @@ pub struct NameMapping {
#[serde(rename_all = "kebab-case")]
pub struct MappedField {
#[serde(skip_serializing_if = "Option::is_none")]
- pub field_id: Option<i32>,
- pub names: Vec<String>,
+ field_id: Option<i32>,
+ names: Vec<String>,
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
#[serde_as(deserialize_as = "DefaultOnNull")]
- pub fields: Vec<MappedField>,
+ fields: Vec<Arc<MappedField>>,
+}
+
+impl MappedField {
+ /// Create a new [`MappedField`].
+ pub fn new(field_id: Option<i32>, names: Vec<String>, fields:
Vec<MappedField>) -> Self {
+ Self {
+ field_id,
+ names,
+ fields: fields.into_iter().map(Arc::new).collect(),
+ }
+ }
+
+ /// Iceberg field ID when a field's name is present within `names`.
+ pub fn field_id(&self) -> Option<i32> {
+ self.field_id
+ }
+
+ /// Get a reference to names for a mapped field.
+ pub fn names(&self) -> &[String] {
+ &self.names
+ }
+
+ /// Get a reference to the field mapping for any child fields.
+ pub fn fields(&self) -> &[Arc<MappedField>] {
+ &self.fields
+ }
}
#[cfg(test)]
@@ -196,15 +239,17 @@ mod tests {
field_id: Some(4),
names: vec!["latitude".to_string(),
"lat".to_string()],
fields: vec![]
- },
+ }
+ .into(),
MappedField {
field_id: Some(5),
names: vec!["longitude".to_string(),
"long".to_string()],
fields: vec![]
- },
+ }
+ .into(),
]
}
- ]
+ ],
});
}
@@ -234,7 +279,8 @@ mod tests {
field_id: Some(5),
names: vec!["element".to_string()],
fields: vec![],
- }],
+ }
+ .into()],
},
MappedField {
field_id: Some(6),
@@ -244,7 +290,8 @@ mod tests {
field_id: Some(7),
names: vec!["key".to_string()],
fields: vec![],
- },
+ }
+ .into(),
MappedField {
field_id: Some(8),
names: vec!["value".to_string()],
@@ -253,14 +300,17 @@ mod tests {
field_id: Some(9),
names: vec!["key".to_string()],
fields: vec![],
- },
+ }
+ .into(),
MappedField {
field_id: Some(10),
names: vec!["value".to_string()],
fields: vec![],
- },
+ }
+ .into(),
],
- },
+ }
+ .into(),
],
},
MappedField {
@@ -274,14 +324,17 @@ mod tests {
field_id: Some(13),
names: vec!["latitude".to_string()],
fields: vec![],
- },
+ }
+ .into(),
MappedField {
field_id: Some(14),
names: vec!["longitude".to_string()],
fields: vec![],
- },
+ }
+ .into(),
],
- }],
+ }
+ .into()],
},
MappedField {
field_id: Some(15),
@@ -291,12 +344,14 @@ mod tests {
field_id: Some(16),
names: vec!["name".to_string()],
fields: vec![],
- },
+ }
+ .into(),
MappedField {
field_id: Some(17),
names: vec!["age".to_string()],
fields: vec![],
- },
+ }
+ .into(),
],
},
],