You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dk...@apache.org on 2020/05/22 12:17:53 UTC

[avro] branch master updated: [AVRO-2278] getter semantics confusing. (#864)

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 3a098e8  [AVRO-2278] getter semantics confusing. (#864)
3a098e8 is described below

commit 3a098e8be4944216f811211c9e3240fd6f67a4ae
Author: Zoltan Farkas <zo...@yahoo.com>
AuthorDate: Fri May 22 08:17:43 2020 -0400

    [AVRO-2278] getter semantics confusing. (#864)
    
    * [fix] getter semantics confusing.
    
    impossible to distinguish between a correct field with the value null.
    and a nonsense field.
    
    * [fix]delete soem generated class
    
    * [fix]delete soem generated class
    
    * [fix]delete soem generated class
    
    * [add] sync up exception behavior for consistency, and better messages.
    
    * [add] helper method.
---
 .../src/main/java/org/apache/avro/generic/GenericData.java  |  8 +++++---
 .../main/java/org/apache/avro/generic/GenericRecord.java    |  5 +++++
 .../java/org/apache/avro/specific/SpecificRecordBase.java   | 13 +++++++++++--
 .../apache/avro/TestReadingWritingDataInEvolvedSchemas.java |  8 +++++++-
 .../src/test/java/org/apache/avro/TestSchemaBuilder.java    |  5 ++---
 .../test/java/org/apache/avro/generic/TestGenericData.java  |  7 +++----
 .../avro/compiler/specific/templates/java/classic/record.vm |  4 ++--
 .../output-string/avro/examples/baseball/FieldTest.java     |  4 ++--
 .../output-string/avro/examples/baseball/Player.java        |  4 ++--
 lang/java/tools/src/test/compiler/output/Player.java        |  4 ++--
 10 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
index dede107..77cd4af 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericData.java
@@ -237,8 +237,9 @@ public class GenericData {
     @Override
     public void put(String key, Object value) {
       Schema.Field field = schema.getField(key);
-      if (field == null)
+      if (field == null) {
         throw new AvroRuntimeException("Not a valid schema field: " + key);
+      }
 
       values[field.pos()] = value;
     }
@@ -251,8 +252,9 @@ public class GenericData {
     @Override
     public Object get(String key) {
       Field field = schema.getField(key);
-      if (field == null)
-        return null;
+      if (field == null) {
+        throw new AvroRuntimeException("Not a valid schema field: " + key);
+      }
       return values[field.pos()];
     }
 
diff --git a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericRecord.java b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericRecord.java
index a2ba9b5..9479896 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/generic/GenericRecord.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/generic/GenericRecord.java
@@ -27,4 +27,9 @@ public interface GenericRecord extends IndexedRecord {
 
   /** Return the value of a field given its name. */
   Object get(String key);
+
+  /** Return true if record has field with name: key */
+  default boolean hasField(String key) {
+    return getSchema().getField(key) != null;
+  }
 }
diff --git a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificRecordBase.java b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificRecordBase.java
index f2950b3..07df303 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificRecordBase.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificRecordBase.java
@@ -21,6 +21,7 @@ import java.io.Externalizable;
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
 import java.io.IOException;
+import org.apache.avro.AvroRuntimeException;
 
 import org.apache.avro.Conversion;
 import org.apache.avro.Schema;
@@ -56,12 +57,20 @@ public abstract class SpecificRecordBase
 
   @Override
   public void put(String fieldName, Object value) {
-    put(getSchema().getField(fieldName).pos(), value);
+    Schema.Field field = getSchema().getField(fieldName);
+    if (field == null) {
+      throw new AvroRuntimeException("Not a valid schema field: " + fieldName);
+    }
+    put(field.pos(), value);
   }
 
   @Override
   public Object get(String fieldName) {
-    return get(getSchema().getField(fieldName).pos());
+    Schema.Field field = getSchema().getField(fieldName);
+    if (field == null) {
+      throw new AvroRuntimeException("Not a valid schema field: " + fieldName);
+    }
+    return get(field.pos());
   }
 
   public Conversion<?> getConversion(String fieldName) {
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java b/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
index d065102..6b118bb 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestReadingWritingDataInEvolvedSchemas.java
@@ -34,6 +34,7 @@ import org.apache.avro.generic.GenericDatumReader;
 import org.apache.avro.generic.GenericDatumWriter;
 import org.apache.avro.generic.GenericRecord;
 import org.apache.avro.io.*;
+import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -342,7 +343,12 @@ public class TestReadingWritingDataInEvolvedSchemas {
     byte[] encoded = encodeGenericBlob(record);
     Record decoded = decodeGenericBlob(INT_RECORD, writer, encoded);
     assertEquals(42, decoded.get(FIELD_A));
-    assertNull(decoded.get("newTopField"));
+    try {
+      decoded.get("newTopField");
+      Assert.fail("get should throw a exception");
+    } catch (AvroRuntimeException ex) {
+      Assert.assertEquals("Not a valid schema field: newTopField", ex.getMessage());
+    }
   }
 
   @Test
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java
index afc3026..23a2865 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java
@@ -645,8 +645,7 @@ public class TestSchemaBuilder {
     String strdef = "\u0003";
     HashMap<String, String> mapdef = new HashMap<>();
     mapdef.put("a", "A");
-    ArrayList<String> arrdef = new ArrayList<>();
-    arrdef.add("arr");
+    List<String> arrdef = Collections.singletonList("arr");
 
     Schema rec = SchemaBuilder.record("inner").fields().name("f").type().intType().noDefault().endRecord();
 
@@ -721,7 +720,7 @@ public class TestSchemaBuilder {
     for (CharSequence c : arr) {
       Assert.assertTrue(arrdef.contains(c.toString()));
     }
-    Assert.assertEquals(newRec.get("arrF"), newRec.get("arrU"));
+    Assert.assertEquals(newRec.get("arrayF"), newRec.get("arrayU"));
     Assert.assertEquals(recdef, newRec.get("recordF"));
     Assert.assertEquals(recdef2, newRec.get("recordU"));
     Assert.assertEquals("S", newRec.get("byName").toString());
diff --git a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
index ae43c18..27006ad 100644
--- a/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
+++ b/lang/java/avro/src/test/java/org/apache/avro/generic/TestGenericData.java
@@ -160,12 +160,11 @@ public class TestGenericData {
     assertFalse(record1.equals(record2));
   }
 
-  @Test
+  @Test(expected = AvroRuntimeException.class)
   public void testRecordGetFieldDoesntExist() throws Exception {
-    List<Field> fields = new ArrayList<>();
-    Schema schema = Schema.createRecord(fields);
+    Schema schema = Schema.createRecord("test", "doc", "test", false, Collections.EMPTY_LIST);
     GenericData.Record record = new GenericData.Record(schema);
-    assertNull(record.get("does not exist"));
+    record.get("does not exist");
   }
 
   @Test
diff --git a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
index 74118c3..b37a16f 100755
--- a/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
+++ b/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm
@@ -176,7 +176,7 @@ static {
     case $i: return ${this.mangle($field.name(), $schema.isError())};
 #set ($i = $i + 1)
 #end
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
@@ -204,7 +204,7 @@ static {
     case $i: ${this.mangle($field.name(), $schema.isError())} = #if(${this.javaType($field.schema())} != "java.lang.Object" && ${this.javaType($field.schema())} != "java.lang.String")(${this.javaType($field.schema())})#{end}value$#if(${this.javaType($field.schema())} == "java.lang.String") != null ? value$.toString() : null#{end}; break;
 #set ($i = $i + 1)
 #end
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
diff --git a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
index 6d08f85..bb636f7 100644
--- a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
+++ b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/FieldTest.java
@@ -120,7 +120,7 @@ static {
     case 3: return timestampMicros;
     case 4: return timeMillis;
     case 5: return timeMicros;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
@@ -150,7 +150,7 @@ static {
     case 3: timestampMicros = (java.time.Instant)value$; break;
     case 4: timeMillis = (java.time.LocalTime)value$; break;
     case 5: timeMicros = (java.time.LocalTime)value$; break;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
diff --git a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
index 0a0c91b..70a9543 100644
--- a/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
+++ b/lang/java/tools/src/test/compiler/output-string/avro/examples/baseball/Player.java
@@ -108,7 +108,7 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen
     case 1: return first_name;
     case 2: return last_name;
     case 3: return position;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
@@ -120,7 +120,7 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen
     case 1: first_name = value$ != null ? value$.toString() : null; break;
     case 2: last_name = value$ != null ? value$.toString() : null; break;
     case 3: position = (java.util.List<avro.examples.baseball.Position>)value$; break;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
diff --git a/lang/java/tools/src/test/compiler/output/Player.java b/lang/java/tools/src/test/compiler/output/Player.java
index a4c0e64..be47d95 100644
--- a/lang/java/tools/src/test/compiler/output/Player.java
+++ b/lang/java/tools/src/test/compiler/output/Player.java
@@ -108,7 +108,7 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen
     case 1: return first_name;
     case 2: return last_name;
     case 3: return position;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }
 
@@ -120,7 +120,7 @@ public class Player extends org.apache.avro.specific.SpecificRecordBase implemen
     case 1: first_name = (java.lang.CharSequence)value$; break;
     case 2: last_name = (java.lang.CharSequence)value$; break;
     case 3: position = (java.util.List<avro.examples.baseball.Position>)value$; break;
-    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
+    default: throw new IndexOutOfBoundsException("Invalid index: " + field$);
     }
   }