You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by hu...@apache.org on 2025/10/24 10:58:11 UTC

(doris) 02/02: refactor TDataAccessPath

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

huajianlan pushed a commit to branch nested_column_prune
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 7bfc0dac45960eca5f6756bc1363afbf42f8d8b7
Author: 924060929 <la...@selectdb.com>
AuthorDate: Fri Oct 24 18:57:41 2025 +0800

    refactor TDataAccessPath
---
 .../org/apache/doris/analysis/AccessPathInfo.java  |   8 +-
 .../org/apache/doris/analysis/SlotDescriptor.java  |  26 +--
 .../rewrite/AccessPathExpressionCollector.java     |  34 +++-
 .../nereids/rules/rewrite/NestedColumnPruning.java | 181 ++++++++++++++-------
 .../nereids/rules/rewrite/SlotTypeReplacer.java    |  46 ++++--
 .../nereids/trees/expressions/SlotReference.java   |  31 ++--
 .../functions/scalar/StructElement.java            |   6 +-
 .../org/apache/doris/nereids/types/StructType.java |   4 +
 .../java/org/apache/doris/planner/ScanNode.java    |  50 ++++--
 .../rules/rewrite/PruneNestedColumnTest.java       |  34 ++--
 gensrc/thrift/Descriptors.thrift                   |  23 ++-
 11 files changed, 286 insertions(+), 157 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AccessPathInfo.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AccessPathInfo.java
index 24501a469d7..3df7baada4d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AccessPathInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AccessPathInfo.java
@@ -21,16 +21,18 @@
 package org.apache.doris.analysis;
 
 import org.apache.doris.nereids.types.DataType;
-import org.apache.doris.thrift.TColumnAccessPaths;
+import org.apache.doris.thrift.TColumnAccessPath;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;
 
+import java.util.List;
+
 /** AccessPathInfo */
 @Data
 @AllArgsConstructor
 public class AccessPathInfo {
     private DataType prunedType;
-    private TColumnAccessPaths allAccessPaths;
-    private TColumnAccessPaths predicateAccessPaths;
+    private List<TColumnAccessPath> allAccessPaths;
+    private List<TColumnAccessPath> predicateAccessPaths;
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
index 4160842d208..4ecec5b30aa 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
@@ -24,7 +24,7 @@ import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.ColumnStats;
 import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.catalog.Type;
-import org.apache.doris.thrift.TColumnAccessPaths;
+import org.apache.doris.thrift.TColumnAccessPath;
 import org.apache.doris.thrift.TSlotDescriptor;
 
 import com.google.common.base.MoreObjects;
@@ -76,10 +76,10 @@ public class SlotDescriptor {
     private boolean needMaterialize = true;
     private boolean isAutoInc = false;
     private Expr virtualColumn = null;
-    private TColumnAccessPaths allAccessPaths;
-    private TColumnAccessPaths predicateAccessPaths;
-    private TColumnAccessPaths displayAllAccessPaths;
-    private TColumnAccessPaths displayPredicateAccessPaths;
+    private List<TColumnAccessPath> allAccessPaths;
+    private List<TColumnAccessPath> predicateAccessPaths;
+    private List<TColumnAccessPath> displayAllAccessPaths;
+    private List<TColumnAccessPath> displayPredicateAccessPaths;
 
     public SlotDescriptor(SlotId id, TupleDescriptor parent) {
 
@@ -134,35 +134,35 @@ public class SlotDescriptor {
         return this.subColPath;
     }
 
-    public TColumnAccessPaths getAllAccessPaths() {
+    public List<TColumnAccessPath> getAllAccessPaths() {
         return allAccessPaths;
     }
 
-    public void setAllAccessPaths(TColumnAccessPaths allAccessPaths) {
+    public void setAllAccessPaths(List<TColumnAccessPath> allAccessPaths) {
         this.allAccessPaths = allAccessPaths;
     }
 
-    public TColumnAccessPaths getPredicateAccessPaths() {
+    public List<TColumnAccessPath> getPredicateAccessPaths() {
         return predicateAccessPaths;
     }
 
-    public void setPredicateAccessPaths(TColumnAccessPaths predicateAccessPaths) {
+    public void setPredicateAccessPaths(List<TColumnAccessPath> predicateAccessPaths) {
         this.predicateAccessPaths = predicateAccessPaths;
     }
 
-    public TColumnAccessPaths getDisplayAllAccessPaths() {
+    public List<TColumnAccessPath> getDisplayAllAccessPaths() {
         return displayAllAccessPaths;
     }
 
-    public void setDisplayAllAccessPaths(TColumnAccessPaths displayAllAccessPaths) {
+    public void setDisplayAllAccessPaths(List<TColumnAccessPath> displayAllAccessPaths) {
         this.displayAllAccessPaths = displayAllAccessPaths;
     }
 
-    public TColumnAccessPaths getDisplayPredicateAccessPaths() {
+    public List<TColumnAccessPath> getDisplayPredicateAccessPaths() {
         return displayPredicateAccessPaths;
     }
 
-    public void setDisplayPredicateAccessPaths(TColumnAccessPaths displayPredicateAccessPaths) {
+    public void setDisplayPredicateAccessPaths(List<TColumnAccessPath> displayPredicateAccessPaths) {
         this.displayPredicateAccessPaths = displayPredicateAccessPaths;
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java
index 8bd794f5422..57fe9fefcc5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java
@@ -51,6 +51,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionVisit
 import org.apache.doris.nereids.types.DataType;
 import org.apache.doris.nereids.types.NestedColumnPrunable;
 import org.apache.doris.nereids.util.Utils;
+import org.apache.doris.thrift.TAccessPathType;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
@@ -102,7 +103,7 @@ public class AccessPathExpressionCollector extends DefaultExpressionVisitor<Void
             context.accessPathBuilder.addPrefix(slotReference.getName());
             ImmutableList<String> path = Utils.fastToImmutableList(context.accessPathBuilder.accessPath);
             int slotId = slotReference.getExprId().asInt();
-            slotToAccessPaths.put(slotId, new CollectAccessPathResult(path, context.bottomFilter));
+            slotToAccessPaths.put(slotId, new CollectAccessPathResult(path, context.bottomFilter, context.type));
         }
         return null;
     }
@@ -348,6 +349,15 @@ public class AccessPathExpressionCollector extends DefaultExpressionVisitor<Void
         return visit(arraySortBy, context);
     }
 
+    // @Override
+    // public Void visitIsNull(IsNull isNull, CollectorContext context) {
+    //     if (context.accessPathBuilder.isEmpty()) {
+    //         context.setType(TAccessPathType.META);
+    //         return continueCollectAccessPath(isNull.child(), context);
+    //     }
+    //     return visit(isNull, context);
+    // }
+
     private Void collectArrayPathInLambda(Lambda lambda, CollectorContext context) {
         List<Expression> arguments = lambda.getArguments();
         Map<String, Expression> nameToArray = Maps.newLinkedHashMap();
@@ -376,11 +386,21 @@ public class AccessPathExpressionCollector extends DefaultExpressionVisitor<Void
         private StatementContext statementContext;
         private AccessPathBuilder accessPathBuilder;
         private boolean bottomFilter;
+        private TAccessPathType type;
 
         public CollectorContext(StatementContext statementContext, boolean bottomFilter) {
             this.statementContext = statementContext;
             this.accessPathBuilder = new AccessPathBuilder();
             this.bottomFilter = bottomFilter;
+            this.type = TAccessPathType.DATA;
+        }
+
+        public TAccessPathType getType() {
+            return type;
+        }
+
+        public void setType(TAccessPathType type) {
+            this.type = type;
         }
     }
 
@@ -405,6 +425,10 @@ public class AccessPathExpressionCollector extends DefaultExpressionVisitor<Void
             return accessPath;
         }
 
+        public boolean isEmpty() {
+            return accessPath.isEmpty();
+        }
+
         @Override
         public String toString() {
             return String.join(".", accessPath);
@@ -415,10 +439,16 @@ public class AccessPathExpressionCollector extends DefaultExpressionVisitor<Void
     public static class CollectAccessPathResult {
         private final List<String> path;
         private final boolean isPredicate;
+        private final TAccessPathType type;
 
-        public CollectAccessPathResult(List<String> path, boolean isPredicate) {
+        public CollectAccessPathResult(List<String> path, boolean isPredicate, TAccessPathType type) {
             this.path = path;
             this.isPredicate = isPredicate;
+            this.type = type;
+        }
+
+        public TAccessPathType getType() {
+            return type;
         }
 
         public List<String> getPath() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/NestedColumnPruning.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/NestedColumnPruning.java
index 609b577c6a2..0f99b576cae 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/NestedColumnPruning.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/NestedColumnPruning.java
@@ -24,6 +24,7 @@ import org.apache.doris.nereids.exceptions.AnalysisException;
 import org.apache.doris.nereids.jobs.JobContext;
 import org.apache.doris.nereids.rules.rewrite.AccessPathExpressionCollector.CollectAccessPathResult;
 import org.apache.doris.nereids.trees.expressions.Slot;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.visitor.CustomRewriter;
 import org.apache.doris.nereids.types.ArrayType;
@@ -34,8 +35,9 @@ import org.apache.doris.nereids.types.StructField;
 import org.apache.doris.nereids.types.StructType;
 import org.apache.doris.qe.SessionVariable;
 import org.apache.doris.thrift.TAccessPathType;
-import org.apache.doris.thrift.TColumnAccessPaths;
-import org.apache.doris.thrift.TColumnNameAccessPath;
+import org.apache.doris.thrift.TColumnAccessPath;
+import org.apache.doris.thrift.TDataAccessPath;
+import org.apache.doris.thrift.TMetaAccessPath;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
@@ -97,12 +99,12 @@ public class NestedColumnPruning implements CustomRewriter {
         Map<Slot, DataTypeAccessTree> slotIdToAllAccessTree = new LinkedHashMap<>();
         Map<Slot, DataTypeAccessTree> slotIdToPredicateAccessTree = new LinkedHashMap<>();
 
-        Comparator<List<String>> pathComparator
-                = Comparator.comparing(a -> StringUtils.join(a, "."));
+        Comparator<Pair<TAccessPathType, List<String>>> pathComparator = Comparator.comparing(
+                l -> StringUtils.join(l.second, "."));
 
-        Multimap<Integer, List<String>> allAccessPaths = TreeMultimap.create(
+        Multimap<Integer, Pair<TAccessPathType, List<String>>> allAccessPaths = TreeMultimap.create(
                 Comparator.naturalOrder(), pathComparator);
-        Multimap<Integer, List<String>> predicateAccessPaths = TreeMultimap.create(
+        Multimap<Integer, Pair<TAccessPathType, List<String>>> predicateAccessPaths = TreeMultimap.create(
                 Comparator.naturalOrder(), pathComparator);
 
         // first: build access data type tree
@@ -111,18 +113,21 @@ public class NestedColumnPruning implements CustomRewriter {
             List<CollectAccessPathResult> collectAccessPathResults = kv.getValue();
             for (CollectAccessPathResult collectAccessPathResult : collectAccessPathResults) {
                 List<String> path = collectAccessPathResult.getPath();
+                TAccessPathType pathType = collectAccessPathResult.getType();
                 DataTypeAccessTree allAccessTree = slotIdToAllAccessTree.computeIfAbsent(
-                        slot, i -> DataTypeAccessTree.ofRoot(slot)
+                        slot, i -> DataTypeAccessTree.ofRoot(slot, pathType)
                 );
-                allAccessTree.setAccessByPath(path, 0);
-                allAccessPaths.put(slot.getExprId().asInt(), path);
+                allAccessTree.setAccessByPath(path, 0, pathType);
+                allAccessPaths.put(slot.getExprId().asInt(), Pair.of(pathType, path));
 
                 if (collectAccessPathResult.isPredicate()) {
                     DataTypeAccessTree predicateAccessTree = slotIdToPredicateAccessTree.computeIfAbsent(
-                            slot, i -> DataTypeAccessTree.ofRoot(slot)
+                            slot, i -> DataTypeAccessTree.ofRoot(slot, pathType)
+                    );
+                    predicateAccessTree.setAccessByPath(path, 0, pathType);
+                    predicateAccessPaths.put(
+                            slot.getExprId().asInt(), Pair.of(pathType, path)
                     );
-                    predicateAccessTree.setAccessByPath(path, 0);
-                    predicateAccessPaths.put(slot.getExprId().asInt(), path);
                 }
             }
         }
@@ -133,51 +138,97 @@ public class NestedColumnPruning implements CustomRewriter {
             DataTypeAccessTree accessTree = kv.getValue();
             DataType prunedDataType = accessTree.pruneDataType().orElse(slot.getDataType());
 
-            List<TColumnNameAccessPath> allPaths = new ArrayList<>();
-            for (List<String> path : allAccessPaths.get(slot.getExprId().asInt())) {
-                if (path == null) {
-                    throw new AnalysisException("This is a bug, please report this");
+            List<TColumnAccessPath> allPaths = new ArrayList<>();
+            boolean accessWholeColumn = false;
+            TAccessPathType accessWholeColumnType = TAccessPathType.META;
+            for (Pair<TAccessPathType, List<String>> pathInfo : allAccessPaths.get(slot.getExprId().asInt())) {
+                if (pathInfo.first == TAccessPathType.DATA) {
+                    TDataAccessPath dataAccessPath = new TDataAccessPath();
+                    dataAccessPath.setPath(new ArrayList<>(pathInfo.second));
+                    TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.DATA);
+                    accessPath.setDataAccessPath(dataAccessPath);
+                    allPaths.add(accessPath);
+                } else {
+                    TMetaAccessPath dataAccessPath = new TMetaAccessPath();
+                    dataAccessPath.setPath(new ArrayList<>(pathInfo.second));
+                    TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.META);
+                    accessPath.setMetaAccessPath(dataAccessPath);
+                    allPaths.add(accessPath);
                 }
-                TColumnNameAccessPath tPath = new TColumnNameAccessPath();
-                tPath.setPath(path);
                 // only retain access the whole root
-                if (path.size() == 1) {
-                    allPaths = ImmutableList.of(tPath);
-                    break;
+                if (pathInfo.second.size() == 1) {
+                    accessWholeColumn = true;
+                    if (pathInfo.first == TAccessPathType.DATA) {
+                        accessWholeColumnType = TAccessPathType.DATA;
+                    }
+                } else {
+                    accessWholeColumnType = TAccessPathType.DATA;
                 }
-                allPaths.add(tPath);
             }
-            TColumnAccessPaths allPath = new TColumnAccessPaths();
-            allPath.type = TAccessPathType.NAME;
-            allPath.setNameAccessPaths(allPaths);
-
-            TColumnAccessPaths predicatePath = new TColumnAccessPaths();
-            predicatePath.type = TAccessPathType.NAME;
-            predicatePath.setNameAccessPaths(new ArrayList<>());
-            result.put(slot.getExprId().asInt(), new AccessPathInfo(prunedDataType, allPath, predicatePath));
+            if (accessWholeColumn) {
+                TColumnAccessPath accessPath = new TColumnAccessPath(accessWholeColumnType);
+                SlotReference slotReference = (SlotReference) kv.getKey();
+                String wholeColumnName = slotReference.getOriginalColumn().get().getName();
+                if (accessWholeColumnType == TAccessPathType.DATA) {
+                    accessPath.setDataAccessPath(new TDataAccessPath(ImmutableList.of(wholeColumnName)));
+                } else {
+                    accessPath.setMetaAccessPath(new TMetaAccessPath(ImmutableList.of(wholeColumnName)));
+                }
+                allPaths = ImmutableList.of(accessPath);
+            }
+            result.put(slot.getExprId().asInt(), new AccessPathInfo(prunedDataType, allPaths, new ArrayList<>()));
         }
 
         // third: build predicate access path
         for (Entry<Slot, DataTypeAccessTree> kv : slotIdToPredicateAccessTree.entrySet()) {
             Slot slot = kv.getKey();
 
-            List<TColumnNameAccessPath> predicatePaths = new ArrayList<>();
-            for (List<String> path : predicateAccessPaths.get(slot.getExprId().asInt())) {
-                if (path == null) {
+            List<TColumnAccessPath> predicatePaths = new ArrayList<>();
+            boolean accessWholeColumn = false;
+            TAccessPathType accessWholeColumnType = TAccessPathType.META;
+            for (Pair<TAccessPathType, List<String>> pathInfo : predicateAccessPaths.get(slot.getExprId().asInt())) {
+                if (pathInfo == null) {
                     throw new AnalysisException("This is a bug, please report this");
                 }
-                TColumnNameAccessPath tPath = new TColumnNameAccessPath();
-                tPath.setPath(path);
+
+                if (pathInfo.first == TAccessPathType.DATA) {
+                    TDataAccessPath dataAccessPath = new TDataAccessPath();
+                    dataAccessPath.setPath(new ArrayList<>(pathInfo.second));
+                    TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.DATA);
+                    accessPath.setDataAccessPath(dataAccessPath);
+                    predicatePaths.add(accessPath);
+                } else {
+                    TMetaAccessPath dataAccessPath = new TMetaAccessPath();
+                    dataAccessPath.setPath(new ArrayList<>(pathInfo.second));
+                    TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.META);
+                    accessPath.setMetaAccessPath(dataAccessPath);
+                    predicatePaths.add(accessPath);
+                }
                 // only retain access the whole root
-                if (path.size() == 1) {
-                    predicatePaths = ImmutableList.of(tPath);
-                    break;
+                if (pathInfo.second.size() == 1) {
+                    accessWholeColumn = true;
+                    if (pathInfo.first == TAccessPathType.DATA) {
+                        accessWholeColumnType = TAccessPathType.DATA;
+                    }
+                } else {
+                    accessWholeColumnType = TAccessPathType.DATA;
+                }
+            }
+
+            if (accessWholeColumn) {
+                TColumnAccessPath accessPath = new TColumnAccessPath(accessWholeColumnType);
+                SlotReference slotReference = (SlotReference) kv.getKey();
+                String wholeColumnName = slotReference.getOriginalColumn().get().getName();
+                if (accessWholeColumnType == TAccessPathType.DATA) {
+                    accessPath.setDataAccessPath(new TDataAccessPath(ImmutableList.of(wholeColumnName)));
+                } else {
+                    accessPath.setMetaAccessPath(new TMetaAccessPath(ImmutableList.of(wholeColumnName)));
                 }
-                predicatePaths.add(tPath);
+                predicatePaths = ImmutableList.of(accessPath);
             }
 
             AccessPathInfo accessPathInfo = result.get(slot.getExprId().asInt());
-            accessPathInfo.getPredicateAccessPaths().name_access_paths.addAll(predicatePaths);
+            accessPathInfo.getPredicateAccessPaths().addAll(predicatePaths);
         }
 
         return result;
@@ -188,18 +239,20 @@ public class NestedColumnPruning implements CustomRewriter {
         private boolean isRoot;
         private boolean accessPartialChild;
         private boolean accessAll;
+        private TAccessPathType pathType;
         private Map<String, DataTypeAccessTree> children = new LinkedHashMap<>();
 
-        public DataTypeAccessTree(DataType type) {
-            this(false, type);
+        public DataTypeAccessTree(DataType type, TAccessPathType pathType) {
+            this(false, type, pathType);
         }
 
-        public DataTypeAccessTree(boolean isRoot, DataType type) {
+        public DataTypeAccessTree(boolean isRoot, DataType type, TAccessPathType pathType) {
             this.isRoot = isRoot;
             this.type = type;
+            this.pathType = pathType;
         }
 
-        public void setAccessByPath(List<String> path, int accessIndex) {
+        public void setAccessByPath(List<String> path, int accessIndex, TAccessPathType pathType) {
             if (accessIndex >= path.size()) {
                 accessAll = true;
                 return;
@@ -207,19 +260,23 @@ public class NestedColumnPruning implements CustomRewriter {
                 accessPartialChild = true;
             }
 
-            if (type.isStructType()) {
+            if (pathType == TAccessPathType.DATA) {
+                this.pathType = TAccessPathType.DATA;
+            }
+
+            if (this.type.isStructType()) {
                 String fieldName = path.get(accessIndex);
                 DataTypeAccessTree child = children.get(fieldName);
-                child.setAccessByPath(path, accessIndex + 1);
+                child.setAccessByPath(path, accessIndex + 1, pathType);
                 return;
-            } else if (type.isArrayType()) {
+            } else if (this.type.isArrayType()) {
                 DataTypeAccessTree child = children.get("*");
                 if (path.get(accessIndex).equals("*")) {
                     // enter this array and skip next *
-                    child.setAccessByPath(path, accessIndex + 1);
+                    child.setAccessByPath(path, accessIndex + 1, pathType);
                 }
                 return;
-            } else if (type.isMapType()) {
+            } else if (this.type.isMapType()) {
                 String fieldName = path.get(accessIndex);
                 if (fieldName.equals("*")) {
                     // access value by the key, so we should access key and access value, then prune the value's type.
@@ -227,7 +284,7 @@ public class NestedColumnPruning implements CustomRewriter {
                     DataTypeAccessTree keysChild = children.get("KEYS");
                     DataTypeAccessTree valuesChild = children.get("VALUES");
                     keysChild.accessAll = true;
-                    valuesChild.setAccessByPath(path, accessIndex + 1);
+                    valuesChild.setAccessByPath(path, accessIndex + 1, pathType);
                     return;
                 } else if (fieldName.equals("KEYS")) {
                     // only access the keys and not need enter keys, because it must be primitive type.
@@ -240,35 +297,35 @@ public class NestedColumnPruning implements CustomRewriter {
                     // e.g. map_values(map_columns)[0] will access the array of values first,
                     //      and then access the array, so the access path is ['VALUES', '*']
                     DataTypeAccessTree valuesChild = children.get("VALUES");
-                    valuesChild.setAccessByPath(path, accessIndex + 1);
+                    valuesChild.setAccessByPath(path, accessIndex + 1, pathType);
                     return;
                 }
             } else if (isRoot) {
-                children.get(path.get(accessIndex)).setAccessByPath(path, accessIndex + 1);
+                children.get(path.get(accessIndex)).setAccessByPath(path, accessIndex + 1, pathType);
                 return;
             }
-            throw new AnalysisException("unsupported data type: " + type);
+            throw new AnalysisException("unsupported data type: " + this.type);
         }
 
-        public static DataTypeAccessTree ofRoot(Slot slot) {
-            DataTypeAccessTree child = of(slot.getDataType());
-            DataTypeAccessTree root = new DataTypeAccessTree(true, NullType.INSTANCE);
+        public static DataTypeAccessTree ofRoot(Slot slot, TAccessPathType pathType) {
+            DataTypeAccessTree child = of(slot.getDataType(), pathType);
+            DataTypeAccessTree root = new DataTypeAccessTree(true, NullType.INSTANCE, pathType);
             root.children.put(slot.getName(), child);
             return root;
         }
 
-        public static DataTypeAccessTree of(DataType type) {
-            DataTypeAccessTree root = new DataTypeAccessTree(type);
+        public static DataTypeAccessTree of(DataType type, TAccessPathType pathType) {
+            DataTypeAccessTree root = new DataTypeAccessTree(type, pathType);
             if (type instanceof StructType) {
                 StructType structType = (StructType) type;
                 for (Entry<String, StructField> kv : structType.getNameToFields().entrySet()) {
-                    root.children.put(kv.getKey(), of(kv.getValue().getDataType()));
+                    root.children.put(kv.getKey(), of(kv.getValue().getDataType(), pathType));
                 }
             } else if (type instanceof ArrayType) {
-                root.children.put("*", of(((ArrayType) type).getItemType()));
+                root.children.put("*", of(((ArrayType) type).getItemType(), pathType));
             } else if (type instanceof MapType) {
-                root.children.put("KEYS", of(((MapType) type).getKeyType()));
-                root.children.put("VALUES", of(((MapType) type).getValueType()));
+                root.children.put("KEYS", of(((MapType) type).getKeyType(), pathType));
+                root.children.put("VALUES", of(((MapType) type).getValueType(), pathType));
             }
             return root;
         }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SlotTypeReplacer.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SlotTypeReplacer.java
index ba4a82ac851..043e9c7bdc1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SlotTypeReplacer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/SlotTypeReplacer.java
@@ -61,8 +61,9 @@ import org.apache.doris.nereids.types.MapType;
 import org.apache.doris.nereids.types.StructType;
 import org.apache.doris.nereids.util.MoreFieldsThread;
 import org.apache.doris.thrift.TAccessPathType;
-import org.apache.doris.thrift.TColumnAccessPaths;
-import org.apache.doris.thrift.TColumnNameAccessPath;
+import org.apache.doris.thrift.TColumnAccessPath;
+import org.apache.doris.thrift.TDataAccessPath;
+import org.apache.doris.thrift.TMetaAccessPath;
 
 import com.google.common.collect.ImmutableCollection;
 import com.google.common.collect.ImmutableList;
@@ -380,13 +381,13 @@ public class SlotTypeReplacer extends DefaultPlanRewriter<Void> {
                         continue;
                     }
                     SlotReference slotReference = (SlotReference) slot;
-                    Optional<TColumnAccessPaths> allAccessPaths = slotReference.getAllAccessPaths();
+                    Optional<List<TColumnAccessPath>> allAccessPaths = slotReference.getAllAccessPaths();
                     if (!allAccessPaths.isPresent() || !slotReference.getOriginalColumn().isPresent()) {
                         continue;
                     }
-                    TColumnAccessPaths allAccessPathsWithId
+                    List<TColumnAccessPath> allAccessPathsWithId
                             = replaceIcebergAccessPathToId(allAccessPaths.get(), slotReference);
-                    TColumnAccessPaths predicateAccessPathsWithId = replaceIcebergAccessPathToId(
+                    List<TColumnAccessPath> predicateAccessPathsWithId = replaceIcebergAccessPathToId(
                             slotReference.getPredicateAccessPaths().get(), slotReference);
                     replaceSlots.set(i, ((SlotReference) slot).withAccessPaths(
                             allAccessPathsWithId,
@@ -573,20 +574,31 @@ public class SlotTypeReplacer extends DefaultPlanRewriter<Void> {
         return e.withChildren(newChildren);
     }
 
-    private TColumnAccessPaths replaceIcebergAccessPathToId(
-            TColumnAccessPaths originAccessPaths, SlotReference slotReference) {
+    private List<TColumnAccessPath> replaceIcebergAccessPathToId(
+            List<TColumnAccessPath> originAccessPaths, SlotReference slotReference) {
         Column column = slotReference.getOriginalColumn().get();
-        List<TColumnNameAccessPath> replacedAllAccessPaths = new ArrayList<>();
-        for (TColumnNameAccessPath nameAccessPath : originAccessPaths.name_access_paths) {
-            List<String> icebergColumnAccessPath = new ArrayList<>(nameAccessPath.path);
-            replaceIcebergAccessPathToId(
-                    icebergColumnAccessPath, 0, slotReference.getDataType(), column
-            );
-            replacedAllAccessPaths.add(new TColumnNameAccessPath(icebergColumnAccessPath));
+        List<TColumnAccessPath> replacedAccessPaths = new ArrayList<>();
+        for (TColumnAccessPath accessPath : originAccessPaths) {
+            List<String> icebergColumnAccessPath = new ArrayList<>();
+            if (accessPath.type == TAccessPathType.DATA) {
+                icebergColumnAccessPath.addAll(accessPath.data_access_path.path);
+                replaceIcebergAccessPathToId(
+                        icebergColumnAccessPath, 0, slotReference.getDataType(), column
+                );
+                TColumnAccessPath newAccessPath = new TColumnAccessPath(TAccessPathType.DATA);
+                newAccessPath.data_access_path = new TDataAccessPath(icebergColumnAccessPath);
+                replacedAccessPaths.add(newAccessPath);
+            } else {
+                icebergColumnAccessPath.addAll(accessPath.meta_access_path.path);
+                replaceIcebergAccessPathToId(
+                        icebergColumnAccessPath, 0, slotReference.getDataType(), column
+                );
+                TColumnAccessPath newAccessPath = new TColumnAccessPath(TAccessPathType.META);
+                newAccessPath.meta_access_path = new TMetaAccessPath(icebergColumnAccessPath);
+                replacedAccessPaths.add(newAccessPath);
+            }
         }
-        TColumnAccessPaths accessPathWithId = new TColumnAccessPaths(TAccessPathType.NAME);
-        accessPathWithId.name_access_paths = replacedAllAccessPaths;
-        return accessPathWithId;
+        return replacedAccessPaths;
     }
 
     private void replaceIcebergAccessPathToId(List<String> originPath, int index, DataType type, Column column) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
index cb1a45e9170..1c77dc669ac 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
@@ -24,7 +24,7 @@ import org.apache.doris.nereids.exceptions.UnboundException;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.DataType;
 import org.apache.doris.nereids.util.Utils;
-import org.apache.doris.thrift.TColumnAccessPaths;
+import org.apache.doris.thrift.TColumnAccessPath;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
@@ -57,10 +57,10 @@ public class SlotReference extends Slot {
     // that need return original table and name for view not its original table if u query a view
     private final TableIf oneLevelTable;
     private final Column oneLevelColumn;
-    private final Optional<TColumnAccessPaths> allAccessPaths;
-    private final Optional<TColumnAccessPaths> predicateAccessPaths;
-    private final Optional<TColumnAccessPaths> displayAllAccessPaths;
-    private final Optional<TColumnAccessPaths> displayPredicateAccessPaths;
+    private final Optional<List<TColumnAccessPath>> allAccessPaths;
+    private final Optional<List<TColumnAccessPath>> predicateAccessPaths;
+    private final Optional<List<TColumnAccessPath>> displayAllAccessPaths;
+    private final Optional<List<TColumnAccessPath>> displayPredicateAccessPaths;
 
     public SlotReference(String name, DataType dataType) {
         this(StatementScopeIdGenerator.newExprId(), name, dataType, true, ImmutableList.of(),
@@ -121,9 +121,9 @@ public class SlotReference extends Slot {
             List<String> qualifier, @Nullable TableIf originalTable, @Nullable Column originalColumn,
             @Nullable TableIf oneLevelTable, Column oneLevelColumn,
             List<String> subPath, Optional<Pair<Integer, Integer>> indexInSql,
-            Optional<TColumnAccessPaths> allAccessPaths, Optional<TColumnAccessPaths> predicateAccessPaths,
-            Optional<TColumnAccessPaths> displayAllAccessPaths,
-            Optional<TColumnAccessPaths> displayPredicateAccessPaths) {
+            Optional<List<TColumnAccessPath>> allAccessPaths, Optional<List<TColumnAccessPath>> predicateAccessPaths,
+            Optional<List<TColumnAccessPath>> displayAllAccessPaths,
+            Optional<List<TColumnAccessPath>> displayPredicateAccessPaths) {
         super(indexInSql);
         this.exprId = exprId;
         this.name = name;
@@ -364,7 +364,8 @@ public class SlotReference extends Slot {
         return originalColumn != null ? originalColumn.isAutoInc() : false;
     }
 
-    public SlotReference withAccessPaths(TColumnAccessPaths allAccessPaths, TColumnAccessPaths predicateAccessPaths) {
+    public SlotReference withAccessPaths(
+            List<TColumnAccessPath> allAccessPaths, List<TColumnAccessPath> predicateAccessPaths) {
         return new SlotReference(exprId, name, dataType, nullable, qualifier,
                 originalTable, originalColumn, oneLevelTable, oneLevelColumn,
                 subPath, indexInSqlString, Optional.of(allAccessPaths), Optional.of(predicateAccessPaths),
@@ -372,27 +373,27 @@ public class SlotReference extends Slot {
     }
 
     public SlotReference withAccessPaths(
-            TColumnAccessPaths allAccessPaths, TColumnAccessPaths predicateAccessPaths,
-            TColumnAccessPaths displayAllAccessPaths, TColumnAccessPaths displayPredicateAccessPaths) {
+            List<TColumnAccessPath> allAccessPaths, List<TColumnAccessPath> predicateAccessPaths,
+            List<TColumnAccessPath> displayAllAccessPaths, List<TColumnAccessPath> displayPredicateAccessPaths) {
         return new SlotReference(exprId, name, dataType, nullable, qualifier,
                 originalTable, originalColumn, oneLevelTable, oneLevelColumn,
                 subPath, indexInSqlString, Optional.of(allAccessPaths), Optional.of(predicateAccessPaths),
                 Optional.of(displayAllAccessPaths), Optional.of(displayPredicateAccessPaths));
     }
 
-    public Optional<TColumnAccessPaths> getAllAccessPaths() {
+    public Optional<List<TColumnAccessPath>> getAllAccessPaths() {
         return allAccessPaths;
     }
 
-    public Optional<TColumnAccessPaths> getPredicateAccessPaths() {
+    public Optional<List<TColumnAccessPath>> getPredicateAccessPaths() {
         return predicateAccessPaths;
     }
 
-    public Optional<TColumnAccessPaths> getDisplayAllAccessPaths() {
+    public Optional<List<TColumnAccessPath>> getDisplayAllAccessPaths() {
         return displayAllAccessPaths;
     }
 
-    public Optional<TColumnAccessPaths> getDisplayPredicateAccessPaths() {
+    public Optional<List<TColumnAccessPath>> getDisplayPredicateAccessPaths() {
         return displayPredicateAccessPaths;
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StructElement.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StructElement.java
index 63169513423..ed29818b688 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StructElement.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/StructElement.java
@@ -30,6 +30,7 @@ import org.apache.doris.nereids.trees.expressions.literal.StringLikeLiteral;
 import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
 import org.apache.doris.nereids.types.DataType;
 import org.apache.doris.nereids.types.NullType;
+import org.apache.doris.nereids.types.StructField;
 import org.apache.doris.nereids.types.StructType;
 
 import com.google.common.base.Preconditions;
@@ -99,10 +100,11 @@ public class StructElement extends ScalarFunction
             }
         } else if (child(1) instanceof StringLikeLiteral) {
             String name = ((StringLikeLiteral) child(1)).getStringValue();
-            if (!structArgType.getNameToFields().containsKey(name.toLowerCase())) {
+            StructField field = structArgType.getField(name);
+            if (field == null) {
                 throw new AnalysisException("the specified field name " + name + " was not found: " + this.toSql());
             } else {
-                retType = structArgType.getNameToFields().get(name).getDataType();
+                retType = field.getDataType();
             }
         } else {
             throw new AnalysisException("struct_element only allows"
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/StructType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/StructType.java
index a1c263976f6..8296ac28281 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/StructType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/StructType.java
@@ -75,6 +75,10 @@ public class StructType extends DataType implements ComplexDataType, NestedColum
         return nameToFields;
     }
 
+    public StructField getField(String name) {
+        return nameToFields.get(name.toLowerCase());
+    }
+
     @Override
     public DataType conversion() {
         return new StructType(fields.stream().map(StructField::conversion).collect(Collectors.toList()));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java
index 44715603903..465a11d152c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/ScanNode.java
@@ -53,8 +53,8 @@ import org.apache.doris.qe.ConnectContext;
 import org.apache.doris.rpc.RpcException;
 import org.apache.doris.statistics.StatisticalType;
 import org.apache.doris.system.Backend;
-import org.apache.doris.thrift.TColumnAccessPaths;
-import org.apache.doris.thrift.TColumnNameAccessPath;
+import org.apache.doris.thrift.TAccessPathType;
+import org.apache.doris.thrift.TColumnAccessPath;
 import org.apache.doris.thrift.TNetworkAddress;
 import org.apache.doris.thrift.TPlanNode;
 import org.apache.doris.thrift.TScanRange;
@@ -570,33 +570,45 @@ public abstract class ScanNode extends PlanNode implements SplitGenerator {
             }
             String displayAllAccessPathsString = null;
             if (slot.getDisplayAllAccessPaths() != null
-                    && slot.getDisplayAllAccessPaths().name_access_paths != null
-                    && !slot.getDisplayAllAccessPaths().name_access_paths.isEmpty()) {
+                    && slot.getDisplayAllAccessPaths() != null
+                    && !slot.getDisplayAllAccessPaths().isEmpty()) {
                 if (this instanceof IcebergScanNode) {
                     displayAllAccessPathsString = mergeIcebergAccessPathsWithId(
                             slot.getAllAccessPaths(),
                             slot.getDisplayAllAccessPaths()
                     );
                 } else {
-                    displayAllAccessPathsString = slot.getDisplayAllAccessPaths().name_access_paths
+                    displayAllAccessPathsString = slot.getDisplayAllAccessPaths()
                             .stream()
-                            .map(a -> StringUtils.join(a.path, "."))
+                            .map(a -> {
+                                if (a.type == TAccessPathType.DATA) {
+                                    return StringUtils.join(a.data_access_path.path, ".");
+                                } else {
+                                    return StringUtils.join(a.meta_access_path.path, ".");
+                                }
+                            })
                             .collect(Collectors.joining(", "));
                 }
             }
             String displayPredicateAccessPathsString = null;
             if (slot.getDisplayPredicateAccessPaths() != null
-                    && slot.getDisplayPredicateAccessPaths().name_access_paths != null
-                    && !slot.getDisplayPredicateAccessPaths().name_access_paths.isEmpty()) {
+                    && slot.getDisplayPredicateAccessPaths() != null
+                    && !slot.getDisplayPredicateAccessPaths().isEmpty()) {
                 if (this instanceof IcebergScanNode) {
                     displayPredicateAccessPathsString = mergeIcebergAccessPathsWithId(
                             slot.getPredicateAccessPaths(),
                             slot.getDisplayPredicateAccessPaths()
                     );
                 } else {
-                    displayPredicateAccessPathsString = slot.getPredicateAccessPaths().name_access_paths
+                    displayPredicateAccessPathsString = slot.getPredicateAccessPaths()
                             .stream()
-                            .map(a -> StringUtils.join(a.path, "."))
+                            .map(a -> {
+                                if (a.type == TAccessPathType.DATA) {
+                                    return StringUtils.join(a.data_access_path.path, ".");
+                                } else {
+                                    return StringUtils.join(a.meta_access_path.path, ".");
+                                }
+                            })
                             .collect(Collectors.joining(", "));
                 }
             }
@@ -629,16 +641,20 @@ public abstract class ScanNode extends PlanNode implements SplitGenerator {
     }
 
     private String mergeIcebergAccessPathsWithId(
-            TColumnAccessPaths accessPaths, TColumnAccessPaths displayAccessPaths) {
+            List<TColumnAccessPath> accessPaths, List<TColumnAccessPath> displayAccessPaths) {
         List<String> mergeDisplayAccessPaths = Lists.newArrayList();
-        for (int i = 0; i < displayAccessPaths.name_access_paths.size(); i++) {
-            TColumnNameAccessPath nameAccessPath = displayAccessPaths.name_access_paths.get(i);
-            TColumnNameAccessPath idAccessPath = accessPaths.name_access_paths.get(i);
+        for (int i = 0; i < displayAccessPaths.size(); i++) {
+            TColumnAccessPath displayAccessPath = displayAccessPaths.get(i);
+            TColumnAccessPath idAccessPath = accessPaths.get(i);
+            List<String> nameAccessPathStrings = displayAccessPath.type == TAccessPathType.DATA
+                    ? displayAccessPath.data_access_path.path : displayAccessPath.meta_access_path.path;
+            List<String> idAccessPathStrings = idAccessPath.type == TAccessPathType.DATA
+                    ? idAccessPath.data_access_path.path : idAccessPath.meta_access_path.path;
 
             List<String> mergedPath = new ArrayList<>();
-            for (int j = 0; j < idAccessPath.path.size(); j++) {
-                String name = nameAccessPath.path.get(j);
-                String id = idAccessPath.path.get(j);
+            for (int j = 0; j < idAccessPathStrings.size(); j++) {
+                String name = nameAccessPathStrings.get(j);
+                String id = idAccessPathStrings.get(j);
                 if (name.equals(id)) {
                     mergedPath.add(name);
                 } else {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
index ec8f26e1a43..40980803931 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java
@@ -39,7 +39,9 @@ import org.apache.doris.nereids.util.PlanChecker;
 import org.apache.doris.planner.OlapScanNode;
 import org.apache.doris.planner.PlanFragment;
 import org.apache.doris.thrift.TAccessPathType;
-import org.apache.doris.thrift.TColumnNameAccessPath;
+import org.apache.doris.thrift.TColumnAccessPath;
+import org.apache.doris.thrift.TDataAccessPath;
+import org.apache.doris.thrift.TMetaAccessPath;
 import org.apache.doris.utframe.TestWithFeService;
 
 import com.google.common.collect.ImmutableList;
@@ -413,8 +415,8 @@ public class PruneNestedColumnTest extends TestWithFeService implements MemoPatt
     }
 
     private void assertColumn(String sql, String expectType,
-            List<TColumnNameAccessPath> expectAllAccessPaths,
-            List<TColumnNameAccessPath> expectPredicateAccessPaths) throws Exception {
+            List<TColumnAccessPath> expectAllAccessPaths,
+            List<TColumnAccessPath> expectPredicateAccessPaths) throws Exception {
         Pair<PhysicalPlan, List<SlotDescriptor>> result = collectComplexSlots(sql);
         PhysicalPlan physicalPlan = result.first;
         List<SlotDescriptor> slotDescriptors = result.second;
@@ -426,16 +428,14 @@ public class PruneNestedColumnTest extends TestWithFeService implements MemoPatt
         Assertions.assertEquals(1, slotDescriptors.size());
         Assertions.assertEquals(expectType, slotDescriptors.get(0).getType().toString());
 
-        Assertions.assertEquals(TAccessPathType.NAME, slotDescriptors.get(0).getAllAccessPaths().type);
-        TreeSet<TColumnNameAccessPath> expectAllAccessPathSet = new TreeSet<>(expectAllAccessPaths);
-        TreeSet<TColumnNameAccessPath> actualAllAccessPaths
-                = new TreeSet<>(slotDescriptors.get(0).getAllAccessPaths().name_access_paths);
+        TreeSet<TColumnAccessPath> expectAllAccessPathSet = new TreeSet<>(expectAllAccessPaths);
+        TreeSet<TColumnAccessPath> actualAllAccessPaths
+                = new TreeSet<>(slotDescriptors.get(0).getAllAccessPaths());
         Assertions.assertEquals(expectAllAccessPathSet, actualAllAccessPaths);
 
-        Assertions.assertEquals(TAccessPathType.NAME, slotDescriptors.get(0).getPredicateAccessPaths().type);
-        TreeSet<TColumnNameAccessPath> expectPredicateAccessPathSet = new TreeSet<>(expectPredicateAccessPaths);
-        TreeSet<TColumnNameAccessPath> actualPredicateAccessPaths
-                = new TreeSet<>(slotDescriptors.get(0).getPredicateAccessPaths().name_access_paths);
+        TreeSet<TColumnAccessPath> expectPredicateAccessPathSet = new TreeSet<>(expectPredicateAccessPaths);
+        TreeSet<TColumnAccessPath> actualPredicateAccessPaths
+                = new TreeSet<>(slotDescriptors.get(0).getPredicateAccessPaths());
         Assertions.assertEquals(expectPredicateAccessPathSet, actualPredicateAccessPaths);
 
         Map<Integer, DataType> slotIdToDataTypes = new LinkedHashMap<>();
@@ -503,7 +503,15 @@ public class PruneNestedColumnTest extends TestWithFeService implements MemoPatt
         return Pair.of(physicalPlan, complexSlots);
     }
 
-    private TColumnNameAccessPath path(String... path) {
-        return new TColumnNameAccessPath(ImmutableList.copyOf(path));
+    private TColumnAccessPath path(String... path) {
+        TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.DATA);
+        accessPath.data_access_path = new TDataAccessPath(ImmutableList.copyOf(path));
+        return accessPath;
+    }
+
+    private TColumnAccessPath metaPath(String... path) {
+        TColumnAccessPath accessPath = new TColumnAccessPath(TAccessPathType.META);
+        accessPath.meta_access_path = new TMetaAccessPath(ImmutableList.copyOf(path));
+        return accessPath;
     }
 }
diff --git a/gensrc/thrift/Descriptors.thrift b/gensrc/thrift/Descriptors.thrift
index 4eee5d9de50..9012b7074c2 100644
--- a/gensrc/thrift/Descriptors.thrift
+++ b/gensrc/thrift/Descriptors.thrift
@@ -28,11 +28,11 @@ enum TPatternType {
 }
 
 enum TAccessPathType {
-  NAME = 1,
-  // ICEBERG = 2 // implement in the future
+  DATA = 1,
+  META = 2 // use to prune `where s.data is not null` by only scan the meta of s.data
 }
 
-struct TColumnNameAccessPath {
+struct TDataAccessPath {
    // the specification of special path:
    //   <empty>: access the whole complex column
    //   *:
@@ -60,17 +60,14 @@ struct TColumnNameAccessPath {
    1: required list<string> path
 }
 
-/*
-// implement in the future
-struct TIcebergColumnAccessPath {
-   1: required list<i64> path
+struct TMetaAccessPath {
+  1: required list<string> path
 }
-*/
 
-struct TColumnAccessPaths {
+struct TColumnAccessPath {
   1: required TAccessPathType type
-  2: optional list<TColumnNameAccessPath> name_access_paths
-  // 3: optional list<TIcebergColumnAccessPath> iceberg_column_access_paths // implement in the future
+  2: optional TDataAccessPath data_access_path
+  3: optional TMetaAccessPath meta_access_path
 }
 
 struct TColumn {
@@ -123,8 +120,8 @@ struct TSlotDescriptor {
   16: optional string col_default_value
   17: optional Types.TPrimitiveType primitive_type = Types.TPrimitiveType.INVALID_TYPE
   18: optional Exprs.TExpr virtual_column_expr
-  19: optional TColumnAccessPaths all_access_paths
-  20: optional TColumnAccessPaths predicate_access_paths
+  19: optional list<TColumnAccessPath> all_access_paths
+  20: optional list<TColumnAccessPath> predicate_access_paths
 }
 
 struct TTupleDescriptor {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org