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

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


The following commit(s) were added to refs/heads/master by this push:
     new b004396f7b0 [improvement](external) Enable FileScannerV2 for batch 
mode (#65437)
b004396f7b0 is described below

commit b004396f7b016f40470d08d62bfe2114e21a1180
Author: Gabriel <[email protected]>
AuthorDate: Fri Jul 10 23:16:06 2026 +0800

    [improvement](external) Enable FileScannerV2 for batch mode (#65437)
---
 be/src/exec/operator/file_scan_operator.cpp        | 24 ++++++-
 be/src/exec/operator/file_scan_operator.h          |  6 ++
 be/src/exec/scan/file_scanner_v2.cpp               | 28 +++++++-
 be/src/exec/scan/file_scanner_v2.h                 |  5 ++
 be/src/exec/scan/split_source_connector.h          | 29 --------
 be/test/exec/scan/file_scanner_v2_test.cpp         | 80 +++++++++++++---------
 .../doris/datasource/hive/source/HiveScanNode.java | 10 +++
 .../java/org/apache/doris/qe/SessionVariable.java  | 10 ++-
 .../datasource/hive/source/HiveScanNodeTest.java   | 12 ++++
 .../org/apache/doris/qe/SessionVariablesTest.java  | 10 +++
 10 files changed, 147 insertions(+), 67 deletions(-)

diff --git a/be/src/exec/operator/file_scan_operator.cpp 
b/be/src/exec/operator/file_scan_operator.cpp
index d4035d37e27..58aadfc87a6 100644
--- a/be/src/exec/operator/file_scan_operator.cpp
+++ b/be/src/exec/operator/file_scan_operator.cpp
@@ -102,6 +102,26 @@ ScannerScheduler* 
FileScanLocalState::scan_scheduler(RuntimeState* state) const
     return state->get_query_ctx()->get_remote_scan_scheduler();
 }
 
+#ifdef BE_TEST
+bool FileScanLocalState::TEST_should_use_file_scanner_v2(const TQueryOptions& 
query_options,
+                                                         bool is_load,
+                                                         const 
TFileScanRangeParams& scan_params) {
+    return _should_use_file_scanner_v2(query_options, is_load, scan_params);
+}
+#endif
+
+bool FileScanLocalState::_should_use_file_scanner_v2(const TQueryOptions& 
query_options,
+                                                     bool is_load,
+                                                     const 
TFileScanRangeParams& scan_params) {
+    const bool is_transactional_hive =
+            scan_params.__isset.table_format_params &&
+            scan_params.table_format_params.table_format_type == 
"transactional_hive";
+    return query_options.__isset.enable_file_scanner_v2 && 
query_options.enable_file_scanner_v2 &&
+           !is_load && scan_params.format_type != TFileFormatType::FORMAT_WAL 
&&
+           scan_params.format_type != TFileFormatType::FORMAT_ES_HTTP &&
+           scan_params.format_type != TFileFormatType::FORMAT_LANCE && 
!is_transactional_hive;
+}
+
 Status FileScanLocalState::_init_scanners(std::list<ScannerSPtr>* scanners) {
     if (_split_source->num_scan_ranges() == 0) {
         _eos = true;
@@ -131,9 +151,7 @@ Status 
FileScanLocalState::_init_scanners(std::list<ScannerSPtr>* scanners) {
             
state()->desc_tbl().get_tuple_descriptor(scan_params->src_tuple_id) != nullptr;
     // TODO: Use scanner v2 for all queries.
     const bool use_file_scanner_v2 =
-            state()->query_options().__isset.enable_file_scanner_v2 &&
-            state()->query_options().enable_file_scanner_v2 && !is_load &&
-            _split_source->all_scan_ranges_match(*scan_params, 
FileScannerV2::is_supported);
+            _should_use_file_scanner_v2(state()->query_options(), is_load, 
*scan_params);
     _operator_profile->add_info_string("UseScannerV2", use_file_scanner_v2 ? 
"true" : "false");
     for (int i = 0; i < _max_scanners; ++i) {
         ScannerSPtr scanner;
diff --git a/be/src/exec/operator/file_scan_operator.h 
b/be/src/exec/operator/file_scan_operator.h
index c47488fa357..7d8fae51b78 100644
--- a/be/src/exec/operator/file_scan_operator.h
+++ b/be/src/exec/operator/file_scan_operator.h
@@ -54,6 +54,10 @@ public:
     int max_scanners_concurrency(RuntimeState* state) const override;
     int min_scanners_concurrency(RuntimeState* state) const override;
     ScannerScheduler* scan_scheduler(RuntimeState* state) const override;
+#ifdef BE_TEST
+    static bool TEST_should_use_file_scanner_v2(const TQueryOptions& 
query_options, bool is_load,
+                                                const TFileScanRangeParams& 
scan_params);
+#endif
 
 private:
     friend class FileScanner;
@@ -65,6 +69,8 @@ private:
         return PushDownType::PARTIAL_ACCEPTABLE;
     }
     bool _push_down_topn(const RuntimePredicate& predicate) override;
+    static bool _should_use_file_scanner_v2(const TQueryOptions& 
query_options, bool is_load,
+                                            const TFileScanRangeParams& 
scan_params);
 
     PushDownType _should_push_down_is_null_predicate(VectorizedFnCall* 
fn_call) const override {
         return fn_call->fn().name.function_name == "is_null_pred" ||
diff --git a/be/src/exec/scan/file_scanner_v2.cpp 
b/be/src/exec/scan/file_scanner_v2.cpp
index 10327f37374..10b5f850ea3 100644
--- a/be/src/exec/scan/file_scanner_v2.cpp
+++ b/be/src/exec/scan/file_scanner_v2.cpp
@@ -212,6 +212,11 @@ Status rewrite_slot_refs_to_global_index(
 } // namespace
 
 #ifdef BE_TEST
+Status FileScannerV2::TEST_validate_scan_range(const TFileScanRangeParams& 
params,
+                                               const TFileRangeDesc& range) {
+    return _validate_scan_range(params, range);
+}
+
 Status FileScannerV2::TEST_to_file_format(TFileFormatType::type format_type,
                                           format::FileFormat* file_format) {
     return _to_file_format(format_type, file_format);
@@ -273,6 +278,16 @@ bool FileScannerV2::is_supported(const 
TFileScanRangeParams& params, const TFile
     }
 }
 
+Status FileScannerV2::_validate_scan_range(const TFileScanRangeParams& params,
+                                           const TFileRangeDesc& range) {
+    if (!is_supported(params, range)) {
+        return Status::NotSupported(
+                "FileScannerV2 does not support table format {} with file 
format {}",
+                table_format_name(range), 
to_string(get_range_format_type(params, range)));
+    }
+    return Status::OK();
+}
+
 FileScannerV2::FileScannerV2(RuntimeState* state, FileScanLocalState* 
local_state, int64_t limit,
                              std::shared_ptr<SplitSourceConnector> 
split_source,
                              RuntimeProfile* profile, ShardedKVCache* kv_cache,
@@ -321,7 +336,7 @@ Status FileScannerV2::init(RuntimeState* state, const 
VExprContextSPtrs& conjunc
 Status FileScannerV2::_open_impl(RuntimeState* state) {
     RETURN_IF_CANCELLED(state);
     RETURN_IF_ERROR(Scanner::_open_impl(state));
-    RETURN_IF_ERROR(_split_source->get_next(&_first_scan_range, 
&_current_range));
+    RETURN_IF_ERROR(_get_next_scan_range(&_first_scan_range));
     if (_first_scan_range) {
         RETURN_IF_ERROR(_create_table_reader_for_format(_current_range, 
&_table_reader));
         DORIS_CHECK(_table_reader != nullptr);
@@ -331,6 +346,15 @@ Status FileScannerV2::_open_impl(RuntimeState* state) {
     return Status::OK();
 }
 
+Status FileScannerV2::_get_next_scan_range(bool* has_next) {
+    DORIS_CHECK(has_next != nullptr);
+    RETURN_IF_ERROR(_split_source->get_next(has_next, &_current_range));
+    if (*has_next) {
+        RETURN_IF_ERROR(_validate_scan_range(*_params, _current_range));
+    }
+    return Status::OK();
+}
+
 Status FileScannerV2::_get_block_impl(RuntimeState* state, Block* block, bool* 
eof) {
     while (true) {
         RETURN_IF_CANCELLED(state);
@@ -373,7 +397,7 @@ Status FileScannerV2::_prepare_next_split(bool* eos) {
     while (true) {
         bool has_next = _first_scan_range;
         if (!_first_scan_range) {
-            RETURN_IF_ERROR(_split_source->get_next(&has_next, 
&_current_range));
+            RETURN_IF_ERROR(_get_next_scan_range(&has_next));
         }
         _first_scan_range = false;
         if (!has_next || _should_stop) {
diff --git a/be/src/exec/scan/file_scanner_v2.h 
b/be/src/exec/scan/file_scanner_v2.h
index 07e772b4188..66242b610f4 100644
--- a/be/src/exec/scan/file_scanner_v2.h
+++ b/be/src/exec/scan/file_scanner_v2.h
@@ -65,6 +65,8 @@ public:
 
     static bool is_supported(const TFileScanRangeParams& params, const 
TFileRangeDesc& range);
 #ifdef BE_TEST
+    static Status TEST_validate_scan_range(const TFileScanRangeParams& params,
+                                           const TFileRangeDesc& range);
     static Status TEST_to_file_format(TFileFormatType::type format_type,
                                       format::FileFormat* file_format);
     static bool TEST_is_partition_slot(const TFileScanSlotInfo& slot_info,
@@ -104,6 +106,9 @@ protected:
     bool _should_update_load_counters() const override;
 
 private:
+    static Status _validate_scan_range(const TFileScanRangeParams& params,
+                                       const TFileRangeDesc& range);
+    Status _get_next_scan_range(bool* has_next);
     TFileFormatType::type _get_current_format_type() const;
     Status _init_io_ctx();
     Status _init_expr_ctxes();
diff --git a/be/src/exec/scan/split_source_connector.h 
b/be/src/exec/scan/split_source_connector.h
index 320f6f90d0d..5926baff303 100644
--- a/be/src/exec/scan/split_source_connector.h
+++ b/be/src/exec/scan/split_source_connector.h
@@ -17,8 +17,6 @@
 
 #pragma once
 
-#include <functional>
-
 #include "common/config.h"
 #include "core/custom_allocator.h"
 #include "runtime/runtime_state.h"
@@ -47,15 +45,6 @@ public:
 
     virtual TFileScanRangeParams* get_params() = 0;
 
-    virtual bool all_scan_ranges_match(
-            const TFileScanRangeParams& params,
-            const std::function<bool(const TFileScanRangeParams&, const 
TFileRangeDesc&)>&
-                    predicate) {
-        (void)params;
-        (void)predicate;
-        return false;
-    }
-
 protected:
     template <typename T, typename V1 = std::vector<T>, typename V2 = 
std::vector<T>>
         requires(std::is_same_v<std::remove_cvref_t<V1>,
@@ -136,24 +125,6 @@ public:
         throw Exception(
                 Status::FatalError("Unreachable, params is got by 
file_scan_range_params_map"));
     }
-
-    bool all_scan_ranges_match(
-            const TFileScanRangeParams& params,
-            const std::function<bool(const TFileScanRangeParams&, const 
TFileRangeDesc&)>&
-                    predicate) override {
-        if (_scan_ranges.empty()) {
-            return false;
-        }
-        for (const auto& scan_range : _scan_ranges) {
-            const auto& file_scan_range = 
scan_range.scan_range.ext_scan_range.file_scan_range;
-            for (const auto& range : file_scan_range.ranges) {
-                if (!predicate(params, range)) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
 };
 
 /**
diff --git a/be/test/exec/scan/file_scanner_v2_test.cpp 
b/be/test/exec/scan/file_scanner_v2_test.cpp
index 6ce0f4ce4cd..9df8dcb54f4 100644
--- a/be/test/exec/scan/file_scanner_v2_test.cpp
+++ b/be/test/exec/scan/file_scanner_v2_test.cpp
@@ -31,7 +31,7 @@
 #include "core/assert_cast.h"
 #include "core/data_type/data_type_number.h"
 #include "core/data_type/data_type_string.h"
-#include "exec/scan/split_source_connector.h"
+#include "exec/operator/file_scan_operator.h"
 #include "exprs/runtime_filter_expr.h"
 #include "exprs/vdirect_in_predicate.h"
 #include "exprs/vslot_ref.h"
@@ -59,12 +59,6 @@ TFileRangeDesc hudi_range_with_delta_logs() {
     return range;
 }
 
-TScanRangeParams scan_range_param(const TFileRangeDesc& range) {
-    TScanRangeParams params;
-    params.scan_range.ext_scan_range.file_scan_range.ranges.push_back(range);
-    return params;
-}
-
 VExprSPtr slot_ref(int slot_id, int column_id, DataTypePtr type, const 
std::string& name) {
     return VSlotRef::create_shared(slot_id, column_id, -1, std::move(type), 
name);
 }
@@ -109,6 +103,7 @@ TEST(FileScannerV2Test, SupportedFormatMatrix) {
             {"jdbc", TFileFormatType::FORMAT_PARQUET, std::nullopt, false},
             {"", TFileFormatType::FORMAT_JNI, std::nullopt, false},
             {"hive", TFileFormatType::FORMAT_ORC, std::nullopt, true},
+            {"transactional_hive", TFileFormatType::FORMAT_ORC, std::nullopt, 
false},
             {"jdbc", TFileFormatType::FORMAT_JNI, std::nullopt, true},
             {"hive", TFileFormatType::FORMAT_JNI, std::nullopt, false},
             {"", TFileFormatType::FORMAT_CSV_PLAIN, std::nullopt, true},
@@ -132,6 +127,8 @@ TEST(FileScannerV2Test, SupportedFormatMatrix) {
             {"hive", TFileFormatType::FORMAT_ARROW, std::nullopt, false},
             {"", TFileFormatType::FORMAT_ARROW, std::nullopt, false},
             {"", TFileFormatType::FORMAT_WAL, std::nullopt, false},
+            {"", TFileFormatType::FORMAT_ES_HTTP, std::nullopt, false},
+            {"", TFileFormatType::FORMAT_LANCE, std::nullopt, false},
     };
 
     for (const auto& test_case : cases) {
@@ -153,35 +150,54 @@ TEST(FileScannerV2Test, SupportedFormatMatrix) {
     EXPECT_FALSE(FileScannerV2::is_supported(params, 
hudi_range_with_delta_logs()));
 }
 
-// Scenario: SplitSourceConnector should route to FileScannerV2 only when 
every scan range in the
-// source is supported; one unsupported table format or file format must make 
the match fail.
-TEST(FileScannerV2Test, 
SplitSourceAllScanRangesMatchRequiresEveryRangeSupported) {
+TEST(FileScannerV2Test, FileScanLocalStateSelectsV2ForSupportedQueriesOnly) {
+    TQueryOptions query_options;
+    TFileScanRangeParams params;
+    params.__set_format_type(TFileFormatType::FORMAT_PARQUET);
+
+    
EXPECT_FALSE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
false, params));
+
+    query_options.__set_enable_file_scanner_v2(true);
+    
EXPECT_TRUE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
false, params));
+    
EXPECT_FALSE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
true, params));
+
+    const std::vector<TFileFormatType::type> unsupported_formats {
+            TFileFormatType::FORMAT_WAL,
+            TFileFormatType::FORMAT_ES_HTTP,
+            TFileFormatType::FORMAT_LANCE,
+    };
+    for (const auto format : unsupported_formats) {
+        params.__set_format_type(format);
+        EXPECT_FALSE(
+                
FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, false, 
params));
+    }
+
+    params.__set_format_type(TFileFormatType::FORMAT_ORC);
+    TTableFormatFileDesc table_format_params;
+    table_format_params.__set_table_format_type("transactional_hive");
+    params.__set_table_format_params(table_format_params);
+    
EXPECT_FALSE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
false, params));
+
+    params.table_format_params.__set_table_format_type("hive");
+    
EXPECT_TRUE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
false, params));
+
+    query_options.__set_enable_file_scanner_v2(false);
+    
EXPECT_FALSE(FileScanLocalState::TEST_should_use_file_scanner_v2(query_options, 
false, params));
+}
+
+// Scenario: Once FileScannerV2 is selected, an unsupported range must fail 
instead of falling back
+// to FileScanner.
+TEST(FileScannerV2Test, ValidateScanRangeRejectsUnsupportedRange) {
     TFileScanRangeParams params;
     params.__set_format_type(TFileFormatType::FORMAT_PARQUET);
 
     const auto supported = range_with_format("hive", 
TFileFormatType::FORMAT_PARQUET);
-    const auto unsupported_table = range_with_format("lakesoul", 
TFileFormatType::FORMAT_PARQUET);
-    const auto unsupported_format = range_with_format("hive", 
TFileFormatType::FORMAT_WAL);
-
-    LocalSplitSourceConnector all_supported(
-            {scan_range_param(supported),
-             scan_range_param(range_with_format("iceberg", 
TFileFormatType::FORMAT_PARQUET))},
-            1);
-    EXPECT_TRUE(all_supported.all_scan_ranges_match(params, 
FileScannerV2::is_supported));
-
-    LocalSplitSourceConnector hudi_supported(
-            {scan_range_param(supported),
-             scan_range_param(range_with_format("hudi", 
TFileFormatType::FORMAT_PARQUET))},
-            1);
-    EXPECT_TRUE(hudi_supported.all_scan_ranges_match(params, 
FileScannerV2::is_supported));
-
-    LocalSplitSourceConnector table_mismatch(
-            {scan_range_param(supported), 
scan_range_param(unsupported_table)}, 1);
-    EXPECT_FALSE(table_mismatch.all_scan_ranges_match(params, 
FileScannerV2::is_supported));
-
-    LocalSplitSourceConnector format_mismatch(
-            {scan_range_param(supported), 
scan_range_param(unsupported_format)}, 1);
-    EXPECT_FALSE(format_mismatch.all_scan_ranges_match(params, 
FileScannerV2::is_supported));
+    EXPECT_TRUE(FileScannerV2::TEST_validate_scan_range(params, 
supported).ok());
+
+    const auto unsupported = range_with_format("lakesoul", 
TFileFormatType::FORMAT_PARQUET);
+    const auto status = FileScannerV2::TEST_validate_scan_range(params, 
unsupported);
+    EXPECT_TRUE(status.is<ErrorCode::NOT_IMPLEMENTED_ERROR>());
+    EXPECT_NE(status.to_string().find("lakesoul"), std::string::npos);
 }
 
 // Scenario: FileScannerV2 converts only the file formats implemented by 
format_v2 readers and
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/source/HiveScanNode.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/source/HiveScanNode.java
index 5d1bb33f59a..f936eccd59e 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/source/HiveScanNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/hive/source/HiveScanNode.java
@@ -58,6 +58,7 @@ import org.apache.doris.thrift.TFileAttributes;
 import org.apache.doris.thrift.TFileCompressType;
 import org.apache.doris.thrift.TFileFormatType;
 import org.apache.doris.thrift.TFileRangeDesc;
+import org.apache.doris.thrift.TFileScanRangeParams;
 import org.apache.doris.thrift.TFileTextScanRangeParams;
 import org.apache.doris.thrift.TPushAggOp;
 import org.apache.doris.thrift.TTableFormatFileDesc;
@@ -135,6 +136,7 @@ public class HiveScanNode extends FileQueryScanNode {
         super.doInitialize();
 
         if (hmsTable.isHiveTransactionalTable()) {
+            markTransactionalHiveScanParams(params);
             this.hiveTransaction = new 
HiveTransaction(DebugUtil.printId(ConnectContext.get().queryId()),
                     ConnectContext.get().getQualifiedUser(), hmsTable, 
hmsTable.isFullAcidTable());
             Env.getCurrentHiveTransactionMgr().register(hiveTransaction);
@@ -142,6 +144,14 @@ public class HiveScanNode extends FileQueryScanNode {
         }
     }
 
+    static void markTransactionalHiveScanParams(TFileScanRangeParams 
scanParams) {
+        // BE selects the scanner before remote batch splits are fetched, so 
expose the table format
+        // in scan-level params as well as in each range.
+        TTableFormatFileDesc tableFormatParams = new TTableFormatFileDesc();
+        
tableFormatParams.setTableFormatType(TableFormatType.TRANSACTIONAL_HIVE.value());
+        scanParams.setTableFormatParams(tableFormatParams);
+    }
+
     protected List<HivePartition> getPartitions() throws AnalysisException {
         long startTime = System.currentTimeMillis();
         List<HivePartition> resPartitions = Lists.newArrayList();
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index edae724ae16..907f2f0b538 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -3032,9 +3032,10 @@ public class SessionVariable implements Serializable, 
Writable {
     public static final String ENABLE_MC_LIMIT_SPLIT_OPTIMIZATION = 
"enable_mc_limit_split_optimization";
     @VarAttrDef.VarAttr(
             name = ENABLE_EXTERNAL_TABLE_BATCH_MODE,
+            fuzzy = true,
             description = {"使能外表的 batch mode 功能", "Enable the batch mode 
function of the external table."},
             needForward = true)
-    public boolean enableExternalTableBatchMode = false;
+    public boolean enableExternalTableBatchMode = true;
 
     @VarAttrDef.VarAttr(
             name = ENABLE_MC_LIMIT_SPLIT_OPTIMIZATION,
@@ -4001,6 +4002,13 @@ public class SessionVariable implements Serializable, 
Writable {
         this.hiveTextCompression = Util.getRandomString(
                 "gzip", "defalte", "bzip2", "zstd", "lz4", "lzo", "snappy", 
"plain");
 
+        // batch mode
+        this.enableExternalTableBatchMode = random.nextBoolean();
+        if (this.enableExternalTableBatchMode) {
+            this.numPartitionsInBatchMode = Util.getRandomInt(0, 1024, 
Integer.MAX_VALUE);
+            this.numFilesInBatchMode = Util.getRandomInt(0, 1024, 
Integer.MAX_VALUE);
+        }
+
         // common
         this.enableCountPushDownForExternalTable = random.nextBoolean();
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/source/HiveScanNodeTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/source/HiveScanNodeTest.java
index 197d8c1fc61..e0c7b0464e0 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/source/HiveScanNodeTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/datasource/hive/source/HiveScanNodeTest.java
@@ -19,6 +19,7 @@ package org.apache.doris.datasource.hive.source;
 
 import org.apache.doris.analysis.TupleDescriptor;
 import org.apache.doris.analysis.TupleId;
+import org.apache.doris.datasource.TableFormatType;
 import org.apache.doris.datasource.hive.HMSExternalCatalog;
 import org.apache.doris.datasource.hive.HMSExternalTable;
 import org.apache.doris.datasource.hive.HiveExternalMetaCache;
@@ -26,6 +27,7 @@ import 
org.apache.doris.nereids.trees.plans.logical.LogicalFileScan.SelectedPart
 import org.apache.doris.planner.PlanNodeId;
 import org.apache.doris.planner.ScanContext;
 import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.thrift.TFileScanRangeParams;
 
 import com.google.common.collect.ImmutableMap;
 import org.junit.Assert;
@@ -115,6 +117,16 @@ public class HiveScanNodeTest {
         Assert.assertFalse(node.hasPartitionPredicate());
     }
 
+    @Test
+    public void testMarkTransactionalHiveScanParams() {
+        TFileScanRangeParams scanParams = new TFileScanRangeParams();
+        HiveScanNode.markTransactionalHiveScanParams(scanParams);
+
+        Assert.assertTrue(scanParams.isSetTableFormatParams());
+        Assert.assertEquals(TableFormatType.TRANSACTIONAL_HIVE.value(),
+                scanParams.getTableFormatParams().getTableFormatType());
+    }
+
     private HiveScanNode createHiveScanNode() {
         return createHiveScanNode(false);
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
index a8446efb451..5f86bf41f85 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/SessionVariablesTest.java
@@ -171,6 +171,16 @@ public class SessionVariablesTest extends 
TestWithFeService {
         }, varAttr.description());
     }
 
+    @Test
+    public void testExternalTableBatchModeDefaultsAndFuzzyAttribute() throws 
Exception {
+        SessionVariable sessionVar = new SessionVariable();
+        Assertions.assertTrue(sessionVar.getEnableExternalTableBatchMode());
+
+        Field field = 
SessionVariable.class.getDeclaredField("enableExternalTableBatchMode");
+        VarAttrDef.VarAttr varAttr = 
field.getAnnotation(VarAttrDef.VarAttr.class);
+        Assertions.assertTrue(varAttr.fuzzy());
+    }
+
     @Test
     public void testForceEagerAggHintParseWhenSetSessionVariable() throws 
Exception {
         SessionVariable sessionVar = new SessionVariable();


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

Reply via email to