Skip to content

Commit eac45aa

Browse files
committed
support nullable value in 'tags' in AddAction
1 parent 95b41cf commit eac45aa

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

derive-macros/src/lib.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,35 @@ fn gen_schema_fields(data: &Data) -> TokenStream {
119119
}
120120
});
121121
if have_schema_null {
122-
if let Some(last_ident) = type_path.path.segments.last().map(|seg| &seg.ident) {
123-
if last_ident != "HashMap" {
124-
return Error::new(
122+
// Check if the type is HashMap or Option<HashMap>
123+
let last_segment = type_path.path.segments.last();
124+
let is_valid = if let Some(seg) = last_segment {
125+
let last_ident = &seg.ident;
126+
if last_ident == "HashMap" {
127+
true
128+
} else if last_ident == "Option" {
129+
// Check if Option wraps HashMap
130+
if let PathArguments::AngleBracketed(args) = &seg.arguments {
131+
args.args.iter().any(|arg| {
132+
if let syn::GenericArgument::Type(Type::Path(inner_path)) = arg {
133+
inner_path.path.segments.last().map(|s| &s.ident) == Some(&syn::Ident::new("HashMap", Span::call_site()))
134+
} else {
135+
false
136+
}
137+
})
138+
} else {
139+
false
140+
}
141+
} else {
142+
false
143+
}
144+
} else {
145+
false
146+
};
147+
148+
if !is_valid {
149+
if let Some(last_ident) = last_segment.map(|seg| &seg.ident) {
150+
return Error::new(
125151
last_ident.span(),
126152
format!("Can only use allow_null_container_values on HashMap fields, not {last_ident}")
127153
).to_compile_error()

kernel/src/actions/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ pub(crate) struct Add {
721721

722722
/// Map containing metadata about this logical file.
723723
#[cfg_attr(test, serde(skip_serializing_if = "Option::is_none"))]
724+
#[allow_null_container_values]
724725
pub tags: Option<HashMap<String, String>>,
725726

726727
/// Information about deletion vector (DV) associated with this add action
@@ -1075,7 +1076,7 @@ mod tests {
10751076
StructField::nullable("stats", DataType::STRING),
10761077
StructField::nullable(
10771078
"tags",
1078-
MapType::new(DataType::STRING, DataType::STRING, false),
1079+
MapType::new(DataType::STRING, DataType::STRING, true),
10791080
),
10801081
deletion_vector_field(),
10811082
StructField::nullable("baseRowId", DataType::LONG),

kernel/src/schema/derive_macro_utils.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,10 @@ impl<T: ToNullableContainerType> GetNullableContainerStructField for T {
116116
StructField::not_null(name, T::to_nullable_container_type())
117117
}
118118
}
119+
120+
// Blanket impl for optional container types with nullable values
121+
impl<T: ToNullableContainerType> GetNullableContainerStructField for Option<T> {
122+
fn get_nullable_container_struct_field(name: impl Into<String>) -> StructField {
123+
StructField::nullable(name, T::to_nullable_container_type())
124+
}
125+
}

0 commit comments

Comments
 (0)