You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by lp...@apache.org on 2022/07/12 13:16:01 UTC

[hive] branch master updated: HIVE-26380: Fix NPE when reading a struct field with null value from iceberg table (#3426) (Laszlo Pinter, reviewed by Adam Szita)

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

lpinter pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 723d5227048 HIVE-26380: Fix NPE when reading a struct field with null value from iceberg table (#3426) (Laszlo Pinter, reviewed by Adam Szita)
723d5227048 is described below

commit 723d52270488b8dbc108db1a9925d1c569415039
Author: László Pintér <47...@users.noreply.github.com>
AuthorDate: Tue Jul 12 15:15:48 2022 +0200

    HIVE-26380: Fix NPE when reading a struct field with null value from iceberg table (#3426) (Laszlo Pinter, reviewed by Adam Szita)
---
 .../IcebergRecordObjectInspector.java              |  6 ++++++
 .../iceberg/mr/hive/TestHiveIcebergInserts.java    | 24 ++++++++++++++++++++++
 .../TestIcebergRecordObjectInspector.java          | 10 +++++++++
 3 files changed, 40 insertions(+)

diff --git a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/serde/objectinspector/IcebergRecordObjectInspector.java b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/serde/objectinspector/IcebergRecordObjectInspector.java
index 1f56b4ce947..da5245bc779 100644
--- a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/serde/objectinspector/IcebergRecordObjectInspector.java
+++ b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/serde/objectinspector/IcebergRecordObjectInspector.java
@@ -72,11 +72,17 @@ public final class IcebergRecordObjectInspector extends StructObjectInspector {
 
   @Override
   public Object getStructFieldData(Object o, StructField structField) {
+    if (o == null) {
+      return null;
+    }
     return ((Record) o).get(((IcebergRecordStructField) structField).position());
   }
 
   @Override
   public List<Object> getStructFieldsDataAsList(Object o) {
+    if (o == null) {
+      return null;
+    }
     Record record = (Record) o;
     return structFields
             .stream()
diff --git a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergInserts.java b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergInserts.java
index 7e3c72bf310..efb08c36d95 100644
--- a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergInserts.java
+++ b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/TestHiveIcebergInserts.java
@@ -332,6 +332,30 @@ public class TestHiveIcebergInserts extends HiveIcebergStorageHandlerWithEngineB
     HiveIcebergTestUtils.validateData(target2, target2Records, 1);
   }
 
+  @Test
+  public void testStructMapWithNull() throws IOException {
+    Assume.assumeTrue("Vectorized parquet read throws class cast exception",
+        !(fileFormat == FileFormat.PARQUET && isVectorized));
+    Schema schema = new Schema(required(1, "id", Types.LongType.get()),
+        required(2, "mapofstructs", Types.MapType.ofRequired(3, 4, Types.StringType.get(),
+            Types.StructType.of(required(5, "something", Types.StringType.get()),
+                required(6, "someone", Types.StringType.get()),
+                required(7, "somewhere", Types.StringType.get())
+            ))
+        )
+    );
+
+    List<Record> records = TestHelper.RecordsBuilder.newInstance(schema)
+        .add(0L, ImmutableMap.of())
+        .build();
+
+    testTables.createTable(shell, "mapwithnull", schema, fileFormat, records);
+
+    List<Object[]> results = shell.executeStatement("select mapofstructs['context'].someone FROM mapwithnull");
+    Assert.assertEquals(1, results.size());
+    Assert.assertNull(results.get(0)[0]);
+  }
+
   @Test
   public void testWriteWithDefaultWriteFormat() {
     Assume.assumeTrue("Testing the default file format is enough for a single scenario.",
diff --git a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/serde/objectinspector/TestIcebergRecordObjectInspector.java b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/serde/objectinspector/TestIcebergRecordObjectInspector.java
index b67042b5eed..80a687f6f4a 100644
--- a/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/serde/objectinspector/TestIcebergRecordObjectInspector.java
+++ b/iceberg/iceberg-handler/src/test/java/org/apache/iceberg/mr/hive/serde/objectinspector/TestIcebergRecordObjectInspector.java
@@ -61,4 +61,14 @@ public class TestIcebergRecordObjectInspector {
     Assert.assertEquals(innerRecord.get(0), innerSoi.getStructFieldData(innerData, stringField));
   }
 
+  @Test
+  public void testIcebergRecordObjectInspectorWithRowNull() {
+    Schema schema = new Schema(required(1, "integer_field", Types.IntegerType.get()),
+        required(2, "struct_field", Types.StructType.of(Types.NestedField.required(3, "string_field",
+            Types.StringType.get()))));
+    StructObjectInspector soi = (StructObjectInspector) IcebergObjectInspector.create(schema);
+    Assert.assertNull(soi.getStructFieldsDataAsList(null));
+    StructField integerField = soi.getStructFieldRef("integer_field");
+    Assert.assertNull(soi.getStructFieldData(null, integerField));
+  }
 }