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 2023/06/16 21:27:39 UTC
[avro] branch branch-1.11 updated: AVRO-3772: [Rust] Use the enum default field instead of the field default (#2294)
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 1c0817f07 AVRO-3772: [Rust] Use the enum default field instead of the field default (#2294)
1c0817f07 is described below
commit 1c0817f07cffb8cdde331ffbf8edc8ec212cb1b6
Author: Martin Grigorov <ma...@users.noreply.github.com>
AuthorDate: Sat Jun 17 00:26:50 2023 +0300
AVRO-3772: [Rust] Use the enum default field instead of the field default (#2294)
Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
(cherry picked from commit 2fb183159212e28fbea99dba60a491abe8cb7a96)
---
lang/rust/avro/src/error.rs | 3 ++
lang/rust/avro/src/schema.rs | 49 ++++++++++++++++++++++++++++++
lang/rust/avro/src/schema_compatibility.rs | 32 +++++++++----------
lang/rust/avro/src/types.rs | 30 ++++++++++++------
lang/rust/avro_derive/src/lib.rs | 1 +
5 files changed, 89 insertions(+), 26 deletions(-)
diff --git a/lang/rust/avro/src/error.rs b/lang/rust/avro/src/error.rs
index 17e2c4e8e..b9b6ccf66 100644
--- a/lang/rust/avro/src/error.rs
+++ b/lang/rust/avro/src/error.rs
@@ -307,6 +307,9 @@ pub enum Error {
#[error("Duplicate enum symbol {0}")]
EnumSymbolDuplicate(String),
+ #[error("Default value for enum must be a string! Got: {0}")]
+ EnumDefaultWrongType(serde_json::Value),
+
#[error("No `items` in array")]
GetArrayItemsField,
diff --git a/lang/rust/avro/src/schema.rs b/lang/rust/avro/src/schema.rs
index aa5013ffb..9fb5bacc5 100644
--- a/lang/rust/avro/src/schema.rs
+++ b/lang/rust/avro/src/schema.rs
@@ -692,6 +692,8 @@ pub struct EnumSchema {
pub doc: Documentation,
/// The set of symbols of the schema
pub symbols: Vec<String>,
+ /// An optional default symbol used for compatibility
+ pub default: Option<String>,
/// The custom attributes of the schema
pub attributes: BTreeMap<String, Value>,
}
@@ -1486,11 +1488,21 @@ impl Parser {
existing_symbols.insert(symbol);
}
+ let mut default: Option<String> = None;
+ if let Some(value) = complex.get("default") {
+ if let Value::String(ref s) = *value {
+ default = Some(s.clone());
+ } else {
+ return Err(Error::EnumDefaultWrongType(value.clone()));
+ }
+ }
+
let schema = Schema::Enum(EnumSchema {
name,
aliases: aliases.clone(),
doc: complex.doc(),
symbols,
+ default,
attributes: self.get_custom_attributes(complex, vec!["symbols"]),
});
@@ -2828,6 +2840,7 @@ mod tests {
aliases: None,
doc: None,
symbols: vec!["one".to_string(), "two".to_string(), "three".to_string()],
+ default: None,
attributes: Default::default(),
}),
order: RecordFieldOrder::Ascending,
@@ -2847,6 +2860,7 @@ mod tests {
aliases: None,
doc: None,
symbols: vec!["one".to_string(), "two".to_string(), "three".to_string()],
+ default: None,
attributes: Default::default(),
}),
order: RecordFieldOrder::Ascending,
@@ -2964,6 +2978,7 @@ mod tests {
"clubs".to_owned(),
"hearts".to_owned(),
],
+ default: None,
attributes: Default::default(),
});
@@ -4715,4 +4730,38 @@ mod tests {
Ok(())
}
+
+ #[test]
+ fn test_avro_3772_enum_default_wrong_type() -> TestResult {
+ let schema = r#"
+ {
+ "type": "record",
+ "name": "test",
+ "fields": [
+ {"name": "a", "type": "long", "default": 42},
+ {"name": "b", "type": "string"},
+ {
+ "name": "c",
+ "type": {
+ "type": "enum",
+ "name": "suit",
+ "symbols": ["diamonds", "spades", "clubs", "hearts"],
+ "default": 123
+ }
+ }
+ ]
+ }
+ "#;
+
+ match Schema::parse_str(schema) {
+ Err(err) => {
+ assert_eq!(
+ err.to_string(),
+ "Default value for enum must be a string! Got: 123"
+ );
+ }
+ _ => panic!("Expected an error"),
+ }
+ Ok(())
+ }
}
diff --git a/lang/rust/avro/src/schema_compatibility.rs b/lang/rust/avro/src/schema_compatibility.rs
index b8cd46119..b661054d6 100644
--- a/lang/rust/avro/src/schema_compatibility.rs
+++ b/lang/rust/avro/src/schema_compatibility.rs
@@ -912,7 +912,7 @@ mod tests {
}
#[test]
- fn avro_3772_enum_default() -> TestResult {
+ fn test_avro_3772_enum_default() -> TestResult {
let writer_raw_schema = r#"
{
"type": "record",
@@ -925,9 +925,9 @@ mod tests {
"type": {
"type": "enum",
"name": "suit",
- "symbols": ["diamonds", "spades", "clubs", "hearts"]
- },
- "default": "spades"
+ "symbols": ["diamonds", "spades", "clubs", "hearts"],
+ "default": "spades"
+ }
}
]
}
@@ -944,10 +944,10 @@ mod tests {
"name": "c",
"type": {
"type": "enum",
- "name": "suit",
- "symbols": ["diamonds", "spades", "ninja", "hearts"]
- },
- "default": "spades"
+ "name": "suit",
+ "symbols": ["diamonds", "spades", "ninja", "hearts"],
+ "default": "spades"
+ }
}
]
}
@@ -976,7 +976,7 @@ mod tests {
}
#[test]
- fn avro_3772_enum_default_less_symbols() -> TestResult {
+ fn test_avro_3772_enum_default_less_symbols() -> TestResult {
let writer_raw_schema = r#"
{
"type": "record",
@@ -989,9 +989,9 @@ mod tests {
"type": {
"type": "enum",
"name": "suit",
- "symbols": ["diamonds", "spades", "clubs", "hearts"]
- },
- "default": "spades"
+ "symbols": ["diamonds", "spades", "clubs", "hearts"],
+ "default": "spades"
+ }
}
]
}
@@ -1008,10 +1008,10 @@ mod tests {
"name": "c",
"type": {
"type": "enum",
- "name": "suit",
- "symbols": ["hearts", "spades"]
- },
- "default": "spades"
+ "name": "suit",
+ "symbols": ["hearts", "spades"],
+ "default": "spades"
+ }
}
]
}
diff --git a/lang/rust/avro/src/types.rs b/lang/rust/avro/src/types.rs
index b0a022347..7bb933a4b 100644
--- a/lang/rust/avro/src/types.rs
+++ b/lang/rust/avro/src/types.rs
@@ -624,9 +624,11 @@ impl Value {
Schema::Union(ref inner) => {
self.resolve_union(inner, names, enclosing_namespace, field_default)
}
- Schema::Enum(EnumSchema { ref symbols, .. }) => {
- self.resolve_enum(symbols, field_default)
- }
+ Schema::Enum(EnumSchema {
+ ref symbols,
+ ref default,
+ ..
+ }) => self.resolve_enum(symbols, default, field_default),
Schema::Array(ref inner) => self.resolve_array(inner, names, enclosing_namespace),
Schema::Map(ref inner) => self.resolve_map(inner, names, enclosing_namespace),
Schema::Record(RecordSchema { ref fields, .. }) => {
@@ -848,14 +850,15 @@ impl Value {
fn resolve_enum(
self,
symbols: &[String],
- field_default: &Option<JsonValue>,
+ enum_default: &Option<String>,
+ _field_default: &Option<JsonValue>,
) -> Result<Self, Error> {
let validate_symbol = |symbol: String, symbols: &[String]| {
if let Some(index) = symbols.iter().position(|item| item == &symbol) {
Ok(Value::Enum(index as u32, symbol))
} else {
- match field_default {
- Some(JsonValue::String(default)) => {
+ match enum_default {
+ Some(default) => {
if let Some(index) = symbols.iter().position(|item| item == default) {
Ok(Value::Enum(index as u32, default.clone()))
} else {
@@ -973,10 +976,15 @@ impl Value {
Some(value) => value,
None => match field.default {
Some(ref value) => match field.schema {
- Schema::Enum(EnumSchema { ref symbols, .. }) => {
- Value::from(value.clone())
- .resolve_enum(symbols, &field.default.clone())?
- }
+ Schema::Enum(EnumSchema {
+ ref symbols,
+ ref default,
+ ..
+ }) => Value::from(value.clone()).resolve_enum(
+ symbols,
+ default,
+ &field.default.clone(),
+ )?,
Schema::Union(ref union_schema) => {
let first = &union_schema.variants()[0];
// NOTE: this match exists only to optimize null defaults for large
@@ -1236,6 +1244,7 @@ mod tests {
"diamonds".to_string(),
"clubs".to_string(),
],
+ default: None,
attributes: Default::default(),
});
@@ -1282,6 +1291,7 @@ mod tests {
"clubs".to_string(),
"spades".to_string(),
],
+ default: None,
attributes: Default::default(),
});
diff --git a/lang/rust/avro_derive/src/lib.rs b/lang/rust/avro_derive/src/lib.rs
index 5e80e70af..5b36839be 100644
--- a/lang/rust/avro_derive/src/lib.rs
+++ b/lang/rust/avro_derive/src/lib.rs
@@ -222,6 +222,7 @@ fn get_data_enum_schema_def(
aliases: #enum_aliases,
doc: #doc,
symbols: vec![#(#symbols.to_owned()),*],
+ default: None,
attributes: Default::default(),
})
})