You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@orc.apache.org by do...@apache.org on 2026/06/16 17:06:56 UTC
(orc) branch branch-2.1 updated: ORC-2177: Fix array conversion with empty first batch
This is an automated email from the ASF dual-hosted git repository.
dongjoon-hyun pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/orc.git
The following commit(s) were added to refs/heads/branch-2.1 by this push:
new 4cc79423f ORC-2177: Fix array conversion with empty first batch
4cc79423f is described below
commit 4cc79423f79c97ed3e0f0512b2e4a274a4f92aec
Author: sychen <sy...@ctrip.com>
AuthorDate: Tue Jun 16 10:00:49 2026 -0700
ORC-2177: Fix array conversion with empty first batch
### What changes were proposed in this pull request?
Add a `batchSize > 0` guard in `ConvertTreeReader.convertVector()` before accessing index 0.
### Why are the changes needed?
When reading an ORC file with schema evolution converting `array<int>` to `array<string>`, an `ArrayIndexOutOfBoundsException` is thrown if the first batch processed by the element reader has `childCount=0` (i.e., all rows in the batch contain empty arrays).
```java
java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at org.apache.orc.impl.ConvertTreeReaderFactory$StringGroupFromAnyIntegerTreeReader.setConvertVectorElement(ConvertTreeReaderFactory.java:1094)
at org.apache.orc.impl.ConvertTreeReaderFactory$ConvertTreeReader.convertVector(ConvertTreeReaderFactory.java:305)
at org.apache.orc.impl.ConvertTreeReaderFactory$StringGroupFromAnyIntegerTreeReader.nextVector(ConvertTreeReaderFactory.java:1115)
at org.apache.orc.impl.TreeReaderFactory$ListTreeReader.nextVector(TreeReaderFactory.java:2892)
at org.apache.orc.impl.reader.tree.StructBatchReader.readBatchColumn(StructBatchReader.java:66)
at org.apache.orc.impl.reader.tree.StructBatchReader.nextBatchForLevel(StructBatchReader.java:101)
at org.apache.orc.impl.reader.tree.StructBatchReader.nextBatch(StructBatchReader.java:78)
at org.apache.orc.impl.RecordReaderImpl.nextBatch(RecordReaderImpl.java:1444)
```
### How was this patch tested?
Added `testIntArrayToStringArrayFirstBatchAllEmpty` in `TestConvertTreeReaderFactory`
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Claude
Closes #2638 from cxzl25/ORC-2177.
Authored-by: sychen <sy...@ctrip.com>
Signed-off-by: Dongjoon Hyun <do...@apache.org>
(cherry picked from commit 6d125348a6aca67919de4e12c2a3b8c07a3cdefb)
Signed-off-by: Dongjoon Hyun <do...@apache.org>
---
.../apache/orc/impl/ConvertTreeReaderFactory.java | 12 ++++----
.../orc/impl/TestConvertTreeReaderFactory.java | 34 ++++++++++++++++++++++
2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/java/core/src/java/org/apache/orc/impl/ConvertTreeReaderFactory.java b/java/core/src/java/org/apache/orc/impl/ConvertTreeReaderFactory.java
index 6886b551e..aed0a44ac 100644
--- a/java/core/src/java/org/apache/orc/impl/ConvertTreeReaderFactory.java
+++ b/java/core/src/java/org/apache/orc/impl/ConvertTreeReaderFactory.java
@@ -299,11 +299,13 @@ public class ConvertTreeReaderFactory extends TreeReaderFactory {
resultColVector.reset();
if (fromColVector.isRepeating) {
resultColVector.isRepeating = true;
- if (fromColVector.noNulls || !fromColVector.isNull[0]) {
- setConvertVectorElement(0);
- } else {
- resultColVector.noNulls = false;
- resultColVector.isNull[0] = true;
+ if (batchSize > 0) {
+ if (fromColVector.noNulls || !fromColVector.isNull[0]) {
+ setConvertVectorElement(0);
+ } else {
+ resultColVector.noNulls = false;
+ resultColVector.isNull[0] = true;
+ }
}
} else if (fromColVector.noNulls) {
for (int i = 0; i < batchSize; i++) {
diff --git a/java/core/src/test/org/apache/orc/impl/TestConvertTreeReaderFactory.java b/java/core/src/test/org/apache/orc/impl/TestConvertTreeReaderFactory.java
index 53f94cbf7..c1bbcfe4c 100644
--- a/java/core/src/test/org/apache/orc/impl/TestConvertTreeReaderFactory.java
+++ b/java/core/src/test/org/apache/orc/impl/TestConvertTreeReaderFactory.java
@@ -745,4 +745,38 @@ public class TestConvertTreeReaderFactory implements TestConf {
readDecimalInNullStripe("decimal(18,2)", DecimalColumnVector.class,
new String[]{"null", "1024", "1"});
}
+
+ @Test
+ public void testIntArrayToStringArrayFirstBatchAllEmpty() throws Exception {
+ TypeDescription fileSchema = TypeDescription.fromString("struct<col1:array<int>>");
+ TypeDescription readerSchema = TypeDescription.fromString("struct<col1:array<string>>");
+
+ try (Writer w = OrcFile.createWriter(testFilePath,
+ OrcFile.writerOptions(conf).setSchema(fileSchema))) {
+ VectorizedRowBatch b = fileSchema.createRowBatch(3);
+ ListColumnVector lc = (ListColumnVector) b.cols[0];
+ for (int i = 0; i < 3; i++) {
+ lc.offsets[i] = 0;
+ lc.lengths[i] = 0;
+ }
+ lc.childCount = 0;
+ b.size = 3;
+ w.addRowBatch(b);
+ }
+
+ try (Reader reader = OrcFile.createReader(testFilePath, OrcFile.readerOptions(conf));
+ RecordReader rows = reader.rows(reader.options().schema(readerSchema))) {
+ VectorizedRowBatch rb = readerSchema.createRowBatch(3);
+ assertTrue(rows.nextBatch(rb));
+ ListColumnVector r = (ListColumnVector) rb.cols[0];
+ // Cast verifies schema evolution took effect (would be LongColumnVector without evolution)
+ BytesColumnVector child = (BytesColumnVector) r.child;
+ assertEquals(0, r.childCount);
+ for (int i = 0; i < 3; i++) {
+ assertEquals(0, r.lengths[i], "row " + i + " should be empty array");
+ }
+ } finally {
+ fs.delete(testFilePath, false);
+ }
+ }
}