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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new a794109e3bb branch-4.1: [fix](hive table) Fill Hive meta cache when 
loading row count for queries #63470 (#63800)
a794109e3bb is described below

commit a794109e3bb5d6e639f7ae941a1eb6fc08391e3d
Author: yujun <[email protected]>
AuthorDate: Fri May 29 14:49:34 2026 +0800

    branch-4.1: [fix](hive table) Fill Hive meta cache when loading row count 
for queries #63470 (#63800)
    
    cherry-pick: #63470
---
 .../doris/datasource/ExternalRowCountCache.java    |  53 ++++---
 .../org/apache/doris/datasource/ExternalTable.java |  13 +-
 .../doris/datasource/hive/HMSExternalTable.java    |  28 ++--
 .../datasource/ExternalRowCountCacheTest.java      |  66 +++++++-
 .../datasource/hive/HMSExternalTableTest.java      | 176 +++++++++++++++++++++
 5 files changed, 297 insertions(+), 39 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalRowCountCache.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalRowCountCache.java
index 352f733f8e7..f32ba5ae20c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalRowCountCache.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalRowCountCache.java
@@ -83,40 +83,49 @@ public class ExternalRowCountCache {
     public static class RowCountCacheLoader extends 
BasicAsyncCacheLoader<RowCountKey, Optional<Long>> {
         @Override
         protected Optional<Long> doLoad(RowCountKey rowCountKey) {
-            try {
-                TableIf table = 
StatisticsUtil.findTable(rowCountKey.catalogId, rowCountKey.dbId, 
rowCountKey.tableId);
-                return Optional.of(table.fetchRowCount());
-            } catch (Exception e) {
-                String message = String.format("Failed to get table row count 
with catalogId %s, dbId %s, tableId %s. "
-                                + "Reason %s",
-                        rowCountKey.catalogId, rowCountKey.dbId, 
rowCountKey.tableId, e.getMessage());
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug(message, e);
-                } else {
-                    LOG.warn(message);
-                }
+            return loadRowCount(rowCountKey, false);
+        }
+    }
 
-                // Return Optional.empty() will cache this empty value in 
memory,
-                // so we can't try to load the row count until the cache 
expire.
-                // Throw an exception here will cause too much stack log in 
fe.out.
-                // So we return null when exception happen.
-                // Null may raise NPE in caller, but that is expected.
-                // We catch that NPE and return a default value -1 without 
keep the value in cache,
-                // so we can trigger the load function to fetch row count 
again next time in this exception case.
-                return null;
+    static Optional<Long> loadRowCount(RowCountKey rowCountKey, boolean 
fillMetaCache) {
+        try {
+            ExternalTable table = (ExternalTable) StatisticsUtil.findTable(
+                    rowCountKey.catalogId, rowCountKey.dbId, 
rowCountKey.tableId);
+            return 
Optional.of(table.fetchRowCountWithMetaCache(fillMetaCache));
+        } catch (Exception e) {
+            String message = String.format("Failed to get table row count with 
catalogId %s, dbId %s, tableId %s. "
+                            + "Reason %s",
+                    rowCountKey.catalogId, rowCountKey.dbId, 
rowCountKey.tableId, e.getMessage());
+            if (LOG.isDebugEnabled()) {
+                LOG.warn(message, e);
+            } else {
+                LOG.warn(message);
             }
+
+            // Return Optional.empty() will cache this empty value in memory,
+            // so we can't try to load the row count until the cache expire.
+            // Throw an exception here will cause too much stack log in fe.out.
+            // So we return null when exception happen.
+            // Null may raise NPE in caller, but that is expected.
+            // We catch that NPE and return a default value -1 without keep 
the value in cache,
+            // so we can trigger the load function to fetch row count again 
next time in this exception case.
+            return null;
         }
     }
 
     /**
      * Get cached row count for the given table. Return -1 if cached not 
loaded or table not exists.
      * Cached will be loaded async.
+     * @param fillMetaCache whether loading the row count may fill external 
metadata caches
      * @return Cached row count or -1 if not exist
      */
-    public long getCachedRowCount(long catalogId, long dbId, long tableId) {
+    public long getCachedRowCount(long catalogId, long dbId, long tableId, 
boolean fillMetaCache) {
         RowCountKey key = new RowCountKey(catalogId, dbId, tableId);
         try {
-            CompletableFuture<Optional<Long>> f = rowCountCache.get(key);
+            CompletableFuture<Optional<Long>> f = fillMetaCache
+                    ? rowCountCache.get(key, (rowCountKey, executor) -> 
CompletableFuture.supplyAsync(
+                            () -> loadRowCount(rowCountKey, true), executor))
+                    : rowCountCache.get(key);
             // Get row count synchronously by default.
             if (ConnectContext.get() == null
                     || 
ConnectContext.get().getSessionVariable().fetchHiveRowCountSync) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java
index 800f98cea77..f5786423b6e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/ExternalTable.java
@@ -251,7 +251,8 @@ public class ExternalTable implements TableIf, Writable, 
GsonPostProcessable {
             return TableIf.UNKNOWN_ROW_COUNT;
         }
         // All external table should get external row count from cache.
-        return 
Env.getCurrentEnv().getExtMetaCacheMgr().getRowCountCache().getCachedRowCount(catalog.getId(),
 dbId, id);
+        return Env.getCurrentEnv().getExtMetaCacheMgr().getRowCountCache()
+                .getCachedRowCount(catalog.getId(), dbId, id, true);
     }
 
     @Override
@@ -265,7 +266,8 @@ public class ExternalTable implements TableIf, Writable, 
GsonPostProcessable {
         }
         // getExtMetaCacheMgr().getRowCountCache().getCachedRowCount() is an 
asynchronous non-blocking operation.
         // For tables that are not in the cache, it will load asynchronously 
and return -1.
-        return 
Env.getCurrentEnv().getExtMetaCacheMgr().getRowCountCache().getCachedRowCount(catalog.getId(),
 dbId, id);
+        return Env.getCurrentEnv().getExtMetaCacheMgr().getRowCountCache()
+                .getCachedRowCount(catalog.getId(), dbId, id, false);
     }
 
     @Override
@@ -277,6 +279,13 @@ public class ExternalTable implements TableIf, Writable, 
GsonPostProcessable {
         return UNKNOWN_ROW_COUNT;
     }
 
+    /**
+     * Fetch row count, and allow the load path to fill external metadata 
cache if supported.
+     */
+    public long fetchRowCountWithMetaCache(boolean fillMetaCache) {
+        return fetchRowCount();
+    }
+
     @Override
     public long getAvgRowLength() {
         return 0;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java
index 137ee718741..b7add486018 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/HMSExternalTable.java
@@ -776,13 +776,22 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
 
     @Override
     public long fetchRowCount() {
+        return fetchRowCountInternal(false);
+    }
+
+    @Override
+    public long fetchRowCountWithMetaCache(boolean fillMetaCache) {
+        return fetchRowCountInternal(fillMetaCache);
+    }
+
+    private long fetchRowCountInternal(boolean fillMetaCache) {
         makeSureInitialized();
         // Get row count from hive metastore property.
         long rowCount = getRowCountFromExternalSource();
         // Only hive table supports estimate row count by listing file.
         if (rowCount == UNKNOWN_ROW_COUNT && dlaType.equals(DLAType.HIVE)) {
             LOG.info("Will estimate row count for table {} from file list.", 
name);
-            rowCount = getRowCountFromFileList();
+            rowCount = getRowCountFromFileList(fillMetaCache);
         }
         return rowCount;
     }
@@ -937,7 +946,7 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
     @Override
     public List<Long> getChunkSizes() {
         HiveExternalMetaCache.HivePartitionValues partitionValues = 
getAllPartitionValues();
-        List<HiveExternalMetaCache.FileCacheValue> filesByPartitions = 
getFilesForPartitions(partitionValues, 0);
+        List<HiveExternalMetaCache.FileCacheValue> filesByPartitions = 
getFilesForPartitions(partitionValues, 0, false);
         List<Long> result = Lists.newArrayList();
         for (HiveExternalMetaCache.FileCacheValue files : filesByPartitions) {
             for (HiveExternalMetaCache.HiveFileStatus file : files.getFiles()) 
{
@@ -1041,7 +1050,7 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
     /**
      * Estimate hive table row count : totalFileSize/estimatedRowSize
      */
-    private long getRowCountFromFileList() {
+    private long getRowCountFromFileList(boolean fillMetaCache) {
         if (!GlobalVariable.enable_get_row_count_from_file_list) {
             return UNKNOWN_ROW_COUNT;
         }
@@ -1055,7 +1064,7 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
             // Get files for all partitions.
             int samplePartitionSize = Config.hive_stats_partition_sample_size;
             List<HiveExternalMetaCache.FileCacheValue> filesByPartitions =
-                    getFilesForPartitions(partitionValues, 
samplePartitionSize);
+                    getFilesForPartitions(partitionValues, 
samplePartitionSize, fillMetaCache);
             LOG.info("Number of files selected for hive table {} is {}", name, 
filesByPartitions.size());
             long totalSize = 0;
             // Calculate the total file size.
@@ -1121,7 +1130,7 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
     // Get all files related to given partition values
     // If sampleSize > 0, randomly choose part of partitions of the whole 
table.
     private List<HiveExternalMetaCache.FileCacheValue> getFilesForPartitions(
-            HiveExternalMetaCache.HivePartitionValues partitionValues, int 
sampleSize) {
+            HiveExternalMetaCache.HivePartitionValues partitionValues, int 
sampleSize, boolean fillMetaCache) {
         if (isView()) {
             return Lists.newArrayList();
         }
@@ -1146,9 +1155,10 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
             for (PartitionItem item : partitionItems) {
                 partitionValuesList.add(((ListPartitionItem) 
item).getItems().get(0).getPartitionValuesAsStringList());
             }
-            // get partitions without cache, so that it will not invalid the 
cache when executing
-            // non query request such as `show table status`
-            hivePartitions = cache.getAllPartitionsWithoutCache(this, 
partitionValuesList);
+            // Non-query requests such as `show table status` should not fill 
heavy metadata caches.
+            hivePartitions = fillMetaCache
+                    ? cache.getAllPartitionsWithCache(this, 
partitionValuesList)
+                    : cache.getAllPartitionsWithoutCache(this, 
partitionValuesList);
             LOG.info("Partition list size for hive partition table {} is {}", 
name, hivePartitions.size());
         } else {
             hivePartitions.add(new HivePartition(getOrBuildNameMapping(), true,
@@ -1161,7 +1171,7 @@ public class HMSExternalTable extends ExternalTable 
implements MTMVRelatedTableI
                 LOG.debug("Chosen partition for table {}. [{}]", name, 
partition.toString());
             }
         }
-        return cache.getFilesByPartitions(hivePartitions, false, true, new 
FileSystemDirectoryLister(), null);
+        return cache.getFilesByPartitions(hivePartitions, fillMetaCache, true, 
new FileSystemDirectoryLister(), null);
     }
 
     @Override
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/ExternalRowCountCacheTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/ExternalRowCountCacheTest.java
index aac07d2d747..075806aa82b 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/ExternalRowCountCacheTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/ExternalRowCountCacheTest.java
@@ -19,17 +19,71 @@ package org.apache.doris.datasource;
 
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.common.ThreadPoolManager;
+import org.apache.doris.statistics.util.StatisticsUtil;
 
+import com.google.common.util.concurrent.MoreExecutors;
 import mockit.Mock;
 import mockit.MockUp;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
 
 import java.util.Optional;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.atomic.AtomicInteger;
 
 public class ExternalRowCountCacheTest {
+    @Test
+    public void testRowCountKeyUsesTableIdAsCacheIdentity() {
+        ExternalRowCountCache.RowCountKey key1 = new 
ExternalRowCountCache.RowCountKey(1, 2, 3);
+        ExternalRowCountCache.RowCountKey key2 = new 
ExternalRowCountCache.RowCountKey(2, 3, 3);
+
+        Assertions.assertEquals(key1, key2);
+        Assertions.assertEquals(key1.hashCode(), key2.hashCode());
+    }
+
+    @Test
+    public void testLoadRowCountPassesFillMetaCacheToTable() {
+        ExternalTable table = Mockito.mock(ExternalTable.class);
+        Mockito.when(table.fetchRowCountWithMetaCache(true)).thenReturn(100L);
+        Mockito.when(table.fetchRowCountWithMetaCache(false)).thenReturn(200L);
+
+        new MockUp<StatisticsUtil>() {
+            @Mock
+            public TableIf findTable(long catalogId, long dbId, long tblId) {
+                return table;
+            }
+        };
+
+        ExternalRowCountCache.RowCountKey key = new 
ExternalRowCountCache.RowCountKey(1, 2, 3);
+        Assertions.assertEquals(100L, ExternalRowCountCache.loadRowCount(key, 
true).get());
+        Assertions.assertEquals(200L, ExternalRowCountCache.loadRowCount(key, 
false).get());
+
+        Mockito.verify(table).fetchRowCountWithMetaCache(true);
+        Mockito.verify(table).fetchRowCountWithMetaCache(false);
+    }
+
+    @Test
+    public void testGetCachedRowCountPassesFillMetaCacheToLoader() {
+        ExternalTable table = Mockito.mock(ExternalTable.class);
+        Mockito.when(table.fetchRowCountWithMetaCache(true)).thenReturn(100L);
+        Mockito.when(table.fetchRowCountWithMetaCache(false)).thenReturn(200L);
+
+        new MockUp<StatisticsUtil>() {
+            @Mock
+            public TableIf findTable(long catalogId, long dbId, long tblId) {
+                return table;
+            }
+        };
+
+        ExternalRowCountCache cache = new 
ExternalRowCountCache(MoreExecutors.newDirectExecutorService());
+        Assertions.assertEquals(100L, cache.getCachedRowCount(1, 2, 3, true));
+        Assertions.assertEquals(200L, cache.getCachedRowCount(1, 2, 4, false));
+
+        Mockito.verify(table).fetchRowCountWithMetaCache(true);
+        Mockito.verify(table).fetchRowCountWithMetaCache(false);
+    }
+
     @Test
     public void testLoadWithException() throws Exception {
         ThreadPoolExecutor executor = 
ThreadPoolManager.newDaemonFixedThreadPool(
@@ -44,7 +98,7 @@ public class ExternalRowCountCacheTest {
             }
         };
         ExternalRowCountCache cache = new ExternalRowCountCache(executor);
-        long cachedRowCount = cache.getCachedRowCount(1, 1, 1);
+        long cachedRowCount = cache.getCachedRowCount(1, 1, 1, false);
         Assertions.assertEquals(TableIf.UNKNOWN_ROW_COUNT, cachedRowCount);
         for (int i = 0; i < 60; i++) {
             if (counter.get() == 1) {
@@ -61,16 +115,16 @@ public class ExternalRowCountCacheTest {
                 return Optional.of(100L);
             }
         };
-        cache.getCachedRowCount(1, 1, 1);
+        cache.getCachedRowCount(1, 1, 1, false);
         for (int i = 0; i < 60; i++) {
-            cachedRowCount = cache.getCachedRowCount(1, 1, 1);
+            cachedRowCount = cache.getCachedRowCount(1, 1, 1, false);
             if (cachedRowCount != TableIf.UNKNOWN_ROW_COUNT) {
                 Assertions.assertEquals(100, cachedRowCount);
                 break;
             }
             Thread.sleep(1000);
         }
-        cachedRowCount = cache.getCachedRowCount(1, 1, 1);
+        cachedRowCount = cache.getCachedRowCount(1, 1, 1, false);
         Assertions.assertEquals(100, cachedRowCount);
         Assertions.assertEquals(2, counter.get());
 
@@ -86,10 +140,10 @@ public class ExternalRowCountCacheTest {
                 return Optional.of(100L);
             }
         };
-        cachedRowCount = cache.getCachedRowCount(2, 2, 2);
+        cachedRowCount = cache.getCachedRowCount(2, 2, 2, false);
         Assertions.assertEquals(100, cachedRowCount);
         Thread.sleep(1000);
-        cachedRowCount = cache.getCachedRowCount(2, 2, 2);
+        cachedRowCount = cache.getCachedRowCount(2, 2, 2, false);
         Assertions.assertEquals(100, cachedRowCount);
         for (int i = 0; i < 60; i++) {
             if (counter.get() == 3) {
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalTableTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalTableTest.java
index bd29766f39e..e68d3704a0c 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalTableTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/HMSExternalTableTest.java
@@ -17,10 +17,32 @@
 
 package org.apache.doris.datasource.hive;
 
+import org.apache.doris.catalog.Column;
+import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.ListPartitionItem;
+import org.apache.doris.catalog.PartitionItem;
+import org.apache.doris.catalog.PartitionKey;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.jmockit.Deencapsulation;
+import org.apache.doris.datasource.ExternalMetaCacheMgr;
+import org.apache.doris.fs.FileSystemDirectoryLister;
+
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
 import mockit.Injectable;
+import org.apache.hadoop.hive.metastore.api.SerDeInfo;
+import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
+import org.apache.hadoop.hive.metastore.api.Table;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 
 
 /**
@@ -88,6 +110,160 @@ public class HMSExternalTableTest {
         Assertions.assertEquals(TEST_VIEW_TEXT, table.getViewText());
     }
 
+    private Table buildRemoteTableWithInputFormat(String inputFormatName) {
+        SerDeInfo serDeInfo = new SerDeInfo();
+        
serDeInfo.setSerializationLib("org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe");
+        StorageDescriptor sd = new StorageDescriptor();
+        sd.setInputFormat(inputFormatName);
+        sd.setSerdeInfo(serDeInfo);
+        Table remoteTable = new Table();
+        remoteTable.setSd(sd);
+        return remoteTable;
+    }
+
+    @Test
+    public void testFetchRowCountFillsMetaCacheOnlyWhenRequested() throws 
Exception {
+        long catalogId = 100L;
+        String localDbName = "test_db";
+        String partitionValue = "2026-05-21";
+        String inputFormat = "org.apache.hadoop.mapred.TextInputFormat";
+        String partitionLocation = 
"file:///tmp/doris_hms_row_count_cache/dt=2026-05-21";
+
+        HMSExternalCatalog catalog = Mockito.mock(HMSExternalCatalog.class);
+        HMSExternalDatabase db = Mockito.mock(HMSExternalDatabase.class);
+        Mockito.when(catalog.getId()).thenReturn(catalogId);
+        Mockito.when(catalog.getName()).thenReturn("test_catalog");
+        Mockito.when(catalog.getProperties()).thenReturn(ImmutableMap.of());
+        Mockito.when(db.getFullName()).thenReturn(localDbName);
+
+        Table remoteTable = buildRemoteTableWithInputFormat(inputFormat);
+        remoteTable.setParameters(ImmutableMap.of());
+        TestHMSExternalTableForMetaCache table = new 
TestHMSExternalTableForMetaCache(
+                catalog, db, remoteTable, partitionValue);
+        Deencapsulation.setField(table, "dlaType", 
HMSExternalTable.DLAType.HIVE);
+
+        List<HivePartition> partitions = Collections.singletonList(new 
HivePartition(
+                null, false, inputFormat, partitionLocation, 
Collections.singletonList(partitionValue),
+                Collections.emptyMap()));
+        HiveExternalMetaCache.FileCacheValue fileCacheValue = new 
HiveExternalMetaCache.FileCacheValue();
+        HiveExternalMetaCache.HiveFileStatus status = new 
HiveExternalMetaCache.HiveFileStatus();
+        status.setLength(128L);
+        fileCacheValue.getFiles().add(status);
+        List<HiveExternalMetaCache.FileCacheValue> files = 
Collections.singletonList(fileCacheValue);
+
+        HiveExternalMetaCache hiveCache = 
Mockito.mock(HiveExternalMetaCache.class);
+        Mockito.when(hiveCache.getAllPartitionsWithCache(Mockito.eq(table), 
Mockito.anyList()))
+                .thenReturn(partitions);
+        Mockito.when(hiveCache.getAllPartitionsWithoutCache(Mockito.eq(table), 
Mockito.anyList()))
+                .thenReturn(partitions);
+        Mockito.when(hiveCache.getFilesByPartitions(Mockito.eq(partitions), 
Mockito.eq(true), Mockito.eq(true),
+                        Mockito.any(FileSystemDirectoryLister.class), 
Mockito.isNull()))
+                .thenReturn(files);
+        Mockito.when(hiveCache.getFilesByPartitions(Mockito.eq(partitions), 
Mockito.eq(false), Mockito.eq(true),
+                        Mockito.any(FileSystemDirectoryLister.class), 
Mockito.isNull()))
+                .thenReturn(files);
+
+        Env env = Mockito.mock(Env.class);
+        ExternalMetaCacheMgr extMetaCacheMgr = 
Mockito.mock(ExternalMetaCacheMgr.class);
+        Mockito.when(env.getExtMetaCacheMgr()).thenReturn(extMetaCacheMgr);
+        Mockito.when(extMetaCacheMgr.hive(catalogId)).thenReturn(hiveCache);
+
+        try (MockedStatic<Env> mockedEnv = Mockito.mockStatic(Env.class)) {
+            mockedEnv.when(Env::getCurrentEnv).thenReturn(env);
+
+            Assertions.assertEquals(32L, 
table.fetchRowCountWithMetaCache(true));
+            
Mockito.verify(hiveCache).getAllPartitionsWithCache(Mockito.eq(table), 
Mockito.anyList());
+            Mockito.verify(hiveCache, Mockito.never())
+                    .getAllPartitionsWithoutCache(Mockito.eq(table), 
Mockito.anyList());
+            
Mockito.verify(hiveCache).getFilesByPartitions(Mockito.eq(partitions), 
Mockito.eq(true),
+                    Mockito.eq(true), 
Mockito.any(FileSystemDirectoryLister.class), Mockito.isNull());
+
+            Mockito.clearInvocations(hiveCache);
+
+            Assertions.assertEquals(32L, table.fetchRowCount());
+            
Mockito.verify(hiveCache).getAllPartitionsWithoutCache(Mockito.eq(table), 
Mockito.anyList());
+            Mockito.verify(hiveCache, Mockito.never())
+                    .getAllPartitionsWithCache(Mockito.eq(table), 
Mockito.anyList());
+            
Mockito.verify(hiveCache).getFilesByPartitions(Mockito.eq(partitions), 
Mockito.eq(false),
+                    Mockito.eq(true), 
Mockito.any(FileSystemDirectoryLister.class), Mockito.isNull());
+        }
+    }
+
+    private static class TestHMSExternalTableWithRemote extends 
HMSExternalTable {
+        private final Table remoteTable;
+
+        public TestHMSExternalTableWithRemote(HMSExternalCatalog catalog,
+                HMSExternalDatabase db, Table remoteTable) {
+            super(1L, "test_table", "test_table", catalog, db);
+            this.remoteTable = remoteTable;
+        }
+
+        @Override
+        public Table getRemoteTable() {
+            return remoteTable;
+        }
+
+        @Override
+        protected synchronized void makeSureInitialized() {
+            this.objectCreated = true;
+        }
+    }
+
+    private static class TestHMSExternalTableForMetaCache extends 
TestHMSExternalTableWithRemote {
+        private final Column dataColumn = new Column("c1", Type.INT);
+        private final Column partitionColumn = new Column("dt", Type.VARCHAR);
+        private final HiveExternalMetaCache.HivePartitionValues 
partitionValues;
+
+        public TestHMSExternalTableForMetaCache(HMSExternalCatalog catalog, 
HMSExternalDatabase db,
+                Table remoteTable, String partitionValue) throws Exception {
+            super(catalog, db, remoteTable);
+            PartitionKey partitionKey = 
PartitionKey.createListPartitionKeyWithTypes(
+                    Lists.newArrayList(new 
org.apache.doris.analysis.PartitionValue(partitionValue)),
+                    Lists.newArrayList(Type.VARCHAR),
+                    true);
+            PartitionItem partitionItem = new 
ListPartitionItem(Lists.newArrayList(partitionKey));
+            long partitionId = 1L;
+            Map<Long, PartitionItem> idToPartitionItem = 
ImmutableMap.of(partitionId, partitionItem);
+            this.partitionValues = new 
HiveExternalMetaCache.HivePartitionValues(
+                    idToPartitionItem,
+                    HashBiMap.create(ImmutableMap.of("dt=" + partitionValue, 
partitionId)),
+                    ImmutableMap.of(partitionId, 
Collections.singletonList(partitionValue)));
+        }
+
+        @Override
+        public List<Column> getFullSchema() {
+            return Lists.newArrayList(dataColumn, partitionColumn);
+        }
+
+        @Override
+        public boolean isView() {
+            return false;
+        }
+
+        @Override
+        public List<Type> 
getPartitionColumnTypes(java.util.Optional<org.apache.doris.datasource.mvcc.MvccSnapshot>
+                snapshot) {
+            return Collections.singletonList(Type.VARCHAR);
+        }
+
+        @Override
+        public List<Column> getPartitionColumns() {
+            return Collections.singletonList(partitionColumn);
+        }
+
+        @Override
+        public List<Column> 
getPartitionColumns(java.util.Optional<org.apache.doris.datasource.mvcc.MvccSnapshot>
+                snapshot) {
+            return Collections.singletonList(partitionColumn);
+        }
+
+        @Override
+        public HiveExternalMetaCache.HivePartitionValues 
getHivePartitionValues(
+                
java.util.Optional<org.apache.doris.datasource.mvcc.MvccSnapshot> snapshot) {
+            return partitionValues;
+        }
+    }
+
     /**
      * Test implementation of HMSExternalTable that allows setting view texts
      * Uses parent's getViewText() implementation for actual testing


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to