diff --git ql/src/java/org/apache/hadoop/hive/ql/io/avro/AvroGenericRecordReader.java ql/src/java/org/apache/hadoop/hive/ql/io/avro/AvroGenericRecordReader.java index 1381514..8d58d74 100644 --- ql/src/java/org/apache/hadoop/hive/ql/io/avro/AvroGenericRecordReader.java +++ ql/src/java/org/apache/hadoop/hive/ql/io/avro/AvroGenericRecordReader.java @@ -57,6 +57,7 @@ final private long start; final private long stop; protected JobConf jobConf; + final private boolean isEmptyInput; /** * A unique ID for each record reader. */ @@ -78,9 +79,17 @@ public AvroGenericRecordReader(JobConf job, FileSplit split, Reporter reporter) gdr.setExpected(latest); } - this.reader = new DataFileReader(new FsInput(split.getPath(), job), gdr); - this.reader.sync(split.getStart()); - this.start = reader.tell(); + if (split.getLength() == 0) { + this.isEmptyInput = true; + this.start = 0; + this.reader = null; + } + else { + this.isEmptyInput = false; + this.reader = new DataFileReader(new FsInput(split.getPath(), job), gdr); + this.reader.sync(split.getStart()); + this.start = reader.tell(); + } this.stop = split.getStart() + split.getLength(); this.recordReaderID = new UID(); } @@ -146,7 +155,7 @@ private boolean pathIsInPartition(Path split, String partitionPath) { @Override public boolean next(NullWritable nullWritable, AvroGenericRecordWritable record) throws IOException { - if(!reader.hasNext() || reader.pastSync(stop)) { + if(isEmptyInput || !reader.hasNext() || reader.pastSync(stop)) { return false; } @@ -170,12 +179,13 @@ public AvroGenericRecordWritable createValue() { @Override public long getPos() throws IOException { - return reader.tell(); + return isEmptyInput ? 0 : reader.tell(); } @Override public void close() throws IOException { - reader.close(); + if (isEmptyInput == false) + reader.close(); } @Override diff --git ql/src/test/org/apache/hadoop/hive/ql/io/avro/TestAvroGenericRecordReader.java ql/src/test/org/apache/hadoop/hive/ql/io/avro/TestAvroGenericRecordReader.java new file mode 100644 index 0000000..6d4356a --- /dev/null +++ ql/src/test/org/apache/hadoop/hive/ql/io/avro/TestAvroGenericRecordReader.java @@ -0,0 +1,59 @@ +/** + * 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 + * + * http://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.hadoop.hive.ql.io.avro; + +import org.apache.hadoop.mapred.FileSplit; +import org.apache.hadoop.mapred.JobConf; +import org.apache.hadoop.mapred.Reporter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +public class TestAvroGenericRecordReader { + + @Mock private JobConf jobConf; + @Mock private FileSplit emptyFileSplit; + @Mock private Reporter reporter; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(emptyFileSplit.getLength()).thenReturn(0l); + } + + @Test + public void emptyFile() throws IOException + { + AvroGenericRecordReader reader = new AvroGenericRecordReader(jobConf, emptyFileSplit, reporter); + + //next() should always return false + Assert.assertEquals(false, reader.next(null, null)); + + //getPos() should always return 0 + Assert.assertEquals(0, reader.getPos()); + + //close() should just do nothing + reader.close(); + } +}