Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 8 additions & 11 deletions arrow-avro/src/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,18 +307,18 @@ impl AvroDataType {
}
}

// Handle JSON nulls per-spec: allowed only for `null` type or unions with null FIRST
// Handle JSON nulls per-spec: allowed only for `null` type or unions with null
if default_json.is_null() {
return match self.codec() {
Codec::Null => Ok(AvroLiteral::Null),
Codec::Union(encodings, _, _) if !encodings.is_empty()
&& matches!(encodings[0].codec(), Codec::Null) =>
Codec::Union(encodings, _, _)
if encodings.iter().any(|enc| matches!(enc.codec(), Codec::Null)) =>
{
Ok(AvroLiteral::Null)
}
_ if self.nullability() == Some(Nullability::NullFirst) => Ok(AvroLiteral::Null),
_ if self.nullability().is_some() => Ok(AvroLiteral::Null),
_ => Err(ArrowError::SchemaError(
"JSON null default is only valid for `null` type or for a union whose first branch is `null`"
"JSON null default is only valid for `null` type or for a union with a `null` branch"
.to_string(),
)),
};
Expand Down Expand Up @@ -2946,12 +2946,9 @@ mod tests {
assert_default_stored(&dt_int_nf, &Value::Null);
let mut dt_int_ns =
AvroDataType::new(Codec::Int32, HashMap::new(), Some(Nullability::NullSecond));
let err2 = dt_int_ns.parse_and_store_default(&Value::Null).unwrap_err();
assert!(
err2.to_string()
.contains("JSON null default is only valid for `null` type"),
"unexpected error: {err2}"
);
let lit3 = dt_int_ns.parse_and_store_default(&Value::Null).unwrap();
assert_eq!(lit3, AvroLiteral::Null);
assert_default_stored(&dt_int_ns, &Value::Null);
}

#[test]
Expand Down
7 changes: 6 additions & 1 deletion arrow-avro/src/reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2936,14 +2936,15 @@ mod test {
},"default":{"x":7}}),
serde_json::json!({"name":"d_nullable_null","type":["null","int"],"default":null}),
serde_json::json!({"name":"d_nullable_value","type":["int","null"],"default":123}),
serde_json::json!({"name":"d_nullable_null_second","type":["int","null"],"default":null}),
],
);
let actual = read_alltypes_with_reader_schema(path, reader_schema);
let num_rows = actual.num_rows();
assert!(num_rows > 0, "skippable_types.avro should contain rows");
assert_eq!(
actual.num_columns(),
22,
23,
"expected exactly our defaulted fields"
);
let mut arrays: Vec<Arc<dyn Array>> = Vec::with_capacity(22);
Expand Down Expand Up @@ -3070,6 +3071,10 @@ mod test {
arrays.push(Arc::new(Int32Array::from_iter_values(std::iter::repeat_n(
123, num_rows,
))));
arrays.push(Arc::new(Int32Array::from_iter(std::iter::repeat_n(
None::<i32>,
num_rows,
))));
let expected = RecordBatch::try_new(actual.schema(), arrays).unwrap();
assert_eq!(
actual, expected,
Expand Down
Loading