You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2022/10/10 20:10:10 UTC
[avro] branch branch-1.11 updated: AVRO-3632: [Rust] Handle defaults in unions according to the spec (#1901)
This is an automated email from the ASF dual-hosted git repository.
mgrigorov pushed a commit to branch branch-1.11
in repository https://gitbox.apache.org/repos/asf/avro.git
The following commit(s) were added to refs/heads/branch-1.11 by this push:
new 21f60bafa AVRO-3632: [Rust] Handle defaults in unions according to the spec (#1901)
21f60bafa is described below
commit 21f60bafab505fd051568a9d28a731130c127ab5
Author: Santiago Fraire Willemoes <sa...@gmail.com>
AuthorDate: Mon Oct 10 22:09:47 2022 +0200
AVRO-3632: [Rust] Handle defaults in unions according to the spec (#1901)
(cherry picked from commit 92d57060f98f60de2a5e6eb95a91bc2bc5a61db6)
---
lang/rust/avro/src/error.rs | 3 +++
lang/rust/avro/src/schema.rs | 32 ++++++++++++++++++++++++++++----
lang/rust/avro/tests/schema.rs | 29 +++++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index ec6e22aee..4f7098d2f 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -229,6 +229,9 @@ pub enum Error {
#[error("Unions cannot contain duplicate types")]
GetUnionDuplicate,
+ #[error("Union's first type {0:?} must match the `default`'s value type {1:?}")]
+ GetDefaultUnion(SchemaKind, ValueKind),
+
#[error("JSON value {0} claims to be u64 but cannot be converted")]
GetU64FromJson(serde_json::Number),
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index bbf13138d..f29406ffd 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -866,7 +866,7 @@ impl Parser {
match *value {
Value::String(ref t) => self.parse_known_schema(t.as_str(), enclosing_namespace),
Value::Object(ref data) => self.parse_complex(data, enclosing_namespace),
- Value::Array(ref data) => self.parse_union(data, enclosing_namespace),
+ Value::Array(ref data) => self.parse_union(data, enclosing_namespace, None),
_ => Err(Error::ParseSchemaFromValidJson),
}
}
@@ -1148,7 +1148,10 @@ impl Parser {
other => self.parse_known_schema(other, enclosing_namespace),
},
Some(&Value::Object(ref data)) => self.parse_complex(data, enclosing_namespace),
- Some(&Value::Array(ref variants)) => self.parse_union(variants, enclosing_namespace),
+ Some(&Value::Array(ref variants)) => {
+ let default = complex.get("default");
+ self.parse_union(variants, enclosing_namespace, default)
+ }
Some(unknown) => Err(Error::GetComplexType(unknown.clone())),
None => Err(Error::GetComplexTypeField),
}
@@ -1373,11 +1376,32 @@ impl Parser {
&mut self,
items: &[Value],
enclosing_namespace: &Namespace,
+ default: Option<&Value>,
) -> AvroResult<Schema> {
items
.iter()
.map(|v| self.parse(v, enclosing_namespace))
.collect::<Result<Vec<_>, _>>()
+ .and_then(|schemas| {
+ if let Some(default_value) = default.cloned() {
+ let avro_value = types::Value::from(default_value);
+ let first_schema = schemas.first();
+ if let Some(schema) = first_schema {
+ // Try to resolve the schema
+ let resolved_value = avro_value.to_owned().resolve(schema);
+ match resolved_value {
+ Ok(_) => {}
+ Err(_) => {
+ return Err(Error::GetDefaultUnion(
+ SchemaKind::from(schema),
+ types::ValueKind::from(avro_value),
+ ));
+ }
+ }
+ }
+ }
+ Ok(schemas)
+ })
.and_then(|schemas| Ok(Schema::Union(UnionSchema::new(schemas)?)))
}
@@ -2182,7 +2206,7 @@ mod tests {
"name": "OptionA",
"type": "record",
"fields": [
- {"name": "field_one", "type": ["null", "A"], "default": "null"}
+ {"name": "field_one", "type": ["null", "A"], "default": null}
]
}"#;
@@ -2199,7 +2223,7 @@ mod tests {
fields: vec![RecordField {
name: "field_one".to_string(),
doc: None,
- default: Some(Value::String("null".to_string())),
+ default: Some(Value::Null),
schema: Schema::Union(
UnionSchema::new(vec![
Schema::Null,
diff --git a/lang/rust/avro/tests/schema.rs b/lang/rust/avro/tests/schema.rs
index 044a78e55..0fc18921f 100644
--- a/lang/rust/avro/tests/schema.rs
+++ b/lang/rust/avro/tests/schema.rs
@@ -133,6 +133,35 @@ const UNION_EXAMPLES: &[(&str, bool)] = &[
]"#,
false,
),
+ // Unions with default values
+ (
+ r#"{"name": "foo", "type": ["string", "long"], "default": "bar"}"#,
+ true,
+ ),
+ (
+ r#"{"name": "foo", "type": ["long", "string"], "default": 1}"#,
+ true,
+ ),
+ (
+ r#"{"name": "foo", "type": ["null", "string"], "default": null}"#,
+ true,
+ ),
+ (
+ r#"{"name": "foo", "type": ["string", "long"], "default": 1}"#,
+ false,
+ ),
+ (
+ r#"{"name": "foo", "type": ["string", "null"], "default": null}"#,
+ false,
+ ),
+ (
+ r#"{"name": "foo", "type": ["null", "string"], "default": "null"}"#,
+ false,
+ ),
+ (
+ r#"{"name": "foo", "type": ["long", "string"], "default": "str"}"#,
+ false,
+ ),
];
const RECORD_EXAMPLES: &[(&str, bool)] = &[