This is an automated email from the ASF dual-hosted git repository. rskraba pushed a commit to branch branch-1.11 in repository https://gitbox.apache.org/repos/asf/avro.git
commit 6cf169a4b02de5b36fa3fb1396c42e0fd3358bad Author: Zike Yang <[email protected]> AuthorDate: Thu Jul 7 07:18:25 2022 +0800 AVRO-3219: Add nullable enum type field support in Avro.Reflect (#1348) * AVRO-3219: Add nullable enum type field support. Signed-off-by: Zike Yang <[email protected]> * Apply comments. Signed-off-by: Zike Yang <[email protected]> * Fix mistakenly removed the enum type check. Signed-off-by: Zike Yang <[email protected]> --- lang/csharp/src/apache/main/Reflect/ClassCache.cs | 16 +++++++++-- lang/csharp/src/apache/test/Reflect/TestReflect.cs | 33 ++++++++++++++++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/lang/csharp/src/apache/main/Reflect/ClassCache.cs b/lang/csharp/src/apache/main/Reflect/ClassCache.cs index d01d11b49..a64e06d26 100644 --- a/lang/csharp/src/apache/main/Reflect/ClassCache.cs +++ b/lang/csharp/src/apache/main/Reflect/ClassCache.cs @@ -263,17 +263,27 @@ namespace Avro.Reflect EnumCache.AddEnumNameMapItem(ns, objType); break; case UnionSchema us: - if (us.Schemas.Count == 2 && (us.Schemas[0].Tag == Schema.Type.Null || us.Schemas[1].Tag == Schema.Type.Null) && objType.IsClass) + if (us.Schemas.Count == 2 && (us.Schemas[0].Tag == Schema.Type.Null || us.Schemas[1].Tag == Schema.Type.Null)) { // in this case objType will match the non null type in the union foreach (var o in us.Schemas) { - if (o.Tag != Schema.Type.Null) + if (o.Tag == Schema.Type.Null) + { + continue; + } + + if (objType.IsClass) { LoadClassCache(objType, o); } - } + var innerType = Nullable.GetUnderlyingType(objType); + if (innerType != null && innerType.IsEnum) + { + LoadClassCache(innerType, o); + } + } } else { diff --git a/lang/csharp/src/apache/test/Reflect/TestReflect.cs b/lang/csharp/src/apache/test/Reflect/TestReflect.cs index bea5ef23f..5cf572539 100644 --- a/lang/csharp/src/apache/test/Reflect/TestReflect.cs +++ b/lang/csharp/src/apache/test/Reflect/TestReflect.cs @@ -40,17 +40,22 @@ namespace Avro.Test public EnumResolutionEnum enumType { get; set; } } + class NullableEnumResolutionRecord + { + public EnumResolutionEnum? enumType { get; set; } + } + [TestCase] public void TestEnumResolution() { Schema writerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + - "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\": \"EnumType\", \"symbols\": [\"FIRST\", \"SECOND\"]} }]}"); + "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\": \"EnumType\", \"symbols\": [\"FIRST\", \"SECOND\"]} }]}"); var testRecord = new EnumResolutionRecord(); Schema readerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + - "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\":" + - " \"EnumType\", \"symbols\": [\"THIRD\", \"FIRST\", \"SECOND\"]} }]}");; + "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\":" + + " \"EnumType\", \"symbols\": [\"THIRD\", \"FIRST\", \"SECOND\"]} }]}");; testRecord.enumType = EnumResolutionEnum.SECOND; // serialize @@ -61,6 +66,28 @@ namespace Avro.Test Assert.AreEqual( EnumResolutionEnum.SECOND, rec2.enumType ); } + [TestCase] + public void TestNullableEnumResolution() + { + Schema writerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + + "\"fields\":[{\"name\":\"enumType\",\"type\":[\"null\", { \"type\": \"enum\", \"name\": " + + "\"EnumType\",\"symbols\": [\"THIRD\", \"FIRST\", \"SECOND\"]}] }]}"); + + var testRecord = new NullableEnumResolutionRecord(); + + Schema readerSchema = Schema.Parse("{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"Avro.Test\"," + + "\"fields\":[{\"name\":\"enumType\",\"type\":[\"null\", { \"type\": \"enum\", \"name\": " + + "\"EnumType\", \"symbols\": [\"THIRD\", \"FIRST\", \"SECOND\"]}] }]}"); + testRecord.enumType = EnumResolutionEnum.SECOND; + + // serialize + var stream = serialize(writerSchema, testRecord); + + // deserialize + var rec2 = deserialize<NullableEnumResolutionRecord>(stream, writerSchema, readerSchema); + Assert.AreEqual( EnumResolutionEnum.SECOND, rec2.enumType ); + } + private static S deserialize<S>(Stream ms, Schema ws, Schema rs) where S : class { long initialPos = ms.Position;
