This is an automated email from the ASF dual-hosted git repository.

dkulp pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new ed2dbd4d8 AVRO-2764: explain union
ed2dbd4d8 is described below

commit ed2dbd4d871e9ab1992c39e38d9d56f33ce55127
Author: Christophe Le Saec <[email protected]>
AuthorDate: Thu Jul 27 14:38:11 2023 +0200

    AVRO-2764: explain union
---
 .../avro/src/main/java/org/apache/avro/Schema.java |  8 +++
 .../test/java/org/apache/avro/TestUnionError.java  | 84 ++++++++++++++++++++++
 2 files changed, 92 insertions(+)

diff --git a/lang/java/avro/src/main/java/org/apache/avro/Schema.java 
b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
index 97513f52f..14924c184 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Schema.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
@@ -48,6 +48,8 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.apache.avro.util.internal.Accessor;
 import org.apache.avro.util.internal.Accessor.FieldAccessor;
 import org.apache.avro.util.internal.JacksonUtils;
@@ -1280,6 +1282,12 @@ public abstract class Schema extends JsonProperties 
implements Serializable {
         type.toJson(names, gen);
       gen.writeEndArray();
     }
+
+    @Override
+    public String getName() {
+      return super.getName()
+          + 
this.getTypes().stream().map(Schema::getName).collect(Collectors.joining(", ", 
"[", "]"));
+    }
   }
 
   private static class FixedSchema extends NamedSchema {
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestUnionError.java 
b/lang/java/avro/src/test/java/org/apache/avro/TestUnionError.java
new file mode 100644
index 000000000..7f5e48fb9
--- /dev/null
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestUnionError.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.avro;
+
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericDatumWriter;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.BinaryDecoder;
+import org.apache.avro.io.BinaryEncoder;
+import org.apache.avro.io.DecoderFactory;
+import org.apache.avro.io.EncoderFactory;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class TestUnionError {
+
+  @Test
+  void unionErrorMessage() throws IOException {
+    String writerSchemaJson = "            {\n" + "              \"type\" : 
\"record\",\n"
+        + "              \"name\" : \"C\",\n" + "              \"fields\" : [ 
{\n"
+        + "                \"name\" : \"c\",\n" + "                \"type\" : 
[ {\n"
+        + "                  \"type\" : \"record\",\n" + "                  
\"name\" : \"A\",\n"
+        + "                  \"fields\" : [ {\n" + "                    
\"name\" : \"amount\",\n"
+        + "                    \"type\" : \"int\"\n" + "                  } 
]\n" + "                }, {\n"
+        + "                  \"type\" : \"record\",\n" + "                  
\"name\" : \"B\",\n"
+        + "                  \"fields\" : [ {\n" + "                    
\"name\" : \"amount1\",\n"
+        + "                    \"type\" : \"int\"\n" + "                  } 
]\n" + "                } ]\n"
+        + "              } ]\n" + "            }";
+    Schema writerSchema = new Schema.Parser().parse(writerSchemaJson);
+
+    String readerSchemaJson = " {\n" + "              \"type\" : 
\"record\",\n" + "              \"name\" : \"C1\",\n"
+        + "              \"fields\" : [ {\n" + "                \"name\" : 
\"c\",\n"
+        + "                \"type\" : [ {\n" + "                  \"type\" : 
\"record\",\n"
+        + "                  \"name\" : \"A\",\n" + "                  
\"fields\" : [ {\n"
+        + "                    \"name\" : \"amount\",\n" + "                   
 \"type\" : \"int\"\n"
+        + "                  } ]\n" + "                }, \"float\" ]\n" + "   
           } ]\n" + "            }";
+    Schema readerSchema = new Schema.Parser().parse(readerSchemaJson);
+
+    List<Schema> unionSchemas = writerSchema.getField("c").schema().getTypes();
+
+    GenericRecord r = new GenericData.Record(writerSchema);
+    GenericRecord b = new GenericData.Record(unionSchemas.get(1));
+    b.put("amount1", 12);
+    r.put("c", b);
+
+    ByteArrayOutputStream outs = new ByteArrayOutputStream();
+    GenericDatumWriter<GenericRecord> datumWriter = new 
GenericDatumWriter<>(writerSchema);
+    BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(outs, null);
+    datumWriter.write(r, encoder);
+    encoder.flush();
+
+    InputStream ins = new ByteArrayInputStream(outs.toByteArray());
+    BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(ins, null);
+
+    GenericDatumReader<GenericRecord> datumReader = new 
GenericDatumReader<>(writerSchema, readerSchema);
+    AvroTypeException avroException = assertThrows(AvroTypeException.class, () 
-> datumReader.read(null, decoder));
+    assertEquals("Found B, expecting union[A, float]", 
avroException.getMessage());
+  }
+}

Reply via email to