[ 
https://issues.apache.org/jira/browse/AVRO-3786?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17742869#comment-17742869
 ] 

Evan Blackwell commented on AVRO-3786:
--------------------------------------

Additionally, here's the test that I created that more closely resembles a part 
of our schema to find this error
{code:java}
#[test]
    fn 
deserialize_union_with_record_with_enum_defined_inline_reader_has_different_indices()
 -> TestResult {
        #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, 
serde::Deserialize, serde::Serialize)]
        pub enum DefinedInRecord {
            #[serde(rename = "val0")]
            Val0,
            #[serde(rename = "val1")]
            Val1,
            #[serde(rename = "val2")]
            Val2,
            #[serde(rename = "UNKNOWN")]
            Unknown,
        }
        #[derive(Debug, PartialEq, Eq, Clone, serde::Deserialize, 
serde::Serialize)]
        pub struct Parent {
            pub date: i64,
            #[serde(rename = "barUse")]
            pub bar_use: Bar,
            #[serde(rename = "bazUse")]
            pub baz_use: Option<Vec<Baz>>,
            #[serde(rename = "definedInRecord")]
            pub defined_in_record: DefinedInRecord,
            #[serde(rename = "optionalString")]
            pub optional_string: Option<String>,
        }
        #[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, 
serde::Deserialize, serde::Serialize)]
        pub enum Baz {
            #[serde(rename = "baz0")]
            Baz0,
            #[serde(rename = "baz1")]
            Baz1,
            #[serde(rename = "baz2")]
            Baz2,
        }
        #[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,
            pub baz: Baz,
            pub parent: Option<Parent>,
        }
        let writer_schema = r#"{
            "type": "record",
            "name": "Foo",
            "namespace": "fake",
            "fields":
            [
                {
                    "name": "barInit",
                    "type":
                    {
                        "type": "enum",
                        "name": "Bar",
                        "symbols":
                        [
                            "bar0",
                            "bar1",
                            "bar2"
                        ],
                        "default": "bar0"
                    }
                },
                {
                    "name": "baz",
                    "type":
                    {
                        "type": "enum",
                        "name": "Baz",
                        "symbols":
                        [
                            "baz0",
                            "baz1",
                            "baz2"
                        ],
                        "default": "baz0"
                    }
                },
                {
                    "name": "parent",
                    "type": [
                        "null",
                        {
                            "type": "record",
                            "name": "Parent",
                            "fields": [
                                {
                                    "name": "date",
                                    "type": {
                                      "type": "long",
                                      "avro.java.long": "Long"
                                    }
                                },
                                {
                                    "name": "barUse",
                                    "type": "Bar"
                                },
                                {
                                    "name": "bazUse",
                                    "type": [
                                        "null",
                                        {
                                            "type": "array",
                                            "items": {
                                                "type": "Baz"
                                            }
                                        }
                                    ]
                                },
                                {
                                    "name": "definedInRecord",
                                    "type": {
                                      "name": "DefinedInRecord",
                                      "type": "enum",
                                      "symbols": [
                                        "val0",
                                        "val1",
                                        "val2",
                                        "UNKNOWN"
                                      ],
                                      "default": "UNKNOWN"
                                    }
                                },
                                {
                                  "name": "optionalString",
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }"#;
        let reader_schema = r#"{
            "type": "record",
            "name": "Foo",
            "namespace": "fake",
            "fields":
            [
                {
                    "name": "barInit",
                    "type":
                    {
                        "type": "enum",
                        "name": "Bar",
                        "symbols":
                        [
                            "bar0",
                            "bar2"
                        ],
                        "default": "bar0"
                    }
                },
                {
                    "name": "baz",
                    "type":
                    {
                        "type": "enum",
                        "name": "Baz",
                        "symbols":
                        [
                            "baz0",
                            "baz2"
                        ],
                        "default": "baz0"
                    }
                },
                {
                    "name": "parent",
                    "type": [
                        "null",
                        {
                            "type": "record",
                            "name": "Parent",
                            "fields": [
                                {
                                    "name": "date",
                                    "type": {
                                      "type": "long",
                                      "avro.java.long": "Long"
                                    }
                                },
                                {
                                    "name": "barUse",
                                    "type": "Bar"
                                },
                                {
                                    "name": "bazUse",
                                    "type": [
                                        "null",
                                        {
                                            "type": "array",
                                            "items": {
                                                "type": "Baz"
                                            }
                                        }
                                    ]
                                },
                                {
                                    "name": "definedInRecord",
                                    "type": {
                                      "name": "DefinedInRecord",
                                      "type": "enum",
                                      "symbols": [
                                        "val1",
                                        "val2",
                                        "UNKNOWN"
                                      ],
                                      "default": "UNKNOWN"
                                    }
                                },
                                {
                                  "name": "optionalString",
                                  "type": [
                                    "null",
                                    "string"
                                  ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }"#;
        let writer_schema = Schema::parse_str(writer_schema)?;
        let foo = Foo {
            bar_init: Bar::Bar0,
            baz: Baz::Baz0,
            parent: Some(Parent {
                bar_use: Bar::Bar0,
                baz_use: Some(vec![Baz::Baz0]),
                optional_string: Some("test".to_string()),
                date: 1689197893,
                defined_in_record: DefinedInRecord::Val1
            })
        };
        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(), 3);
                assert_eq!(fields[0].0, "barInit");
                assert_eq!(fields[0].1, types::Value::Enum(0, 
"bar0".to_string()));
                // TODO: better validation
            }
            _ => panic!("Expected Value::Record"),
        }
        Ok(())
    } {code}

> [Rust] Deserialization results in FindUnionVariant error if the writer and 
> reader have the same symbol but at different positions
> ---------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: AVRO-3786
>                 URL: https://issues.apache.org/jira/browse/AVRO-3786
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: rust
>            Reporter: Evan Blackwell
>            Assignee: Martin Tzvetanov Grigorov
>            Priority: Major
>              Labels: pull-request-available
>             Fix For: 1.12.0, 1.11.3
>
>          Time Spent: 20m
>  Remaining Estimate: 0h
>
> When calling from_avro_datum with a reader schema that has the same enum 
> symbol but in a different position as the writer schema, a FindUnionVariant 
> error occurs. The value in the message is available in both schemas. The enum 
> is defined elsewhere in the schema, so it's worth checking if the problem is 
> with the reference type or the enum itself.
>  
> Sample test
> {code:java}
> #[test]
>     fn deserialize_union_with_different_enum_order() -> 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":
>                         [
>                             "bar1"
>                         ],
>                         "default": "bar1"
>                     }
>                 },
>                 {
>                     "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::Bar1} ),
>         };
>         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: assert barUseParent value
>             }
>             _ => panic!("Expected Value::Record"),
>         }        Ok(())
>     }         Ok(())    } {code}
> Resulting error:
> {code:java}
> apache_avro::error::Error: Could not find matching type in union {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to