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 2022/02/02 19:48:25 UTC

[avro] branch branch-1.11 updated: Avro-2862: Fix primitive schemas losing metadata properties (#1438)

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 7b7ed02  Avro-2862: Fix primitive schemas losing metadata properties (#1438)
7b7ed02 is described below

commit 7b7ed02fee2c32f7d3ed3b6e02691e565077525e
Author: Cody <cs...@users.noreply.github.com>
AuthorDate: Wed Feb 2 14:47:44 2022 -0500

    Avro-2862: Fix primitive schemas losing metadata properties (#1438)
    
    * Fix primitive schemas losing metadata properties
    
    * Add null assertion
    
    * PR comments on styling
    
    * Variable name changes
    
    (cherry picked from commit ac85ba202a476fdd42acf4f074dfbffedd680f2b)
---
 .../src/apache/main/Schema/PrimitiveSchema.cs      | 20 ++++++++--
 lang/csharp/src/apache/main/Schema/Schema.cs       | 15 +++++++-
 lang/csharp/src/apache/test/Schema/SchemaTests.cs  | 43 ++++++++++++++++++++++
 3 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/lang/csharp/src/apache/main/Schema/PrimitiveSchema.cs b/lang/csharp/src/apache/main/Schema/PrimitiveSchema.cs
index 1a55c2f..23c2cee 100644
--- a/lang/csharp/src/apache/main/Schema/PrimitiveSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/PrimitiveSchema.cs
@@ -16,8 +16,7 @@
  * limitations under the License.
  */
 using System;
-using System.Collections.Generic;
-using System.Text;
+using System.Linq;
 using Newtonsoft.Json;
 
 namespace Avro
@@ -82,7 +81,22 @@ namespace Avro
         /// <param name="encspace"></param>
         protected internal override void WriteJson(JsonTextWriter w, SchemaNames names, string encspace)
         {
-            w.WriteValue(Name);
+            if(this.Props?.Any() == true)
+            {
+                w.WriteStartObject();
+                w.WritePropertyName("type");
+                w.WriteValue(Name);
+                foreach(var prop in Props)
+                {
+                    w.WritePropertyName(prop.Key);
+                    w.WriteRawValue(prop.Value);
+                }
+                w.WriteEndObject();
+            }
+            else
+            {
+                w.WriteValue(Name);
+            }
         }
 
         /// <summary>
diff --git a/lang/csharp/src/apache/main/Schema/Schema.cs b/lang/csharp/src/apache/main/Schema/Schema.cs
index d14b016..69de388 100644
--- a/lang/csharp/src/apache/main/Schema/Schema.cs
+++ b/lang/csharp/src/apache/main/Schema/Schema.cs
@@ -202,8 +202,19 @@ namespace Avro
                 }
                 else if (jtype.Type == JTokenType.Array)
                     return UnionSchema.NewInstance(jtype as JArray, props, names, encspace);
-                else if (jtype.Type == JTokenType.Object && null != jo["logicalType"]) // logical type based on a complex type
-                    return LogicalSchema.NewInstance(jtok, props, names, encspace);
+                else if (jtype.Type == JTokenType.Object)
+                {
+                    if (null != jo["logicalType"]) // logical type based on a complex type
+                    {
+                        return LogicalSchema.NewInstance(jtok, props, names, encspace);
+                    }
+
+                    var schema = ParseJson(jtype, names, encspace); // primitive schemas are allowed to have additional metadata properties
+                    if (schema is PrimitiveSchema)
+                    {
+                        return schema;
+                    }
+                }
             }
             throw new AvroTypeException($"Invalid JSON for schema: {jtok} at '{jtok.Path}'");
         }
diff --git a/lang/csharp/src/apache/test/Schema/SchemaTests.cs b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
index 5c44f78..44d66fe 100644
--- a/lang/csharp/src/apache/test/Schema/SchemaTests.cs
+++ b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
@@ -185,6 +185,49 @@ namespace Avro.Test
             }
         }
 
+        [TestCase("{ \"type\": \"null\", \"metafield\": \"abc\" }", Schema.Type.Null)]
+        [TestCase("{ \"type\": \"boolean\", \"metafield\": \"abc\" }", Schema.Type.Boolean)]
+        [TestCase("{ \"type\": \"int\", \"metafield\": \"abc\" }", Schema.Type.Int)]
+        [TestCase("{ \"type\": \"long\", \"metafield\": \"abc\" }", Schema.Type.Long)]
+        [TestCase("{ \"type\": \"float\", \"metafield\": \"abc\" }", Schema.Type.Float)]
+        [TestCase("{ \"type\": \"double\", \"metafield\": \"abc\" }", Schema.Type.Double)]
+        [TestCase("{ \"type\": \"bytes\", \"metafield\": \"abc\" }", Schema.Type.Bytes)]
+        [TestCase("{ \"type\": \"string\", \"metafield\": \"abc\" }", Schema.Type.String)]
+        public void TestPrimitiveWithMetadata(string rawSchema, Schema.Type type)
+        {
+            Schema definedSchema = Schema.Parse(rawSchema);
+            Assert.IsTrue(definedSchema is PrimitiveSchema);
+            Assert.AreEqual(type.ToString().ToLower(), definedSchema.Name);
+            Assert.AreEqual(type, definedSchema.Tag);
+
+            testEquality(rawSchema, definedSchema);
+            testToString(definedSchema);
+
+            Assert.True(definedSchema.ToString().Contains("metafield"));
+
+            var rawRecordSchema = "{\"type\":\"record\",\"name\":\"Foo\"," +
+                "\"fields\":[{\"name\":\"f1\",\"type\":" + rawSchema +
+                "}]}";
+            Schema baseRecordSchema = Schema.Parse(rawRecordSchema);
+            Assert.AreEqual(Schema.Type.Record, baseRecordSchema.Tag);
+            RecordSchema recordSchema = baseRecordSchema as RecordSchema;
+            Assert.IsNotNull(recordSchema);
+            Assert.AreEqual(1, recordSchema.Count);
+
+            Assert.IsTrue(recordSchema["f1"].Schema is PrimitiveSchema);
+            Assert.AreEqual(type.ToString().ToLower(), recordSchema["f1"].Schema.Name);
+            Assert.AreEqual(type, recordSchema["f1"].Schema.Tag);
+
+            testEquality(rawRecordSchema, baseRecordSchema);
+            testToString(recordSchema["f1"].Schema);
+
+            Assert.True(baseRecordSchema.ToString().Contains("metafield"));
+            Assert.True(recordSchema["f1"].Schema.ToString().Contains("metafield"));
+
+            Assert.True(definedSchema.Equals(recordSchema["f1"].Schema));
+            Assert.AreEqual(definedSchema.GetHashCode(),recordSchema["f1"].Schema.GetHashCode());
+        }
+
         [TestCase("{\"type\":\"record\",\"name\":\"LongList\"," +
             "\"fields\":[{\"name\":\"f1\",\"type\":\"long\"}," +
             "{\"name\":\"f2\",\"type\": \"int\"}]}",