Skip to content

Commit 609b792

Browse files
feat: re-export name mapping (#1116)
## Which issue does this PR close? Likely helps towards #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]>
1 parent e8f795e commit 609b792

File tree

2 files changed

+73
-17
lines changed

2 files changed

+73
-17
lines changed

crates/iceberg/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ mod view_version;
3838
pub use datatypes::*;
3939
pub use manifest::*;
4040
pub use manifest_list::*;
41+
pub use name_mapping::*;
4142
pub use partition::*;
4243
pub use schema::*;
4344
pub use snapshot::*;

crates/iceberg/src/spec/name_mapping.rs renamed to crates/iceberg/src/spec/name_mapping/mod.rs

+72-17
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,31 @@
1717

1818
//! Iceberg name mapping.
1919
20+
use std::sync::Arc;
21+
2022
use serde::{Deserialize, Serialize};
2123
use serde_with::{serde_as, DefaultOnNull};
2224

25+
/// Property name for name mapping.
26+
pub const DEFAULT_SCHEMA_NAME_MAPPING: &str = "schema.name-mapping.default";
27+
2328
/// Iceberg fallback field name to ID mapping.
2429
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
2530
#[serde(transparent)]
2631
pub struct NameMapping {
27-
pub root: Vec<MappedField>,
32+
root: Vec<MappedField>,
33+
}
34+
35+
impl NameMapping {
36+
/// Create a new [`NameMapping`] given a collection of mapped fields.
37+
pub fn new(fields: Vec<MappedField>) -> Self {
38+
Self { root: fields }
39+
}
40+
41+
/// Get a reference to fields which are to be mapped from name to field ID.
42+
pub fn fields(&self) -> &[MappedField] {
43+
&self.root
44+
}
2845
}
2946

3047
/// Maps field names to IDs.
@@ -33,12 +50,38 @@ pub struct NameMapping {
3350
#[serde(rename_all = "kebab-case")]
3451
pub struct MappedField {
3552
#[serde(skip_serializing_if = "Option::is_none")]
36-
pub field_id: Option<i32>,
37-
pub names: Vec<String>,
53+
field_id: Option<i32>,
54+
names: Vec<String>,
3855
#[serde(default)]
3956
#[serde(skip_serializing_if = "Vec::is_empty")]
4057
#[serde_as(deserialize_as = "DefaultOnNull")]
41-
pub fields: Vec<MappedField>,
58+
fields: Vec<Arc<MappedField>>,
59+
}
60+
61+
impl MappedField {
62+
/// Create a new [`MappedField`].
63+
pub fn new(field_id: Option<i32>, names: Vec<String>, fields: Vec<MappedField>) -> Self {
64+
Self {
65+
field_id,
66+
names,
67+
fields: fields.into_iter().map(Arc::new).collect(),
68+
}
69+
}
70+
71+
/// Iceberg field ID when a field's name is present within `names`.
72+
pub fn field_id(&self) -> Option<i32> {
73+
self.field_id
74+
}
75+
76+
/// Get a reference to names for a mapped field.
77+
pub fn names(&self) -> &[String] {
78+
&self.names
79+
}
80+
81+
/// Get a reference to the field mapping for any child fields.
82+
pub fn fields(&self) -> &[Arc<MappedField>] {
83+
&self.fields
84+
}
4285
}
4386

4487
#[cfg(test)]
@@ -196,15 +239,17 @@ mod tests {
196239
field_id: Some(4),
197240
names: vec!["latitude".to_string(), "lat".to_string()],
198241
fields: vec![]
199-
},
242+
}
243+
.into(),
200244
MappedField {
201245
field_id: Some(5),
202246
names: vec!["longitude".to_string(), "long".to_string()],
203247
fields: vec![]
204-
},
248+
}
249+
.into(),
205250
]
206251
}
207-
]
252+
],
208253
});
209254
}
210255

@@ -234,7 +279,8 @@ mod tests {
234279
field_id: Some(5),
235280
names: vec!["element".to_string()],
236281
fields: vec![],
237-
}],
282+
}
283+
.into()],
238284
},
239285
MappedField {
240286
field_id: Some(6),
@@ -244,7 +290,8 @@ mod tests {
244290
field_id: Some(7),
245291
names: vec!["key".to_string()],
246292
fields: vec![],
247-
},
293+
}
294+
.into(),
248295
MappedField {
249296
field_id: Some(8),
250297
names: vec!["value".to_string()],
@@ -253,14 +300,17 @@ mod tests {
253300
field_id: Some(9),
254301
names: vec!["key".to_string()],
255302
fields: vec![],
256-
},
303+
}
304+
.into(),
257305
MappedField {
258306
field_id: Some(10),
259307
names: vec!["value".to_string()],
260308
fields: vec![],
261-
},
309+
}
310+
.into(),
262311
],
263-
},
312+
}
313+
.into(),
264314
],
265315
},
266316
MappedField {
@@ -274,14 +324,17 @@ mod tests {
274324
field_id: Some(13),
275325
names: vec!["latitude".to_string()],
276326
fields: vec![],
277-
},
327+
}
328+
.into(),
278329
MappedField {
279330
field_id: Some(14),
280331
names: vec!["longitude".to_string()],
281332
fields: vec![],
282-
},
333+
}
334+
.into(),
283335
],
284-
}],
336+
}
337+
.into()],
285338
},
286339
MappedField {
287340
field_id: Some(15),
@@ -291,12 +344,14 @@ mod tests {
291344
field_id: Some(16),
292345
names: vec!["name".to_string()],
293346
fields: vec![],
294-
},
347+
}
348+
.into(),
295349
MappedField {
296350
field_id: Some(17),
297351
names: vec!["age".to_string()],
298352
fields: vec![],
299-
},
353+
}
354+
.into(),
300355
],
301356
},
302357
],

0 commit comments

Comments
 (0)