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

ayushtkn 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 93384557984 HIVE-29341: Iceberg: [V3] NULL initial default for STRUCT 
column (#6565)
93384557984 is described below

commit 93384557984a2dd92c9de42f5fe89976939fef9d
Author: ramitg254 <[email protected]>
AuthorDate: Fri Jul 3 19:16:54 2026 +0530

    HIVE-29341: Iceberg: [V3] NULL initial default for STRUCT column (#6565)
---
 .../apache/iceberg/hive/HiveSchemaConverter.java   |  31 ++++---
 .../org/apache/iceberg/hive/HiveSchemaUtil.java    |  76 +++++++++------
 .../apache/iceberg/hive/TestHiveSchemaUtil.java    |   2 +-
 .../iceberg/mr/hive/HiveIcebergMetaHook.java       |  12 +--
 .../mr/hive/vector/HiveVectorizedReader.java       |   7 ++
 .../iceberg/mr/mapreduce/IcebergRecordReader.java  |  26 +++++-
 .../queries/positive/iceberg_initial_default.q     |  27 +++++-
 .../positive/iceberg_alter_default_column.q.out    |   8 +-
 .../results/positive/iceberg_default_column.q.out  |  12 +--
 .../results/positive/iceberg_initial_default.q.out | 102 +++++++++++++++------
 .../vector/VectorizedDummyColumnReader.java        |  27 +++++-
 11 files changed, 236 insertions(+), 94 deletions(-)

diff --git 
a/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaConverter.java
 
b/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaConverter.java
index 1b743343163..07631516cd4 100644
--- 
a/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaConverter.java
+++ 
b/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaConverter.java
@@ -58,21 +58,22 @@ private HiveSchemaConverter(boolean autoConvert) {
   static Schema convert(List<String> names, List<TypeInfo> typeInfos, 
List<String> comments, boolean autoConvert,
       Map<String, String> defaultValues) {
     HiveSchemaConverter converter = new HiveSchemaConverter(autoConvert);
-    return new Schema(converter.convertInternal(names, typeInfos, 
defaultValues, comments));
+    return new Schema(converter.convertInternal(names, typeInfos, 
defaultValues, comments, false));
   }
 
-  public static Type convert(TypeInfo typeInfo, boolean autoConvert, String 
defaultValue) {
+  public static Type convert(TypeInfo typeInfo, boolean autoConvert, String 
defaultValue,
+      boolean shouldAddInitialDefault) {
     HiveSchemaConverter converter = new HiveSchemaConverter(autoConvert);
-    return converter.convertType(typeInfo, defaultValue);
+    return converter.convertType(typeInfo, defaultValue, 
shouldAddInitialDefault);
   }
 
   List<Types.NestedField> convertInternal(List<String> names, List<TypeInfo> 
typeInfos,
-      Map<String, String> defaultValues, List<String> comments) {
+      Map<String, String> defaultValues, List<String> comments, boolean 
shouldAddInitialDefault) {
     List<Types.NestedField> result = 
Lists.newArrayListWithExpectedSize(names.size());
     int outerId = id + names.size();
     id = outerId;
     for (int i = 0; i < names.size(); ++i) {
-      Type type = convertType(typeInfos.get(i), 
defaultValues.get(names.get(i)));
+      Type type = convertType(typeInfos.get(i), 
defaultValues.get(names.get(i)), shouldAddInitialDefault);
       String columnName = names.get(i);
       Types.NestedField.Builder fieldBuilder =
           Types.NestedField.builder()
@@ -87,6 +88,9 @@ List<Types.NestedField> convertInternal(List<String> names, 
List<TypeInfo> typeI
           Object icebergDefaultValue = 
HiveSchemaUtil.getDefaultValue(defaultValues.get(columnName), type);
           if (icebergDefaultValue != null) {
             
fieldBuilder.withWriteDefault(Expressions.lit(icebergDefaultValue));
+            if (shouldAddInitialDefault) {
+              
fieldBuilder.withInitialDefault(Expressions.lit(icebergDefaultValue));
+            }
           }
         } else if (!type.isStructType()) {
           throw new UnsupportedOperationException(
@@ -99,7 +103,7 @@ List<Types.NestedField> convertInternal(List<String> names, 
List<TypeInfo> typeI
     return result;
   }
 
-  Type convertType(TypeInfo typeInfo, String defaultValue) {
+  Type convertType(TypeInfo typeInfo, String defaultValue, boolean 
shouldAddInitialDefault) {
     switch (typeInfo.getCategory()) {
       case PRIMITIVE:
         switch (((PrimitiveTypeInfo) typeInfo).getPrimitiveCategory()) {
@@ -161,21 +165,24 @@ Type convertType(TypeInfo typeInfo, String defaultValue) {
         }
       case STRUCT:
         StructTypeInfo structTypeInfo = (StructTypeInfo) typeInfo;
-        List<Types.NestedField> fields =
-            convertInternal(structTypeInfo.getAllStructFieldNames(), 
structTypeInfo.getAllStructFieldTypeInfos(),
-                HiveSchemaUtil.getDefaultValuesMap(null, defaultValue), 
Collections.emptyList());
+        List<Types.NestedField> fields = convertInternal(
+            structTypeInfo.getAllStructFieldNames(),
+            structTypeInfo.getAllStructFieldTypeInfos(),
+            HiveSchemaUtil.getDefaultValuesMap(null, defaultValue),
+            Collections.emptyList(),
+            shouldAddInitialDefault);
         return Types.StructType.of(fields);
       case MAP:
         MapTypeInfo mapTypeInfo = (MapTypeInfo) typeInfo;
         int keyId = id++;
-        Type keyType = convertType(mapTypeInfo.getMapKeyTypeInfo(), 
defaultValue);
+        Type keyType = convertType(mapTypeInfo.getMapKeyTypeInfo(), 
defaultValue, shouldAddInitialDefault);
         int valueId = id++;
-        Type valueType = convertType(mapTypeInfo.getMapValueTypeInfo(), 
defaultValue);
+        Type valueType = convertType(mapTypeInfo.getMapValueTypeInfo(), 
defaultValue, shouldAddInitialDefault);
         return Types.MapType.ofOptional(keyId, valueId, keyType, valueType);
       case LIST:
         ListTypeInfo listTypeInfo = (ListTypeInfo) typeInfo;
         int listId = id++;
-        Type listType = convertType(listTypeInfo.getListElementTypeInfo(), 
defaultValue);
+        Type listType = convertType(listTypeInfo.getListElementTypeInfo(), 
defaultValue, shouldAddInitialDefault);
         return Types.ListType.ofOptional(listId, listType);
       case VARIANT:
         return Types.VariantType.get();
diff --git 
a/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaUtil.java
 
b/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaUtil.java
index b1563040bcb..3f18deab4ea 100644
--- 
a/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaUtil.java
+++ 
b/iceberg/iceberg-catalog/src/main/java/org/apache/iceberg/hive/HiveSchemaUtil.java
@@ -25,6 +25,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
@@ -148,10 +149,11 @@ public static TypeInfo convert(Type type) {
    *
    * @param typeInfo     The Hive type
    * @param defaultValue the default value for the column, if any
+   * @param shouldAddInitialDefault whether to set initial default for the 
column or not
    * @return The Iceberg type
    */
-  public static Type convert(TypeInfo typeInfo, String defaultValue) {
-    return HiveSchemaConverter.convert(typeInfo, false, defaultValue);
+  public static Type convert(TypeInfo typeInfo, String defaultValue, boolean 
shouldAddInitialDefault) {
+    return HiveSchemaConverter.convert(typeInfo, false, defaultValue, 
shouldAddInitialDefault);
   }
 
   /**
@@ -418,7 +420,8 @@ public static void setDefaultValues(Record record, 
List<Types.NestedField> missi
     for (Types.NestedField field : missingFields) {
       if (field.type().isStructType()) {
         // Attempt to build the nested struct with its defaults
-        Record nestedRecord = 
buildStructWithDefaults(field.type().asStructType());
+        Record nestedRecord = buildStructFromDefaults(
+            field.type().asStructType(), Types.NestedField::writeDefault);
         if (nestedRecord != null) {
           record.setField(field.name(), nestedRecord);
         }
@@ -430,23 +433,39 @@ public static void setDefaultValues(Record record, 
List<Types.NestedField> missi
   }
 
   /**
-   * Recursively builds a struct populated with write defaults.
-   * * @return A populated Record, or null if no nested fields have defaults.
+   * Backfills struct column that is null on read using nested {@code 
initialDefault} metadata.
+   * This applies to rows written before {@code ADD COLUMNS} added the struct.
+   * Spec allows struct defaults as {@code {}} (see 
https://iceberg.apache.org/spec/#default-values), but
+   * {@code UpdateSchema} add column only supports defaults of underlying 
primitives and keeping the
+   * struct default as null due to which we need to backfill that nested 
default record while reading;
+   * if empty structs are allowed, this backfill can be removed.
    */
-  private static Record buildStructWithDefaults(Types.StructType structType) {
+  public static void backfillStructInitialDefaults(
+      Record iceRecord, Map<String, Record> initialDefaultStructsByColumn) {
+    for (Map.Entry<String, Record> columnAndInitialDefaultStruct : 
initialDefaultStructsByColumn.entrySet()) {
+      String columnName = columnAndInitialDefaultStruct.getKey();
+      if (iceRecord.getField(columnName) == null) {
+        iceRecord.setField(columnName, 
columnAndInitialDefaultStruct.getValue());
+      }
+    }
+  }
+
+  /**
+   * Recursively builds a struct populated with underlying field defaults.
+   * @return A populated Record, or null if no nested fields have defaults.
+   */
+  public static Record buildStructFromDefaults(
+      Types.StructType structType, Function<Types.NestedField, Object> 
defaultForField) {
     Record nestedRecord = GenericRecord.create(structType);
     boolean hasAnyDefault = false;
 
     for (Types.NestedField field : structType.fields()) {
-      if (field.writeDefault() != null) {
-        Object defaultValue = convertToWriteType(field.writeDefault(), 
field.type());
-        nestedRecord.setField(field.name(), defaultValue);
+      Object defaultValue = defaultForField.apply(field);
+      if (defaultValue != null) {
+        nestedRecord.setField(field.name(), convertToWriteType(defaultValue, 
field.type()));
         hasAnyDefault = true;
       } else if (field.type().isStructType()) {
-        // Recursively process deeper nested structs
-        Record deeperRecord = 
buildStructWithDefaults(field.type().asStructType());
-
-        // If the deeper struct has defaults, attach it and flag this current 
struct as populated
+        Record deeperRecord = 
buildStructFromDefaults(field.type().asStructType(), defaultForField);
         if (deeperRecord != null) {
           nestedRecord.setField(field.name(), deeperRecord);
           hasAnyDefault = true;
@@ -454,10 +473,24 @@ private static Record 
buildStructWithDefaults(Types.StructType structType) {
       }
     }
 
-    // If no fields (or nested fields) had defaults, return null to avoid an 
empty struct
     return hasAnyDefault ? nestedRecord : null;
   }
 
+  public static Map<String, Object> getStructInitialDefaults(Types.StructType 
structType) {
+    Map<String, Object> result = Maps.newHashMap();
+    for (Types.NestedField field : structType.fields()) {
+      if (field.initialDefault() != null) {
+        result.put(field.name(), field.initialDefault());
+      } else if (field.type().isStructType()) {
+        Map<String, Object> nested = 
getStructInitialDefaults(field.type().asStructType());
+        if (!nested.isEmpty()) {
+          result.put(field.name(), nested);
+        }
+      }
+    }
+    return result;
+  }
+
   /**
    * Sets a value into a {@link Record} using a struct-only field path 
(top-level column or nested
    * through structs). Intermediate struct records are created as needed.
@@ -496,21 +529,6 @@ private static Record getOrCreateStructRecord(
     return record;
   }
 
-  // Special method for nested structs that always applies defaults to null 
fields
-  private static void setDefaultValuesForNestedStruct(Record record, 
List<Types.NestedField> fields) {
-    for (Types.NestedField field : fields) {
-      Object fieldValue = record.getField(field.name());
-
-      if (field.writeDefault() != null) {
-        Object defaultValue = convertToWriteType(field.writeDefault(), 
field.type());
-        record.setField(field.name(), defaultValue);
-      } else if (field.type().isStructType()) {
-        // Recursively process nested structs
-        setDefaultValuesForNestedStruct((Record) fieldValue, 
field.type().asStructType().fields());
-      }
-    }
-  }
-
   public static Object convertToWriteType(Object value, Type type) {
     if (value == null) {
       return null;
diff --git 
a/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveSchemaUtil.java
 
b/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveSchemaUtil.java
index 6daf3aeca5d..6234a6f8db5 100644
--- 
a/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveSchemaUtil.java
+++ 
b/iceberg/iceberg-catalog/src/test/java/org/apache/iceberg/hive/TestHiveSchemaUtil.java
@@ -220,7 +220,7 @@ private void checkConvert(TypeInfo typeInfo, Type type) {
     // Convert to TypeInfo
     assertThat(HiveSchemaUtil.convert(type)).isEqualTo(typeInfo);
     // Convert to Type
-    assertEquals(type, HiveSchemaUtil.convert(typeInfo, null));
+    assertEquals(type, HiveSchemaUtil.convert(typeInfo, null, true));
   }
 
   /**
diff --git 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/HiveIcebergMetaHook.java
 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/HiveIcebergMetaHook.java
index 5a2bbbf7021..271ce74bfb7 100644
--- 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/HiveIcebergMetaHook.java
+++ 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/HiveIcebergMetaHook.java
@@ -741,16 +741,16 @@ private void 
handleAddColumns(org.apache.hadoop.hive.metastore.api.Table hmsTabl
         (List<SQLDefaultConstraint>) SessionStateUtil.getResource(conf, 
SessionStateUtil.COLUMN_DEFAULTS).orElse(null);
     Map<String, String> defaultValues = 
Stream.ofNullable(sqlDefaultConstraints).flatMap(Collection::stream)
         .collect(Collectors.toMap(SQLDefaultConstraint::getColumn_name, 
SQLDefaultConstraint::getDefault_value));
-    boolean isORc = isOrcFileFormat(hmsTable);
+    boolean isOrc = isOrcFileFormat(hmsTable);
     for (FieldSchema addedCol : addedCols) {
       String defaultValue = defaultValues.get(addedCol.getName());
-      Type type = 
HiveSchemaUtil.convert(TypeInfoUtils.getTypeInfoFromTypeString(addedCol.getType()),
 defaultValue);
+      Type type = 
HiveSchemaUtil.convert(TypeInfoUtils.getTypeInfoFromTypeString(addedCol.getType()),
 defaultValue,
+          !isOrc);
       Literal<Object> defaultVal = Optional.ofNullable(defaultValue).filter(v 
-> !type.isStructType())
           .map(v -> Expressions.lit(HiveSchemaUtil.getDefaultValue(v, 
type))).orElse(null);
-
       // ORC doesn't have support for initialDefault from iceberg layer, we 
only need to set default for writeDefault.
-      updateSchema.addColumn(addedCol.getName(), type, addedCol.getComment(), 
isORc ? null : defaultVal);
-      if (isORc && defaultVal != null) {
+      updateSchema.addColumn(addedCol.getName(), type, addedCol.getComment(), 
isOrc ? null : defaultVal);
+      if (isOrc && defaultVal != null) {
         updateSchema.updateColumnDefault(addedCol.getName(), defaultVal);
       }
     }
@@ -933,7 +933,7 @@ private void 
handlePartitionRename(HiveSchemaUtil.SchemaDifference schemaDiffere
   }
 
   private Type.PrimitiveType getPrimitiveTypeOrThrow(FieldSchema field) throws 
MetaException {
-    Type newType = 
HiveSchemaUtil.convert(TypeInfoUtils.getTypeInfoFromTypeString(field.getType()),
 null);
+    Type newType = 
HiveSchemaUtil.convert(TypeInfoUtils.getTypeInfoFromTypeString(field.getType()),
 null, true);
     if (!(newType instanceof Type.PrimitiveType)) {
       throw new MetaException(String.format("Cannot promote type of column: 
'%s' to a non-primitive type: %s.",
           field.getName(), newType));
diff --git 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/vector/HiveVectorizedReader.java
 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/vector/HiveVectorizedReader.java
index 834d762062d..4189b3aea20 100644
--- 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/vector/HiveVectorizedReader.java
+++ 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/hive/vector/HiveVectorizedReader.java
@@ -52,6 +52,7 @@
 import org.apache.iceberg.Schema;
 import org.apache.iceberg.Table;
 import org.apache.iceberg.expressions.Expression;
+import org.apache.iceberg.hive.HiveSchemaUtil;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.CloseableIterator;
 import org.apache.iceberg.mr.InputFormatConfig;
@@ -187,6 +188,12 @@ static Map<String, Object> 
getInitialColumnDefaults(List<Types.NestedField> colu
     for (Types.NestedField column : columns) {
       if (column.initialDefault() != null) {
         columnDefaults.put(column.name(), column.initialDefault());
+      } else if (column.type().isStructType()) {
+        Map<String, Object> structDefaults =
+            
HiveSchemaUtil.getStructInitialDefaults(column.type().asStructType());
+        if (!structDefaults.isEmpty()) {
+          columnDefaults.put(column.name(), structDefaults);
+        }
       }
     }
     return columnDefaults;
diff --git 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/mapreduce/IcebergRecordReader.java
 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/mapreduce/IcebergRecordReader.java
index e3d03a6bee6..96f8705a3f7 100644
--- 
a/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/mapreduce/IcebergRecordReader.java
+++ 
b/iceberg/iceberg-handler/src/main/java/org/apache/iceberg/mr/mapreduce/IcebergRecordReader.java
@@ -53,6 +53,7 @@
 import org.apache.iceberg.data.parquet.GenericParquetReaders;
 import org.apache.iceberg.encryption.EncryptedFiles;
 import org.apache.iceberg.expressions.Expression;
+import org.apache.iceberg.hive.HiveSchemaUtil;
 import org.apache.iceberg.io.CloseableIterable;
 import org.apache.iceberg.io.CloseableIterator;
 import org.apache.iceberg.io.InputFile;
@@ -63,6 +64,7 @@
 import org.apache.iceberg.orc.ORC;
 import org.apache.iceberg.parquet.Parquet;
 import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
+import org.apache.iceberg.relocated.com.google.common.collect.Maps;
 import org.apache.iceberg.types.Type;
 import org.apache.iceberg.types.TypeUtil;
 import org.apache.iceberg.types.Types;
@@ -173,7 +175,29 @@ private CloseableIterable openGeneric(FileScanTask task, 
Schema readSchema) {
       default -> throw new UnsupportedOperationException(
           String.format("Cannot read %s file: %s", file.format().name(), 
file.location()));
     };
-    return applyResidualFiltering(iterable, residual, readSchema);
+    return applyResidualFiltering(withStructInitialDefaultsBackfill(iterable, 
readSchema), residual, readSchema);
+  }
+
+  private CloseableIterable<T> 
withStructInitialDefaultsBackfill(CloseableIterable<T> iterable, Schema 
readSchema) {
+    Map<String, Record> initialDefaultStructsByColumn = Maps.newHashMap();
+    for (Types.NestedField column : readSchema.columns()) {
+      if (column.type().isStructType()) {
+        Record initialDefaultStruct = HiveSchemaUtil
+            .buildStructFromDefaults(column.type().asStructType(), 
Types.NestedField::initialDefault);
+        if (initialDefaultStruct != null) {
+          initialDefaultStructsByColumn.put(column.name(), 
initialDefaultStruct);
+        }
+      }
+    }
+    if (initialDefaultStructsByColumn.isEmpty()) {
+      return iterable;
+    }
+    return CloseableIterable.transform(iterable, row -> {
+      if (row instanceof Record curIceRecord) {
+        HiveSchemaUtil.backfillStructInitialDefaults(curIceRecord, 
initialDefaultStructsByColumn);
+      }
+      return row;
+    });
   }
 
   private CloseableIterable<T> newAvroIterable(
diff --git 
a/iceberg/iceberg-handler/src/test/queries/positive/iceberg_initial_default.q 
b/iceberg/iceberg-handler/src/test/queries/positive/iceberg_initial_default.q
index c0c058bcd5d..c7007114e5b 100644
--- 
a/iceberg/iceberg-handler/src/test/queries/positive/iceberg_initial_default.q
+++ 
b/iceberg/iceberg-handler/src/test/queries/positive/iceberg_initial_default.q
@@ -13,7 +13,14 @@ ALTER TABLE ice_parq ADD COLUMNS (point STRUCT<x:INT, y:INT> 
DEFAULT '{"x":100,"
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general');
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New 
York"}}');
 
 INSERT INTO ice_parq (id) VALUES (2);
 
@@ -45,7 +52,14 @@ ALTER TABLE ice_avro ADD COLUMNS (point STRUCT<x:INT, y:INT> 
DEFAULT '{"x":100,"
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general');
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New 
York"}}');
 
 INSERT INTO ice_avro (id) VALUES (2);
 
@@ -77,7 +91,14 @@ ALTER TABLE ice_orc ADD COLUMNS (point STRUCT<x:INT, y:INT> 
DEFAULT '{"x":100,"y
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general');
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New 
York"}}');
 
 INSERT INTO ice_orc (id) VALUES (2);
 
diff --git 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_alter_default_column.q.out
 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_alter_default_column.q.out
index bb1ae6aa060..ee405875b38 100644
--- 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_alter_default_column.q.out
+++ 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_alter_default_column.q.out
@@ -60,7 +60,7 @@ POSTHOOK: query: SELECT * FROM ice_t ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_t
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
 2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
 PREHOOK: query: ALTER TABLE ice_t REPLACE COLUMNS (id INT,
   point STRUCT<x:INT, y:INT> DEFAULT '{"x":100,"y":99}',
@@ -94,7 +94,7 @@ POSTHOOK: query: SELECT * FROM ice_t ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_t
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 PREHOOK: query: ALTER TABLE ice_t CHANGE COLUMN point point STRUCT<x:INT, 
y:INT> DEFAULT '{"x":100,"y":88}'
 PREHOOK: type: ALTERTABLE_RENAMECOL
@@ -128,7 +128,7 @@ POSTHOOK: query: SELECT * FROM ice_t ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_t
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 PREHOOK: query: ALTER TABLE ice_t CHANGE COLUMN point point_new STRUCT<x:INT, 
y:INT> DEFAULT '{"x":55,"y":88}'
@@ -155,7 +155,7 @@ POSTHOOK: query: SELECT * FROM ice_t ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_t
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
 4      {"x":55,"y":88} unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     general
diff --git 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_default_column.q.out
 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_default_column.q.out
index 8400d21d357..5ff787ef67b 100644
--- 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_default_column.q.out
+++ 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_default_column.q.out
@@ -170,11 +170,11 @@ POSTHOOK: query: SELECT * FROM t3 ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@t3
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-2      {"x":null,"y":7}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general NULL
-3      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general NULL
-4      {"x":100,"y":99}        NULL    25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general NULL
-5      {"x":100,"y":99}        custom_name     30      50000.0 true    
2024-01-01      2024-01-01 10:00:00     100.00  general NULL
-6      {"x":null,"y":null}     unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general NULL
-7      NULL    null    NULL    50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general NULL
+2      {"x":null,"y":7}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+4      {"x":100,"y":99}        NULL    25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+5      {"x":100,"y":99}        custom_name     30      50000.0 true    
2024-01-01      2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+6      {"x":null,"y":null}     unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+7      NULL    null    NULL    50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general {"name":"John","address":{"street":"Main 
St","city":"New York"}}
 8      NULL    null    NULL    50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general {"name":"John","address":{"street":"Main 
St","city":"New York"}}
 9      NULL    null    NULL    50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general 
{"name":null,"address":{"street":null,"city":"Bangalore"}}
diff --git 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_initial_default.q.out
 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_initial_default.q.out
index da857354d81..d15997e7d81 100644
--- 
a/iceberg/iceberg-handler/src/test/results/positive/iceberg_initial_default.q.out
+++ 
b/iceberg/iceberg-handler/src/test/results/positive/iceberg_initial_default.q.out
@@ -28,7 +28,14 @@ PREHOOK: query: ALTER TABLE ice_parq ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DEF
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 PREHOOK: type: ALTERTABLE_ADDCOLS
 PREHOOK: Input: default@ice_parq
 PREHOOK: Output: default@ice_parq
@@ -40,7 +47,14 @@ POSTHOOK: query: ALTER TABLE ice_parq ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DE
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 POSTHOOK: type: ALTERTABLE_ADDCOLS
 POSTHOOK: Input: default@ice_parq
 POSTHOOK: Output: default@ice_parq
@@ -60,8 +74,8 @@ POSTHOOK: query: SELECT * FROM ice_parq ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_parq
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: ALTER TABLE ice_parq CHANGE COLUMN point point STRUCT<x:INT, 
y:INT> DEFAULT '{"x":100,"y":88}'
 PREHOOK: type: ALTERTABLE_RENAMECOL
 PREHOOK: Input: default@ice_parq
@@ -94,9 +108,9 @@ POSTHOOK: query: SELECT * FROM ice_parq ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_parq
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: CREATE TABLE ice_avro (
   id INT)
 STORED BY ICEBERG  stored as avro
@@ -127,7 +141,14 @@ PREHOOK: query: ALTER TABLE ice_avro ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DEF
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 PREHOOK: type: ALTERTABLE_ADDCOLS
 PREHOOK: Input: default@ice_avro
 PREHOOK: Output: default@ice_avro
@@ -139,7 +160,14 @@ POSTHOOK: query: ALTER TABLE ice_avro ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DE
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 POSTHOOK: type: ALTERTABLE_ADDCOLS
 POSTHOOK: Input: default@ice_avro
 POSTHOOK: Output: default@ice_avro
@@ -159,8 +187,8 @@ POSTHOOK: query: SELECT * FROM ice_avro ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_avro
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: ALTER TABLE ice_avro CHANGE COLUMN point point STRUCT<x:INT, 
y:INT> DEFAULT '{"x":100,"y":88}'
 PREHOOK: type: ALTERTABLE_RENAMECOL
 PREHOOK: Input: default@ice_avro
@@ -193,9 +221,9 @@ POSTHOOK: query: SELECT * FROM ice_avro ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_avro
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: CREATE TABLE ice_orc (
   id INT)
 STORED BY ICEBERG stored as orc
@@ -226,7 +254,14 @@ PREHOOK: query: ALTER TABLE ice_orc ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DEFA
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 PREHOOK: type: ALTERTABLE_ADDCOLS
 PREHOOK: Input: default@ice_orc
 PREHOOK: Output: default@ice_orc
@@ -238,7 +273,14 @@ POSTHOOK: query: ALTER TABLE ice_orc ADD COLUMNS (point 
STRUCT<x:INT, y:INT> DEF
   created_date DATE DEFAULT '2024-01-01',
   created_ts TIMESTAMP DEFAULT '2024-01-01T10:00:00',
   score DECIMAL(5,2) DEFAULT 100.00,
-  category STRING DEFAULT 'general')
+  category STRING DEFAULT 'general',
+  person STRUCT<
+    name: STRING,
+    address: STRUCT<
+      street: STRING,
+      city: STRING
+    >
+  > DEFAULT '{"name":"John","address":{"street":"Main St","city":"New York"}}')
 POSTHOOK: type: ALTERTABLE_ADDCOLS
 POSTHOOK: Input: default@ice_orc
 POSTHOOK: Output: default@ice_orc
@@ -258,8 +300,8 @@ POSTHOOK: query: SELECT * FROM ice_orc ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_orc
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    
NULL
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: ALTER TABLE ice_orc CHANGE COLUMN point point STRUCT<x:INT, 
y:INT> DEFAULT '{"x":100,"y":88}'
 PREHOOK: type: ALTERTABLE_RENAMECOL
 PREHOOK: Input: default@ice_orc
@@ -292,9 +334,9 @@ POSTHOOK: query: SELECT * FROM ice_orc ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_orc
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    
NULL
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: SELECT * FROM ice_parq ORDER BY id
 PREHOOK: type: QUERY
 PREHOOK: Input: default@ice_parq
@@ -303,9 +345,9 @@ POSTHOOK: query: SELECT * FROM ice_parq ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_parq
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: SELECT * FROM ice_avro ORDER BY id
 PREHOOK: type: QUERY
 PREHOOK: Input: default@ice_avro
@@ -314,9 +356,9 @@ POSTHOOK: query: SELECT * FROM ice_avro ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_avro
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    unknown 25      50000.0 true    2024-01-01      2024-01-01 
10:00:00     100.00  general
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
 PREHOOK: query: SELECT * FROM ice_orc ORDER BY id
 PREHOOK: type: QUERY
 PREHOOK: Input: default@ice_orc
@@ -325,6 +367,6 @@ POSTHOOK: query: SELECT * FROM ice_orc ORDER BY id
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@ice_orc
 POSTHOOK: Output: hdfs://### HDFS PATH ###
-1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
-2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
-3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general
+1      NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    
NULL
+2      {"x":100,"y":99}        unknown 25      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
+3      {"x":100,"y":88}        unknown 21      50000.0 true    2024-01-01      
2024-01-01 10:00:00     100.00  general 
{"name":"John","address":{"street":"Main St","city":"New York"}}
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/io/parquet/vector/VectorizedDummyColumnReader.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/io/parquet/vector/VectorizedDummyColumnReader.java
index e8d95ccd158..e4a2e931ea0 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/io/parquet/vector/VectorizedDummyColumnReader.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/io/parquet/vector/VectorizedDummyColumnReader.java
@@ -24,14 +24,19 @@
 import org.apache.hadoop.hive.ql.exec.vector.DecimalColumnVector;
 import org.apache.hadoop.hive.ql.exec.vector.DoubleColumnVector;
 import org.apache.hadoop.hive.ql.exec.vector.LongColumnVector;
+import org.apache.hadoop.hive.ql.exec.vector.StructColumnVector;
 import org.apache.hadoop.hive.ql.exec.vector.TimestampColumnVector;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.StructTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 
 /**
  * A dummy vectorized parquet reader used for schema evolution.
@@ -49,10 +54,13 @@ public VectorizedDummyColumnReader(Object defaultValue) {
 
   @Override
   public void readBatch(int total, ColumnVector col, TypeInfo typeInfo) throws 
IOException {
+    fillColumnWithDefault(col, typeInfo, defaultValue);
+  }
 
+  private void fillColumnWithDefault(ColumnVector col, TypeInfo typeInfo, 
Object value) throws IOException {
     col.isRepeating = true;
     // Case 1: No default → (all nulls)
-    if (defaultValue == null) {
+    if (value == null) {
       Arrays.fill(col.isNull, true);
       col.noNulls = false;
       return;
@@ -63,12 +71,27 @@ public void readBatch(int total, ColumnVector col, TypeInfo 
typeInfo) throws IOE
     col.isNull[0] = false;
 
     if (typeInfo.getCategory() == ObjectInspector.Category.PRIMITIVE) {
-      fillPrimitive(col, (PrimitiveTypeInfo) typeInfo, defaultValue);
+      fillPrimitive(col, (PrimitiveTypeInfo) typeInfo, value);
+    } else if (typeInfo.getCategory() == ObjectInspector.Category.STRUCT) {
+      fillStruct(col, (StructTypeInfo) typeInfo, value);
     } else {
       throw new IOException("Unsupported type category in DummyColumnReader: " 
+ typeInfo.getCategory());
     }
   }
 
+  private void fillStruct(ColumnVector col, StructTypeInfo structTypeInfo, 
Object defaultValue) throws IOException {
+    StructColumnVector structCol = (StructColumnVector) col;
+    List<String> fieldNames = structTypeInfo.getAllStructFieldNames();
+    List<TypeInfo> fieldTypes = structTypeInfo.getAllStructFieldTypeInfos();
+    Map<String, Object> fieldDefaults = defaultValue instanceof Map ?
+        (Map<String, Object>) defaultValue :
+        Collections.emptyMap();
+
+    for (int i = 0; i < fieldNames.size(); i++) {
+      fillColumnWithDefault(structCol.fields[i], fieldTypes.get(i), 
fieldDefaults.get(fieldNames.get(i)));
+    }
+  }
+
   /**
    * Fill the column with the given value.
    * @param col   the column to fill


Reply via email to