From 4e7eafa0669dace70113cb5e92ac075a207f0856 Mon Sep 17 00:00:00 2001 From: Douglass Cutting Date: Thu, 3 Jun 2010 23:45:54 +0000 Subject: [PATCH] Merge r935526 from trunk to 1.3 branch. Fixes: AVRO-517. git-svn-id: https://svn.apache.org/repos/asf/avro/branches/branch-1.3@951211 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 2 ++ .../avro/generic/GenericDatumReader.java | 5 ++++- .../org/apache/avro/io/ResolvingDecoder.java | 19 +++++++++++++++++++ .../avro/io/TestResolvingIOResolving.java | 10 ++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/CHANGES.txt b/CHANGES.txt index fb9d7c0149c..3266b373343 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -18,6 +18,8 @@ Avro 1.3.3 (Unreleased) AVRO-548. Python client should handle CLIENT handshake match status correctly. (hammer) + AVRO-517. Resolving Decoder fails in some cases. (thiru) + Avro 1.3.2 (31 March 2010) IMPROVEMENTS diff --git a/lang/java/src/java/org/apache/avro/generic/GenericDatumReader.java b/lang/java/src/java/org/apache/avro/generic/GenericDatumReader.java index 23759184850..91ff3010273 100644 --- a/lang/java/src/java/org/apache/avro/generic/GenericDatumReader.java +++ b/lang/java/src/java/org/apache/avro/generic/GenericDatumReader.java @@ -67,7 +67,10 @@ public D read(D reuse, Decoder in) throws IOException { if (resolver == null) { resolver = ResolvingDecoder.resolve(actual, expected); } - return (D) read(reuse, expected, new ResolvingDecoder(resolver, in)); + ResolvingDecoder r = new ResolvingDecoder(resolver, in); + D result = (D) read(reuse, expected, r); + r.drain(); + return result; } /** Called to read data.*/ diff --git a/lang/java/src/java/org/apache/avro/io/ResolvingDecoder.java b/lang/java/src/java/org/apache/avro/io/ResolvingDecoder.java index f64ca154336..cfd76c1091f 100644 --- a/lang/java/src/java/org/apache/avro/io/ResolvingDecoder.java +++ b/lang/java/src/java/org/apache/avro/io/ResolvingDecoder.java @@ -121,6 +121,25 @@ public final Schema.Field[] readFieldOrder() throws IOException { return ((Symbol.FieldOrderAction) parser.advance(Symbol.FIELD_ACTION)). fields; } + + /** + * Consume any more data that has been written by the writer but not + * needed by the reader so that the the underlying decoder is in proper + * shape for the next record. This situation happens when, for example, + * the writer writes a record with two fields and the reader needs only the + * first field. + * + * This function should be called after completely decoding an object but + * before next object can be decoded from the same underlying decoder + * either directly or through another resolving decoder. If the same resolving + * decoder is used for the next object as well, calling this method is + * optional; the state of this resolving decoder ensures that any leftover + * portions are consumed before the next object is decoded. + * @throws IOException + */ + public final void drain() throws IOException { + parser.processImplicitActions(); + } @Override public long readLong() throws IOException { diff --git a/lang/java/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java b/lang/java/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java index e0100795854..35382c59a4d 100644 --- a/lang/java/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java +++ b/lang/java/src/test/java/org/apache/avro/io/TestResolvingIOResolving.java @@ -79,6 +79,16 @@ public static Collection data3() { private static Object[][] dataForResolvingTests() { // The mnemonics are the same as {@link TestValidatingIO#testSchemas} return new Object[][] { + // Projection + { "{\"type\":\"record\",\"name\":\"r\",\"fields\":[" + + "{\"name\":\"f1\", \"type\":\"string\"}," + + "{\"name\":\"f2\", \"type\":\"string\"}," + + "{\"name\":\"f3\", \"type\":\"int\"}]}", "S10S10IS10S10I", + new Object[] { "s1", "s2", 100, "t1", "t2", 200 }, + "{\"type\":\"record\",\"name\":\"r\",\"fields\":[" + + "{\"name\":\"f1\", \"type\":\"string\" }," + + "{\"name\":\"f2\", \"type\":\"string\"}]}", "RS10S10RS10S10", + new Object[] { "s1", "s2", "t1", "t2" } }, // Reordered fields { "{\"type\":\"record\",\"name\":\"r\",\"fields\":[" + "{\"name\":\"f1\", \"type\":\"int\"},"