You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@impala.apache.org by st...@apache.org on 2021/05/21 00:10:39 UTC

[impala] branch master updated: IMPALA-10485: Support Iceberg field-id based column resolution in the ORC scanner

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

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


The following commit(s) were added to refs/heads/master by this push:
     new ced7b7d  IMPALA-10485: Support Iceberg field-id based column resolution in the ORC scanner
ced7b7d is described below

commit ced7b7d221cda30c65504e18082bb0af6c3cb595
Author: Zoltan Borok-Nagy <bo...@cloudera.com>
AuthorDate: Tue Mar 30 15:40:32 2021 +0200

    IMPALA-10485: Support Iceberg field-id based column resolution in the ORC scanner
    
    Currently the ORC scanner only supports position-based column
    resolution. This patch adds Iceberg field-id based column resolution
    which will be the default for Iceberg tables. It is needed to support
    schema evolution in the future, i.e. ALTER TABLE DROP/RENAME COLUMNS.
    (The Parquet scanner already supports Iceberg field-id based column
    resolution)
    
    Testing
     * added e2e test 'iceberg-orc-field-id.test' by copying the contents of
       nested-types-scanner-basic,
       nested-types-scanner-array-materialization,
       nested-types-scanner-position,
       nested-types-scanner-maps,
       and executing the queries on an Iceberg table with ORC data files
    
    Change-Id: Ia2b1abcc25ad2268aa96dff032328e8951dbfb9d
    Reviewed-on: http://gerrit.cloudera.org:8080/17398
    Reviewed-by: Impala Public Jenkins <im...@cloudera.com>
    Tested-by: Impala Public Jenkins <im...@cloudera.com>
---
 be/src/exec/orc-metadata-utils.cc                  |  179 +-
 be/src/exec/orc-metadata-utils.h                   |   32 +-
 be/src/exec/parquet/parquet-metadata-utils.cc      |   10 +-
 be/src/exec/parquet/parquet-metadata-utils.h       |    6 +-
 be/src/service/query-options-test.cc               |    2 +-
 be/src/service/query-options.cc                    |    4 +-
 be/src/util/debug-util.cc                          |    2 +-
 be/src/util/debug-util.h                           |    2 +-
 common/thrift/Query.thrift                         |   12 +-
 testdata/data/README                               |    6 +
 ...-0d37ec144fff-job_16171873329050_0002-00001.orc |  Bin 0 -> 2333 bytes
 ...-0d37ec144fff-job_16171873329050_0002-00001.orc |  Bin 0 -> 1734 bytes
 .../46b4a907-2ff3-4799-ba4a-074d04734265-m0.avro   |  Bin 0 -> 3657 bytes
 ...933-1-46b4a907-2ff3-4799-ba4a-074d04734265.avro |  Bin 0 -> 1888 bytes
 .../metadata/v1.metadata.json                      |  184 ++
 .../metadata/v2.metadata.json                      |  206 ++
 .../metadata/version-hint.text                     |    1 +
 .../functional/functional_schema_template.sql      |   14 +
 .../datasets/functional/schema_constraints.csv     |    2 +
 .../queries/QueryTest/iceberg-orc-field-id.test    | 2266 ++++++++++++++++++++
 tests/query_test/test_iceberg.py                   |    3 +
 21 files changed, 2883 insertions(+), 48 deletions(-)

diff --git a/be/src/exec/orc-metadata-utils.cc b/be/src/exec/orc-metadata-utils.cc
index 49ec782..190acc9 100644
--- a/be/src/exec/orc-metadata-utils.cc
+++ b/be/src/exec/orc-metadata-utils.cc
@@ -26,8 +26,41 @@ using boost::algorithm::iequals;
 
 namespace impala {
 
+inline int GetFieldIdFromStr(const std::string& str) {
+  try {
+    return std::stoi(str);
+  } catch (std::exception&) {
+    return -1;
+  }
+}
+
+OrcSchemaResolver::OrcSchemaResolver(const HdfsTableDescriptor& tbl_desc,
+    const orc::Type* root, const char* filename, bool is_table_acid) :
+    tbl_desc_(tbl_desc), root_(root), filename_(filename),
+    is_table_full_acid_(is_table_acid) {
+  DetermineFullAcidSchema();
+  if (tbl_desc_.IsIcebergTable()) {
+    schema_resolution_strategy_ = TSchemaResolutionStrategy::FIELD_ID;
+  } else {
+    schema_resolution_strategy_ = TSchemaResolutionStrategy::POSITION;
+  }
+}
+
 Status OrcSchemaResolver::ResolveColumn(const SchemaPath& col_path,
     const orc::Type** node, bool* pos_field, bool* missing_field) const {
+  if (schema_resolution_strategy_ == TSchemaResolutionStrategy::POSITION) {
+    return ResolveColumnByPosition(col_path, node, pos_field, missing_field);
+  } else if (schema_resolution_strategy_ == TSchemaResolutionStrategy::FIELD_ID) {
+    return ResolveColumnByIcebergFieldId(col_path, node, pos_field, missing_field);
+  } else {
+    DCHECK(false);
+    return Status(Substitute("Invalid schema resolution strategy: $0",
+        schema_resolution_strategy_));
+  }
+}
+
+Status OrcSchemaResolver::ResolveColumnByPosition(const SchemaPath& col_path,
+    const orc::Type** node, bool* pos_field, bool* missing_field) const {
   const ColumnType* table_col_type = nullptr;
   *node = root_;
   *pos_field = false;
@@ -66,43 +99,135 @@ Status OrcSchemaResolver::ResolveColumn(const SchemaPath& col_path,
       return Status::OK();
     }
     *node = (*node)->getSubtype(file_idx);
-    if (table_col_type->type == TYPE_ARRAY) {
-      DCHECK_EQ(table_col_type->children.size(), 1);
-      if ((*node)->getKind() != orc::TypeKind::LIST) {
-        return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
-            PrintPath(tbl_desc_, GetCanonicalSchemaPath(table_path, i)), "array",
-            (*node)->toString());
-      }
-    } else if (table_col_type->type == TYPE_MAP) {
-      DCHECK_EQ(table_col_type->children.size(), 2);
-      if ((*node)->getKind() != orc::TypeKind::MAP) {
-        return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
-            PrintPath(tbl_desc_, GetCanonicalSchemaPath(table_path, i)), "map",
-            (*node)->toString());
+    RETURN_IF_ERROR(ValidateType(*table_col_type, **node, table_path, i));
+  }
+  return Status::OK();
+}
+
+Status OrcSchemaResolver::ValidateType(const ColumnType& table_col_type,
+    const orc::Type& orc_type, const SchemaPath& table_path,
+    int current_idx) const {
+  if (table_col_type.type == TYPE_ARRAY) {
+    RETURN_IF_ERROR(ValidateArray(table_col_type, orc_type, table_path, current_idx));
+  } else if (table_col_type.type == TYPE_MAP) {
+    RETURN_IF_ERROR(ValidateMap(table_col_type, orc_type, table_path, current_idx));
+  } else if (table_col_type.type == TYPE_STRUCT) {
+    RETURN_IF_ERROR(ValidateStruct(table_col_type, orc_type, table_path, current_idx));
+  } else {
+    DCHECK(!table_col_type.IsComplexType());
+    DCHECK_EQ(current_idx, table_path.size() - 1);
+    RETURN_IF_ERROR(ValidatePrimitiveType(table_col_type, orc_type));
+  }
+  return Status::OK();
+}
+
+Status OrcSchemaResolver::ValidateStruct(const ColumnType& type,
+    const orc::Type& orc_type, const SchemaPath& col_path,
+    int current_idx) const {
+  DCHECK_GT(type.children.size(), 0);
+  if (orc_type.getKind() != orc::TypeKind::STRUCT) {
+    return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
+        PrintPath(tbl_desc_, GetCanonicalSchemaPath(col_path, current_idx)), "struct",
+        orc_type.toString());
+  }
+  return Status::OK();
+}
+
+Status OrcSchemaResolver::ValidateArray(const ColumnType& type,
+    const orc::Type& orc_type, const SchemaPath& col_path,
+    int current_idx) const {
+  DCHECK_EQ(type.children.size(), 1);
+  if (orc_type.getKind() != orc::TypeKind::LIST) {
+    return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
+        PrintPath(tbl_desc_, GetCanonicalSchemaPath(col_path, current_idx)), "array",
+        orc_type.toString());
+  }
+  return Status::OK();
+}
+
+Status OrcSchemaResolver::ValidateMap(const ColumnType& type,
+    const orc::Type& orc_type, const SchemaPath& col_path,
+    int current_idx) const {
+  DCHECK_EQ(type.children.size(), 2);
+  if (orc_type.getKind() != orc::TypeKind::MAP) {
+    return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
+        PrintPath(tbl_desc_, GetCanonicalSchemaPath(col_path, current_idx)), "map",
+        orc_type.toString());
+  }
+  return Status::OK();
+}
+
+Status OrcSchemaResolver::ResolveColumnByIcebergFieldId(const SchemaPath& col_path,
+    const orc::Type** node, bool* pos_field, bool* missing_field) const {
+  const ColumnType* table_col_type = nullptr;
+  *node = root_;
+  *pos_field = false;
+  *missing_field = false;
+  if (col_path.empty()) return Status::OK();
+  for (int i = 0; i < col_path.size(); ++i) {
+    int table_idx = col_path[i];
+    if (i == 0) {
+      table_col_type = &tbl_desc_.col_descs()[table_idx].type();
+      int field_id = tbl_desc_.col_descs()[table_idx].field_id();
+      *node = FindChildWithFieldId(*node, field_id);
+      if (*node == nullptr) {
+        *missing_field = true;
+        return Status::OK();
       }
-    } else if (table_col_type->type == TYPE_STRUCT) {
-      DCHECK_GT(table_col_type->children.size(), 0);
-      if ((*node)->getKind() != orc::TypeKind::STRUCT) {
-        return Status(TErrorCode::ORC_NESTED_TYPE_MISMATCH, filename_,
-            PrintPath(tbl_desc_, GetCanonicalSchemaPath(table_path, i)), "struct",
-            (*node)->toString());
+      RETURN_IF_ERROR(ValidateType(*table_col_type, **node, col_path, i));
+      continue;
+    }
+    if (table_col_type->type == TYPE_STRUCT) {
+      // Resolve struct field by field id.
+      DCHECK_LT(table_idx, table_col_type->field_ids.size());
+      const int field_id = table_col_type->field_ids[table_idx];
+      *node = FindChildWithFieldId(*node, field_id);
+    } else if (table_col_type->type == TYPE_ARRAY) {
+      if (table_idx == SchemaPathConstants::ARRAY_POS) {
+        *pos_field = true;
+        break;  // return *node as the ARRAY node
       }
-    } else {
-      DCHECK(!table_col_type->IsComplexType());
-      DCHECK_EQ(i, table_path.size() - 1);
-      RETURN_IF_ERROR(ValidateType(*table_col_type, **node));
+      DCHECK_EQ(table_idx, SchemaPathConstants::ARRAY_ITEM);
+      *node = (*(node))->getSubtype(table_idx);
+    } else if (table_col_type->type == TYPE_MAP) {
+      DCHECK(table_idx == SchemaPathConstants::MAP_KEY ||
+             table_idx == SchemaPathConstants::MAP_VALUE);
+      // At this point we've found a MAP with a matching field id. It's safe to resolve
+      // the child (key or value) by position.
+      *node = (*(node))->getSubtype(table_idx);
     }
+    if (*node == nullptr) {
+      *missing_field = true;
+      return Status::OK();
+    }
+    table_col_type = &table_col_type->children[table_idx];
+    RETURN_IF_ERROR(ValidateType(*table_col_type, **node, col_path, i));
   }
   return Status::OK();
 }
 
+const orc::Type* OrcSchemaResolver::FindChildWithFieldId(const orc::Type* node,
+    const int field_id) const {
+  const std::string& ICEBERG_FIELD_ID = "iceberg.id";
+  for (int i = 0; i < node->getSubtypeCount(); ++i) {
+    const orc::Type* child = node->getSubtype(i);
+    DCHECK(child != nullptr);
+    if (!child->hasAttributeKey(ICEBERG_FIELD_ID)) return nullptr;
+    std::string field_id_str = child->getAttributeValue(ICEBERG_FIELD_ID);
+    int64_t child_field_id = GetFieldIdFromStr(field_id_str);
+    if (child_field_id == -1) return nullptr;
+    if (child_field_id == field_id) return child;
+  }
+  return nullptr;
+}
+
 SchemaPath OrcSchemaResolver::GetCanonicalSchemaPath(const SchemaPath& col_path,
-    int last_idx) const {
-  DCHECK_LT(last_idx, col_path.size());
+    int current_idx) const {
+  DCHECK_LT(current_idx, col_path.size());
   SchemaPath ret;
   ret.reserve(col_path.size());
   std::copy_if(col_path.begin(),
-               col_path.begin() + last_idx + 1,
+               col_path.begin() + current_idx + 1,
                std::back_inserter(ret),
                [](int i) { return i >= 0; });
   return ret;
@@ -182,7 +307,7 @@ void OrcSchemaResolver::TranslateColPaths(const SchemaPath& col_path,
   DCHECK_EQ(table_col_path->size(), file_col_path->size());
 }
 
-Status OrcSchemaResolver::ValidateType(const ColumnType& type,
+Status OrcSchemaResolver::ValidatePrimitiveType(const ColumnType& type,
     const orc::Type& orc_type) const {
   switch (orc_type.getKind()) {
     case orc::TypeKind::BOOLEAN:
diff --git a/be/src/exec/orc-metadata-utils.h b/be/src/exec/orc-metadata-utils.h
index 4c2dfb2..a600dbf 100644
--- a/be/src/exec/orc-metadata-utils.h
+++ b/be/src/exec/orc-metadata-utils.h
@@ -42,10 +42,7 @@ constexpr int CURRENT_TRANSCACTION_TYPE_ID = 5;
 class OrcSchemaResolver {
  public:
   OrcSchemaResolver(const HdfsTableDescriptor& tbl_desc, const orc::Type* root,
-      const char* filename, bool is_table_acid) : tbl_desc_(tbl_desc), root_(root),
-      filename_(filename), is_table_full_acid_(is_table_acid) {
-        DetermineFullAcidSchema();
-      }
+      const char* filename, bool is_table_acid);
 
   /// Resolve SchemaPath into orc::Type (ORC column representation)
   /// 'pos_field' is set to true if 'col_path' reference the index field of an array
@@ -62,6 +59,23 @@ class OrcSchemaResolver {
   bool IsAcidColumn(const SchemaPath& col_path) const;
 
  private:
+  TSchemaResolutionStrategy::type schema_resolution_strategy_;
+
+  /// Resolve column based on position. This only works when the fields in the HMS
+  /// table schema match the file schema (apart from Hive ACID schema differences which
+  /// are being handled).
+  Status ResolveColumnByPosition(const SchemaPath& col_path, const orc::Type** node,
+      bool* pos_field, bool* missing_field) const;
+
+  /// Resolve column based on the Iceberg field ids. This way we will retrieve the
+  /// Iceberg field ids from the HMS table via 'col_path', then find the corresponding
+  /// field in the ORC file.
+  Status ResolveColumnByIcebergFieldId(const SchemaPath& col_path, const orc::Type** node,
+      bool* pos_field, bool* missing_field) const;
+
+  /// Finds child of 'node' that has Iceberg field id equals to 'field_id'.
+  const orc::Type* FindChildWithFieldId(const orc::Type* node, const int field_id) const;
+
   /// Translates 'col_path' to non-canonical table and file paths. These non-canonical
   /// paths have the same lengths. To achieve that they might contain -1 values that must
   /// be ignored. These paths are useful for tables that have different table and file
@@ -101,7 +115,15 @@ class OrcSchemaResolver {
   bool is_file_full_acid_;
 
   /// Validate whether the ColumnType is compatible with the orc type
-  Status ValidateType(const ColumnType& type, const orc::Type& orc_type) const
+  Status ValidateType(const ColumnType& type, const orc::Type& orc_type,
+    const SchemaPath& col_path, int last_idx) const WARN_UNUSED_RESULT;
+  Status ValidateStruct(const ColumnType& type, const orc::Type& orc_type,
+      const SchemaPath& col_path, int last_idx) const WARN_UNUSED_RESULT;
+  Status ValidateArray(const ColumnType& type, const orc::Type& orc_type,
+      const SchemaPath& col_path, int last_idx) const WARN_UNUSED_RESULT;
+  Status ValidateMap(const ColumnType& type, const orc::Type& orc_type,
+      const SchemaPath& col_path, int last_idx) const WARN_UNUSED_RESULT;
+  Status ValidatePrimitiveType(const ColumnType& type, const orc::Type& orc_type) const
       WARN_UNUSED_RESULT;
 };
 }
diff --git a/be/src/exec/parquet/parquet-metadata-utils.cc b/be/src/exec/parquet/parquet-metadata-utils.cc
index c999e60..6de2e76 100644
--- a/be/src/exec/parquet/parquet-metadata-utils.cc
+++ b/be/src/exec/parquet/parquet-metadata-utils.cc
@@ -713,7 +713,7 @@ SchemaNode* ParquetSchemaResolver::NextSchemaNode(
 
   int file_idx;
   int table_idx = path[next_idx];
-  if (fallback_schema_resolution_ == TParquetFallbackSchemaResolution::type::NAME) {
+  if (fallback_schema_resolution_ == TSchemaResolutionStrategy::type::NAME) {
     if (next_idx == 0) {
       // Resolve top-level table column by name.
       DCHECK_LT(table_idx, tbl_desc_.col_descs().size());
@@ -745,7 +745,7 @@ SchemaNode* ParquetSchemaResolver::NextSchemaNode(
       }
     }
   } else if (fallback_schema_resolution_ ==
-        TParquetFallbackSchemaResolution::type::FIELD_ID) {
+        TSchemaResolutionStrategy::type::FIELD_ID) {
     // Resolution by field id for Iceberg table.
     if (next_idx == 0) {
       // Resolve top-level table column by field id.
@@ -772,7 +772,7 @@ SchemaNode* ParquetSchemaResolver::NextSchemaNode(
   } else {
     // Resolution by position.
     DCHECK_EQ(fallback_schema_resolution_,
-        TParquetFallbackSchemaResolution::type::POSITION);
+        TSchemaResolutionStrategy::type::POSITION);
     if (next_idx == 0) {
       // For top-level columns, the first index in a path includes the table's partition
       // keys.
@@ -784,9 +784,9 @@ SchemaNode* ParquetSchemaResolver::NextSchemaNode(
 
   if (file_idx >= node->children.size()) {
     string schema_resolution_mode = "unknown";
-    auto entry = _TParquetFallbackSchemaResolution_VALUES_TO_NAMES.find(
+    auto entry = _TSchemaResolutionStrategy_VALUES_TO_NAMES.find(
         fallback_schema_resolution_);
-    if (entry != _TParquetFallbackSchemaResolution_VALUES_TO_NAMES.end()) {
+    if (entry != _TSchemaResolutionStrategy_VALUES_TO_NAMES.end()) {
       schema_resolution_mode = entry->second;
     }
     VLOG_FILE << Substitute(
diff --git a/be/src/exec/parquet/parquet-metadata-utils.h b/be/src/exec/parquet/parquet-metadata-utils.h
index dffc61b..9c84c3e 100644
--- a/be/src/exec/parquet/parquet-metadata-utils.h
+++ b/be/src/exec/parquet/parquet-metadata-utils.h
@@ -140,7 +140,7 @@ struct SchemaNode {
 class ParquetSchemaResolver {
  public:
   ParquetSchemaResolver(const HdfsTableDescriptor& tbl_desc,
-      TParquetFallbackSchemaResolution::type fallback_schema_resolution,
+      TSchemaResolutionStrategy::type fallback_schema_resolution,
       TParquetArrayResolution::type array_resolution)
     : tbl_desc_(tbl_desc),
       fallback_schema_resolution_(fallback_schema_resolution),
@@ -148,7 +148,7 @@ class ParquetSchemaResolver {
       filename_(NULL) {
     // We set FIELD_ID for Iceberg tables.
     if (tbl_desc_.IsIcebergTable()) {
-      fallback_schema_resolution_ = TParquetFallbackSchemaResolution::type::FIELD_ID;
+      fallback_schema_resolution_ = TSchemaResolutionStrategy::type::FIELD_ID;
     }
   }
 
@@ -238,7 +238,7 @@ class ParquetSchemaResolver {
       const SchemaPath& path, int idx) const;
 
   const HdfsTableDescriptor& tbl_desc_;
-  TParquetFallbackSchemaResolution::type fallback_schema_resolution_;
+  TSchemaResolutionStrategy::type fallback_schema_resolution_;
   const TParquetArrayResolution::type array_resolution_;
   const char* filename_;
 
diff --git a/be/src/service/query-options-test.cc b/be/src/service/query-options-test.cc
index c6a706f..4212b58 100644
--- a/be/src/service/query-options-test.cc
+++ b/be/src/service/query-options-test.cc
@@ -222,7 +222,7 @@ TEST(QueryOptions, SetEnumOptions) {
   TestEnumCase(options, CASE(explain_level, TExplainLevel,
       (MINIMAL, STANDARD, EXTENDED, VERBOSE)), true);
   TestEnumCase(options, CASE(parquet_fallback_schema_resolution,
-      TParquetFallbackSchemaResolution, (POSITION, NAME, FIELD_ID)), true);
+      TSchemaResolutionStrategy, (POSITION, NAME, FIELD_ID)), true);
   TestEnumCase(options, CASE(parquet_array_resolution, TParquetArrayResolution,
       (THREE_LEVEL, TWO_LEVEL, TWO_LEVEL_THEN_THREE_LEVEL)), true);
   TestEnumCase(options, CASE(default_file_format, THdfsFileFormat,
diff --git a/be/src/service/query-options.cc b/be/src/service/query-options.cc
index 7fb68a2..2862aee 100644
--- a/be/src/service/query-options.cc
+++ b/be/src/service/query-options.cc
@@ -442,9 +442,9 @@ Status impala::SetQueryOption(const string& key, const string& value,
         break;
       }
       case TImpalaQueryOptions::PARQUET_FALLBACK_SCHEMA_RESOLUTION: {
-        TParquetFallbackSchemaResolution::type enum_type;
+        TSchemaResolutionStrategy::type enum_type;
         RETURN_IF_ERROR(GetThriftEnum(value, "parquet fallback schema resolution",
-            _TParquetFallbackSchemaResolution_VALUES_TO_NAMES, &enum_type));
+            _TSchemaResolutionStrategy_VALUES_TO_NAMES, &enum_type));
         query_options->__set_parquet_fallback_schema_resolution(enum_type);
         break;
       }
diff --git a/be/src/util/debug-util.cc b/be/src/util/debug-util.cc
index de43741..711ab83 100644
--- a/be/src/util/debug-util.cc
+++ b/be/src/util/debug-util.cc
@@ -90,7 +90,7 @@ PRINT_THRIFT_ENUM_IMPL(TJoinOp)
 PRINT_THRIFT_ENUM_IMPL(TKuduReadMode)
 PRINT_THRIFT_ENUM_IMPL(TMetricKind)
 PRINT_THRIFT_ENUM_IMPL(TParquetArrayResolution)
-PRINT_THRIFT_ENUM_IMPL(TParquetFallbackSchemaResolution)
+PRINT_THRIFT_ENUM_IMPL(TSchemaResolutionStrategy)
 PRINT_THRIFT_ENUM_IMPL(TPlanNodeType)
 PRINT_THRIFT_ENUM_IMPL(TPrefetchMode)
 PRINT_THRIFT_ENUM_IMPL(TReplicaPreference)
diff --git a/be/src/util/debug-util.h b/be/src/util/debug-util.h
index 0165093..7f8d962 100644
--- a/be/src/util/debug-util.h
+++ b/be/src/util/debug-util.h
@@ -68,7 +68,7 @@ std::string PrintThriftEnum(const TJoinOp::type& value);
 std::string PrintThriftEnum(const TKuduReadMode::type& value);
 std::string PrintThriftEnum(const TMetricKind::type& value);
 std::string PrintThriftEnum(const TParquetArrayResolution::type& value);
-std::string PrintThriftEnum(const TParquetFallbackSchemaResolution::type& value);
+std::string PrintThriftEnum(const TSchemaResolutionStrategy::type& value);
 std::string PrintThriftEnum(const TPlanNodeType::type& value);
 std::string PrintThriftEnum(const TPrefetchMode::type& value);
 std::string PrintThriftEnum(const TReplicaPreference::type& value);
diff --git a/common/thrift/Query.thrift b/common/thrift/Query.thrift
index 5dd288f..a03f84b 100644
--- a/common/thrift/Query.thrift
+++ b/common/thrift/Query.thrift
@@ -26,10 +26,16 @@ include "Results.thrift"
 include "CatalogObjects.thrift"
 include "LineageGraph.thrift"
 
-enum TParquetFallbackSchemaResolution {
+// Enum for schema resolution strategies. A schema resolution strategy
+// determines how columns/fields are looked up in the data files.
+enum TSchemaResolutionStrategy {
+  // Resolve columns based on position. This assumes that the HMS
+  // table schema and the file schema are in sync.
   POSITION = 0
+  // Resolve columns by names.
   NAME = 1
-  // Valid for Iceberg tables
+  // Valid for Iceberg tables. This resolves columns by using the
+  // Iceberg field ids.
   FIELD_ID = 2
 }
 
@@ -185,7 +191,7 @@ struct TQueryOptions {
   // Determines how to resolve Parquet files' schemas in the absence of field IDs (which
   // is always, since fields IDs are NYI). Valid values are "position" (default) and
   // "name".
-  43: optional TParquetFallbackSchemaResolution parquet_fallback_schema_resolution = 0
+  43: optional TSchemaResolutionStrategy parquet_fallback_schema_resolution = 0
 
   // Multi-threaded execution: degree of parallelism (= number of active threads) per
   // query per backend.
diff --git a/testdata/data/README b/testdata/data/README
index 3325e65..44fc188 100644
--- a/testdata/data/README
+++ b/testdata/data/README
@@ -550,6 +550,12 @@ testdata/data/iceberg_test. Iceberg table location contains
 two directories: metadata, which contains table metadata managed
 by iceberg; data, which contains the data files.
 
+iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc:
+Iceberg table generated by Hive 3.1 + Iceberg 0.11. Originally it was a HiveCatalog
+table, so I've renamed the metadata JSON files and added a version-hint.text file.
+I've also edited the metadata JSON and AVRO files to remove 'hdfs://localhost:20500',
+and updated the file paths. Now it can be used as a HadoopCatalog table.
+
 hudi_parquet:
 IMPALA-8778: Support read Apache Hudi tables
 Hudi parquet is a special format of parquet files managed by Apache Hudi
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00000-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00000-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc
new file mode 100644
index 0000000..26d49d1
Binary files /dev/null and b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00000-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc differ
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00001-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00001-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc
new file mode 100644
index 0000000..2829e50
Binary files /dev/null and b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/data/00001-0-boroknagyz_20210331133358_b718b2ff-9f49-4056-a5ed-0d37ec144fff-job_16171873329050_0002-00001.orc differ
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/46b4a907-2ff3-4799-ba4a-074d04734265-m0.avro b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/46b4a907-2ff3-4799-ba4a-074d04734265-m0.avro
new file mode 100644
index 0000000..5ac80ac
Binary files /dev/null and b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/46b4a907-2ff3-4799-ba4a-074d04734265-m0.avro differ
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/snap-8747481058330439933-1-46b4a907-2ff3-4799-ba4a-074d04734265.avro b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/snap-8747481058330439933-1-46b4a907-2ff3-4799-ba4a-074d04734265.avro
new file mode 100644
index 0000000..0acc913
Binary files /dev/null and b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/snap-8747481058330439933-1-46b4a907-2ff3-4799-ba4a-074d04734265.avro differ
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v1.metadata.json b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v1.metadata.json
new file mode 100644
index 0000000..966a3a2
--- /dev/null
+++ b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v1.metadata.json
@@ -0,0 +1,184 @@
+{
+  "format-version" : 1,
+  "table-uuid" : "8a46331e-8746-4fb1-9cc3-1c02546bc51e",
+  "location" : "/test-warehouse/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc",
+  "last-updated-ms" : 1617190429548,
+  "last-column-id" : 29,
+  "schema" : {
+    "type" : "struct",
+    "fields" : [ {
+      "id" : 1,
+      "name" : "id",
+      "required" : false,
+      "type" : "long"
+    }, {
+      "id" : 2,
+      "name" : "int_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 7,
+        "element" : "int",
+        "element-required" : false
+      }
+    }, {
+      "id" : 3,
+      "name" : "int_array_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 8,
+        "element" : {
+          "type" : "list",
+          "element-id" : 9,
+          "element" : "int",
+          "element-required" : false
+        },
+        "element-required" : false
+      }
+    }, {
+      "id" : 4,
+      "name" : "int_map",
+      "required" : false,
+      "type" : {
+        "type" : "map",
+        "key-id" : 10,
+        "key" : "string",
+        "value-id" : 11,
+        "value" : "int",
+        "value-required" : false
+      }
+    }, {
+      "id" : 5,
+      "name" : "int_map_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 12,
+        "element" : {
+          "type" : "map",
+          "key-id" : 13,
+          "key" : "string",
+          "value-id" : 14,
+          "value" : "int",
+          "value-required" : false
+        },
+        "element-required" : false
+      }
+    }, {
+      "id" : 6,
+      "name" : "nested_struct",
+      "required" : false,
+      "type" : {
+        "type" : "struct",
+        "fields" : [ {
+          "id" : 15,
+          "name" : "a",
+          "required" : false,
+          "type" : "int"
+        }, {
+          "id" : 16,
+          "name" : "b",
+          "required" : false,
+          "type" : {
+            "type" : "list",
+            "element-id" : 19,
+            "element" : "int",
+            "element-required" : false
+          }
+        }, {
+          "id" : 17,
+          "name" : "c",
+          "required" : false,
+          "type" : {
+            "type" : "struct",
+            "fields" : [ {
+              "id" : 20,
+              "name" : "d",
+              "required" : false,
+              "type" : {
+                "type" : "list",
+                "element-id" : 21,
+                "element" : {
+                  "type" : "list",
+                  "element-id" : 22,
+                  "element" : {
+                    "type" : "struct",
+                    "fields" : [ {
+                      "id" : 23,
+                      "name" : "e",
+                      "required" : false,
+                      "type" : "int"
+                    }, {
+                      "id" : 24,
+                      "name" : "f",
+                      "required" : false,
+                      "type" : "string"
+                    } ]
+                  },
+                  "element-required" : false
+                },
+                "element-required" : false
+              }
+            } ]
+          }
+        }, {
+          "id" : 18,
+          "name" : "g",
+          "required" : false,
+          "type" : {
+            "type" : "map",
+            "key-id" : 25,
+            "key" : "string",
+            "value-id" : 26,
+            "value" : {
+              "type" : "struct",
+              "fields" : [ {
+                "id" : 27,
+                "name" : "h",
+                "required" : false,
+                "type" : {
+                  "type" : "struct",
+                  "fields" : [ {
+                    "id" : 28,
+                    "name" : "i",
+                    "required" : false,
+                    "type" : {
+                      "type" : "list",
+                      "element-id" : 29,
+                      "element" : "double",
+                      "element-required" : false
+                    }
+                  } ]
+                }
+              } ]
+            },
+            "value-required" : false
+          }
+        } ]
+      }
+    } ]
+  },
+  "partition-spec" : [ ],
+  "default-spec-id" : 0,
+  "partition-specs" : [ {
+    "spec-id" : 0,
+    "fields" : [ ]
+  } ],
+  "default-sort-order-id" : 0,
+  "sort-orders" : [ {
+    "order-id" : 0,
+    "fields" : [ ]
+  } ],
+  "properties" : {
+    "engine.hive.enabled" : "true",
+    "bucketing_version" : "2",
+    "EXTERNAL" : "TRUE",
+    "storage_handler" : "org.apache.iceberg.mr.hive.HiveIcebergStorageHandler",
+    "write.format.default" : "ORC"
+  },
+  "current-snapshot-id" : -1,
+  "snapshots" : [ ],
+  "snapshot-log" : [ ],
+  "metadata-log" : [ ]
+}
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v2.metadata.json b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v2.metadata.json
new file mode 100644
index 0000000..20e40d0
--- /dev/null
+++ b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v2.metadata.json
@@ -0,0 +1,206 @@
+{
+  "format-version" : 1,
+  "table-uuid" : "8a46331e-8746-4fb1-9cc3-1c02546bc51e",
+  "location" : "/test-warehouse/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc",
+  "last-updated-ms" : 1617190450845,
+  "last-column-id" : 29,
+  "schema" : {
+    "type" : "struct",
+    "fields" : [ {
+      "id" : 1,
+      "name" : "id",
+      "required" : false,
+      "type" : "long"
+    }, {
+      "id" : 2,
+      "name" : "int_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 7,
+        "element" : "int",
+        "element-required" : false
+      }
+    }, {
+      "id" : 3,
+      "name" : "int_array_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 8,
+        "element" : {
+          "type" : "list",
+          "element-id" : 9,
+          "element" : "int",
+          "element-required" : false
+        },
+        "element-required" : false
+      }
+    }, {
+      "id" : 4,
+      "name" : "int_map",
+      "required" : false,
+      "type" : {
+        "type" : "map",
+        "key-id" : 10,
+        "key" : "string",
+        "value-id" : 11,
+        "value" : "int",
+        "value-required" : false
+      }
+    }, {
+      "id" : 5,
+      "name" : "int_map_array",
+      "required" : false,
+      "type" : {
+        "type" : "list",
+        "element-id" : 12,
+        "element" : {
+          "type" : "map",
+          "key-id" : 13,
+          "key" : "string",
+          "value-id" : 14,
+          "value" : "int",
+          "value-required" : false
+        },
+        "element-required" : false
+      }
+    }, {
+      "id" : 6,
+      "name" : "nested_struct",
+      "required" : false,
+      "type" : {
+        "type" : "struct",
+        "fields" : [ {
+          "id" : 15,
+          "name" : "a",
+          "required" : false,
+          "type" : "int"
+        }, {
+          "id" : 16,
+          "name" : "b",
+          "required" : false,
+          "type" : {
+            "type" : "list",
+            "element-id" : 19,
+            "element" : "int",
+            "element-required" : false
+          }
+        }, {
+          "id" : 17,
+          "name" : "c",
+          "required" : false,
+          "type" : {
+            "type" : "struct",
+            "fields" : [ {
+              "id" : 20,
+              "name" : "d",
+              "required" : false,
+              "type" : {
+                "type" : "list",
+                "element-id" : 21,
+                "element" : {
+                  "type" : "list",
+                  "element-id" : 22,
+                  "element" : {
+                    "type" : "struct",
+                    "fields" : [ {
+                      "id" : 23,
+                      "name" : "e",
+                      "required" : false,
+                      "type" : "int"
+                    }, {
+                      "id" : 24,
+                      "name" : "f",
+                      "required" : false,
+                      "type" : "string"
+                    } ]
+                  },
+                  "element-required" : false
+                },
+                "element-required" : false
+              }
+            } ]
+          }
+        }, {
+          "id" : 18,
+          "name" : "g",
+          "required" : false,
+          "type" : {
+            "type" : "map",
+            "key-id" : 25,
+            "key" : "string",
+            "value-id" : 26,
+            "value" : {
+              "type" : "struct",
+              "fields" : [ {
+                "id" : 27,
+                "name" : "h",
+                "required" : false,
+                "type" : {
+                  "type" : "struct",
+                  "fields" : [ {
+                    "id" : 28,
+                    "name" : "i",
+                    "required" : false,
+                    "type" : {
+                      "type" : "list",
+                      "element-id" : 29,
+                      "element" : "double",
+                      "element-required" : false
+                    }
+                  } ]
+                }
+              } ]
+            },
+            "value-required" : false
+          }
+        } ]
+      }
+    } ]
+  },
+  "partition-spec" : [ ],
+  "default-spec-id" : 0,
+  "partition-specs" : [ {
+    "spec-id" : 0,
+    "fields" : [ ]
+  } ],
+  "default-sort-order-id" : 0,
+  "sort-orders" : [ {
+    "order-id" : 0,
+    "fields" : [ ]
+  } ],
+  "properties" : {
+    "engine.hive.enabled" : "true",
+    "bucketing_version" : "2",
+    "EXTERNAL" : "TRUE",
+    "storage_handler" : "org.apache.iceberg.mr.hive.HiveIcebergStorageHandler",
+    "write.format.default" : "ORC"
+  },
+  "current-snapshot-id" : 8747481058330439933,
+  "snapshots" : [ {
+    "snapshot-id" : 8747481058330439933,
+    "timestamp-ms" : 1617190450845,
+    "summary" : {
+      "operation" : "append",
+      "added-data-files" : "2",
+      "added-records" : "8",
+      "added-files-size" : "4067",
+      "changed-partition-count" : "1",
+      "total-records" : "8",
+      "total-data-files" : "2",
+      "total-delete-files" : "0",
+      "total-position-deletes" : "0",
+      "total-equality-deletes" : "0"
+    },
+    "manifest-list" : "/test-warehouse/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/snap-8747481058330439933-1-46b4a907-2ff3-4799-ba4a-074d04734265.avro"
+  } ],
+  "snapshot-log" : [ {
+    "timestamp-ms" : 1617190450845,
+    "snapshot-id" : 8747481058330439933
+  } ],
+  "metadata-log" : [ {
+    "timestamp-ms" : 1617190429548,
+    "metadata-file" : "/test-warehouse/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/v1.metadata.json"
+  } ]
+}
diff --git a/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/version-hint.text b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/version-hint.text
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc/metadata/version-hint.text
@@ -0,0 +1 @@
+2
diff --git a/testdata/datasets/functional/functional_schema_template.sql b/testdata/datasets/functional/functional_schema_template.sql
index e209cee..5698947 100644
--- a/testdata/datasets/functional/functional_schema_template.sql
+++ b/testdata/datasets/functional/functional_schema_template.sql
@@ -3019,6 +3019,20 @@ hadoop fs -put -f ${IMPALA_HOME}/testdata/data/iceberg_test/hadoop_catalog/icebe
 ---- DATASET
 functional
 ---- BASE_TABLE_NAME
+complextypestbl_iceberg_orc
+---- CREATE
+CREATE EXTERNAL TABLE IF NOT EXISTS {db_name}{db_suffix}.{table_name}
+STORED AS ICEBERG
+TBLPROPERTIES('iceberg.file_format'='orc', 'iceberg.catalog'='hadoop.catalog',
+              'iceberg.catalog_location'='/test-warehouse/iceberg_test/hadoop_catalog',
+              'iceberg.table_identifier'='ice.complextypestbl_iceberg_orc');
+---- DEPENDENT_LOAD
+`hadoop fs -mkdir -p /test-warehouse/iceberg_test/hadoop_catalog/ice && \
+hadoop fs -put -f ${IMPALA_HOME}/testdata/data/iceberg_test/hadoop_catalog/ice/complextypestbl_iceberg_orc /test-warehouse/iceberg_test/hadoop_catalog/ice
+====
+---- DATASET
+functional
+---- BASE_TABLE_NAME
 iceberg_resolution_test_external
 ---- CREATE
 CREATE EXTERNAL TABLE IF NOT EXISTS {db_name}{db_suffix}.{table_name}
diff --git a/testdata/datasets/functional/schema_constraints.csv b/testdata/datasets/functional/schema_constraints.csv
index ad52f4f..0d77eb7 100644
--- a/testdata/datasets/functional/schema_constraints.csv
+++ b/testdata/datasets/functional/schema_constraints.csv
@@ -61,6 +61,8 @@ table_name:customer_multiblock, constraint:restrict_to, table_format:parquet/non
 table_name:hudi_partitioned, constraint:restrict_to, table_format:parquet/none/none
 table_name:hudi_non_partitioned, constraint:restrict_to, table_format:parquet/none/none
 table_name:hudi_as_parquet, constraint:restrict_to, table_format:parquet/none/none
+# Iceberg tests are executed in the PARQUET file format dimension
+table_name:complextypestbl_iceberg_orc, constraint:restrict_to, table_format:parquet/none/none
 table_name:hadoop_catalog_test_external, constraint:restrict_to, table_format:parquet/none/none
 table_name:iceberg_int_partitioned, constraint:restrict_to, table_format:parquet/none/none
 table_name:iceberg_non_partitioned, constraint:restrict_to, table_format:parquet/none/none
diff --git a/testdata/workloads/functional-query/queries/QueryTest/iceberg-orc-field-id.test b/testdata/workloads/functional-query/queries/QueryTest/iceberg-orc-field-id.test
new file mode 100644
index 0000000..1d3d1a4
--- /dev/null
+++ b/testdata/workloads/functional-query/queries/QueryTest/iceberg-orc-field-id.test
@@ -0,0 +1,2266 @@
+====
+---- QUERY
+select id from complextypestbl_iceberg_orc
+---- RESULTS
+1
+2
+3
+4
+5
+6
+7
+8
+---- TYPES
+bigint
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc
+---- RESULTS
+8
+---- TYPES
+bigint
+====
+---- QUERY
+select id from complextypestbl_iceberg_orc where id > 3
+---- RESULTS
+4
+5
+6
+7
+8
+---- TYPES
+bigint
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.int_array
+---- RESULTS
+1
+2
+3
+NULL
+1
+2
+NULL
+3
+NULL
+-1
+---- TYPES
+int
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.int_array
+---- RESULTS
+10
+---- TYPES
+bigint
+====
+---- QUERY
+select count(item) from complextypestbl_iceberg_orc.int_array
+---- RESULTS
+7
+---- TYPES
+bigint
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.int_array_array.item
+---- RESULTS
+1
+2
+3
+4
+NULL
+1
+2
+NULL
+3
+NULL
+4
+5
+6
+-1
+-2
+---- TYPES
+int
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.int_array_array.item where item > 3
+---- RESULTS
+4
+4
+5
+6
+---- TYPES
+int
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.int_array_array.item
+---- RESULTS
+15
+---- TYPES
+bigint
+====
+---- QUERY
+select count(item) from complextypestbl_iceberg_orc.int_array_array.item
+---- RESULTS
+12
+---- TYPES
+bigint
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.int_array_array
+---- RESULTS
+11
+---- TYPES
+bigint
+====
+---- QUERY
+select nested_struct.a from complextypestbl_iceberg_orc
+---- RESULTS
+1
+NULL
+NULL
+NULL
+NULL
+NULL
+7
+-1
+---- TYPES
+int
+====
+---- QUERY
+select count(nested_struct.a) from complextypestbl_iceberg_orc
+---- RESULTS
+3
+---- TYPES
+bigint
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.nested_struct.b
+---- RESULTS
+1
+NULL
+2
+3
+NULL
+-1
+---- TYPES
+int
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.nested_struct.b
+---- RESULTS
+6
+---- TYPES
+bigint
+====
+---- QUERY
+select count(item) from complextypestbl_iceberg_orc.nested_struct.b
+---- RESULTS
+4
+---- TYPES
+bigint
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.nested_struct.b where item is null;
+---- RESULTS
+NULL
+NULL
+---- TYPES
+int
+====
+---- QUERY
+select inner_array.item.e from complextypestbl_iceberg_orc.nested_struct.c.d.item inner_array
+---- RESULTS
+10
+-10
+11
+NULL
+10
+NULL
+-10
+NULL
+11
+NULL
+NULL
+-1
+---- TYPES
+int
+====
+---- QUERY
+select count(inner_array.item.e) from complextypestbl_iceberg_orc.nested_struct.c.d.item inner_array
+---- RESULTS
+7
+---- TYPES
+bigint
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.nested_struct.c.d.item inner_array
+---- RESULTS
+12
+---- TYPES
+bigint
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.nested_struct.c.d.item inner_array
+where inner_array.item.f = 'bbb'
+---- RESULTS
+2
+---- TYPES
+bigint
+====
+---- QUERY
+select inner_array.item.e, inner_array.item.f
+from complextypestbl_iceberg_orc.nested_struct.c.d.item inner_array
+---- RESULTS
+10,'aaa'
+-10,'bbb'
+11,'c'
+NULL,'NULL'
+10,'aaa'
+NULL,'NULL'
+-10,'bbb'
+NULL,'NULL'
+11,'c'
+NULL,'NULL'
+NULL,'NULL'
+-1,'nonnullable'
+---- TYPES
+int,string
+====
+---- QUERY
+select count(*) from complextypestbl_iceberg_orc.nested_struct.c.d
+---- RESULTS
+10
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array
+select id, a.item from complextypestbl_iceberg_orc t, t.int_array a
+---- RESULTS
+1,1
+1,2
+1,3
+2,NULL
+2,1
+2,2
+2,NULL
+2,3
+2,NULL
+8,-1
+---- TYPES
+bigint,int
+====
+---- QUERY
+-- Materialize array (for now, may be optimized away someday)
+select a.item from complextypestbl_iceberg_orc t, t.int_array a
+---- RESULTS
+1
+2
+3
+NULL
+1
+2
+NULL
+3
+NULL
+-1
+---- TYPES
+int
+====
+---- QUERY
+-- Materialize scalar and array
+select id, cnt from complextypestbl_iceberg_orc t, (select count(item) cnt from t.int_array) v
+---- RESULTS
+1,3
+2,3
+3,0
+4,0
+5,0
+6,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array
+select cnt from complextypestbl_iceberg_orc t, (select count(item) cnt from t.int_array) v
+---- RESULTS
+3
+3
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array with no slots
+select id, cnt from complextypestbl_iceberg_orc t, (select count(*) cnt from t.int_array) v
+---- RESULTS
+1,3
+2,6
+3,0
+4,0
+5,0
+6,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array with no slots
+select cnt from complextypestbl_iceberg_orc t, (select count(*) cnt from t.int_array) v
+---- RESULTS
+3
+6
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array that is flattened version of nested arrays
+select id, a.item from complextypestbl_iceberg_orc t, t.int_array_array.item a
+---- RESULTS
+1,1
+1,2
+1,3
+1,4
+2,NULL
+2,1
+2,2
+2,NULL
+2,3
+2,NULL
+2,4
+7,5
+7,6
+8,-1
+8,-2
+---- TYPES
+bigint,int
+====
+---- QUERY
+-- Materialize array that is flattened version of nested arrays
+select a.item from complextypestbl_iceberg_orc t, t.int_array_array.item a
+---- RESULTS
+1
+2
+3
+4
+NULL
+1
+2
+NULL
+3
+NULL
+4
+5
+6
+-1
+-2
+---- TYPES
+int
+====
+---- QUERY
+-- Materialize scalar and array that is flattened version of nested arrays
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(item) cnt from t.int_array_array.item) v
+---- RESULTS
+1,4
+2,4
+3,0
+4,0
+5,0
+6,0
+7,2
+8,2
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array that is flattened version of nested arrays
+select cnt from complextypestbl_iceberg_orc t,
+(select count(item) cnt from t.int_array_array.item) v
+---- RESULTS
+4
+4
+0
+0
+0
+0
+2
+2
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array with no slots that is flattened version of nested
+-- arrays
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.int_array_array.item) v
+---- RESULTS
+1,4
+2,7
+3,0
+4,0
+5,0
+6,0
+7,2
+8,2
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array with no slots that is flattened version of nested arrays
+select cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.int_array_array.item) v
+---- RESULTS
+4
+7
+0
+0
+0
+0
+2
+2
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array with no slots that is count of nested arrays
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.int_array_array) v
+---- RESULTS
+1,2
+2,4
+3,1
+4,0
+5,0
+6,0
+7,2
+8,2
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array with no slots that is count of nested arrays
+select cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.int_array_array) v
+---- RESULTS
+2
+4
+1
+0
+0
+0
+2
+2
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array of arrays
+select id, a2.item from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1,1
+1,2
+1,3
+1,4
+2,NULL
+2,1
+2,2
+2,NULL
+2,3
+2,NULL
+2,4
+7,5
+7,6
+8,-1
+8,-2
+---- TYPES
+bigint,int
+====
+---- QUERY
+-- Materialize array of arrays
+select a2.item from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1
+2
+3
+4
+NULL
+1
+2
+NULL
+3
+NULL
+4
+5
+6
+-1
+-2
+---- TYPES
+int
+====
+---- QUERY
+-- Materialize scalar and array of arrays
+select id, cnt from complextypestbl_iceberg_orc t, t.int_array_array a1,
+(select count(a2.item) cnt from a1.item a2) v
+---- RESULTS
+1,2
+1,2
+2,2
+2,2
+2,0
+2,0
+3,0
+7,0
+7,2
+8,2
+8,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of arrays
+select cnt from complextypestbl_iceberg_orc t, t.int_array_array a1,
+(select count(a2.item) cnt from a1.item a2) v
+---- RESULTS
+2
+2
+2
+2
+0
+0
+0
+0
+2
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array of arrays with no slots
+select id, cnt from complextypestbl_iceberg_orc t, t.int_array_array a1,
+(select count(*) cnt from a1.item a2) v
+---- RESULTS
+1,2
+1,2
+2,4
+2,3
+2,0
+2,0
+3,0
+7,0
+7,2
+8,2
+8,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of arrays with no slots
+select cnt from complextypestbl_iceberg_orc t, t.int_array_array a1,
+(select count(*) cnt from a1.item a2) v
+---- RESULTS
+2
+2
+4
+3
+0
+0
+0
+0
+2
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize nested array
+select cnt from complextypestbl_iceberg_orc.int_array_array a1,
+(select count(a2.item) cnt from a1.item a2) v
+---- RESULTS
+2
+2
+2
+2
+0
+0
+0
+0
+2
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize nested array with no slots
+select cnt from complextypestbl_iceberg_orc.int_array_array a1,
+(select count(*) cnt from a1.item a2) v
+---- RESULTS
+2
+2
+4
+3
+0
+0
+0
+0
+2
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar, array, and array of arrays
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(item) cnt2 from a1.item a2) v2
+---- RESULTS
+1,3,2
+1,3,2
+2,3,2
+2,3,2
+2,3,0
+2,3,0
+3,0,0
+7,0,0
+7,0,2
+8,1,2
+8,1,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize scalar, array of no slots, and array of arrays of no slots
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(*) cnt2 from a1.item a2) v2
+---- RESULTS
+1,3,2
+1,3,2
+2,6,4
+2,6,3
+2,6,0
+2,6,0
+3,0,0
+7,0,0
+7,0,2
+8,1,2
+8,1,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize scalar, array, and array of arrays of no slots
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(*) cnt2 from a1.item a2) v2
+---- RESULTS
+1,3,2
+1,3,2
+2,3,4
+2,3,3
+2,3,0
+2,3,0
+3,0,0
+7,0,0
+7,0,2
+8,1,2
+8,1,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize scalar, array of no slots, and array of arrays
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(item) cnt2 from a1.item a2) v2
+---- RESULTS
+1,3,2
+1,3,2
+2,6,2
+2,6,2
+2,6,0
+2,6,0
+3,0,0
+7,0,0
+7,0,2
+8,1,2
+8,1,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize array, and array of arrays
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(item) cnt2 from a1.item a2) v2
+---- RESULTS
+3,2
+3,2
+3,2
+3,2
+3,0
+3,0
+0,0
+0,0
+0,2
+1,2
+1,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of no slots, and array of arrays of no slots
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(*) cnt2 from a1.item a2) v2
+---- RESULTS
+3,2
+3,2
+6,4
+6,3
+6,0
+6,0
+0,0
+0,0
+0,2
+1,2
+1,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array, and array of arrays of no slots
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(*) cnt2 from a1.item a2) v2
+---- RESULTS
+3,2
+3,2
+3,4
+3,3
+3,0
+3,0
+0,0
+0,0
+0,2
+1,2
+1,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of no slots, and array of arrays
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.int_array) v1,
+t.int_array_array a1, (select count(item) cnt2 from a1.item a2) v2
+---- RESULTS
+3,2
+3,2
+6,2
+6,2
+6,0
+6,0
+0,0
+0,0
+0,2
+1,2
+1,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalar, array, and flattened version of nested arrays
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+(select count(item) cnt2 from t.int_array_array.item) v2
+---- RESULTS
+1,3,4
+2,3,4
+3,0,0
+4,0,0
+5,0,0
+6,0,0
+7,0,2
+8,1,2
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize array and flattened version of nested arrays
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+(select count(item) cnt2 from t.int_array_array.item) v2
+---- RESULTS
+3,4
+3,4
+0,0
+0,0
+0,0
+0,0
+0,2
+1,2
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalar, array, and flattened version of nested arrays with no slots
+select id, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+(select count(*) cnt2 from t.int_array_array.item) v2
+---- RESULTS
+1,3,4
+2,3,7
+3,0,0
+4,0,0
+5,0,0
+6,0,0
+7,0,2
+8,1,2
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+-- Materialize array and flattened version of nested arrays with no slots
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.int_array) v1,
+(select count(*) cnt2 from t.int_array_array.item) v2
+---- RESULTS
+3,4
+3,7
+0,0
+0,0
+0,0
+0,0
+0,2
+1,2
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalar and deeply nested array
+select id, e, f from complextypestbl_iceberg_orc t, t.nested_struct.c.d.item
+---- RESULTS
+1,10,'aaa'
+1,-10,'bbb'
+1,11,'c'
+2,NULL,'NULL'
+2,10,'aaa'
+2,NULL,'NULL'
+2,-10,'bbb'
+2,NULL,'NULL'
+2,11,'c'
+2,NULL,'NULL'
+7,NULL,'NULL'
+8,-1,'nonnullable'
+---- TYPES
+bigint,int,string
+====
+---- QUERY
+-- Materialize deeply nested array
+select e, f from complextypestbl_iceberg_orc t, t.nested_struct.c.d.item
+---- RESULTS
+10,'aaa'
+-10,'bbb'
+11,'c'
+NULL,'NULL'
+10,'aaa'
+NULL,'NULL'
+-10,'bbb'
+NULL,'NULL'
+11,'c'
+NULL,'NULL'
+NULL,'NULL'
+-1,'nonnullable'
+---- TYPES
+int,string
+====
+---- QUERY
+-- Materialize scalar and complicated nested array (may be optimized away someday)
+select id, arr.item.e, arr.item.f from complextypestbl_iceberg_orc t, t.nested_struct.c.d, d.item arr
+---- RESULTS
+1,10,'aaa'
+1,-10,'bbb'
+1,11,'c'
+2,NULL,'NULL'
+2,10,'aaa'
+2,NULL,'NULL'
+2,-10,'bbb'
+2,NULL,'NULL'
+2,11,'c'
+2,NULL,'NULL'
+7,NULL,'NULL'
+8,-1,'nonnullable'
+---- TYPES
+bigint,int,string
+====
+---- QUERY
+-- Materialize complicated nested array (may be optimized away someday)
+select arr.item.e, arr.item.f from complextypestbl_iceberg_orc t, t.nested_struct.c.d, d.item arr
+---- RESULTS
+10,'aaa'
+-10,'bbb'
+11,'c'
+NULL,'NULL'
+10,'aaa'
+NULL,'NULL'
+-10,'bbb'
+NULL,'NULL'
+11,'c'
+NULL,'NULL'
+NULL,'NULL'
+-1,'nonnullable'
+---- TYPES
+int,string
+====
+---- QUERY
+-- Materialize scalar and array of arrays, with structs in schema
+select id, cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(arr.item.e) cnt from d.item arr) v
+---- RESULTS
+1,2
+1,1
+2,2
+2,1
+2,0
+2,0
+7,0
+7,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of arrays, with structs in schema
+select cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(arr.item.e) cnt from d.item arr) v
+---- RESULTS
+2
+1
+2
+1
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array of arrays of no slots, with structs in schema
+select id, cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(*) cnt from d.item arr) v
+---- RESULTS
+1,2
+1,1
+2,5
+2,2
+2,0
+2,0
+7,0
+7,1
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of arrays of no slots, with structs in schema
+select cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(*) cnt from d.item arr) v
+---- RESULTS
+2
+1
+5
+2
+0
+0
+0
+1
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array of no slots counting nested arrays, with structs in schema
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d) v
+---- RESULTS
+1,2
+2,4
+3,0
+4,0
+5,0
+6,0
+7,3
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of no slots counting nested arrays, with structs in schema
+select cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d) v
+---- RESULTS
+2
+4
+0
+0
+0
+0
+3
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalars, array, and array of arrays, with structs in schema
+select id, t.nested_struct.a, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(arr.item.e) cnt2 from d.item arr) v2
+---- RESULTS
+1,1,1,2
+1,1,1,1
+2,NULL,0,2
+2,NULL,0,1
+2,NULL,0,0
+2,NULL,0,0
+7,7,2,0
+7,7,2,0
+7,7,2,0
+8,-1,1,1
+---- TYPES
+bigint,int,bigint,bigint
+====
+---- QUERY
+-- Materialize array and array of arrays, with structs in schema
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(arr.item.e) cnt2 from d.item arr) v2
+---- RESULTS
+1,2
+1,1
+0,2
+0,1
+0,0
+0,0
+2,0
+2,0
+2,0
+1,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalars, array with no slots, and array of arrays with no slots, with
+-- structs in schema
+select id, t.nested_struct.a, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(*) cnt2 from d.item arr) v2
+---- RESULTS
+1,1,1,2
+1,1,1,1
+2,NULL,1,5
+2,NULL,1,2
+2,NULL,1,0
+2,NULL,1,0
+7,7,3,0
+7,7,3,1
+7,7,3,0
+8,-1,1,1
+---- TYPES
+bigint,int,bigint,bigint
+====
+---- QUERY
+-- Materialize array with no slots and array of arrays with no slots, with structs in
+-- schema
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(*) cnt2 from d.item arr) v2
+---- RESULTS
+1,2
+1,1
+1,5
+1,2
+1,0
+1,0
+3,0
+3,1
+3,0
+1,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalars, array, and array of arrays with no slots, with structs in schema
+select id, t.nested_struct.a, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(*) cnt2 from d.item arr) v2
+---- RESULTS
+1,1,1,2
+1,1,1,1
+2,NULL,0,5
+2,NULL,0,2
+2,NULL,0,0
+2,NULL,0,0
+7,7,2,0
+7,7,2,1
+7,7,2,0
+8,-1,1,1
+---- TYPES
+bigint,int,bigint,bigint
+====
+---- QUERY
+-- Materialize array and array of arrays with no slots, with structs in schema
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(item) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(*) cnt2 from d.item arr) v2
+---- RESULTS
+1,2
+1,1
+0,5
+0,2
+0,0
+0,0
+2,0
+2,1
+2,0
+1,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalars, array with no slots, and array of arrays, with structs in schema
+select id, t.nested_struct.a, cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(arr.item.e) cnt2 from d.item arr) v2
+---- RESULTS
+1,1,1,2
+1,1,1,1
+2,NULL,1,2
+2,NULL,1,1
+2,NULL,1,0
+2,NULL,1,0
+7,7,3,0
+7,7,3,0
+7,7,3,0
+8,-1,1,1
+---- TYPES
+bigint,int,bigint,bigint
+====
+---- QUERY
+-- Materialize array with no slots and array of arrays, with structs in schema
+select cnt1, cnt2 from complextypestbl_iceberg_orc t,
+(select count(*) cnt1 from t.nested_struct.b) v1,
+t.nested_struct.c.d, (select count(arr.item.e) cnt2 from d.item arr) v2
+---- RESULTS
+1,2
+1,1
+1,2
+1,1
+1,0
+1,0
+3,0
+3,0
+3,0
+1,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize scalar and complicated nested array
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(e) cnt from t.nested_struct.c.d.item) v
+---- RESULTS
+1,3
+2,3
+3,0
+4,0
+5,0
+6,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize complicated nested array
+select cnt from complextypestbl_iceberg_orc t,
+(select count(e) cnt from t.nested_struct.c.d.item) v
+---- RESULTS
+3
+3
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and complicated nested array with no slots
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d.item) v
+---- RESULTS
+1,3
+2,7
+3,0
+4,0
+5,0
+6,0
+7,1
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize complicated nested array with no slots
+select cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d.item) v
+---- RESULTS
+3
+7
+0
+0
+0
+0
+1
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and array of arrays, with structs in schema
+select id, cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(f) cnt from d.item) v
+---- RESULTS
+1,2
+1,1
+2,2
+2,1
+2,0
+2,0
+7,0
+7,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize array of arrays, with structs in schema
+select cnt from complextypestbl_iceberg_orc t, t.nested_struct.c.d,
+(select count(f) cnt from d.item) v
+---- RESULTS
+2
+1
+2
+1
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and nested array from struct
+select nested_struct.a, f from complextypestbl_iceberg_orc t, t.nested_struct.c.d.item
+---- RESULTS
+1,'aaa'
+1,'bbb'
+1,'c'
+NULL,'NULL'
+NULL,'aaa'
+NULL,'NULL'
+NULL,'bbb'
+NULL,'NULL'
+NULL,'c'
+NULL,'NULL'
+7,'NULL'
+-1,'nonnullable'
+---- TYPES
+int,string
+====
+---- QUERY
+-- Materialize scalar and nested array from struct
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(f) cnt from t.nested_struct.c.d.item) v;
+---- RESULTS
+1,3
+2,3
+3,0
+4,0
+5,0
+6,0
+7,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize nested array from struct
+select cnt from complextypestbl_iceberg_orc t,
+(select count(f) cnt from t.nested_struct.c.d.item) v;
+---- RESULTS
+3
+3
+0
+0
+0
+0
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and nested array with no slots, with structs in schema
+select id, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d.item) v;
+---- RESULTS
+1,3
+2,7
+3,0
+4,0
+5,0
+6,0
+7,1
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+-- Materialize nested array with no slots, with structs in schema
+select cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d.item) v;
+---- RESULTS
+3
+7
+0
+0
+0
+0
+1
+1
+---- TYPES
+bigint
+====
+---- QUERY
+-- Materialize scalar and flattened array with no slots from struct
+select nested_struct.a, cnt from complextypestbl_iceberg_orc t,
+(select count(*) cnt from t.nested_struct.c.d.item) v
+---- RESULTS
+1,3
+NULL,7
+NULL,0
+NULL,0
+NULL,0
+NULL,0
+7,1
+-1,1
+---- TYPES
+int,bigint
+====
+---- QUERY
+-- Materialize array and nested array from struct
+select a1.item, a2.f
+from complextypestbl_iceberg_orc t, t.nested_struct.b a1, t.nested_struct.c.d.item a2
+---- RESULTS
+1,'aaa'
+1,'bbb'
+1,'c'
+NULL,'NULL'
+NULL,'aaa'
+NULL,'NULL'
+NULL,'bbb'
+NULL,'NULL'
+NULL,'c'
+NULL,'NULL'
+2,'NULL'
+3,'NULL'
+NULL,'NULL'
+-1,'nonnullable'
+---- TYPES
+int,string
+====
+---- QUERY
+-- Materialize scalar, array, and nested array from struct
+select t.nested_struct.a, a1.item, a2.f
+from complextypestbl_iceberg_orc t, t.nested_struct.b a1, t.nested_struct.c.d.item a2
+---- RESULTS
+1,1,'aaa'
+1,1,'bbb'
+1,1,'c'
+NULL,NULL,'NULL'
+NULL,NULL,'aaa'
+NULL,NULL,'NULL'
+NULL,NULL,'bbb'
+NULL,NULL,'NULL'
+NULL,NULL,'c'
+NULL,NULL,'NULL'
+7,2,'NULL'
+7,3,'NULL'
+7,NULL,'NULL'
+-1,-1,'nonnullable'
+---- TYPES
+int,int,string
+====
+---- QUERY
+-- Materialize two instances of the same array
+select id, item from complextypestbl_iceberg_orc t,
+(select item from t.int_array where item = 2
+ union all
+ select item from t.int_array where item != 2
+ union all
+ select item from t.int_array where item is null) v
+---- RESULTS
+1,1
+1,2
+1,3
+2,NULL
+2,1
+2,2
+2,NULL
+2,3
+2,NULL
+8,-1
+---- TYPES
+bigint,int
+====
+---- QUERY
+-- Materialize two instances of the same flattened array, with structs in the schema
+select id, e, f from complextypestbl_iceberg_orc t,
+(select e, f from t.nested_struct.c.d.item where e = 10
+ union all
+ select e, f from t.nested_struct.c.d.item where e != 10
+ union all
+ select e, f from t.nested_struct.c.d.item where e is null) v
+---- RESULTS
+1,10,'aaa'
+1,-10,'bbb'
+1,11,'c'
+2,NULL,'NULL'
+2,10,'aaa'
+2,NULL,'NULL'
+2,-10,'bbb'
+2,NULL,'NULL'
+2,11,'c'
+2,NULL,'NULL'
+7,NULL,'NULL'
+8,-1,'nonnullable'
+---- TYPES
+bigint,int,string
+====
+---- QUERY
+select id, int_array.item, a2.item, a3.item,
+nested_struct.a, b.item, d2.e, d2.f, d3.e, d3.f
+from complextypestbl_iceberg_orc t,
+t.int_array,
+t.int_array_array a1, a1.item a2,
+t.int_array_array.item a3,
+t.nested_struct.b,
+t.nested_struct.c.d, d.item d2,
+t.nested_struct.c.d.item d3
+where a2.item = 1 and a3.item = 2 and d2.e = 10 and d3.e = -10
+---- RESULTS
+1,1,1,2,1,1,10,'aaa',-10,'bbb'
+1,2,1,2,1,1,10,'aaa',-10,'bbb'
+1,3,1,2,1,1,10,'aaa',-10,'bbb'
+2,NULL,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+2,1,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+2,2,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+2,NULL,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+2,3,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+2,NULL,1,2,NULL,NULL,10,'aaa',-10,'bbb'
+---- TYPES
+bigint,int,int,int,int,int,int,string,int,string
+====
+====
+---- QUERY
+select id, pos, item from complextypestbl_iceberg_orc t, t.int_array
+---- RESULTS
+1,0,1
+1,1,2
+1,2,3
+2,0,NULL
+2,1,1
+2,2,2
+2,3,NULL
+2,4,3
+2,5,NULL
+8,0,-1
+---- TYPES
+bigint,bigint,int
+====
+---- QUERY
+select id, pos from complextypestbl_iceberg_orc t, t.int_array
+---- RESULTS
+1,0
+1,1
+1,2
+2,0
+2,1
+2,2
+2,3
+2,4
+2,5
+8,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select pos, item from complextypestbl_iceberg_orc.int_array
+---- RESULTS
+0,1
+1,2
+2,3
+0,NULL
+1,1
+2,2
+3,NULL
+4,3
+5,NULL
+0,-1
+---- TYPES
+bigint,int
+====
+---- QUERY
+select pos from complextypestbl_iceberg_orc.int_array
+---- RESULTS
+0
+1
+2
+0
+1
+2
+3
+4
+5
+0
+---- TYPES
+bigint
+====
+---- QUERY
+select id, pos, item from complextypestbl_iceberg_orc t, t.int_array_array.item
+---- RESULTS
+1,0,1
+1,1,2
+1,0,3
+1,1,4
+2,0,NULL
+2,1,1
+2,2,2
+2,3,NULL
+2,0,3
+2,1,NULL
+2,2,4
+7,0,5
+7,1,6
+8,0,-1
+8,1,-2
+---- TYPES
+bigint,bigint,int
+====
+---- QUERY
+select id, pos from complextypestbl_iceberg_orc t, t.int_array_array.item
+---- RESULTS
+1,0
+1,1
+1,0
+1,1
+2,0
+2,1
+2,2
+2,3
+2,0
+2,1
+2,2
+7,0
+7,1
+8,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select pos, item from complextypestbl_iceberg_orc.int_array_array.item
+---- RESULTS
+0,1
+1,2
+0,3
+1,4
+0,NULL
+1,1
+2,2
+3,NULL
+0,3
+1,NULL
+2,4
+0,5
+1,6
+0,-1
+1,-2
+---- TYPES
+bigint,int
+====
+---- QUERY
+select pos, item from complextypestbl_iceberg_orc.int_array_array.item where pos > 1
+---- RESULTS
+2,2
+3,NULL
+2,4
+---- TYPES
+bigint,int
+====
+---- QUERY
+select pos from complextypestbl_iceberg_orc.int_array_array.item
+---- RESULTS
+0
+1
+0
+1
+0
+1
+2
+3
+0
+1
+2
+0
+1
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+select pos from complextypestbl_iceberg_orc.int_array_array
+---- RESULTS
+0
+1
+0
+1
+2
+3
+0
+0
+1
+0
+1
+---- TYPES
+bigint
+====
+---- QUERY
+select a1.pos, a2.item from complextypestbl_iceberg_orc.int_array_array a1, a1.item a2
+---- RESULTS
+0,1
+0,2
+1,3
+1,4
+0,NULL
+0,1
+0,2
+0,NULL
+1,3
+1,NULL
+1,4
+1,5
+1,6
+0,-1
+0,-2
+---- TYPES
+bigint,int
+====
+---- QUERY
+select a1.pos, a2.pos from complextypestbl_iceberg_orc.int_array_array a1, a1.item a2
+---- RESULTS
+0,0
+0,1
+1,0
+1,1
+0,0
+0,1
+0,2
+0,3
+1,0
+1,1
+1,2
+1,0
+1,1
+0,0
+0,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select a1.pos, a2.pos, a2.item from complextypestbl_iceberg_orc.int_array_array a1, a1.item a2
+---- RESULTS
+0,0,1
+0,1,2
+1,0,3
+1,1,4
+0,0,NULL
+0,1,1
+0,2,2
+0,3,NULL
+1,0,3
+1,1,NULL
+1,2,4
+1,0,5
+1,1,6
+0,0,-1
+0,1,-2
+---- TYPES
+bigint,bigint,int
+====
+---- QUERY
+select id, a1.pos, a2.item
+from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1,0,1
+1,0,2
+1,1,3
+1,1,4
+2,0,NULL
+2,0,1
+2,0,2
+2,0,NULL
+2,1,3
+2,1,NULL
+2,1,4
+7,1,5
+7,1,6
+8,0,-1
+8,0,-2
+---- TYPES
+bigint,bigint,int
+====
+---- QUERY
+select id, a1.pos, a2.pos, a2.item
+from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1,0,0,1
+1,0,1,2
+1,1,0,3
+1,1,1,4
+2,0,0,NULL
+2,0,1,1
+2,0,2,2
+2,0,3,NULL
+2,1,0,3
+2,1,1,NULL
+2,1,2,4
+7,1,0,5
+7,1,1,6
+8,0,0,-1
+8,0,1,-2
+---- TYPES
+bigint,bigint,bigint,int
+====
+---- QUERY
+select id, a1.pos, a2.pos
+from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1,0,0
+1,0,1
+1,1,0
+1,1,1
+2,0,0
+2,0,1
+2,0,2
+2,0,3
+2,1,0
+2,1,1
+2,1,2
+7,1,0
+7,1,1
+8,0,0
+8,0,1
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+select id, a1.pos from complextypestbl_iceberg_orc t, t.int_array_array a1, a1.item a2
+---- RESULTS
+1,0
+1,0
+1,1
+1,1
+2,0
+2,0
+2,0
+2,0
+2,1
+2,1
+2,1
+7,1
+7,1
+8,0
+8,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select id, a1.pos, cnt from complextypestbl_iceberg_orc t, t.int_array_array a1,
+(select count(*) cnt from a1.item) v
+---- RESULTS
+1,0,2
+1,1,2
+2,0,4
+2,1,3
+2,2,0
+2,3,0
+3,0,0
+7,0,0
+7,1,2
+8,0,2
+8,1,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+select id, a1.pos from complextypestbl_iceberg_orc t, t.int_array_array a1
+---- RESULTS
+1,0
+1,1
+2,0
+2,1
+2,2
+2,3
+3,0
+7,0
+7,1
+8,0
+8,1
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select id, pos from complextypestbl_iceberg_orc t, t.nested_struct.c.d
+---- RESULTS
+1,0
+1,1
+2,0
+2,1
+2,2
+2,3
+7,0
+7,1
+7,2
+8,0
+---- TYPES
+bigint,bigint
+====
+---- QUERY
+select pos from complextypestbl_iceberg_orc t, t.nested_struct.c.d
+---- RESULTS
+0
+1
+0
+1
+2
+3
+0
+1
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+select nested_struct.a, pos from complextypestbl_iceberg_orc t, t.nested_struct.c.d
+---- RESULTS
+1,0
+1,1
+NULL,0
+NULL,1
+NULL,2
+NULL,3
+7,0
+7,1
+7,2
+-1,0
+---- TYPES
+int,bigint
+====
+---- QUERY
+select nested_struct.a, b.pos, d.pos
+from complextypestbl_iceberg_orc t, t.nested_struct.b, t.nested_struct.c.d
+---- RESULTS
+1,0,0
+1,0,1
+NULL,0,0
+NULL,0,1
+NULL,0,2
+NULL,0,3
+7,0,0
+7,0,1
+7,0,2
+7,1,0
+7,1,1
+7,1,2
+7,2,0
+7,2,1
+7,2,2
+-1,0,0
+---- TYPES
+int,bigint,bigint
+====
+---- QUERY
+select pos from complextypestbl_iceberg_orc.nested_struct.c.d
+---- RESULTS
+0
+1
+0
+1
+2
+3
+0
+1
+2
+0
+---- TYPES
+bigint
+====
+---- QUERY
+select id, d.pos, i.pos from complextypestbl_iceberg_orc t, t.nested_struct.c.d, d.item i
+---- RESULTS
+1,0,0
+1,0,1
+1,1,0
+2,0,0
+2,0,1
+2,0,2
+2,0,3
+2,0,4
+2,1,0
+2,1,1
+7,1,0
+8,0,0
+---- TYPES
+bigint,bigint,bigint
+====
+---- QUERY
+select id, d.pos, i.pos, i.f from complextypestbl_iceberg_orc t, t.nested_struct.c.d, d.item i
+---- RESULTS
+1,0,0,'aaa'
+1,0,1,'bbb'
+1,1,0,'c'
+2,0,0,'NULL'
+2,0,1,'aaa'
+2,0,2,'NULL'
+2,0,3,'bbb'
+2,0,4,'NULL'
+2,1,0,'c'
+2,1,1,'NULL'
+7,1,0,'NULL'
+8,0,0,'nonnullable'
+---- TYPES
+bigint,bigint,bigint,string
+====
+---- QUERY
+select id, d.pos, i.f from complextypestbl_iceberg_orc t, t.nested_struct.c.d, d.item i
+---- RESULTS
+1,0,'aaa'
+1,0,'bbb'
+1,1,'c'
+2,0,'NULL'
+2,0,'aaa'
+2,0,'NULL'
+2,0,'bbb'
+2,0,'NULL'
+2,1,'c'
+2,1,'NULL'
+7,1,'NULL'
+8,0,'nonnullable'
+---- TYPES
+bigint,bigint,string
+====
+---- QUERY
+select id, nested_struct.a, d1.pos, d2.pos
+from complextypestbl_iceberg_orc t, t.nested_struct.c.d d1, t.nested_struct.c.d d2
+---- RESULTS
+1,1,0,0
+1,1,0,1
+1,1,1,0
+1,1,1,1
+2,NULL,0,0
+2,NULL,0,1
+2,NULL,0,2
+2,NULL,0,3
+2,NULL,1,0
+2,NULL,1,1
+2,NULL,1,2
+2,NULL,1,3
+2,NULL,2,0
+2,NULL,2,1
+2,NULL,2,2
+2,NULL,2,3
+2,NULL,3,0
+2,NULL,3,1
+2,NULL,3,2
+2,NULL,3,3
+7,7,0,0
+7,7,0,1
+7,7,0,2
+7,7,1,0
+7,7,1,1
+7,7,1,2
+7,7,2,0
+7,7,2,1
+7,7,2,2
+8,-1,0,0
+---- TYPES
+bigint,int,bigint,bigint
+====
+---- QUERY
+select nested_struct.a, d1.pos, i1.e, i1.f, d2.pos, i2.e, i2.f
+from complextypestbl_iceberg_orc t, t.nested_struct.c.d d1, d1.item i1,
+     t.nested_struct.c.d d2, d2.item i2
+where i1.e = 10 or i2.e = 10
+---- RESULTS
+1,0,10,'aaa',0,10,'aaa'
+1,0,10,'aaa',0,-10,'bbb'
+1,0,10,'aaa',1,11,'c'
+1,0,-10,'bbb',0,10,'aaa'
+1,1,11,'c',0,10,'aaa'
+NULL,0,10,'aaa',0,NULL,'NULL'
+NULL,0,10,'aaa',0,10,'aaa'
+NULL,0,10,'aaa',0,NULL,'NULL'
+NULL,0,10,'aaa',0,-10,'bbb'
+NULL,0,10,'aaa',0,NULL,'NULL'
+NULL,0,10,'aaa',1,11,'c'
+NULL,0,10,'aaa',1,NULL,'NULL'
+NULL,0,NULL,'NULL',0,10,'aaa'
+NULL,0,NULL,'NULL',0,10,'aaa'
+NULL,0,-10,'bbb',0,10,'aaa'
+NULL,0,NULL,'NULL',0,10,'aaa'
+NULL,1,11,'c',0,10,'aaa'
+NULL,1,NULL,'NULL',0,10,'aaa'
+---- TYPES
+int,bigint,int,string,bigint,int,string
+====
+---- QUERY
+select nested_struct.a, d1.pos, i1.pos, i1.e, i1.f, d2.pos, i2.pos, i2.e, i2.f
+from complextypestbl_iceberg_orc t, t.nested_struct.c.d d1, d1.item i1,
+     t.nested_struct.c.d d2, d2.item i2
+where i1.e = 10 or i2.e = 10
+---- RESULTS
+1,0,0,10,'aaa',0,0,10,'aaa'
+1,0,0,10,'aaa',0,1,-10,'bbb'
+1,0,0,10,'aaa',1,0,11,'c'
+1,0,1,-10,'bbb',0,0,10,'aaa'
+1,1,0,11,'c',0,0,10,'aaa'
+NULL,0,1,10,'aaa',0,0,NULL,'NULL'
+NULL,0,1,10,'aaa',0,1,10,'aaa'
+NULL,0,1,10,'aaa',0,2,NULL,'NULL'
+NULL,0,1,10,'aaa',0,3,-10,'bbb'
+NULL,0,1,10,'aaa',0,4,NULL,'NULL'
+NULL,0,1,10,'aaa',1,0,11,'c'
+NULL,0,1,10,'aaa',1,1,NULL,'NULL'
+NULL,0,0,NULL,'NULL',0,1,10,'aaa'
+NULL,0,2,NULL,'NULL',0,1,10,'aaa'
+NULL,0,3,-10,'bbb',0,1,10,'aaa'
+NULL,0,4,NULL,'NULL',0,1,10,'aaa'
+NULL,1,0,11,'c',0,1,10,'aaa'
+NULL,1,1,NULL,'NULL',0,1,10,'aaa'
+---- TYPES
+int,bigint,bigint,int,string,bigint,bigint,int,string
+====
+---- QUERY
+select nested_struct.a, d1.pos, i1.pos, d2.pos, i2.pos
+from complextypestbl_iceberg_orc t, t.nested_struct.c.d d1, d1.item i1,
+     t.nested_struct.c.d d2, d2.item i2
+where i1.e = 10 or i2.e = 10
+---- RESULTS
+1,0,0,0,0
+1,0,0,0,1
+1,0,0,1,0
+1,0,1,0,0
+1,1,0,0,0
+NULL,0,1,0,0
+NULL,0,1,0,1
+NULL,0,1,0,2
+NULL,0,1,0,3
+NULL,0,1,0,4
+NULL,0,1,1,0
+NULL,0,1,1,1
+NULL,0,0,0,1
+NULL,0,2,0,1
+NULL,0,3,0,1
+NULL,0,4,0,1
+NULL,1,0,0,1
+NULL,1,1,0,1
+---- TYPES
+int,bigint,bigint,bigint,bigint
+====
+---- QUERY
+select d1.pos, i1.pos, d2.pos, i2.pos
+from complextypestbl_iceberg_orc t, t.nested_struct.c.d d1, d1.item i1,
+     t.nested_struct.c.d d2, d2.item i2
+where i1.e = 10 or i2.e = 10
+---- RESULTS
+0,0,0,0
+0,0,0,1
+0,0,1,0
+0,1,0,0
+1,0,0,0
+0,1,0,0
+0,1,0,1
+0,1,0,2
+0,1,0,3
+0,1,0,4
+0,1,1,0
+0,1,1,1
+0,0,0,1
+0,2,0,1
+0,3,0,1
+0,4,0,1
+1,0,0,1
+1,1,0,1
+---- TYPES
+bigint,bigint,bigint,bigint
+====
+---- QUERY
+select id, key, value from complextypestbl_iceberg_orc t, t.int_map
+---- RESULTS
+1,'k1',1
+1,'k2',100
+2,'k1',2
+2,'k2',NULL
+7,'k1',NULL
+7,'k3',NULL
+8,'k1',-1
+---- TYPES
+bigint,string,int
+====
+---- QUERY
+select id, value from complextypestbl_iceberg_orc t, t.int_map
+---- RESULTS
+1,1
+1,100
+2,2
+2,NULL
+7,NULL
+7,NULL
+8,-1
+---- TYPES
+bigint,int
+====
+---- QUERY
+select key, value from complextypestbl_iceberg_orc.int_map
+---- RESULTS
+'k1',1
+'k2',100
+'k1',2
+'k2',NULL
+'k1',NULL
+'k3',NULL
+'k1',-1
+---- TYPES
+string,int
+====
+---- QUERY
+select id, key, value from complextypestbl_iceberg_orc t, t.int_map_array.item
+---- RESULTS
+1,'k1',1
+2,'k3',NULL
+2,'k1',1
+8,'k1',1
+---- TYPES
+bigint,string,int
+====
+---- QUERY
+select id, a.pos, m.key, m.value from complextypestbl_iceberg_orc t, t.int_map_array a, a.item m
+---- RESULTS
+1,0,'k1',1
+2,0,'k3',NULL
+2,0,'k1',1
+8,1,'k1',1
+---- TYPES
+bigint,bigint,string,int
+====
+---- QUERY
+select id, key from complextypestbl_iceberg_orc t, t.nested_struct.g
+---- RESULTS
+1,'foo'
+2,'g1'
+2,'g2'
+2,'g3'
+2,'g4'
+2,'g5'
+5,'foo'
+---- TYPES
+bigint,string
+====
+---- QUERY
+select id, key, item from complextypestbl_iceberg_orc t, t.nested_struct.g, g.value.h.i
+---- RESULTS
+1,'foo',1.1
+2,'g1',2.2
+2,'g1',NULL
+5,'foo',2.2
+5,'foo',3.3
+---- TYPES
+bigint,string,double
+====
+---- QUERY
+select key, item from complextypestbl_iceberg_orc.nested_struct.g, g.value.h.i
+---- RESULTS
+'foo',1.1
+'g1',2.2
+'g1',NULL
+'foo',2.2
+'foo',3.3
+---- TYPES
+string,double
+====
+---- QUERY
+select key, item, pos from complextypestbl_iceberg_orc.nested_struct.g, g.value.h.i
+---- RESULTS
+'foo',1.1,0
+'g1',2.2,0
+'g1',NULL,1
+'foo',2.2,0
+'foo',3.3,1
+---- TYPES
+string,double,bigint
+====
+---- QUERY
+select item from complextypestbl_iceberg_orc.nested_struct.g.value.h.i
+---- RESULTS
+1.1
+2.2
+NULL
+2.2
+3.3
+---- TYPES
+double
+====
diff --git a/tests/query_test/test_iceberg.py b/tests/query_test/test_iceberg.py
index 20c62c8..65c65bb 100644
--- a/tests/query_test/test_iceberg.py
+++ b/tests/query_test/test_iceberg.py
@@ -83,6 +83,9 @@ class TestIcebergTable(ImpalaTestSuite):
     self.run_test_case('QueryTest/iceberg-partition-transform-insert', vector,
         use_db=unique_database)
 
+  def test_iceberg_orc_field_id(self, vector):
+    self.run_test_case('QueryTest/iceberg-orc-field-id', vector)
+
   def test_describe_history(self, vector, unique_database):
     self.run_test_case('QueryTest/iceberg-table-history', vector, use_db=unique_database)