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
commit e217c5e542f6377a73d9ca5346c3ed97a6089f48 Author: Martin Grigorov <[email protected]> AuthorDate: Wed Jan 5 13:37:26 2022 +0200 AVRO-3216 Reuse records' schema by name (#1345) * AVRO-3197 Fallback to the 'type' when the logical type does not support the type Signed-off-by: Martin Tzvetanov Grigorov <[email protected]> * AVRO-3197 Allow only when the "type" is "string" * AVRO-3197 Handle problematic complex type for date/time logical types Read the complex type recursively. It seems Avro Java may produce {"type": {"type": "string", "avro.java.string": "String"}, "logicalType": "timestamp-millis"}}, i.e. logicalType is on the same level as the outer "type" Signed-off-by: Martin Tzvetanov Grigorov <[email protected]> * AVRO-3216 Allow to reuse record's schema by name * AVRO-3216 Extend the test case to do more assertions * AVRO-3216 Print err with Debug (cherry picked from commit b76a437b970889255703ff48f7ee5981dfbcc17a) --- lang/rust/src/schema.rs | 10 ++++-- lang/rust/tests/io.rs | 2 +- lang/rust/tests/schema.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/lang/rust/src/schema.rs b/lang/rust/src/schema.rs index bab99d4..da8c0c3 100644 --- a/lang/rust/src/schema.rs +++ b/lang/rust/src/schema.rs @@ -785,12 +785,16 @@ impl Parser { lookup.insert(field.name.clone(), field.position); } - Ok(Schema::Record { - name, + let schema = Schema::Record { + name: name.clone(), doc: complex.doc(), fields, lookup, - }) + }; + + self.parsed_schemas + .insert(name.fullname(None), schema.clone()); + Ok(schema) } /// Parse a `serde_json::Value` representing a Avro enum type into a diff --git a/lang/rust/tests/io.rs b/lang/rust/tests/io.rs index 93edf0d..c1ab1d7 100644 --- a/lang/rust/tests/io.rs +++ b/lang/rust/tests/io.rs @@ -319,6 +319,6 @@ fn test_type_exception() -> Result<(), String> { match encoded { Ok(_) => Err(String::from("Expected ValidationError, got Ok")), Err(Error::Validation) => Ok(()), - Err(ref e) => Err(format!("Expected ValidationError, got {}", e)), + Err(ref e) => Err(format!("Expected ValidationError, got {:?}", e)), } } diff --git a/lang/rust/tests/schema.rs b/lang/rust/tests/schema.rs index efd9df2..d9fdefc 100644 --- a/lang/rust/tests/schema.rs +++ b/lang/rust/tests/schema.rs @@ -15,8 +15,10 @@ // specific language governing permissions and limitations // under the License. -//! Port of https://github.com/apache/avro/blob/release-1.9.1/lang/py/test/test_schema.py -use avro_rs::{schema::Name, Error, Schema}; +use avro_rs::{ + schema::{Name, RecordField}, + Error, Schema, +}; use lazy_static::lazy_static; fn init() { @@ -830,6 +832,86 @@ fn test_parse_list_with_cross_deps_and_namespaces_error() { let _ = Schema::parse_list(&schema_strs_second).expect_err("Test failed"); } +#[test] +// <https://issues.apache.org/jira/browse/AVRO-3216> +// test that field's RecordSchema could be referenced by a following field by full name +fn test_parse_reused_record_schema_by_fullname() { + init(); + let schema_str = r#" + { + "type" : "record", + "name" : "Weather", + "namespace" : "test", + "doc" : "A weather reading.", + "fields" : [ + { + "name" : "station", + "type" : { + "type" : "string", + "avro.java.string" : "String" + } + }, + { + "name" : "max_temp", + "type" : { + "type" : "record", + "name" : "Temp", + "namespace": "prefix", + "doc" : "A temperature reading.", + "fields" : [ { + "name" : "temp", + "type" : "long" + } ] + } + }, { + "name" : "min_temp", + "type" : "prefix.Temp" + } + ] + } + "#; + + let schema = Schema::parse_str(schema_str); + assert!(schema.is_ok()); + match schema.unwrap() { + Schema::Record { + ref name, + doc: _, + ref fields, + lookup: _, + } => { + assert_eq!(name.fullname(None), "test.Weather", "Name does not match!"); + + assert_eq!(fields.len(), 3, "The number of the fields is not correct!"); + + let RecordField { + ref name, + doc: _, + default: _, + ref schema, + order: _, + position: _, + } = fields.get(2).unwrap(); + + assert_eq!(name, "min_temp"); + + match schema { + Schema::Record { + ref name, + doc: _, + ref fields, + lookup: _, + } => { + assert_eq!(name.fullname(None), "prefix.Temp", "Name does not match!"); + assert_eq!(fields.len(), 1, "The number of the fields is not correct!"); + } + unexpected => unreachable!("Unexpected schema type: {:?}", unexpected), + } + } + unexpected => unreachable!("Unexpected schema type: {:?}", unexpected), + } +} + /// Return all permutations of an input slice fn permutations<T>(list: &[T]) -> Vec<Vec<&T>> { let size = list.len();
