You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2010/01/08 21:16:29 UTC

svn commit: r897316 - in /hadoop/avro/trunk: ./ src/doc/content/xdocs/ src/java/org/apache/avro/generic/ src/java/org/apache/avro/reflect/ src/java/org/apache/avro/specific/ src/test/java/org/apache/avro/

Author: cutting
Date: Fri Jan  8 20:16:21 2010
New Revision: 897316

URL: http://svn.apache.org/viewvc?rev=897316&view=rev
Log:
AVRO-75.  Clarify that missing values with no default value are errors, and fix Java implementation.

Modified:
    hadoop/avro/trunk/CHANGES.txt
    hadoop/avro/trunk/src/doc/content/xdocs/spec.xml
    hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java
    hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumReader.java
    hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificDatumReader.java
    hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java

Modified: hadoop/avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Fri Jan  8 20:16:21 2010
@@ -176,6 +176,9 @@
 
     AVRO-264. Rework Python RPC.  (Jeff Hammerbacher via cutting)
 
+    AVRO-75. Clarify that missing values with no default values cause
+    errors, and fix Java implementation.  (cutting)
+
   OPTIMIZATIONS
 
     AVRO-172. More efficient schema processing (massie)

Modified: hadoop/avro/trunk/src/doc/content/xdocs/spec.xml
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/doc/content/xdocs/spec.xml?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/src/doc/content/xdocs/spec.xml (original)
+++ hadoop/avro/trunk/src/doc/content/xdocs/spec.xml Fri Jan  8 20:16:21 2010
@@ -971,14 +971,13 @@
 
 	    <li>if the reader's record schema has a field with no
               default value, and writer's schema does not have a field
-              with the same name, then the field's value is
-              unset.</li>
+              with the same name, an error is signalled.</li>
 	  </ul>
 	</li>
 
 	<li><strong>if both are enums:</strong>
 	  <p>if the writer's symbol is not present in the reader's
-	    enum, then the enum's value is unset.</p>
+	    enum, then an error is signalled.</p>
 	</li>
 
 	<li><strong>if both are arrays:</strong>

Modified: hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/generic/GenericDatumReader.java Fri Jan  8 20:16:21 2010
@@ -162,11 +162,10 @@
         if (!actualFields.contains(fieldName)) {  // an unset field
           Field f = entry.getValue();
           JsonNode json = f.defaultValue();
-          if (json != null)                       // has default
-            addField(record, fieldName, f.pos(),  // add default
-                     defaultFieldValue(old, f.schema(), json));
-          else if (old != null)                   // remove stale value
-            removeField(record, fieldName, entry.getValue().pos());
+          if (json == null)                       // no default
+            throw new AvroTypeException("No default value for: "+fieldName);
+          addField(record, fieldName, f.pos(),  // add default
+                   defaultFieldValue(old, f.schema(), json));
         }
       }
     }
@@ -187,13 +186,6 @@
     return ((GenericRecord) record).get(name);
   }
 
-  /** Called by the default implementation of {@link #readRecord} to remove a
-   * record field value from a reused instance.  The default implementation is
-   * for {@link GenericRecord}.*/
-  protected void removeField(Object record, String field, int position) {
-    ((GenericRecord) record).remove(field);
-  }
-  
   /** Called by the default implementation of {@link #readRecord} to construct
       a default value for a field. */
   protected Object defaultFieldValue(Object old, Schema schema, JsonNode json)
@@ -206,12 +198,10 @@
         Field f = entry.getValue();
         JsonNode v = json.get(name);
         if (v == null) v = f.defaultValue();
-        if (v != null) {
-          Object o = old != null ? getField(old, name, f.pos()) : null;
-          addField(record, name, f.pos(), defaultFieldValue(o, f.schema(), v));
-        } else if (old != null) {
-          removeField(record, name, f.pos());
-        }
+        if (v == null)
+          throw new AvroTypeException("No default value for: "+name);
+        Object o = old != null ? getField(old, name, f.pos()) : null;
+        addField(record, name, f.pos(), defaultFieldValue(o, f.schema(), v));
       }
       return record;
     case ENUM:

Modified: hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumReader.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumReader.java?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumReader.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/reflect/ReflectDatumReader.java Fri Jan  8 20:16:21 2010
@@ -63,11 +63,6 @@
   }
 
   @Override
-  protected void removeField(Object record, String name, int position) {
-    addField(record, name, position, null);
-  }
-
-  @Override
   @SuppressWarnings(value="unchecked")
   protected Object newArray(Object old, int size, Schema schema) {
     ReflectData data = ReflectData.get();

Modified: hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificDatumReader.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificDatumReader.java?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificDatumReader.java (original)
+++ hadoop/avro/trunk/src/java/org/apache/avro/specific/SpecificDatumReader.java Fri Jan  8 20:16:21 2010
@@ -50,10 +50,6 @@
   protected Object getField(Object record, String name, int position) {
     return ((SpecificRecord)record).get(position);
   }
-  @Override
-  protected void removeField(Object record, String field, int position) {
-    ((SpecificRecord)record).set(position, null);
-  }
 
   @Override
   @SuppressWarnings("unchecked")

Modified: hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java?rev=897316&r1=897315&r2=897316&view=diff
==============================================================================
--- hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java (original)
+++ hadoop/avro/trunk/src/test/java/org/apache/avro/TestSchema.java Fri Jan  8 20:16:21 2010
@@ -392,4 +392,42 @@
     assertEquals("Wrong toString", expected, Schema.parse(expected.toString()));
   }
 
+  @SuppressWarnings(value="unchecked")
+  private static void testNoDefaultField() throws Exception {
+    Schema expected =
+      Schema.parse("{\"type\":\"record\", \"name\":\"Foo\", \"fields\":"+
+                   "[{\"name\":\"f\", \"type\": \"string\"}]}");
+    DatumReader in = new GenericDatumReader(ACTUAL, expected);
+    try {
+      GenericData.Record record = (GenericData.Record)
+        in.read(null, new BinaryDecoder(new ByteArrayInputStream(new byte[0])));
+    } catch (AvroTypeException e) {
+      return;
+    }
+    fail("Should not read: "+expected);
+  }
+
+  @SuppressWarnings(value="unchecked")
+  private static void testEnumMismatch() throws Exception {
+    Schema actual = Schema.parse
+      ("{\"type\":\"enum\",\"name\":\"E\",\"symbols\":[\"X\",\"Y\"]}");
+    Schema expected = Schema.parse
+      ("{\"type\":\"enum\",\"name\":\"E\",\"symbols\":[\"Y\",\"Z\"]}");
+    ByteArrayOutputStream out = new ByteArrayOutputStream();
+    DatumWriter<Object> writer = new GenericDatumWriter<Object>(actual);
+    Encoder encoder = new BinaryEncoder(out);
+    writer.write("Y", encoder);
+    writer.write("X", encoder);
+    byte[] data = out.toByteArray();
+    Decoder decoder = new BinaryDecoder(new ByteArrayInputStream(data));
+    DatumReader in = new GenericDatumReader(actual, expected);
+    assertEquals("Wrong value", "Y", in.read(null, decoder));
+    try {
+      in.read(null, decoder);
+    } catch (AvroTypeException e) {
+      return;
+    }
+    fail("Should not read: "+expected);
+  }
+
 }