This is an automated email from the ASF dual-hosted git repository.

pvary pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new 4e2a9bda37 ORC: Fix NPE when reading/writing variant type with ORC 
format (#18387)
4e2a9bda37 is described below

commit 4e2a9bda3705c55bf37473c7d728d4ffecb698f6
Author: Akash R Nilugal <[email protected]>
AuthorDate: Fri Nov 6 18:05:46 2026 +0530

    ORC: Fix NPE when reading/writing variant type with ORC format (#18387)
---
 .../flink/data/TestFlinkOrcReaderWriter.java       | 46 +++++++++++++++
 .../flink/data/TestFlinkOrcReaderWriter.java       | 46 +++++++++++++++
 .../flink/data/TestFlinkOrcReaderWriter.java       | 46 +++++++++++++++
 .../iceberg/orc/OrcSchemaWithTypeVisitor.java      |  6 +-
 .../apache/iceberg/spark/data/TestOrcWrite.java    | 21 +++++++
 .../iceberg/spark/data/TestSparkOrcReader.java     | 68 ++++++++++++++++++++++
 .../apache/iceberg/spark/data/TestOrcWrite.java    | 21 +++++++
 .../iceberg/spark/data/TestSparkOrcReader.java     | 68 ++++++++++++++++++++++
 .../apache/iceberg/spark/data/TestOrcWrite.java    | 21 +++++++
 .../iceberg/spark/data/TestSparkOrcReader.java     | 68 ++++++++++++++++++++++
 10 files changed, 406 insertions(+), 5 deletions(-)

diff --git 
a/flink/v1.20/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
 
b/flink/v1.20/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
index b7b0a54156..e1df627d87 100644
--- 
a/flink/v1.20/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
+++ 
b/flink/v1.20/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
@@ -18,7 +18,9 @@
  */
 package org.apache.iceberg.flink.data;
 
+import static org.apache.iceberg.types.Types.NestedField.required;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,6 +31,7 @@ import org.apache.flink.table.types.logical.RowType;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.data.DataTestBase;
+import org.apache.iceberg.data.GenericRecord;
 import org.apache.iceberg.data.RandomGenericData;
 import org.apache.iceberg.data.Record;
 import org.apache.iceberg.data.orc.GenericOrcReader;
@@ -39,6 +42,12 @@ import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
+import org.junit.jupiter.api.Test;
 
 public class TestFlinkOrcReaderWriter extends DataTestBase {
   private static final int NUM_RECORDS = 100;
@@ -120,4 +129,41 @@ public class TestFlinkOrcReaderWriter extends DataTestBase 
{
       assertThat(records).isExhausted();
     }
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            required(100, "id", Types.LongType.get()),
+            required(101, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(variantSchema);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .schema(variantSchema)
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .build()) {
+      writer.add(record);
+    }
+
+    try (CloseableIterable<RowData> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(variantSchema)
+            .createReaderFunc(type -> new FlinkOrcReader(variantSchema, type))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
 }
diff --git 
a/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
 
b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
index b7b0a54156..e1df627d87 100644
--- 
a/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
+++ 
b/flink/v2.2/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
@@ -18,7 +18,9 @@
  */
 package org.apache.iceberg.flink.data;
 
+import static org.apache.iceberg.types.Types.NestedField.required;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,6 +31,7 @@ import org.apache.flink.table.types.logical.RowType;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.data.DataTestBase;
+import org.apache.iceberg.data.GenericRecord;
 import org.apache.iceberg.data.RandomGenericData;
 import org.apache.iceberg.data.Record;
 import org.apache.iceberg.data.orc.GenericOrcReader;
@@ -39,6 +42,12 @@ import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
+import org.junit.jupiter.api.Test;
 
 public class TestFlinkOrcReaderWriter extends DataTestBase {
   private static final int NUM_RECORDS = 100;
@@ -120,4 +129,41 @@ public class TestFlinkOrcReaderWriter extends DataTestBase 
{
       assertThat(records).isExhausted();
     }
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            required(100, "id", Types.LongType.get()),
+            required(101, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(variantSchema);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .schema(variantSchema)
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .build()) {
+      writer.add(record);
+    }
+
+    try (CloseableIterable<RowData> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(variantSchema)
+            .createReaderFunc(type -> new FlinkOrcReader(variantSchema, type))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
 }
diff --git 
a/flink/v2.3/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
 
b/flink/v2.3/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
index b7b0a54156..e1df627d87 100644
--- 
a/flink/v2.3/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
+++ 
b/flink/v2.3/flink/src/test/java/org/apache/iceberg/flink/data/TestFlinkOrcReaderWriter.java
@@ -18,7 +18,9 @@
  */
 package org.apache.iceberg.flink.data;
 
+import static org.apache.iceberg.types.Types.NestedField.required;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -29,6 +31,7 @@ import org.apache.flink.table.types.logical.RowType;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.data.DataTestBase;
+import org.apache.iceberg.data.GenericRecord;
 import org.apache.iceberg.data.RandomGenericData;
 import org.apache.iceberg.data.Record;
 import org.apache.iceberg.data.orc.GenericOrcReader;
@@ -39,6 +42,12 @@ import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
+import org.junit.jupiter.api.Test;
 
 public class TestFlinkOrcReaderWriter extends DataTestBase {
   private static final int NUM_RECORDS = 100;
@@ -120,4 +129,41 @@ public class TestFlinkOrcReaderWriter extends DataTestBase 
{
       assertThat(records).isExhausted();
     }
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            required(100, "id", Types.LongType.get()),
+            required(101, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(variantSchema);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .schema(variantSchema)
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .build()) {
+      writer.add(record);
+    }
+
+    try (CloseableIterable<RowData> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(variantSchema)
+            .createReaderFunc(type -> new FlinkOrcReader(variantSchema, type))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
 }
diff --git 
a/orc/src/main/java/org/apache/iceberg/orc/OrcSchemaWithTypeVisitor.java 
b/orc/src/main/java/org/apache/iceberg/orc/OrcSchemaWithTypeVisitor.java
index 222a00c3e1..c701ab7099 100644
--- a/orc/src/main/java/org/apache/iceberg/orc/OrcSchemaWithTypeVisitor.java
+++ b/orc/src/main/java/org/apache/iceberg/orc/OrcSchemaWithTypeVisitor.java
@@ -90,11 +90,7 @@ public abstract class OrcSchemaWithTypeVisitor<T> {
         "Invalid variant metadata fields: %s",
         String.join(", ", names));
 
-    List<TypeDescription> children = variant.getChildren();
-    T metadataResult = visit((Type) null, children.get(0), visitor);
-    T valueResult = visit((Type) null, children.get(1), visitor);
-
-    return visitor.variant(iVariant, variant, metadataResult, valueResult);
+    return visitor.variant(iVariant, variant, null, null);
   }
 
   public T record(
diff --git 
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
 
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
index e149e57e81..55656be6c0 100644
--- 
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
+++ 
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
@@ -20,6 +20,7 @@ package org.apache.iceberg.spark.data;
 
 import static org.apache.iceberg.types.Types.NestedField.optional;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,4 +57,24 @@ public class TestOrcWrite {
     writer.close();
     assertThat(writer.splitOffsets()).as("Split offsets not 
present").isNotEmpty();
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            optional(1, "id", Types.IntegerType.get()),
+            optional(2, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    assertThatThrownBy(
+            () ->
+                ORC.write(Files.localOutput(testFile))
+                    .createWriterFunc(SparkOrcWriter::new)
+                    .schema(variantSchema)
+                    .build())
+        .isInstanceOf(UnsupportedOperationException.class)
+        .hasMessage("Variant is not supported");
+  }
 }
diff --git 
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
 
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
index 3fcfe6845c..3b4493638d 100644
--- 
a/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
+++ 
b/spark/v4.0/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
@@ -30,6 +30,9 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
+import org.apache.iceberg.data.GenericRecord;
+import org.apache.iceberg.data.Record;
+import org.apache.iceberg.data.orc.GenericOrcWriter;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
@@ -37,11 +40,20 @@ import 
org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterators;
 import org.apache.iceberg.spark.data.vectorized.VectorizedSparkOrcReaders;
 import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
 import org.apache.spark.sql.catalyst.InternalRow;
 import org.apache.spark.sql.vectorized.ColumnarBatch;
 import org.junit.jupiter.api.Test;
 
 public class TestSparkOrcReader extends AvroDataTestBase {
+  private static final Schema VARIANT_SCHEMA =
+      new Schema(
+          required(100, "id", Types.LongType.get()),
+          required(101, "payload", Types.VariantType.get()));
+
   @Override
   protected void writeAndValidate(Schema schema) throws IOException {
     final Iterable<InternalRow> expected = RandomData.generateSpark(schema, 
100, 0L);
@@ -124,4 +136,60 @@ public class TestSparkOrcReader extends AvroDataTestBase {
         .isInstanceOf(IllegalArgumentException.class)
         .hasMessageStartingWith("Cannot create MapType with unknown value 
type");
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<InternalRow> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createReaderFunc(readOrcSchema -> new 
SparkOrcReader(VARIANT_SCHEMA, readOrcSchema))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  @Test
+  public void variantIsNotSupportedWhenVectorized() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<ColumnarBatch> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createBatchedReaderFunc(
+                readOrcSchema ->
+                    VectorizedSparkOrcReaders.buildReader(
+                        VARIANT_SCHEMA, readOrcSchema, ImmutableMap.of()))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  private File writeVariantOrcFile() throws IOException {
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(VARIANT_SCHEMA);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .schema(VARIANT_SCHEMA)
+            .build()) {
+      writer.add(record);
+    }
+
+    return testFile;
+  }
 }
diff --git 
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
 
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
index e149e57e81..55656be6c0 100644
--- 
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
+++ 
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
@@ -20,6 +20,7 @@ package org.apache.iceberg.spark.data;
 
 import static org.apache.iceberg.types.Types.NestedField.optional;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,4 +57,24 @@ public class TestOrcWrite {
     writer.close();
     assertThat(writer.splitOffsets()).as("Split offsets not 
present").isNotEmpty();
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            optional(1, "id", Types.IntegerType.get()),
+            optional(2, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    assertThatThrownBy(
+            () ->
+                ORC.write(Files.localOutput(testFile))
+                    .createWriterFunc(SparkOrcWriter::new)
+                    .schema(variantSchema)
+                    .build())
+        .isInstanceOf(UnsupportedOperationException.class)
+        .hasMessage("Variant is not supported");
+  }
 }
diff --git 
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
 
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
index 3fcfe6845c..3b4493638d 100644
--- 
a/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
+++ 
b/spark/v4.1/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
@@ -30,6 +30,9 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
+import org.apache.iceberg.data.GenericRecord;
+import org.apache.iceberg.data.Record;
+import org.apache.iceberg.data.orc.GenericOrcWriter;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
@@ -37,11 +40,20 @@ import 
org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterators;
 import org.apache.iceberg.spark.data.vectorized.VectorizedSparkOrcReaders;
 import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
 import org.apache.spark.sql.catalyst.InternalRow;
 import org.apache.spark.sql.vectorized.ColumnarBatch;
 import org.junit.jupiter.api.Test;
 
 public class TestSparkOrcReader extends AvroDataTestBase {
+  private static final Schema VARIANT_SCHEMA =
+      new Schema(
+          required(100, "id", Types.LongType.get()),
+          required(101, "payload", Types.VariantType.get()));
+
   @Override
   protected void writeAndValidate(Schema schema) throws IOException {
     final Iterable<InternalRow> expected = RandomData.generateSpark(schema, 
100, 0L);
@@ -124,4 +136,60 @@ public class TestSparkOrcReader extends AvroDataTestBase {
         .isInstanceOf(IllegalArgumentException.class)
         .hasMessageStartingWith("Cannot create MapType with unknown value 
type");
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<InternalRow> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createReaderFunc(readOrcSchema -> new 
SparkOrcReader(VARIANT_SCHEMA, readOrcSchema))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  @Test
+  public void variantIsNotSupportedWhenVectorized() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<ColumnarBatch> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createBatchedReaderFunc(
+                readOrcSchema ->
+                    VectorizedSparkOrcReaders.buildReader(
+                        VARIANT_SCHEMA, readOrcSchema, ImmutableMap.of()))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  private File writeVariantOrcFile() throws IOException {
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(VARIANT_SCHEMA);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .schema(VARIANT_SCHEMA)
+            .build()) {
+      writer.add(record);
+    }
+
+    return testFile;
+  }
 }
diff --git 
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
 
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
index e149e57e81..55656be6c0 100644
--- 
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
+++ 
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestOrcWrite.java
@@ -20,6 +20,7 @@ package org.apache.iceberg.spark.data;
 
 import static org.apache.iceberg.types.Types.NestedField.optional;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,4 +57,24 @@ public class TestOrcWrite {
     writer.close();
     assertThat(writer.splitOffsets()).as("Split offsets not 
present").isNotEmpty();
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    Schema variantSchema =
+        new Schema(
+            optional(1, "id", Types.IntegerType.get()),
+            optional(2, "payload", Types.VariantType.get()));
+
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    assertThatThrownBy(
+            () ->
+                ORC.write(Files.localOutput(testFile))
+                    .createWriterFunc(SparkOrcWriter::new)
+                    .schema(variantSchema)
+                    .build())
+        .isInstanceOf(UnsupportedOperationException.class)
+        .hasMessage("Variant is not supported");
+  }
 }
diff --git 
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
 
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
index 3fcfe6845c..3b4493638d 100644
--- 
a/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
+++ 
b/spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/data/TestSparkOrcReader.java
@@ -30,6 +30,9 @@ import java.util.Iterator;
 import java.util.List;
 import org.apache.iceberg.Files;
 import org.apache.iceberg.Schema;
+import org.apache.iceberg.data.GenericRecord;
+import org.apache.iceberg.data.Record;
+import org.apache.iceberg.data.orc.GenericOrcWriter;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.FileAppender;
 import org.apache.iceberg.orc.ORC;
@@ -37,11 +40,20 @@ import 
org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterators;
 import org.apache.iceberg.spark.data.vectorized.VectorizedSparkOrcReaders;
 import org.apache.iceberg.types.Types;
+import org.apache.iceberg.variants.ShreddedObject;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.Variants;
 import org.apache.spark.sql.catalyst.InternalRow;
 import org.apache.spark.sql.vectorized.ColumnarBatch;
 import org.junit.jupiter.api.Test;
 
 public class TestSparkOrcReader extends AvroDataTestBase {
+  private static final Schema VARIANT_SCHEMA =
+      new Schema(
+          required(100, "id", Types.LongType.get()),
+          required(101, "payload", Types.VariantType.get()));
+
   @Override
   protected void writeAndValidate(Schema schema) throws IOException {
     final Iterable<InternalRow> expected = RandomData.generateSpark(schema, 
100, 0L);
@@ -124,4 +136,60 @@ public class TestSparkOrcReader extends AvroDataTestBase {
         .isInstanceOf(IllegalArgumentException.class)
         .hasMessageStartingWith("Cannot create MapType with unknown value 
type");
   }
+
+  @Test
+  public void variantIsNotSupported() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<InternalRow> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createReaderFunc(readOrcSchema -> new 
SparkOrcReader(VARIANT_SCHEMA, readOrcSchema))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  @Test
+  public void variantIsNotSupportedWhenVectorized() throws IOException {
+    File testFile = writeVariantOrcFile();
+
+    try (CloseableIterable<ColumnarBatch> reader =
+        ORC.read(Files.localInput(testFile))
+            .project(VARIANT_SCHEMA)
+            .createBatchedReaderFunc(
+                readOrcSchema ->
+                    VectorizedSparkOrcReaders.buildReader(
+                        VARIANT_SCHEMA, readOrcSchema, ImmutableMap.of()))
+            .build()) {
+      assertThatThrownBy(reader::iterator)
+          .isInstanceOf(UnsupportedOperationException.class)
+          .hasMessage("Variant is not supported");
+    }
+  }
+
+  private File writeVariantOrcFile() throws IOException {
+    File testFile = File.createTempFile("junit", null, temp.toFile());
+    assertThat(testFile.delete()).as("Delete should succeed").isTrue();
+
+    VariantMetadata metadata = Variants.metadata("name");
+    ShreddedObject payload = Variants.object(metadata);
+    payload.put("name", Variants.of("alice"));
+
+    GenericRecord record = GenericRecord.create(VARIANT_SCHEMA);
+    record.setField("id", 1L);
+    record.setField("payload", Variant.of(metadata, payload));
+
+    try (FileAppender<Record> writer =
+        ORC.write(Files.localOutput(testFile))
+            .createWriterFunc(GenericOrcWriter::buildWriter)
+            .schema(VARIANT_SCHEMA)
+            .build()) {
+      writer.add(record);
+    }
+
+    return testFile;
+  }
 }

Reply via email to