[
https://issues.apache.org/jira/browse/AVRO-3787?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
ASF GitHub Bot updated AVRO-3787:
---------------------------------
Labels: pull-request-available (was: )
> [Rust] Deserialization fails to use default if an enum in a record in a union
> is given an unknown symbol
> ---------------------------------------------------------------------------------------------------------
>
> Key: AVRO-3787
> URL: https://issues.apache.org/jira/browse/AVRO-3787
> Project: Apache Avro
> Issue Type: Bug
> Components: rust
> Reporter: Evan Blackwell
> Priority: Major
> Labels: pull-request-available
> Time Spent: 10m
> Remaining Estimate: 0h
>
> When providing from_avro_datum with a reader_schema, there is a
> FindUnionVariant error if * There is a union with one of the types being a
> record that has an enum type field
> * The enum type has a default
> * The value in the message is a symbol in the writer schema but not the
> reader schema
> * The enum can be defined earlier in the schema or inline in the record
> Test that has a reference type and fails
>
> {code:java}
> #[test]
> fn deserialize_union_with_unknown_symbol() -> TestResult {
> #[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize,
> serde::Serialize)]
> pub struct BarUseParent {
> #[serde(rename = "barUse")]
> pub bar_use: Bar,
> }
> #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone,
> serde::Deserialize, serde::Serialize)]
> pub enum Bar {
> #[serde(rename = "bar0")]
> Bar0,
> #[serde(rename = "bar1")]
> Bar1,
> #[serde(rename = "bar2")]
> Bar2,
> }
> #[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize,
> serde::Serialize)]
> pub struct Foo {
> #[serde(rename = "barInit")]
> pub bar_init: Bar,
> #[serde(rename = "barUseParent")]
> pub bar_use_parent: Option<BarUseParent>,
> }
> let writer_schema = r#"{
> "type": "record",
> "name": "Foo",
> "fields":
> [
> {
> "name": "barInit",
> "type":
> {
> "type": "enum",
> "name": "Bar",
> "symbols":
> [
> "bar0",
> "bar1",
> "bar2"
> ],
> "default": "bar0"
> }
> },
> {
> "name": "barUseParent",
> "type": [
> "null",
> {
> "type": "record",
> "name": "BarUseParent",
> "fields": [
> {
> "name": "barUse",
> "type": "Bar"
> }
> ]
> }
> ]
> }
> ]
> }"#;
> let reader_schema = r#"{
> "type": "record",
> "name": "Foo",
> "fields":
> [
> {
> "name": "barInit",
> "type":
> {
> "type": "enum",
> "name": "Bar",
> "symbols":
> [
> "bar0",
> "bar1"
> ],
> "default": "bar0"
> }
> },
> {
> "name": "barUseParent",
> "type": [
> "null",
> {
> "type": "record",
> "name": "BarUseParent",
> "fields": [
> {
> "name": "barUse",
> "type": "Bar"
> }
> ]
> }
> ]
> }
> ]
> }"#;
> let writer_schema = Schema::parse_str(writer_schema)?;
> let foo = Foo {
> bar_init: Bar::Bar1,
> bar_use_parent: Some(BarUseParent { bar_use: Bar::Bar2} ),
> };
> let avro_value = crate::to_value(foo)?;
> assert!(
> avro_value.validate(&writer_schema),
> "value is valid for schema",
> );
> let datum = crate::to_avro_datum(&writer_schema, avro_value)?;
> let mut x = &datum[..];
> let reader_schema = Schema::parse_str(reader_schema)?;
> let deser_value = crate::from_avro_datum(&writer_schema, &mut x,
> Some(&reader_schema))?;
> match deser_value {
> types::Value::Record(fields) => {
> assert_eq!(fields.len(), 2);
> assert_eq!(fields[0].0, "barInit");
> assert_eq!(fields[0].1, types::Value::Enum(1,
> "bar1".to_string()));
> assert_eq!(fields[1].0, "barUseParent");
> // TODO: test value
> }
> _ => panic!("Expected Value::Record"),
> }
> Ok(())
> } {code}
>
>
> Test that defines the enum in the record and fails
>
> {code:java}
> #[test]
> fn deserialize_union_with_unknown_symbol_no_ref() -> TestResult {
> #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone,
> serde::Deserialize, serde::Serialize)]
> pub enum Bar {
> #[serde(rename = "bar0")]
> Bar0,
> #[serde(rename = "bar1")]
> Bar1,
> #[serde(rename = "bar2")]
> Bar2,
> }
> #[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize,
> serde::Serialize)]
> #[serde(default)]
> pub struct BarParent {
> #[serde(rename = "Bar")]
> pub bar: Bar,
> }
> #[inline(always)]
> fn default_barparent_bar() -> Bar { Bar::Bar0 } impl Default
> for BarParent {
> fn default() -> BarParent {
> BarParent {
> bar: default_barparent_bar(),
> }
> }
> }
> #[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize,
> serde::Serialize)]
> pub struct Foo {
> #[serde(rename = "barParent")]
> pub bar_parent: Option<BarParent>,
> }
> let writer_schema = r#"{
> "type": "record",
> "name": "Foo",
> "fields":
> [
> {
> "name": "barParent",
> "type": [
> "null",
> {
> "type": "record",
> "name": "BarParent",
> "fields": [
> {
> "type": "enum",
> "name": "Bar",
> "symbols":
> [
> "bar0",
> "bar1",
> "bar2"
> ],
> "default": "bar0"
> }
> ]
> }
> ]
> }
> ]
> }"#;
> let reader_schema = r#"{
> "type": "record",
> "name": "Foo",
> "fields":
> [
> {
> "name": "barParent",
> "type": [
> "null",
> {
> "type": "record",
> "name": "BarParent",
> "fields": [
> {
> "type": "enum",
> "name": "Bar",
> "symbols":
> [
> "bar0",
> "bar1"
> ],
> "default": "bar0"
> }
> ]
> }
> ]
> }
> ]
> }"#;
> let writer_schema = Schema::parse_str(writer_schema)?;
> let foo = Foo {
> bar_parent: Some(BarParent { bar: Bar::Bar2} ),
> };
> let avro_value = crate::to_value(foo)?;
> assert!(
> avro_value.validate(&writer_schema),
> "value is valid for schema",
> );
> let datum = crate::to_avro_datum(&writer_schema, avro_value)?;
> let mut x = &datum[..];
> let reader_schema = Schema::parse_str(reader_schema)?;
> let deser_value = crate::from_avro_datum(&writer_schema, &mut x,
> Some(&reader_schema))?;
> match deser_value {
> types::Value::Record(fields) => {
> assert_eq!(fields.len(), 1);
> // assert_eq!(fields[0].0, "barInit");
> // assert_eq!(fields[0].1, types::Value::Enum(0,
> "bar0".to_string()));
> assert_eq!(fields[0].0, "barParent");
> // assert_eq!(fields[1].1, types::Value::Enum(1,
> "bar1".to_string()));
> }
> _ => panic!("Expected Value::Record"),
> }
> Ok(())
> } {code}
>
> Both tests fail with the same error:
> {code:java}
> apache_avro::error::Error: Could not find matching type in union {code}
> If I write the same tests but give the value Bar1, then they pass, so it
> seems to only be if it's an unknown symbol.
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)