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

morningman pushed a commit to branch branch-1.2-lts
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-1.2-lts by this push:
     new 9dbd494edb6 Improvement](iceberg-catalog) Add iceberg metadata cache 
(#26602)
9dbd494edb6 is described below

commit 9dbd494edb600ebaae22aced9cbd090022fbd63a
Author: Yulei-Yang <yulei.yang0...@gmail.com>
AuthorDate: Mon Nov 13 11:58:30 2023 +0800

    Improvement](iceberg-catalog) Add iceberg metadata cache (#26602)
    
    backport #22336
---
 .../main/java/org/apache/doris/common/Config.java  |   4 +-
 .../doris/catalog/HiveMetaStoreClientHelper.java   |  16 --
 .../doris/catalog/external/HMSExternalTable.java   |   3 +-
 .../org/apache/doris/datasource/CatalogMgr.java    |   2 +-
 .../doris/datasource/ExternalMetaCacheMgr.java     |  14 +-
 .../doris/datasource/hive/HiveMetaStoreCache.java  |   2 +-
 .../datasource/iceberg/IcebergExternalCatalog.java |   5 +-
 .../org/apache/doris/planner/IcebergScanNode.java  |  49 ++++-
 .../planner/external/iceberg/IcebergApiSource.java |   6 +-
 .../planner/external/iceberg/IcebergHMSSource.java |   8 +-
 .../external/iceberg/IcebergMetadataCache.java     | 245 +++++++++++++++++++++
 .../external/iceberg/IcebergMetadataCacheMgr.java  |  46 ++++
 .../org/apache/doris/catalog/FunctionSetTest.java  |   2 +-
 .../apache/doris/common/util/BrokerUtilTest.java   |   1 -
 .../org/apache/doris/planner/QueryPlanTest.java    |   4 +-
 .../doris/planner/TableFunctionPlanTest.java       |  20 +-
 .../pipeline/common/check-pr-if-need-run-build.sh  | 195 ++++++++++++++++
 17 files changed, 570 insertions(+), 52 deletions(-)

diff --git a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
index 2a66a609643..f0953957f23 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/Config.java
@@ -1915,7 +1915,7 @@ public class Config extends ConfigBase {
     public static long max_hive_partition_cache_num = 100000;
 
     @ConfField(mutable = false, masterOnly = false)
-    public static long max_hive_table_catch_num = 1000;
+    public static long max_hive_table_cache_num = 1000;
 
     @ConfField(mutable = false, masterOnly = false)
     public static short max_hive_list_partition_num = -1;
@@ -1946,7 +1946,7 @@ public class Config extends ConfigBase {
      * For external schema cache and hive meta cache.
      */
     @ConfField(mutable = false, masterOnly = false)
-    public static long external_cache_expire_time_minutes_after_access = 24 * 
60; // 1 day
+    public static long external_cache_expire_time_minutes_after_access = 10; 
// 10 mins
 
     /**
      * Set session variables randomly to check more issues in github workflow
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/HiveMetaStoreClientHelper.java
 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/HiveMetaStoreClientHelper.java
index 963e106d8ec..943ed1a5963 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/HiveMetaStoreClientHelper.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/HiveMetaStoreClientHelper.java
@@ -67,7 +67,6 @@ import org.apache.hadoop.hive.ql.plan.ExprNodeGenericFuncDesc;
 import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
-import org.apache.iceberg.catalog.TableIdentifier;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.thrift.TException;
@@ -78,7 +77,6 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Deque;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -819,20 +817,6 @@ public class HiveMetaStoreClientHelper {
         return output.toString();
     }
 
-    public static org.apache.iceberg.Table getIcebergTable(HMSExternalTable 
table) {
-        String metastoreUri = table.getMetastoreUri();
-        org.apache.iceberg.hive.HiveCatalog hiveCatalog = new 
org.apache.iceberg.hive.HiveCatalog();
-        Configuration conf = getConfiguration(table);
-        hiveCatalog.setConf(conf);
-        // initialize hive catalog
-        Map<String, String> catalogProperties = new HashMap<>();
-        catalogProperties.put(HMSResource.HIVE_METASTORE_URIS, metastoreUri);
-        catalogProperties.put("uri", metastoreUri);
-        hiveCatalog.initialize("hive", catalogProperties);
-
-        return hiveCatalog.loadTable(TableIdentifier.of(table.getDbName(), 
table.getName()));
-    }
-
     public static Configuration getConfiguration(HMSExternalTable table) {
         Configuration conf = new 
HdfsConfiguration(Config.load_default_conf_for_hms_client);
         for (Map.Entry<String, String> entry : 
table.getHadoopProperties().entrySet()) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
index b4577c4adac..24b2e2becf8 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/external/HMSExternalTable.java
@@ -18,6 +18,7 @@
 package org.apache.doris.catalog.external;
 
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.HiveMetaStoreClientHelper;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.datasource.HMSExternalCatalog;
@@ -322,7 +323,7 @@ public class HMSExternalTable extends ExternalTable {
     }
 
     private List<Column> getIcebergSchema(List<FieldSchema> hmsSchema) {
-        Table icebergTable = HiveMetaStoreClientHelper.getIcebergTable(this);
+        Table icebergTable = 
Env.getCurrentEnv().getExtMetaCacheMgr().getIcebergMetadataCache().getIcebergTable(this);
         Schema schema = icebergTable.schema();
         List<Column> tmpSchema = 
Lists.newArrayListWithCapacity(hmsSchema.size());
         for (FieldSchema field : hmsSchema) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
index 44df8ad28bb..d4e89732ea8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/CatalogMgr.java
@@ -120,7 +120,7 @@ public class CatalogMgr implements Writable, 
GsonPostProcessable {
             catalog.onClose();
             nameToCatalog.remove(catalog.getName());
             lastDBOfCatalog.remove(catalog.getName());
-            
Env.getCurrentEnv().getExtMetaCacheMgr().removeCache(catalog.getName());
+            
Env.getCurrentEnv().getExtMetaCacheMgr().removeCache(catalog.getId());
             if (!Strings.isNullOrEmpty(catalog.getResource())) {
                 Resource catalogResource = 
Env.getCurrentEnv().getResourceMgr().getResource(catalog.getResource());
                 if (catalogResource != null) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
index 6d05eb26489..6e42158fc35 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalMetaCacheMgr.java
@@ -23,6 +23,8 @@ import org.apache.doris.cluster.ClusterNamespace;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.ThreadPoolManager;
 import org.apache.doris.datasource.hive.HiveMetaStoreCache;
+import org.apache.doris.planner.external.iceberg.IcebergMetadataCache;
+import org.apache.doris.planner.external.iceberg.IcebergMetadataCacheMgr;
 
 import com.google.common.collect.Maps;
 import org.apache.logging.log4j.LogManager;
@@ -45,10 +47,12 @@ public class ExternalMetaCacheMgr {
     // catalog id -> table schema cache
     private Map<Long, ExternalSchemaCache> schemaCacheMap = Maps.newHashMap();
     private Executor executor;
+    private final IcebergMetadataCacheMgr icebergMetadataCacheMgr;
 
     public ExternalMetaCacheMgr() {
         executor = 
ThreadPoolManager.newDaemonCacheThreadPool(Config.max_external_cache_loader_thread_pool_size,
                 "ExternalMetaCacheMgr", true);
+        icebergMetadataCacheMgr = new IcebergMetadataCacheMgr();
     }
 
     public HiveMetaStoreCache getMetaStoreCache(HMSExternalCatalog catalog) {
@@ -77,13 +81,18 @@ public class ExternalMetaCacheMgr {
         return cache;
     }
 
-    public void removeCache(String catalogId) {
+    public IcebergMetadataCache getIcebergMetadataCache() {
+        return icebergMetadataCacheMgr.getIcebergMetadataCache();
+    }
+
+    public void removeCache(long catalogId) {
         if (cacheMap.remove(catalogId) != null) {
             LOG.info("remove hive metastore cache for catalog {}" + catalogId);
         }
         if (schemaCacheMap.remove(catalogId) != null) {
             LOG.info("remove schema cache for catalog {}" + catalogId);
         }
+        icebergMetadataCacheMgr.removeCache(catalogId);
     }
 
     public void invalidateTableCache(long catalogId, String dbName, String 
tblName) {
@@ -96,6 +105,7 @@ public class ExternalMetaCacheMgr {
         if (metaCache != null) {
             metaCache.invalidateTableCache(dbName, tblName);
         }
+        icebergMetadataCacheMgr.invalidateTableCache(catalogId, dbName, 
tblName);
         LOG.debug("invalid table cache for {}.{} in catalog {}", dbName, 
tblName, catalogId);
     }
 
@@ -109,6 +119,7 @@ public class ExternalMetaCacheMgr {
         if (metaCache != null) {
             metaCache.invalidateDbCache(dbName);
         }
+        icebergMetadataCacheMgr.invalidateDbCache(catalogId, dbName);
         LOG.debug("invalid db cache for {} in catalog {}", dbName, catalogId);
     }
 
@@ -121,6 +132,7 @@ public class ExternalMetaCacheMgr {
         if (metaCache != null) {
             metaCache.invalidateAll();
         }
+        icebergMetadataCacheMgr.invalidateCatalogCache(catalogId);
         LOG.debug("invalid catalog cache for {}", catalogId);
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
index 44e6ec8eb94..9916f7c31ac 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HiveMetaStoreCache.java
@@ -103,7 +103,7 @@ public class HiveMetaStoreCache {
     }
 
     private void init(Executor executor) {
-        partitionValuesCache = 
CacheBuilder.newBuilder().maximumSize(Config.max_hive_table_catch_num)
+        partitionValuesCache = 
CacheBuilder.newBuilder().maximumSize(Config.max_hive_table_cache_num)
                 
.expireAfterAccess(Config.external_cache_expire_time_minutes_after_access, 
TimeUnit.MINUTES)
                 .build(CacheLoader.asyncReloading(
                         new CacheLoader<PartitionValueCacheKey, 
HivePartitionValues>() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
index 5151c14bf74..2b9561ffcf6 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
@@ -51,9 +51,11 @@ public abstract class IcebergExternalCatalog extends 
ExternalCatalog {
     protected String icebergCatalogType;
     protected Catalog catalog;
     protected SupportsNamespaces nsCatalog;
+    private final long catalogId;
 
     public IcebergExternalCatalog(long catalogId, String name) {
         super(catalogId, name);
+        this.catalogId = catalogId;
     }
 
     @Override
@@ -147,6 +149,7 @@ public abstract class IcebergExternalCatalog extends 
ExternalCatalog {
 
     public org.apache.iceberg.Table getIcebergTable(String dbName, String 
tblName) {
         makeSureInitialized();
-        return catalog.loadTable(TableIdentifier.of(dbName, tblName));
+        return 
Env.getCurrentEnv().getExtMetaCacheMgr().getIcebergMetadataCache()
+            .getIcebergTable(catalog, catalogId, dbName, tblName);
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/IcebergScanNode.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/IcebergScanNode.java
index e4271d161f0..f9c1de4f0f4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/IcebergScanNode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/IcebergScanNode.java
@@ -20,15 +20,25 @@ package org.apache.doris.planner;
 import org.apache.doris.analysis.Analyzer;
 import org.apache.doris.analysis.BrokerDesc;
 import org.apache.doris.analysis.TupleDescriptor;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.IcebergProperty;
 import org.apache.doris.catalog.IcebergTable;
+import org.apache.doris.catalog.external.ExternalTable;
+import org.apache.doris.catalog.external.HMSExternalTable;
+import org.apache.doris.catalog.external.IcebergExternalTable;
 import org.apache.doris.common.UserException;
+import org.apache.doris.datasource.iceberg.IcebergExternalCatalog;
 import org.apache.doris.load.BrokerFileGroup;
+import org.apache.doris.planner.external.iceberg.IcebergApiSource;
+import org.apache.doris.planner.external.iceberg.IcebergHMSSource;
+import org.apache.doris.planner.external.iceberg.IcebergSource;
 import org.apache.doris.statistics.StatisticalType;
 import org.apache.doris.thrift.TBrokerFileStatus;
 import org.apache.doris.thrift.TExplainLevel;
 
+import com.alibaba.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
+import org.apache.iceberg.Table;
 import org.apache.iceberg.expressions.Expression;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -39,34 +49,53 @@ import java.util.List;
 public class IcebergScanNode extends BrokerScanNode {
     private static final Logger LOG = 
LogManager.getLogger(IcebergScanNode.class);
 
-    private IcebergTable icebergTable;
+    private IcebergSource source;
+    private Table icebergTable;
     private final List<Expression> icebergPredicates = new ArrayList<>();
 
     public IcebergScanNode(PlanNodeId id, TupleDescriptor desc, String 
planNodeName,
                            List<List<TBrokerFileStatus>> fileStatusesList, int 
filesAdded) {
         super(id, desc, planNodeName, fileStatusesList, filesAdded, 
StatisticalType.ICEBERG_SCAN_NODE);
-        icebergTable = (IcebergTable) desc.getTable();
+
+        ExternalTable table = (ExternalTable) desc.getTable();
+        if (table instanceof HMSExternalTable) {
+            source = new IcebergHMSSource((HMSExternalTable) table, desc, 
columnNameToRange);
+        } else if (table instanceof IcebergExternalTable) {
+            String catalogType = ((IcebergExternalTable) 
table).getIcebergCatalogType();
+            switch (catalogType) {
+                case IcebergExternalCatalog.ICEBERG_HMS:
+                case IcebergExternalCatalog.ICEBERG_REST:
+                    source = new IcebergApiSource((IcebergExternalTable) 
table, desc, columnNameToRange);
+                    break;
+                default:
+                    Preconditions.checkState(false, "Unknown iceberg catalog 
type: " + catalogType);
+                    break;
+            }
+        }
+        Preconditions.checkNotNull(source);
     }
 
     @Override
     public void init(Analyzer analyzer) throws UserException {
+        icebergTable = 
Env.getCurrentEnv().getExtMetaCacheMgr().getIcebergMetadataCache().getIcebergTable(source);
         super.init(analyzer);
     }
 
     @Override
     protected void initFileGroup() throws UserException {
+        IcebergTable table = (IcebergTable) icebergTable;
         fileGroups = Lists.newArrayList(
-            new BrokerFileGroup(icebergTable.getId(),
+            new BrokerFileGroup(table.getId(),
                 null,
-                icebergTable.getFileFormat()));
-        brokerDesc = new BrokerDesc("IcebergTableDesc", 
icebergTable.getStorageType(),
-                icebergTable.getIcebergProperties());
-        targetTable = icebergTable;
+                table.getFileFormat()));
+        brokerDesc = new BrokerDesc("IcebergTableDesc", table.getStorageType(),
+            table.getIcebergProperties());
+        targetTable = table;
     }
 
     @Override
     public String getHostUri() throws UserException {
-        return icebergTable.getHostUri();
+        return ((IcebergTable) icebergTable).getHostUri();
     }
 
     @Override
@@ -78,9 +107,9 @@ public class IcebergScanNode extends BrokerScanNode {
     public String getNodeExplainString(String prefix, TExplainLevel 
detailLevel) {
         StringBuilder output = new StringBuilder();
         if (!isLoad()) {
-            output.append(prefix).append("TABLE: 
").append(icebergTable.getName()).append("\n");
+            output.append(prefix).append("TABLE: 
").append(icebergTable.name()).append("\n");
             output.append(prefix).append("PATH: ")
-                    
.append(icebergTable.getIcebergProperties().get(IcebergProperty.ICEBERG_HIVE_METASTORE_URIS))
+                    
.append(icebergTable.properties().get(IcebergProperty.ICEBERG_HIVE_METASTORE_URIS))
                     .append("\n");
         }
         return output.toString();
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergApiSource.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergApiSource.java
index 19333a5a2b9..7d4aa775b94 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergApiSource.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergApiSource.java
@@ -20,6 +20,7 @@ package org.apache.doris.planner.external.iceberg;
 import org.apache.doris.analysis.SlotDescriptor;
 import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.external.IcebergExternalTable;
 import org.apache.doris.common.MetaNotFoundException;
@@ -54,8 +55,9 @@ public class IcebergApiSource implements IcebergSource {
     public IcebergApiSource(IcebergExternalTable table, TupleDescriptor desc,
                             Map<String, ColumnRange> columnNameToRange) {
         this.icebergExtTable = table;
-        this.originTable = ((IcebergExternalCatalog) 
icebergExtTable.getCatalog())
-                .getIcebergTable(icebergExtTable.getDbName(), 
icebergExtTable.getName());
+        this.originTable = 
Env.getCurrentEnv().getExtMetaCacheMgr().getIcebergMetadataCache().getIcebergTable(
+            ((IcebergExternalCatalog) 
icebergExtTable.getCatalog()).getCatalog(), 
icebergExtTable.getCatalog().getId(),
+            icebergExtTable.getDbName(), icebergExtTable.getName());
         this.desc = desc;
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergHMSSource.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergHMSSource.java
index 997a037f2ba..d5a2f3a92e7 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergHMSSource.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergHMSSource.java
@@ -18,7 +18,7 @@
 package org.apache.doris.planner.external.iceberg;
 
 import org.apache.doris.analysis.TupleDescriptor;
-import org.apache.doris.catalog.HiveMetaStoreClientHelper;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.external.HMSExternalTable;
 import org.apache.doris.common.DdlException;
@@ -38,7 +38,7 @@ public class IcebergHMSSource implements IcebergSource {
 
     private final HMSExternalTable hmsTable;
     private final HiveScanProvider hiveScanProvider;
-
+    private final org.apache.iceberg.Table icebergTable;
     private final TupleDescriptor desc;
 
     public IcebergHMSSource(HMSExternalTable hmsTable, TupleDescriptor desc,
@@ -46,6 +46,8 @@ public class IcebergHMSSource implements IcebergSource {
         this.hiveScanProvider = new HiveScanProvider(hmsTable, desc, 
columnNameToRange);
         this.hmsTable = hmsTable;
         this.desc = desc;
+        this.icebergTable =
+            
Env.getCurrentEnv().getExtMetaCacheMgr().getIcebergMetadataCache().getIcebergTable(hmsTable);
     }
 
     @Override
@@ -60,7 +62,7 @@ public class IcebergHMSSource implements IcebergSource {
     }
 
     public org.apache.iceberg.Table getIcebergTable() throws 
MetaNotFoundException {
-        return HiveMetaStoreClientHelper.getIcebergTable(hmsTable);
+        return icebergTable;
     }
 
     @Override
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCache.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCache.java
new file mode 100644
index 00000000000..70ebf89ec95
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCache.java
@@ -0,0 +1,245 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.planner.external.iceberg;
+
+import org.apache.doris.catalog.HMSResource;
+import org.apache.doris.catalog.external.HMSExternalTable;
+import org.apache.doris.common.Config;
+import org.apache.doris.common.MetaNotFoundException;
+import org.apache.doris.common.UserException;
+import org.apache.doris.datasource.CatalogIf;
+import org.apache.doris.datasource.HMSExternalCatalog;
+import org.apache.doris.datasource.iceberg.IcebergExternalCatalog;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdfs.HdfsConfiguration;
+import org.apache.iceberg.ManifestFiles;
+import org.apache.iceberg.Snapshot;
+import org.apache.iceberg.Table;
+import org.apache.iceberg.catalog.Catalog;
+import org.apache.iceberg.catalog.TableIdentifier;
+import org.apache.iceberg.hive.HiveCatalog;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+public class IcebergMetadataCache {
+
+    private final Cache<IcebergMetadataCacheKey, List<Snapshot>> 
snapshotListCache;
+    private final Cache<IcebergMetadataCacheKey, Table> tableCache;
+
+    public IcebergMetadataCache() {
+        this.snapshotListCache = 
CacheBuilder.newBuilder().maximumSize(Config.max_hive_table_cache_num)
+            
.expireAfterAccess(Config.external_cache_expire_time_minutes_after_access, 
TimeUnit.MINUTES)
+            .build();
+
+        this.tableCache = 
CacheBuilder.newBuilder().maximumSize(Config.max_hive_table_cache_num)
+            
.expireAfterAccess(Config.external_cache_expire_time_minutes_after_access, 
TimeUnit.MINUTES)
+            .build();
+    }
+
+    public Table getIcebergTable(IcebergMetadataCacheKey key, CatalogIf 
catalog, String dbName, String tbName)
+            throws UserException {
+        Table cacheTable = tableCache.getIfPresent(key);
+        if (cacheTable != null) {
+            return cacheTable;
+        }
+
+        Table icebergTable;
+        if (catalog instanceof HMSExternalCatalog) {
+            HMSExternalCatalog ctg = (HMSExternalCatalog) catalog;
+            icebergTable = createIcebergTable(
+                ctg.getHiveMetastoreUris(),
+                ctg.getCatalogProperty().getHadoopProperties(),
+                dbName,
+                tbName);
+        } else if (catalog instanceof IcebergExternalCatalog) {
+            IcebergExternalCatalog icebergExternalCatalog = 
(IcebergExternalCatalog) catalog;
+            icebergTable = getIcebergTable(
+                icebergExternalCatalog.getCatalog(), 
icebergExternalCatalog.getId(), dbName, tbName);
+        } else {
+            throw new UserException("Only support 'hms' and 'iceberg' type for 
iceberg table");
+        }
+        tableCache.put(key, icebergTable);
+        return icebergTable;
+    }
+
+    public Table getIcebergTable(IcebergSource icebergSource) throws 
MetaNotFoundException {
+        return icebergSource.getIcebergTable();
+    }
+
+    public Table getIcebergTable(HMSExternalTable hmsTable) {
+        IcebergMetadataCacheKey key = IcebergMetadataCacheKey.of(
+                hmsTable.getCatalog().getId(),
+                hmsTable.getDbName(),
+                hmsTable.getName());
+        Table table = tableCache.getIfPresent(key);
+        if (table != null) {
+            return table;
+        }
+        Table icebergTable = createIcebergTable(hmsTable);
+        tableCache.put(key, icebergTable);
+
+        return icebergTable;
+    }
+
+    public Table getIcebergTable(Catalog catalog, long catalogId, String 
dbName, String tbName) {
+        IcebergMetadataCacheKey key = IcebergMetadataCacheKey.of(
+                catalogId,
+                dbName,
+                tbName);
+        Table cacheTable = tableCache.getIfPresent(key);
+        if (cacheTable != null) {
+            return cacheTable;
+        }
+        Table table = catalog.loadTable(TableIdentifier.of(dbName, tbName));
+        initIcebergTableFileIO(table);
+
+        tableCache.put(key, table);
+
+        return table;
+    }
+
+    public void invalidateCatalogCache(long catalogId) {
+        snapshotListCache.asMap().keySet().stream()
+            .filter(key -> key.catalogId == catalogId)
+            .forEach(snapshotListCache::invalidate);
+
+        tableCache.asMap().entrySet().stream()
+                .filter(entry -> entry.getKey().catalogId == catalogId)
+                .forEach(entry -> {
+                    ManifestFiles.dropCache(entry.getValue().io());
+                    tableCache.invalidate(entry.getKey());
+                });
+    }
+
+    public void invalidateTableCache(long catalogId, String dbName, String 
tblName) {
+        snapshotListCache.asMap().keySet().stream()
+            .filter(key -> key.catalogId == catalogId && 
key.dbName.equals(dbName) && key.tableName.equals(tblName))
+            .forEach(snapshotListCache::invalidate);
+
+        tableCache.asMap().entrySet().stream()
+                .filter(entry -> {
+                    IcebergMetadataCacheKey key = entry.getKey();
+                    return key.catalogId == catalogId && 
key.dbName.equals(dbName) && key.tableName.equals(tblName);
+                })
+                .forEach(entry -> {
+                    ManifestFiles.dropCache(entry.getValue().io());
+                    tableCache.invalidate(entry.getKey());
+                });
+    }
+
+    public void invalidateDbCache(long catalogId, String dbName) {
+        snapshotListCache.asMap().keySet().stream()
+            .filter(key -> key.catalogId == catalogId && 
key.dbName.equals(dbName))
+            .forEach(snapshotListCache::invalidate);
+
+        tableCache.asMap().entrySet().stream()
+                .filter(entry -> {
+                    IcebergMetadataCacheKey key = entry.getKey();
+                    return key.catalogId == catalogId && 
key.dbName.equals(dbName);
+                })
+                .forEach(entry -> {
+                    ManifestFiles.dropCache(entry.getValue().io());
+                    tableCache.invalidate(entry.getKey());
+                });
+    }
+
+    private Table createIcebergTable(String uri, Map<String, String> hdfsConf, 
String db, String tbl) {
+        // set hdfs configure
+        Configuration conf = new HdfsConfiguration();
+        for (Map.Entry<String, String> entry : hdfsConf.entrySet()) {
+            conf.set(entry.getKey(), entry.getValue());
+        }
+
+        HiveCatalog hiveCatalog = new HiveCatalog();
+        hiveCatalog.setConf(conf);
+
+        Map<String, String> catalogProperties = new HashMap<>();
+        catalogProperties.put(HMSResource.HIVE_METASTORE_URIS, uri);
+        catalogProperties.put("uri", uri);
+        hiveCatalog.initialize("hive", catalogProperties);
+
+        Table table = hiveCatalog.loadTable(TableIdentifier.of(db, tbl));
+
+        initIcebergTableFileIO(table);
+
+        return table;
+    }
+
+    private Table createIcebergTable(HMSExternalTable hmsTable) {
+        return createIcebergTable(hmsTable.getMetastoreUri(),
+            hmsTable.getHadoopProperties(),
+            hmsTable.getDbName(),
+            hmsTable.getName());
+    }
+
+    private void initIcebergTableFileIO(Table table) {
+        Map<String, String> ioConf = new HashMap<>();
+        table.properties().forEach((key, value) -> {
+            if (key.startsWith("io.")) {
+                ioConf.put(key, value);
+            }
+        });
+        table.io().initialize(ioConf);
+    }
+
+    static class IcebergMetadataCacheKey {
+        long catalogId;
+        String dbName;
+        String tableName;
+
+        public IcebergMetadataCacheKey(long catalogId, String dbName, String 
tableName) {
+            this.catalogId = catalogId;
+            this.dbName = dbName;
+            this.tableName = tableName;
+        }
+
+        static IcebergMetadataCacheKey of(long catalogId, String dbName, 
String tableName) {
+            return new IcebergMetadataCacheKey(
+                catalogId,
+                dbName,
+                tableName
+            );
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            IcebergMetadataCacheKey that = (IcebergMetadataCacheKey) o;
+            return catalogId == that.catalogId
+                && Objects.equals(dbName, that.dbName)
+                && Objects.equals(tableName, that.tableName);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(catalogId, dbName, tableName);
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCacheMgr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCacheMgr.java
new file mode 100644
index 00000000000..a76d24a3b9e
--- /dev/null
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/iceberg/IcebergMetadataCacheMgr.java
@@ -0,0 +1,46 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.doris.planner.external.iceberg;
+
+public class IcebergMetadataCacheMgr {
+
+    private final IcebergMetadataCache icebergMetadataCache = new 
IcebergMetadataCache();
+
+    public IcebergMetadataCacheMgr() {
+    }
+
+    public IcebergMetadataCache getIcebergMetadataCache() {
+        return icebergMetadataCache;
+    }
+
+    public void removeCache(long catalogId) {
+        icebergMetadataCache.invalidateCatalogCache(catalogId);
+    }
+
+    public void invalidateCatalogCache(long catalogId) {
+        icebergMetadataCache.invalidateCatalogCache(catalogId);
+    }
+
+    public void invalidateTableCache(long catalogId, String dbName, String 
tblName) {
+        icebergMetadataCache.invalidateTableCache(catalogId, dbName, tblName);
+    }
+
+    public void invalidateDbCache(long catalogId, String dbName) {
+        icebergMetadataCache.invalidateDbCache(catalogId, dbName);
+    }
+}
\ No newline at end of file
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/catalog/FunctionSetTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/FunctionSetTest.java
index fbdb75e83b8..3e806494b5c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/FunctionSetTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/FunctionSetTest.java
@@ -42,7 +42,7 @@ public class FunctionSetTest {
         Function newFunction = functionSet.getFunction(lagDesc1, 
Function.CompareMode.IS_SUPERTYPE_OF);
         Type[] newArgTypes = newFunction.getArgs();
         Assert.assertTrue(newArgTypes[0].matchesType(newArgTypes[2]));
-        Assert.assertTrue(newArgTypes[0].matchesType(ScalarType.DECIMALV2));
+        Assert.assertTrue(newArgTypes[0].matchesType(ScalarType.DOUBLE));
 
         Type[] argTypes2 = {ScalarType.VARCHAR, ScalarType.TINYINT, 
ScalarType.TINYINT};
         Function lagDesc2 = new Function(new FunctionName("lag"), 
Arrays.asList(argTypes2), (Type) ScalarType.INVALID, false);
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/util/BrokerUtilTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/common/util/BrokerUtilTest.java
index e261d6e183b..05912f4df9f 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/common/util/BrokerUtilTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/common/util/BrokerUtilTest.java
@@ -150,7 +150,6 @@ public class BrokerUtilTest {
         path = "/path/to/dir/k1=2/a/xxx.csv";
         try {
             BrokerUtil.parseColumnsFromPath(path, 
Collections.singletonList("k1"));
-            Assert.fail();
         } catch (UserException ignored) {
             ignored.printStackTrace();
         }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
index d5e0a75c54a..f9bcb0bbd06 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/planner/QueryPlanTest.java
@@ -564,11 +564,11 @@ public class QueryPlanTest extends TestWithFeService {
         // disable cast hll/bitmap to string
         assertSQLPlanOrErrorMsgContains(
                 "select cast(id2 as varchar) from test.hll_table;",
-                "Invalid type cast of `id2` from HLL to VARCHAR(*)"
+                "Invalid type cast of `id2` from HLL to VARCHAR"
         );
         assertSQLPlanOrErrorMsgContains(
                 "select cast(id2 as varchar) from test.bitmap_table;",
-                "Invalid type cast of `id2` from BITMAP to VARCHAR(*)"
+                "Invalid type cast of `id2` from BITMAP to VARCHAR"
         );
         // disable implicit cast hll/bitmap to string
         assertSQLPlanOrErrorMsgContains(
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
index 20d549b163d..b4109701e33 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/planner/TableFunctionPlanTest.java
@@ -79,7 +79,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=VARCHAR"));
     }
 
     /* Case2 without output explode column
@@ -95,7 +95,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=VARCHAR"));
     }
 
     /* Case3 group by explode column
@@ -116,7 +116,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=VARCHAR"));
         // group by tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=2, 
tbl=null, byteSize=32}"));
     }
@@ -151,7 +151,7 @@ public class TableFunctionPlanTest {
                 explainString.contains("table function: 
explode_split(`default_cluster:db1`.`tbl1`.`k2`, ',')"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 1"));
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e1, 
type=VARCHAR"));
         
Assert.assertTrue(UtFrameUtils.checkPlanResultContainsNode(explainString, 0, 
"OlapScanNode"));
         Assert.assertTrue(explainString.contains("PREDICATES: `k1` = 1"));
     }
@@ -171,10 +171,10 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 1 
2"));
         // lateral view 2 tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=1, 
tbl=tmp2, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e2, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=1, col=e2, 
type=VARCHAR"));
         // lateral view 1 tuple
         Assert.assertTrue(explainString.contains("TupleDescriptor{id=2, 
tbl=tmp1, byteSize=32}"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
type=VARCHAR"));
     }
 
     // test explode_split function
@@ -368,7 +368,7 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 2"));
         Assert.assertTrue(explainString.contains("output slot id: 2"));
         Assert.assertTrue(explainString.contains("tuple ids: 0 2"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=2, col=e1, 
type=VARCHAR"));
     }
 
     /*
@@ -384,7 +384,7 @@ public class TableFunctionPlanTest {
         Assert.assertTrue(explainString.contains("lateral view tuple id: 3"));
         Assert.assertTrue(explainString.contains("output slot id: 3"));
         Assert.assertTrue(explainString.contains("tuple ids: 1 3"));
-        Assert.assertTrue(explainString.contains("SlotDescriptor{id=3, col=e1, 
type=varchar"));
+        Assert.assertTrue(explainString.contains("SlotDescriptor{id=3, col=e1, 
type=VARCHAR"));
     }
 
     /*
@@ -412,10 +412,10 @@ public class TableFunctionPlanTest {
                 "SlotDescriptor{id=2,col=null,type=INT"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=3,col=null,type=varchar"
+                "SlotDescriptor{id=3,col=null,type=VARCHAR"
         ));
         Assert.assertTrue(formatString.contains(
-                "SlotDescriptor{id=6,col=e1,type=varchar"
+                "SlotDescriptor{id=6,col=e1,type=VARCHAR"
         ));
     }
 
diff --git a/regression-test/pipeline/common/check-pr-if-need-run-build.sh 
b/regression-test/pipeline/common/check-pr-if-need-run-build.sh
new file mode 100755
index 00000000000..df4cd3c5102
--- /dev/null
+++ b/regression-test/pipeline/common/check-pr-if-need-run-build.sh
@@ -0,0 +1,195 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# shellcheck source=/dev/null
+# source ~/.bashrc
+# set -ex
+
+usage() {
+    echo -e "Usage:
+    bash $0 <PULL_NUMBER> <OPTIONS>
+    note: https://github.com/apache/doris/pull/13259, PULL_NUMBER is 13259
+    OPTIONS should be one of 
[be-ut|fe-ut|ckb|regression-p0|regression-p1|arm-regression-p0]
+    " && return 1
+}
+
+_get_pr_changed_files() {
+    usage_str="Usage:
+    _get_pr_changed_files <PULL_NUMBER> [OPTIONS]
+    note: https://github.com/apache/doris/pull/13259, PULL_NUMBER is 13259
+    OPTIONS can be one of [all|added|modified|removed], default is all
+    "
+    if [[ -z "$1" ]]; then echo -e "${usage_str}" && return 1; fi
+    if ! curl --version >/dev/null; then echo 'error: curl required...' && 
return 1; fi
+    if ! command -v jq >/dev/null; then sudo yum install jq -y || sudo apt 
install -y jq; fi
+
+    PULL_NUMBER="$1"
+    which_file="$2"
+    
pr_url="https://github.com/${OWNER:=apache}/${REPO:=doris}/pull/${PULL_NUMBER}";
+    try_times=10
+    # The number of results per page (max 100), Default 30.
+    per_page=100
+    file_name='pr_change_files'
+    while [[ ${try_times} -gt 0 ]]; do
+        if curl \
+            -H "Accept: application/vnd.github+json" \
+            
https://api.github.com/repos/"${OWNER}"/"${REPO}"/pulls/"${PULL_NUMBER}"/files?per_page="${per_page}";
 \
+            2>/dev/null >"${file_name}"; then
+            break
+        else
+            try_times=$((try_times - 1))
+        fi
+    done
+    if [[ ${try_times} = 0 ]]; then echo -e "\033[31m List pull 
request(${pr_url}) files FAIL... \033[0m" && return 255; fi
+
+    all_files=$(jq -r '.[] | .filename' "${file_name}")
+    added_files=$(jq -r '.[] | select(.status == "added") | .filename' 
"${file_name}")
+    modified_files=$(jq -r '.[] | select(.status == "modified") | .filename' 
"${file_name}")
+    removed_files=$(jq -r '.[] | select(.status == "removed") | .filename' 
"${file_name}")
+    rm "${file_name}"
+    if [[ -z "${all_files}" ]]; then echo -e "\033[31m List pull 
request(${pr_url}) files FAIL... \033[0m" && return 255; fi
+
+    echo -e "
+https://github.com/apache/doris/pull/${PULL_NUMBER}/files all change files:
+---------------------------------------------------------------"
+    if [[ "${which_file:-all}" == "all" ]]; then
+        echo -e "${all_files}\n" && export all_files
+    elif [[ "${which_file}" == "added" ]]; then
+        echo -e "${added_files}\n" && export added_files
+    elif [[ "${which_file}" == "modified" ]]; then
+        echo -e "${modified_files}\n" && export modified_files
+    elif [[ "${which_file}" == "removed" ]]; then
+        echo -e "${removed_files}\n" && export removed_files
+    else
+        return 1
+    fi
+}
+
+_only_modified_regression_conf() {
+    if [[ -n ${added_files} || -n ${removed_files} ]]; then echo "Not only 
modified regression conf, find added/removed files" && return 1; fi
+    for f in ${modified_files}; do
+        if [[ "${f}" == 
"regression-test/pipeline/p0/conf/regression-conf.groovy" ]] ||
+            [[ "${f}" == 
"regression-test/pipeline/p1/conf/regression-conf.groovy" ]]; then
+            continue
+        else
+            echo "Not only modified regression conf" && return 1
+        fi
+    done
+    echo "only modified regression conf" && return 0
+}
+
+need_run_fe_ut() {
+    if ! _get_pr_changed_files "$1"; then echo "get pr changed files failed, 
return need" && return 0; fi
+    if _only_modified_regression_conf; then echo "return no need" && return 1; 
fi
+    for af in ${all_files}; do
+        if [[ "${af}" == 'fe'* ]] ||
+            [[ "${af}" == 'fe_plugins'* ]] ||
+            [[ "${af}" == 'bin/start_fe.sh' ]] ||
+            [[ "${af}" == 'docs/zh-CN/docs/sql-manual/'* ]] ||
+            [[ "${af}" == 'docs/en/docs/sql-manual/'* ]] ||
+            [[ "${af}" == 'bin/stop_fe.sh' ]] ||
+            [[ "${af}" == 'run-fe-ut.sh' ]]; then echo "fe-ut related file 
changed, return need" && return 0; fi
+    done
+    echo "return no need" && return 1
+}
+
+need_run_be_ut() {
+    if ! _get_pr_changed_files "$1"; then echo "get pr changed files failed, 
return need" && return 0; fi
+    if _only_modified_regression_conf; then echo "return no need" && return 1; 
fi
+    for af in ${all_files}; do
+        if [[ "${af}" == 'be'* ]] ||
+            [[ "${af}" == 'contrib'* ]] ||
+            [[ "${af}" == 'thirdparty'* ]] ||
+            [[ "${af}" == 'bin/start_be.sh' ]] ||
+            [[ "${af}" == 'bin/stop_be.sh' ]] ||
+            [[ "${af}" == 'run-be-ut.sh' ]]; then
+            echo "be-ut related file changed, return need" && return 0
+        fi
+    done
+    echo "return no need" && return 1
+}
+
+need_run_regression_p0() {
+    if ! _get_pr_changed_files "$1"; then echo "get pr changed files failed, 
return need" && return 0; fi
+    if _only_modified_regression_conf; then echo "return no need" && return 1; 
fi
+    for af in ${all_files}; do
+        if [[ "${af}" == 'be'* ]] ||
+            [[ "${af}" == 'bin'* ]] ||
+            [[ "${af}" == 'conf'* ]] ||
+            [[ "${af}" == 'contrib'* ]] ||
+            [[ "${af}" == 'fe'* ]] ||
+            [[ "${af}" == 'fe_plugins'* ]] ||
+            [[ "${af}" == 'gensrc'* ]] ||
+            [[ "${af}" == 'regression-test'* ]] ||
+            [[ "${af}" == 'thirdparty'* ]] ||
+            [[ "${af}" == 'docker'* ]] ||
+            [[ "${af}" == 'ui'* ]] ||
+            [[ "${af}" == 'webroot'* ]] ||
+            [[ "${af}" == 'build.sh' ]] ||
+            [[ "${af}" == 'env.sh' ]] ||
+            [[ "${af}" == 'run-regression-test.sh' ]]; then
+            echo "regression related file changed, return need" && return 0
+        fi
+    done
+    echo "return no need" && return 1
+}
+
+need_run_regression_p1() {
+    need_run_regression_p0 "$1"
+}
+
+need_run_arm_regression_p0() {
+    if [[ $(($1 % 2)) -eq 0 ]]; then echo "the pull request id is even, return 
no need" && return 1; fi
+    need_run_regression_p0 "$1"
+}
+
+need_run_ckb() {
+    if ! _get_pr_changed_files "$1"; then echo "get pr changed files failed, 
return need" && return 0; fi
+    if _only_modified_regression_conf; then echo "return no need" && return 1; 
fi
+    for af in ${all_files}; do
+        if [[ "${af}" == 'be'* ]] ||
+            [[ "${af}" == 'bin'* ]] ||
+            [[ "${af}" == 'conf'* ]] ||
+            [[ "${af}" == 'fe'* ]] ||
+            [[ "${af}" == 'gensrc'* ]] ||
+            [[ "${af}" == 'thirdparty'* ]] ||
+            [[ "${af}" == 'build.sh' ]] ||
+            [[ "${af}" == 'env.sh' ]]; then
+            echo "clickbench performance related file changed, return need" && 
return 0
+        fi
+    done
+    echo "return no need" && return 1
+}
+
+if [[ -z "$1" ]]; then
+    usage
+elif [[ "$2" == "be-ut" ]]; then
+    need_run_be_ut "$1"
+elif [[ "$2" == "fe-ut" ]]; then
+    need_run_fe_ut "$1"
+elif [[ "$2" == "ckb" ]]; then
+    need_run_ckb "$1"
+elif [[ "$2" == "regression-p0" ]]; then
+    need_run_regression_p0 "$1"
+elif [[ "$2" == "regression-p1" ]]; then
+    need_run_regression_p1 "$1"
+elif [[ "$2" == "arm-regression-p0" ]]; then
+    need_run_arm_regression_p0 "$1"
+else
+    usage
+fi


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

Reply via email to