You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by yi...@apache.org on 2026/10/18 04:24:32 UTC

(doris) branch master updated: [refactor](be) Strengthen enum type safety in execution and expressions (#69174)

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

yiguolei 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 fd9f65df735 [refactor](be) Strengthen enum type safety in execution and expressions (#69174)
fd9f65df735 is described below

commit fd9f65df7358491345020051b955aeabd8b70cf9
Author: Mryange <ya...@selectdb.com>
AuthorDate: Sun Oct 18 12:24:24 2026 +0800

    [refactor](be) Strengthen enum type safety in execution and expressions (#69174)
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Problem Summary:
    
    Root cause: unscoped enums implicitly convert to integers, and integer
    parameters accept unrelated enum values, weakening compile-time type
    checking in BE execution and expressions.
    
    Use scoped enums for tablet routing, function state scope, and geometry
    types/statuses. Replace integer Hash Join template parameters and
    runtime-filter/WKB interfaces with their actual enum types, and update
    source, test, grammar, and benchmark callers. Use constexpr constants
    for scalar-group indexes and remove an unused JSON enum. Existing
    encoded values and DateTime value types remain unchanged.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test:
        - [x] No need to test or manual test. Explain why:
    - [x] This is a refactor/code format and no logic has been changed in
    supported execution paths.
            - [x] Previous test can cover this change.
    - Validation: clang-format 16, git diff --check, and
    build-support/check-build-hygiene.sh passed. BE compilation, unit tests,
    regression tests, and clang-tidy have not been run locally.
    - Behavior changed:
        - [x] No.
    - Does this need documentation?
        - [x] No.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 be/benchmark/benchmark_array_range.hpp             |   9 +-
 be/benchmark/benchmark_binary_arithmetic.hpp       |   4 +-
 be/benchmark/benchmark_character_encoding.hpp      |  11 +-
 be/benchmark/variant/benchmark_variant_segment.hpp |  12 +-
 be/src/core/column/column_vector.h                 |   5 +-
 be/src/exec/common/hash_table/join_hash_table.h    |  14 +-
 be/src/exec/common/join_op_utils.h                 |   4 +-
 be/src/exec/operator/hashjoin_build_sink.h         |   2 +-
 be/src/exec/operator/hashjoin_probe_operator.h     |   4 +-
 .../exec/operator/join/process_hash_table_probe.h  |   2 +-
 .../operator/join/process_hash_table_probe_impl.h  |  26 +--
 be/src/exec/operator/scan_operator.cpp             |   2 +-
 be/src/exec/runtime_filter/utils.cpp               |   2 +-
 be/src/exec/runtime_filter/utils.h                 |   2 +-
 be/src/exec/sink/vtablet_finder.h                  |   2 +-
 be/src/exprs/function/ai/ai_functions.h            |   7 +-
 be/src/exprs/function/array/function_array_index.h |   2 +-
 .../function/array/function_array_shuffle.cpp      |   6 +-
 .../cast/variant_v2/cast_variant_to_scalar.cpp     |  28 ++-
 be/src/exprs/function/function_collection_in.h     |   4 +-
 be/src/exprs/function/function_convert_tz.cpp      |   4 +-
 .../function_date_or_datetime_to_string.cpp        |   4 +-
 .../function/function_datetime_string_to_string.h  |   4 +-
 be/src/exprs/function/function_dict_get.cpp        |   4 +-
 be/src/exprs/function/function_dict_get_many.cpp   |   4 +-
 be/src/exprs/function/function_java_udf.cpp        |   6 +-
 be/src/exprs/function/function_jsonb.cpp           |  15 +-
 .../function/function_other_types_to_date.cpp      |   9 +-
 be/src/exprs/function/function_python_udf.cpp      |   6 +-
 be/src/exprs/function/function_regexp.cpp          |  19 +-
 be/src/exprs/function/function_rpc.cpp             |   4 +-
 be/src/exprs/function/function_rpc.h               |   2 +-
 be/src/exprs/function/function_string_concat.h     |   4 +-
 be/src/exprs/function/function_string_misc.cpp     |   6 +-
 be/src/exprs/function/geo/ByteOrderDataInStream.h  |  14 +-
 be/src/exprs/function/geo/ByteOrderValues.cpp      |  40 ++--
 be/src/exprs/function/geo/ByteOrderValues.h        |  18 +-
 be/src/exprs/function/geo/functions_geo.cpp        |  31 +--
 be/src/exprs/function/geo/geo_common.cpp           |  20 +-
 be/src/exprs/function/geo/geo_common.h             |   4 +-
 be/src/exprs/function/geo/geo_tobinary.cpp         |  16 +-
 be/src/exprs/function/geo/geo_tobinary.h           |   4 +-
 be/src/exprs/function/geo/geo_tobinary_type.h      |   9 +-
 be/src/exprs/function/geo/geo_types.cpp            | 226 ++++++++++-----------
 be/src/exprs/function/geo/geo_types.h              |  10 +-
 be/src/exprs/function/geo/machine.h                |   7 +-
 be/src/exprs/function/geo/wkb_parse.cpp            |  51 ++---
 be/src/exprs/function/geo/wkb_parse.h              |   4 +-
 be/src/exprs/function/geo/wkb_parse_ctx.h          |   2 +-
 be/src/exprs/function/geo/wkt_parse.cpp            |   8 +-
 be/src/exprs/function/geo/wkt_parse_ctx.h          |   2 +-
 be/src/exprs/function/geo/wkt_yacc.y               |  11 +-
 be/src/exprs/function/in.h                         |   4 +-
 be/src/exprs/function/like.cpp                     |   6 +-
 be/src/exprs/function/match.cpp                    |   4 +-
 be/src/exprs/function/random.cpp                   |   6 +-
 be/src/exprs/function_context.cpp                  |  10 +-
 be/src/exprs/function_context.h                    |   2 +-
 be/src/exprs/json_functions.h                      |   8 -
 be/src/exprs/vcase_expr.cpp                        |   2 +-
 be/src/exprs/vcast_expr.cpp                        |   2 +-
 be/src/exprs/vectorized_fn_call.cpp                |   2 +-
 be/src/exprs/vexpr.cpp                             |  19 +-
 be/src/exprs/vexpr_context.cpp                     |   8 +-
 be/src/exprs/vexpr_context.h                       |   3 +-
 be/src/exprs/vin_predicate.cpp                     |   8 +-
 be/src/exprs/vmatch_predicate.cpp                  |   5 +-
 be/src/format_v2/expr/cast.cpp                     |   2 +-
 .../format_v2/expr/equality_delete_predicate.cpp   |   2 +-
 be/src/storage/predicate/like_column_predicate.cpp |   2 +-
 be/test/ai/ai_request_executor_test.cpp            |  14 +-
 .../operator/scan_normalize_predicate_test.cpp     |   4 +-
 .../runtime_filter_expr_sampling_test.cpp          |  18 +-
 be/test/exec/sink/vrow_distribution_test.cpp       |   4 +-
 .../function/function_array_cross_product_test.cpp |   8 +-
 .../exprs/function/function_array_cum_sum_test.cpp |   8 +-
 .../function/function_array_except_all_test.cpp    |   8 +-
 .../exprs/function/function_array_range_test.cpp   |   8 +-
 .../exprs/function/function_array_remove_test.cpp  |   8 +-
 .../exprs/function/function_array_shuffle_test.cpp |   8 +-
 .../exprs/function/function_array_split_test.cpp   |   8 +-
 .../exprs/function/function_array_trim_test.cpp    |  13 +-
 be/test/exprs/function/function_array_zip_test.cpp |   8 +-
 .../function/function_constant_argument_test.cpp   |  11 +-
 be/test/exprs/function/function_geo_test.cpp       |  42 ++--
 be/test/exprs/function/function_hash_test.cpp      |   8 +-
 be/test/exprs/function/function_if_test.cpp        |   8 +-
 be/test/exprs/function/function_jsonb_test.cpp     |  36 ++--
 be/test/exprs/function/function_like_test.cpp      |  89 ++++----
 be/test/exprs/function/function_match_test.cpp     |   2 +-
 be/test/exprs/function/function_math_test.cpp      |  16 +-
 be/test/exprs/function/function_test_util.h        |   8 +-
 be/test/exprs/function/function_time_test.cpp      |  16 +-
 be/test/exprs/function/function_varbinary_test.cpp |   8 +-
 .../exprs/function/function_variant_parse_test.cpp |   9 +-
 be/test/exprs/function/geo/functions_geo_test.cpp  |  64 +++---
 be/test/exprs/function/geo/geo_types_test.cpp      |  92 ++++-----
 be/test/exprs/function/geo/wkb_parse_test.cpp      |  33 +--
 be/test/exprs/function/geo/wkt_parse_test.cpp      |   4 +-
 .../lambda_function/array_map_function_test.cpp    |  79 ++++---
 be/test/exprs/vcolumn_ref_test.cpp                 |   3 +-
 be/test/format_v2/expr/delete_predicate_test.cpp   |   5 +-
 .../query/logical/gram/regex_gram_recall_test.cpp  |   9 +-
 be/test/testutil/mock/mock_in_expr.cpp             |   4 +-
 104 files changed, 785 insertions(+), 689 deletions(-)

diff --git a/be/benchmark/benchmark_array_range.hpp b/be/benchmark/benchmark_array_range.hpp
index fa2fc6a1289..16600376149 100644
--- a/be/benchmark/benchmark_array_range.hpp
+++ b/be/benchmark/benchmark_array_range.hpp
@@ -54,12 +54,13 @@ static void BM_ArrayRange(benchmark::State& state) {
             "array_range", block.get_columns_with_type_and_name(), result_type);
     auto context =
             FunctionContext::create_context(nullptr, result_type, {int_type, int_type, int_type});
-    auto status = function->open(context.get(), FunctionContext::FRAGMENT_LOCAL);
+    auto status =
+            function->open(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string().c_str());
         return;
     }
-    status = function->open(context.get(), FunctionContext::THREAD_LOCAL);
+    status = function->open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string().c_str());
         return;
@@ -74,11 +75,11 @@ static void BM_ArrayRange(benchmark::State& state) {
         benchmark::DoNotOptimize(block.get_by_position(3).column);
         benchmark::ClobberMemory();
     }
-    status = function->close(context.get(), FunctionContext::THREAD_LOCAL);
+    status = function->close(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string().c_str());
     }
-    status = function->close(context.get(), FunctionContext::FRAGMENT_LOCAL);
+    status = function->close(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string().c_str());
     }
diff --git a/be/benchmark/benchmark_binary_arithmetic.hpp b/be/benchmark/benchmark_binary_arithmetic.hpp
index 6a3a0156bc2..a1f2e4639d6 100644
--- a/be/benchmark/benchmark_binary_arithmetic.hpp
+++ b/be/benchmark/benchmark_binary_arithmetic.hpp
@@ -64,8 +64,8 @@ struct BinaryArithmeticRunner {
         }
         ctx = FunctionContext::create_context(nullptr, res_type, {type_a, type_b});
         ctx->set_check_overflow_for_decimal(true);
-        if (!func->open(ctx.get(), FunctionContext::FRAGMENT_LOCAL).ok() ||
-            !func->open(ctx.get(), FunctionContext::THREAD_LOCAL).ok()) {
+        if (!func->open(ctx.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok() ||
+            !func->open(ctx.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL).ok()) {
             throw std::runtime_error(name + " open failed");
         }
         block.insert({nullptr, res_type, "result"});
diff --git a/be/benchmark/benchmark_character_encoding.hpp b/be/benchmark/benchmark_character_encoding.hpp
index e6e84a34a3b..a288787cd31 100644
--- a/be/benchmark/benchmark_character_encoding.hpp
+++ b/be/benchmark/benchmark_character_encoding.hpp
@@ -107,24 +107,27 @@ void BM_character_encoding(benchmark::State& state) {
         return;
     }
     auto context = FunctionContext::create_context(nullptr, result_type, {input_type, string_type});
-    auto status = function->open(context.get(), FunctionContext::FRAGMENT_LOCAL);
+    auto status =
+            function->open(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string());
         return;
     }
     Defer close_fragment {[&] {
-        auto close_status = function->close(context.get(), FunctionContext::FRAGMENT_LOCAL);
+        auto close_status =
+                function->close(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
         if (!close_status.ok()) {
             state.SkipWithError(close_status.to_string());
         }
     }};
-    status = function->open(context.get(), FunctionContext::THREAD_LOCAL);
+    status = function->open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
     if (!status.ok()) {
         state.SkipWithError(status.to_string());
         return;
     }
     Defer close_thread {[&] {
-        auto close_status = function->close(context.get(), FunctionContext::THREAD_LOCAL);
+        auto close_status =
+                function->close(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
         if (!close_status.ok()) {
             state.SkipWithError(close_status.to_string());
         }
diff --git a/be/benchmark/variant/benchmark_variant_segment.hpp b/be/benchmark/variant/benchmark_variant_segment.hpp
index 93456038d20..08f058bf07d 100644
--- a/be/benchmark/variant/benchmark_variant_segment.hpp
+++ b/be/benchmark/variant/benchmark_variant_segment.hpp
@@ -369,11 +369,15 @@ Status parse_json_batch(ColumnPtr json, const LayoutConfig& config, uint32_t row
     DORIS_CHECK(function != nullptr);
     block.insert({nullptr, result_type, "result"});
     auto context = FunctionContext::create_context(nullptr, result_type, {input_type});
-    RETURN_IF_ERROR(function->open(context.get(), FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(function->open(context.get(), FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(
+            function->open(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(
+            function->open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL));
     Status status = function->execute(context.get(), block, {0}, 1, rows);
-    Status close_thread = function->close(context.get(), FunctionContext::THREAD_LOCAL);
-    Status close_fragment = function->close(context.get(), FunctionContext::FRAGMENT_LOCAL);
+    Status close_thread =
+            function->close(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
+    Status close_fragment =
+            function->close(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     RETURN_IF_ERROR(status);
     RETURN_IF_ERROR(close_thread);
     RETURN_IF_ERROR(close_fragment);
diff --git a/be/src/core/column/column_vector.h b/be/src/core/column/column_vector.h
index 9591c13f11e..5f27d18566b 100644
--- a/be/src/core/column/column_vector.h
+++ b/be/src/core/column/column_vector.h
@@ -20,6 +20,7 @@
 
 #pragma once
 
+#include <gen_cpp/PlanNodes_types.h>
 #include <glog/logging.h>
 #include <sys/types.h>
 
@@ -54,7 +55,7 @@
 class SipHash;
 
 namespace doris {
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 struct ProcessHashTableProbe;
 }
 
@@ -77,7 +78,7 @@ private:
     using Self = ColumnVector;
     friend class COWHelper<IColumn, Self>;
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     friend struct doris::ProcessHashTableProbe;
 
     struct less;
diff --git a/be/src/exec/common/hash_table/join_hash_table.h b/be/src/exec/common/hash_table/join_hash_table.h
index bc737352f41..1a622ba00aa 100644
--- a/be/src/exec/common/hash_table/join_hash_table.h
+++ b/be/src/exec/common/hash_table/join_hash_table.h
@@ -47,7 +47,7 @@ public:
         return cal_vector_mem(visited) + cal_vector_mem(first) + cal_vector_mem(next);
     }
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     void prepare_build(size_t num_elem, int batch_size, bool has_null_key,
                        uint32_t force_bucket_size) {
         _has_null_key = has_null_key;
@@ -99,7 +99,7 @@ public:
         _keep_null_key = keep_null_key;
     }
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     auto find_batch(const Key* __restrict keys, const uint32_t* __restrict build_idx_map,
                     int probe_idx, uint32_t build_idx, int probe_rows,
                     uint32_t* __restrict probe_idxs, bool& probe_visited,
@@ -196,7 +196,7 @@ public:
         }
     }
 
-    template <int JoinOpType, bool is_mark_join>
+    template <TJoinOp::type JoinOpType, bool is_mark_join>
     bool iterate_map(ColumnOffset32& build_idxs, ColumnFilterHelper* mark_column_helper) const {
         const auto batch_size = max_batch_size;
         const auto elem_num = visited.size();
@@ -241,7 +241,7 @@ private:
         return lhs == rhs;
     }
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     auto _process_null_aware_left_half_join_for_empty_build_side(int probe_idx, int probe_rows,
                                                                  uint32_t* __restrict probe_idxs,
                                                                  uint32_t* __restrict build_idxs) {
@@ -289,7 +289,7 @@ private:
         return std::tuple {probe_idx, 0U, 0U};
     }
 
-    template <int JoinOpType, bool has_null_map>
+    template <TJoinOp::type JoinOpType, bool has_null_map>
     auto _find_batch_left_semi_anti(const Key* __restrict keys,
                                     const uint32_t* __restrict build_idx_map, int probe_idx,
                                     int probe_rows, uint32_t* __restrict probe_idxs,
@@ -317,7 +317,7 @@ private:
         return std::tuple {probe_idx, 0U, matched_cnt};
     }
 
-    template <int JoinOpType, bool only_need_to_match_one>
+    template <TJoinOp::type JoinOpType, bool only_need_to_match_one>
     auto _find_batch_conjunct(const Key* __restrict keys, const uint32_t* __restrict build_idx_map,
                               int probe_idx, uint32_t build_idx, int probe_rows,
                               uint32_t* __restrict probe_idxs, uint32_t* __restrict build_idxs) {
@@ -370,7 +370,7 @@ private:
         return std::tuple {probe_idx, build_idx, matched_cnt};
     }
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     auto _find_batch_inner_outer_join(const Key* __restrict keys,
                                       const uint32_t* __restrict build_idx_map, int probe_idx,
                                       uint32_t build_idx, int probe_rows,
diff --git a/be/src/exec/common/join_op_utils.h b/be/src/exec/common/join_op_utils.h
index fde0344a171..f0b23a702fd 100644
--- a/be/src/exec/common/join_op_utils.h
+++ b/be/src/exec/common/join_op_utils.h
@@ -52,11 +52,11 @@ inline bool is_asof_join(TJoinOp::type join_op) {
     return join_op == TJoinOp::ASOF_LEFT_INNER_JOIN || join_op == TJoinOp::ASOF_LEFT_OUTER_JOIN;
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 inline constexpr bool is_asof_join_op_v =
         JoinOpType == TJoinOp::ASOF_LEFT_INNER_JOIN || JoinOpType == TJoinOp::ASOF_LEFT_OUTER_JOIN;
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 inline constexpr bool is_asof_outer_join_op_v = JoinOpType == TJoinOp::ASOF_LEFT_OUTER_JOIN;
 
 // ASOF JOIN index with inline values for cache-friendly branchless binary search.
diff --git a/be/src/exec/operator/hashjoin_build_sink.h b/be/src/exec/operator/hashjoin_build_sink.h
index e3eed65e01f..fd91ffa721f 100644
--- a/be/src/exec/operator/hashjoin_build_sink.h
+++ b/be/src/exec/operator/hashjoin_build_sink.h
@@ -216,7 +216,7 @@ struct ProcessHashTableBuild {
               _batch_size(batch_size),
               _state(state) {}
 
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     Status run(HashTableContext& hash_table_ctx, ConstNullMapPtr null_map, bool* has_null_key,
                bool short_circuit_for_null, bool with_other_conjuncts) {
         if (null_map) {
diff --git a/be/src/exec/operator/hashjoin_probe_operator.h b/be/src/exec/operator/hashjoin_probe_operator.h
index fbcec288413..3e4c0207159 100644
--- a/be/src/exec/operator/hashjoin_probe_operator.h
+++ b/be/src/exec/operator/hashjoin_probe_operator.h
@@ -73,7 +73,7 @@ private:
     std::vector<uint16_t> _convert_block_to_null(Block& block);
     Status _extract_join_column(Block& block, const std::vector<int>& res_col_ids);
     friend class HashJoinProbeOperatorX;
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     friend struct ProcessHashTableProbe;
 
     // one probe row may match multiple build rows. and we need output whenever we filled a block.
@@ -184,7 +184,7 @@ private:
                         RuntimeProfile::Counter& expr_call_timer,
                         std::vector<int>& res_col_ids) const;
     friend class HashJoinProbeLocalState;
-    template <int JoinOpType>
+    template <TJoinOp::type JoinOpType>
     friend struct ProcessHashTableProbe;
 
     const TJoinDistributionType::type _join_distribution;
diff --git a/be/src/exec/operator/join/process_hash_table_probe.h b/be/src/exec/operator/join/process_hash_table_probe.h
index f39e865f8cd..f326d8e21dd 100644
--- a/be/src/exec/operator/join/process_hash_table_probe.h
+++ b/be/src/exec/operator/join/process_hash_table_probe.h
@@ -39,7 +39,7 @@ using MutableColumns = std::vector<MutableColumnPtr>;
 using NullMap = ColumnUInt8::Container;
 using ConstNullMapPtr = const NullMap*;
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 struct ProcessHashTableProbe {
     ProcessHashTableProbe(HashJoinProbeLocalState* parent, int batch_size);
     ~ProcessHashTableProbe() = default;
diff --git a/be/src/exec/operator/join/process_hash_table_probe_impl.h b/be/src/exec/operator/join/process_hash_table_probe_impl.h
index e9718a2ed13..f0427259901 100644
--- a/be/src/exec/operator/join/process_hash_table_probe_impl.h
+++ b/be/src/exec/operator/join/process_hash_table_probe_impl.h
@@ -66,7 +66,7 @@ static void mock_column_size(auto& col, size_t size) {
     }
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 ProcessHashTableProbe<JoinOpType>::ProcessHashTableProbe(HashJoinProbeLocalState* parent,
                                                          int batch_size)
         : _parent(parent),
@@ -97,7 +97,7 @@ ProcessHashTableProbe<JoinOpType>::ProcessHashTableProbe(HashJoinProbeLocalState
             probe_output_non_lazy_materialized_count >= CONTIGUOUS_INDICES_CHECK_THRESHOLD;
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 void ProcessHashTableProbe<JoinOpType>::build_side_output_column(MutableColumns& mcol,
                                                                  bool is_mark_join) {
     SCOPED_TIMER(_build_side_output_timer);
@@ -156,7 +156,7 @@ void ProcessHashTableProbe<JoinOpType>::build_side_output_column(MutableColumns&
     }
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 bool ProcessHashTableProbe<JoinOpType>::can_transfer_probe_columns_to_output(
         bool probe_indices_are_contiguous) const {
     constexpr bool probe_side_type_unchanged =
@@ -175,7 +175,7 @@ bool ProcessHashTableProbe<JoinOpType>::can_transfer_probe_columns_to_output(
            _parent->_probe_index == _parent->_probe_block.rows() && _parent->_build_index == 0;
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 void ProcessHashTableProbe<JoinOpType>::probe_side_output_column(MutableColumns& mcol) {
     SCOPED_TIMER(_probe_side_output_timer);
     auto& probe_block = _parent->_probe_block;
@@ -209,7 +209,7 @@ void ProcessHashTableProbe<JoinOpType>::probe_side_output_column(MutableColumns&
     }
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 template <typename HashTableType>
 typename HashTableType::State ProcessHashTableProbe<JoinOpType>::_init_probe_side(
         HashTableType& hash_table_ctx, uint32_t probe_rows, const uint8_t* null_map) {
@@ -249,7 +249,7 @@ typename HashTableType::State ProcessHashTableProbe<JoinOpType>::_init_probe_sid
 // Phase 2: Batch binary search — find ASOF best match for each resolved row.
 // This separation improves cache locality since phase 2 accesses AsofIndexGroup
 // data sequentially without interleaving hash chain walks.
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 template <typename HashTableType>
 uint32_t ProcessHashTableProbe<JoinOpType>::
         _find_batch_asof_optimized( // NOLINT(readability-function-cognitive-complexity)
@@ -507,7 +507,7 @@ uint32_t ProcessHashTableProbe<JoinOpType>::
     return matched_cnt;
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 template <typename HashTableType>
 void ProcessHashTableProbe<JoinOpType>::process_direct_return(HashTableType& hash_table_ctx,
                                                               MutableBlock& mutable_block,
@@ -524,7 +524,7 @@ void ProcessHashTableProbe<JoinOpType>::process_direct_return(HashTableType& has
     output_block->swap(mutable_block.to_block());
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 template <typename HashTableType>
 Status ProcessHashTableProbe<JoinOpType>::process(HashTableType& hash_table_ctx,
                                                   const uint8_t* null_map,
@@ -645,7 +645,7 @@ Status ProcessHashTableProbe<JoinOpType>::process(HashTableType& hash_table_ctx,
     return Status::OK();
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 uint32_t ProcessHashTableProbe<JoinOpType>::_process_probe_null_key(uint32_t probe_index) {
     const auto rows = _build_block->rows();
 
@@ -669,7 +669,7 @@ uint32_t ProcessHashTableProbe<JoinOpType>::_process_probe_null_key(uint32_t pro
     return matched_cnt;
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 Status ProcessHashTableProbe<JoinOpType>::finalize_block_with_filter(Block* output_block,
                                                                      size_t filter_column_id,
                                                                      size_t column_to_keep) {
@@ -755,7 +755,7 @@ Status ProcessHashTableProbe<JoinOpType>::finalize_block_with_filter(Block* outp
      * To avoid using nested loop join, we use the mark join conjunct(`t1.k1 = t2.k1`) as the equal join conjunct.
      * So this query will be a "null aware left anti join", which means the equal conjunct's result should be nullable.
      */
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 Status ProcessHashTableProbe<JoinOpType>::do_mark_join_conjuncts(Block* output_block,
                                                                  const uint8_t* null_map) {
     if (JoinOpType != TJoinOp::LEFT_ANTI_JOIN && JoinOpType != TJoinOp::NULL_AWARE_LEFT_ANTI_JOIN &&
@@ -909,7 +909,7 @@ Status ProcessHashTableProbe<JoinOpType>::do_mark_join_conjuncts(Block* output_b
     }
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 Status ProcessHashTableProbe<JoinOpType>::do_other_join_conjuncts(Block* output_block,
                                                                   DorisVector<uint8_t>& visited) {
     // dispose the other join conjunct exec
@@ -1025,7 +1025,7 @@ Status ProcessHashTableProbe<JoinOpType>::do_other_join_conjuncts(Block* output_
     return Status::OK();
 }
 
-template <int JoinOpType>
+template <TJoinOp::type JoinOpType>
 template <typename HashTableType>
 Status ProcessHashTableProbe<
         JoinOpType>::finish_probing( // NOLINT(readability-function-cognitive-complexity)
diff --git a/be/src/exec/operator/scan_operator.cpp b/be/src/exec/operator/scan_operator.cpp
index 0ed2d762953..7a0c4042883 100644
--- a/be/src/exec/operator/scan_operator.cpp
+++ b/be/src/exec/operator/scan_operator.cpp
@@ -744,7 +744,7 @@ Status ScanLocalStateBase::_normalize_in_predicate(
         // begin to push InPredicate value into ColumnValueRange
         auto* state = reinterpret_cast<InState*>(
                 expr_ctx->fn_context(tmp->fn_context_index())
-                        ->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                        ->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
         // xx in (col, xx, xx) should not be push down
         if (!state->use_set) {
diff --git a/be/src/exec/runtime_filter/utils.cpp b/be/src/exec/runtime_filter/utils.cpp
index 3536067edcc..fbabfbf25e3 100644
--- a/be/src/exec/runtime_filter/utils.cpp
+++ b/be/src/exec/runtime_filter/utils.cpp
@@ -75,7 +75,7 @@ RuntimeFilterType get_runtime_filter_type(const TRuntimeFilterDesc* desc) {
 }
 
 // PFilterType -> RuntimeFilterType
-RuntimeFilterType get_type(int filter_type) {
+RuntimeFilterType get_type(PFilterType filter_type) {
     switch (filter_type) {
     case PFilterType::IN_FILTER: {
         return RuntimeFilterType::IN_FILTER;
diff --git a/be/src/exec/runtime_filter/utils.h b/be/src/exec/runtime_filter/utils.h
index 515a5fe7382..aad1b21d629 100644
--- a/be/src/exec/runtime_filter/utils.h
+++ b/be/src/exec/runtime_filter/utils.h
@@ -90,7 +90,7 @@ std::string filter_type_to_string(RuntimeFilterType type);
 RuntimeFilterType get_runtime_filter_type(const TRuntimeFilterDesc* desc);
 
 // PFilterType -> RuntimeFilterType
-RuntimeFilterType get_type(int filter_type);
+RuntimeFilterType get_type(PFilterType filter_type);
 // RuntimeFilterType -> PFilterType
 PFilterType get_type(RuntimeFilterType type);
 
diff --git a/be/src/exec/sink/vtablet_finder.h b/be/src/exec/sink/vtablet_finder.h
index cdcdcc4182d..e47ed5a8728 100644
--- a/be/src/exec/sink/vtablet_finder.h
+++ b/be/src/exec/sink/vtablet_finder.h
@@ -39,7 +39,7 @@ public:
     // which indicates that we should only compute tablet index in the corresponding partition once for the
     // whole time in olap table sink
     // FIND_TABLET_RANDOM_BUCKET is used for V1 adaptive random bucket mode.
-    enum FindTabletMode {
+    enum class FindTabletMode {
         FIND_TABLET_EVERY_ROW,
         FIND_TABLET_EVERY_BATCH,
         FIND_TABLET_EVERY_SINK,
diff --git a/be/src/exprs/function/ai/ai_functions.h b/be/src/exprs/function/ai/ai_functions.h
index 1ded3e94917..b5a78a07cbb 100644
--- a/be/src/exprs/function/ai/ai_functions.h
+++ b/be/src/exprs/function/ai/ai_functions.h
@@ -67,7 +67,7 @@ public:
     bool is_blockable() const override { return true; }
 
     Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             // Release this execution context's cached clients.
             context->set_function_state(scope, nullptr);
         }
@@ -181,11 +181,12 @@ protected:
                                FunctionContext* context) const {
         // Retain the cache across batches/Blocks.
         auto* executor = static_cast<AIRequestExecutor*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         if (executor == nullptr) {
             auto state = std::make_shared<AIRequestExecutor>();
             executor = state.get();
-            context->set_function_state(FunctionContext::THREAD_LOCAL, std::move(state));
+            context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL,
+                                        std::move(state));
         }
         return executor->execute(request_body, response, config, *adapter,
                                  context->state()->get_query_ctx());
diff --git a/be/src/exprs/function/array/function_array_index.h b/be/src/exprs/function/array/function_array_index.h
index ddeb7dec6e0..14e00f2ad7d 100644
--- a/be/src/exprs/function/array/function_array_index.h
+++ b/be/src/exprs/function/array/function_array_index.h
@@ -112,7 +112,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
 
diff --git a/be/src/exprs/function/array/function_array_shuffle.cpp b/be/src/exprs/function/array/function_array_shuffle.cpp
index f5cc6c86554..45422e1c3d6 100644
--- a/be/src/exprs/function/array/function_array_shuffle.cpp
+++ b/be/src/exprs/function/array/function_array_shuffle.cpp
@@ -69,8 +69,8 @@ public:
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
         // The rows of a block draw from one random sequence that starts from the seed, so a
         // per-row seed would be ignored. Reject a non-constant seed instead.
-        if (scope == FunctionContext::THREAD_LOCAL && context->get_num_args() == 2 &&
-            !context->is_col_constant(1)) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL &&
+            context->get_num_args() == 2 && !context->is_col_constant(1)) {
             return Status::InvalidArgument("The seed of {} must be a constant", get_name());
         }
         return Status::OK();
@@ -136,4 +136,4 @@ void register_function_array_shuffle(SimpleFunctionFactory& factory) {
     factory.register_alias("array_shuffle", "shuffle");
 }
 
-} // namespace doris
\ No newline at end of file
+} // namespace doris
diff --git a/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp b/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp
index ca1e858caad..067d4f381cf 100644
--- a/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp
+++ b/be/src/exprs/function/cast/variant_v2/cast_variant_to_scalar.cpp
@@ -56,21 +56,19 @@ namespace {
 
 constexpr size_t DECIMAL_SCALE_COUNT = DataTypeDecimal128::max_precision() + 1;
 
-enum GroupIndex : size_t {
-    INVALID_GROUP = 0,
-    BOOL_GROUP = INVALID_GROUP + 1,
-    INT_GROUP = BOOL_GROUP + 1,
-    FLOAT_GROUP = INT_GROUP + 1,
-    DOUBLE_GROUP = FLOAT_GROUP + 1,
-    DECIMAL_GROUP_BEGIN = DOUBLE_GROUP + 1,
-    DATE_GROUP = DECIMAL_GROUP_BEGIN + DECIMAL_SCALE_COUNT,
-    TIMESTAMP_NTZ_GROUP = DATE_GROUP + 1,
-    TIMESTAMP_NANOS_GROUP = TIMESTAMP_NTZ_GROUP + 1,
-    TIMESTAMP_TZ_GROUP = TIMESTAMP_NANOS_GROUP + 1,
-    STRING_GROUP = TIMESTAMP_TZ_GROUP + 1,
-    UUID_GROUP = STRING_GROUP + 1,
-    GROUP_COUNT = UUID_GROUP + 1,
-};
+constexpr size_t INVALID_GROUP = 0;
+constexpr size_t BOOL_GROUP = INVALID_GROUP + 1;
+constexpr size_t INT_GROUP = BOOL_GROUP + 1;
+constexpr size_t FLOAT_GROUP = INT_GROUP + 1;
+constexpr size_t DOUBLE_GROUP = FLOAT_GROUP + 1;
+constexpr size_t DECIMAL_GROUP_BEGIN = DOUBLE_GROUP + 1;
+constexpr size_t DATE_GROUP = DECIMAL_GROUP_BEGIN + DECIMAL_SCALE_COUNT;
+constexpr size_t TIMESTAMP_NTZ_GROUP = DATE_GROUP + 1;
+constexpr size_t TIMESTAMP_NANOS_GROUP = TIMESTAMP_NTZ_GROUP + 1;
+constexpr size_t TIMESTAMP_TZ_GROUP = TIMESTAMP_NANOS_GROUP + 1;
+constexpr size_t STRING_GROUP = TIMESTAMP_TZ_GROUP + 1;
+constexpr size_t UUID_GROUP = STRING_GROUP + 1;
+constexpr size_t GROUP_COUNT = UUID_GROUP + 1;
 
 struct ScalarGroup {
     DataTypePtr type;
diff --git a/be/src/exprs/function/function_collection_in.h b/be/src/exprs/function/function_collection_in.h
index ade5681ba48..0e5c29bdc8c 100644
--- a/be/src/exprs/function/function_collection_in.h
+++ b/be/src/exprs/function/function_collection_in.h
@@ -94,7 +94,7 @@ public:
 
     // make data in context into a set
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         int num_args = context->get_num_args();
@@ -136,7 +136,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* in_state = reinterpret_cast<CollectionInState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!in_state) {
             return Status::RuntimeError("function context for function '{}' must have Set;",
                                         get_name());
diff --git a/be/src/exprs/function/function_convert_tz.cpp b/be/src/exprs/function/function_convert_tz.cpp
index 71e7267d021..e2feed2006a 100644
--- a/be/src/exprs/function/function_convert_tz.cpp
+++ b/be/src/exprs/function/function_convert_tz.cpp
@@ -101,7 +101,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         std::shared_ptr<ConvertTzState> state = std::make_shared<ConvertTzState>();
@@ -151,7 +151,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* convert_tz_state = reinterpret_cast<ConvertTzState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!convert_tz_state) {
             return Status::RuntimeError(
                     "funciton context for function '{}' must have ConvertTzState;", get_name());
diff --git a/be/src/exprs/function/function_date_or_datetime_to_string.cpp b/be/src/exprs/function/function_date_or_datetime_to_string.cpp
index 9515e90c46f..88c9340622f 100644
--- a/be/src/exprs/function/function_date_or_datetime_to_string.cpp
+++ b/be/src/exprs/function/function_date_or_datetime_to_string.cpp
@@ -92,7 +92,7 @@ public:
     };
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
 
@@ -184,7 +184,7 @@ private:
 
         size_t offset = 0;
         auto* state = reinterpret_cast<LocaleDayMonthNameState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         const char* const* names_ptr = nullptr;
         if constexpr (std::is_same_v<Transform, DayNameImpl<Transform::OpArgType>>) {
             names_ptr = state->day_names;
diff --git a/be/src/exprs/function/function_datetime_string_to_string.h b/be/src/exprs/function/function_datetime_string_to_string.h
index c1d7071fdb9..89e172f1ddd 100644
--- a/be/src/exprs/function/function_datetime_string_to_string.h
+++ b/be/src/exprs/function/function_datetime_string_to_string.h
@@ -84,7 +84,7 @@ public:
     };
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         std::shared_ptr<FormatState> state = std::make_shared<FormatState>();
@@ -160,7 +160,7 @@ public:
                            ColumnString::Chars& res_data,
                            ColumnString::Offsets& res_offsets) const {
         auto* format_state = reinterpret_cast<FormatState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!format_state) {
             return Status::RuntimeError("funciton context for function '{}' must have FormatState;",
                                         get_name());
diff --git a/be/src/exprs/function/function_dict_get.cpp b/be/src/exprs/function/function_dict_get.cpp
index e3e75566320..8ca79599902 100644
--- a/be/src/exprs/function/function_dict_get.cpp
+++ b/be/src/exprs/function/function_dict_get.cpp
@@ -57,7 +57,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         std::shared_ptr<DictGetState> state = std::make_shared<DictGetState>();
@@ -83,7 +83,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* dict_state = reinterpret_cast<DictGetState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!dict_state) {
             return Status::RuntimeError("funciton context for function '{}' must have dict_state;",
                                         get_name());
diff --git a/be/src/exprs/function/function_dict_get_many.cpp b/be/src/exprs/function/function_dict_get_many.cpp
index 9d06fb5b6db..e077041b98c 100644
--- a/be/src/exprs/function/function_dict_get_many.cpp
+++ b/be/src/exprs/function/function_dict_get_many.cpp
@@ -62,7 +62,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         std::shared_ptr<DictGetManyState> state = std::make_shared<DictGetManyState>();
@@ -88,7 +88,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* dict_state = reinterpret_cast<DictGetManyState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!dict_state) {
             return Status::RuntimeError("funciton context for function '{}' must have dict_state;",
                                         get_name());
diff --git a/be/src/exprs/function/function_java_udf.cpp b/be/src/exprs/function/function_java_udf.cpp
index efdfb90ce26..a49f59d486f 100644
--- a/be/src/exprs/function/function_java_udf.cpp
+++ b/be/src/exprs/function/function_java_udf.cpp
@@ -49,7 +49,7 @@ Status JavaFunctionCall::open(FunctionContext* context, FunctionContext::Functio
     if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
         SCOPED_TIMER(context->get_udf_execute_timer());
         std::shared_ptr<JniContext> jni_ctx = std::make_shared<JniContext>();
-        context->set_function_state(FunctionContext::THREAD_LOCAL, jni_ctx);
+        context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL, jni_ctx);
 
         {
             std::string local_location;
@@ -87,7 +87,7 @@ Status JavaFunctionCall::execute_impl(FunctionContext* context, Block& block,
     JNIEnv* env = nullptr;
     RETURN_IF_ERROR(Jni::Env::Get(&env));
     auto* jni_ctx = reinterpret_cast<JniContext*>(
-            context->get_function_state(FunctionContext::THREAD_LOCAL));
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     SCOPED_TIMER(context->get_udf_execute_timer());
     std::unique_ptr<long[]> input_table;
     RETURN_IF_ERROR(JniDataBridge::to_java_table(&block, num_rows, arguments, input_table));
@@ -120,7 +120,7 @@ Status JavaFunctionCall::close(FunctionContext* context,
                                FunctionContext::FunctionStateScope scope) {
     auto close_func = [context]() {
         auto* jni_ctx = reinterpret_cast<JniContext*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         // JNIContext own some resource and its release method depend on JavaFunctionCall
         // has to release the resource before JavaFunctionCall is deconstructed.
         if (jni_ctx) {
diff --git a/be/src/exprs/function/function_jsonb.cpp b/be/src/exprs/function/function_jsonb.cpp
index a649fb0263c..9a01cdf357c 100644
--- a/be/src/exprs/function/function_jsonb.cpp
+++ b/be/src/exprs/function/function_jsonb.cpp
@@ -140,12 +140,13 @@ public:
         if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
             std::shared_ptr<FunctionJsonbParseState> state =
                     std::make_shared<FunctionJsonbParseState>();
-            context->set_function_state(FunctionContext::FRAGMENT_LOCAL, state);
+            context->set_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL, state);
         }
         if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) {
             if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
-                auto* state = reinterpret_cast<FunctionJsonbParseState*>(
-                        context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                auto* state =
+                        reinterpret_cast<FunctionJsonbParseState*>(context->get_function_state(
+                                FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
                 if (state) {
                     if (context->get_num_args() == 2) {
                         if (context->is_col_constant(1)) {
@@ -232,8 +233,8 @@ public:
         const ColumnString* default_value_str_col = nullptr;
         const NullMap* default_value_nullmap = nullptr;
         if constexpr (parse_error_handle_mode == JsonbParseErrorMode::RETURN_VALUE) {
-            auto* state = reinterpret_cast<FunctionJsonbParseState*>(
-                    context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+            auto* state = reinterpret_cast<FunctionJsonbParseState*>(context->get_function_state(
+                    FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
             if (state && state->has_const_default_value) {
                 constant_default_value = state->default_value;
                 default_value_null_const = state->default_is_null;
@@ -2436,7 +2437,7 @@ private:
         LikeState* state = nullptr;
         if (search_is_const) {
             state = reinterpret_cast<LikeState*>(
-                    context->get_function_state(FunctionContext::THREAD_LOCAL));
+                    context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         }
 
         bool is_one = false;
@@ -2528,7 +2529,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope != FunctionContext::THREAD_LOCAL) {
+        if (scope != FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         if (context->is_col_constant(2)) {
diff --git a/be/src/exprs/function/function_other_types_to_date.cpp b/be/src/exprs/function/function_other_types_to_date.cpp
index 19b4452b67c..8867745fbfd 100644
--- a/be/src/exprs/function/function_other_types_to_date.cpp
+++ b/be/src/exprs/function/function_other_types_to_date.cpp
@@ -478,7 +478,7 @@ struct DateTrunc {
     }
 
     static Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
-        if (scope != FunctionContext::THREAD_LOCAL) {
+        if (scope != FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         // The time unit is a constant, but a constant expression such as an arithmetic one is not
@@ -523,7 +523,7 @@ struct DateTrunc {
                     "Illegal second argument column of function date_trunc. now only support "
                     "[second,minute,hour,day,week,month,quarter,year]");
         }
-        context->set_function_state(FunctionContext::THREAD_LOCAL, state);
+        context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL, state);
         return Status::OK();
     }
 
@@ -538,13 +538,14 @@ struct DateTrunc {
             block.replace_by_position(result, std::move(res));
             return Status::OK();
         }
-        if (context->get_function_state(FunctionContext::THREAD_LOCAL) == nullptr) {
+        if (context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL) ==
+            nullptr) {
             RETURN_IF_ERROR(
                     create_state(context, block.get_by_position(arguments[DateArgIsFirst ? 1 : 0])
                                                   .column->get_data_at(0)));
         }
         auto* state = reinterpret_cast<State*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         state->callback_function(datetime_column, *res, input_rows_count, state->timezone,
                                  state->clamp_to_timestamp_ns_min);
         block.replace_by_position(result, std::move(res));
diff --git a/be/src/exprs/function/function_python_udf.cpp b/be/src/exprs/function/function_python_udf.cpp
index 15f8cee1fa7..9f7e40119ed 100644
--- a/be/src/exprs/function/function_python_udf.cpp
+++ b/be/src/exprs/function/function_python_udf.cpp
@@ -97,7 +97,7 @@ Status PythonFunctionCall::open(FunctionContext* context,
         return Status::InternalError("Python UDF client is null");
     }
 
-    context->set_function_state(FunctionContext::THREAD_LOCAL, client);
+    context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL, client);
     LOG(INFO) << fmt::format("Successfully get python UDF client, process: {}",
                              client->print_process());
     return Status::OK();
@@ -107,7 +107,7 @@ Status PythonFunctionCall::execute_impl(FunctionContext* context, Block& block,
                                         const ColumnNumbers& arguments, uint32_t result,
                                         size_t num_rows) const {
     auto client = reinterpret_cast<PythonUDFClient*>(
-            context->get_function_state(FunctionContext::THREAD_LOCAL));
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     if (!client) {
         LOG(WARNING) << "Python UDF client is null";
         return Status::InternalError("Python UDF client is null");
@@ -177,7 +177,7 @@ Status PythonFunctionCall::execute_impl(FunctionContext* context, Block& block,
 Status PythonFunctionCall::close(FunctionContext* context,
                                  FunctionContext::FunctionStateScope scope) {
     auto client = reinterpret_cast<PythonUDFClient*>(
-            context->get_function_state(FunctionContext::THREAD_LOCAL));
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     if (!client) {
         LOG(WARNING) << "Python UDF client is null";
         return Status::InternalError("Python UDF client is null");
diff --git a/be/src/exprs/function/function_regexp.cpp b/be/src/exprs/function/function_regexp.cpp
index c88a64ce802..9457997f14c 100644
--- a/be/src/exprs/function/function_regexp.cpp
+++ b/be/src/exprs/function/function_regexp.cpp
@@ -329,7 +329,7 @@ struct RegexpCountImpl {
     static int _execute_inner_loop(FunctionContext* context, const StringColumnView& str_col,
                                    const StringColumnView& pattern_col, const size_t index_now) {
         auto* re = reinterpret_cast<re2::RE2*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         std::unique_ptr<re2::RE2> scoped_re;
         if (re == nullptr) {
             std::string error_str;
@@ -385,7 +385,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             if (context->is_col_constant(1)) {
                 DCHECK(!context->get_function_state(scope));
                 const auto pattern_col = context->get_constant_col(1)->column_ptr;
@@ -481,7 +481,7 @@ public:
     }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             if (context->is_col_constant(1)) {
                 DCHECK(!context->get_function_state(scope));
                 const auto pattern_col = context->get_constant_col(1)->column_ptr;
@@ -553,7 +553,8 @@ public:
                             // it for later blocks with a different pattern value.
                             if (context->is_col_constant(1) && !context->is_col_constant(3) &&
                                 input_rows_count > 0 &&
-                                context->get_function_state(FunctionContext::THREAD_LOCAL) ==
+                                context->get_function_state(
+                                        FunctionContext::FunctionStateScope::THREAD_LOCAL) ==
                                         nullptr) {
                                 Status st = compile_constant_pattern(
                                         context, argument_columns[1]->get_data_at(0),
@@ -597,7 +598,7 @@ private:
             return Status::InvalidArgument(error_str);
         }
         std::shared_ptr<re2::RE2> re(scoped_re.release());
-        context->set_function_state(FunctionContext::THREAD_LOCAL, re);
+        context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL, re);
         return Status::OK();
     }
 };
@@ -658,7 +659,7 @@ struct RegexpReplaceImpl {
                                     ColumnString::Chars& result_data,
                                     ColumnString::Offsets& result_offset, const size_t index_now) {
         auto* re = reinterpret_cast<re2::RE2*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         std::unique_ptr<re2::RE2> scoped_re; // destroys re if state->re is nullptr
         if (re == nullptr) {
             std::string error_str;
@@ -777,7 +778,7 @@ private:
                                     ColumnString::Offsets& result_offset, NullMap& null_map,
                                     const size_t index_now) {
         auto* engine = reinterpret_cast<RegexpExtractEngine*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         std::unique_ptr<RegexpExtractEngine> scoped_engine;
 
         if (engine == nullptr) {
@@ -963,7 +964,7 @@ private:
                                               const ColumnString* pattern_col, Handler& handler,
                                               const size_t index_now) {
         auto* engine = reinterpret_cast<RegexpExtractEngine*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         std::unique_ptr<RegexpExtractEngine> scoped_engine;
 
         if (engine == nullptr) {
@@ -1014,7 +1015,7 @@ public:
     bool use_default_implementation_for_nulls() const override { return false; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             if (context->is_col_constant(Impl::PATTERN_ARG_IDX)) {
                 DCHECK(!context->get_function_state(scope));
                 const auto pattern_col =
diff --git a/be/src/exprs/function/function_rpc.cpp b/be/src/exprs/function/function_rpc.cpp
index 80f1f051fe2..3ae8b798149 100644
--- a/be/src/exprs/function/function_rpc.cpp
+++ b/be/src/exprs/function/function_rpc.cpp
@@ -97,12 +97,12 @@ FunctionRPC::FunctionRPC(const TFunction& fn, const DataTypes& argument_types,
         : _argument_types(argument_types), _return_type(return_type), _tfn(fn) {}
 
 Status FunctionRPC::open(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         std::shared_ptr<RPCFnImpl> fn = std::make_shared<RPCFnImpl>(_tfn);
         if (!fn->available()) {
             return Status::InternalError("rpc env init error");
         }
-        context->set_function_state(FunctionContext::FRAGMENT_LOCAL, fn);
+        context->set_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL, fn);
     }
     return Status::OK();
 }
diff --git a/be/src/exprs/function/function_rpc.h b/be/src/exprs/function/function_rpc.h
index 9f4472eeb1b..d1a6ba11f38 100644
--- a/be/src/exprs/function/function_rpc.h
+++ b/be/src/exprs/function/function_rpc.h
@@ -73,7 +73,7 @@ public:
     Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                    uint32_t result, size_t input_rows_count) const override {
         auto* fn = reinterpret_cast<RPCFnImpl*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         return fn->vec_call(context, block, arguments, result, input_rows_count);
     }
 };
diff --git a/be/src/exprs/function/function_string_concat.h b/be/src/exprs/function/function_string_concat.h
index 4cac63b6626..6dd043a6033 100644
--- a/be/src/exprs/function/function_string_concat.h
+++ b/be/src/exprs/function/function_string_concat.h
@@ -70,7 +70,7 @@ public:
     }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         std::shared_ptr<ConcatState> state = std::make_shared<ConcatState>();
@@ -112,7 +112,7 @@ public:
             return Status::OK();
         }
         auto* concat_state = reinterpret_cast<ConcatState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!concat_state) {
             return Status::RuntimeError("funciton context for function '{}' must have ConcatState;",
                                         get_name());
diff --git a/be/src/exprs/function/function_string_misc.cpp b/be/src/exprs/function/function_string_misc.cpp
index fdbedae326c..e6bdbb50f38 100644
--- a/be/src/exprs/function/function_string_misc.cpp
+++ b/be/src/exprs/function/function_string_misc.cpp
@@ -409,7 +409,7 @@ public:
     }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope != FunctionContext::THREAD_LOCAL) {
+        if (scope != FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         if (!context->is_col_constant(1)) {
@@ -1538,7 +1538,7 @@ public:
     ColumnNumbers get_arguments_that_are_always_constant() const override { return {1}; }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
 
@@ -1586,7 +1586,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* state = reinterpret_cast<UnicodeNormalizeState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (state == nullptr || state->normalizer == nullptr) {
             return Status::RuntimeError("unicode_normalize function state is not initialized");
         }
diff --git a/be/src/exprs/function/geo/ByteOrderDataInStream.h b/be/src/exprs/function/geo/ByteOrderDataInStream.h
index 3f6bd465c76..b71667d4fa9 100644
--- a/be/src/exprs/function/geo/ByteOrderDataInStream.h
+++ b/be/src/exprs/function/geo/ByteOrderDataInStream.h
@@ -32,11 +32,11 @@ public:
 
     ~ByteOrderDataInStream() = default;
 
-    void setOrder(int order) { byteOrder = order; };
+    void setOrder(ByteOrderValues::EndianType order) { byteOrder = order; };
 
     unsigned char readByte() {
         if (size() < 1) {
-            return GEO_PARSE_WKB_SYNTAX_ERROR;
+            return static_cast<unsigned char>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
         }
         auto ret = buf[0];
         buf++;
@@ -45,7 +45,7 @@ public:
 
     int32_t readInt() {
         if (size() < 4) {
-            return GEO_PARSE_WKB_SYNTAX_ERROR;
+            return static_cast<int32_t>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
         }
         auto ret = ByteOrderValues::getInt(buf, byteOrder);
         buf += 4;
@@ -54,7 +54,7 @@ public:
 
     uint32_t readUnsigned() {
         if (size() < 4) {
-            return GEO_PARSE_WKB_SYNTAX_ERROR;
+            return static_cast<uint32_t>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
         }
         auto ret = ByteOrderValues::getUnsigned(buf, byteOrder);
         buf += 4;
@@ -63,7 +63,7 @@ public:
 
     int64_t readLong() {
         if (size() < 8) {
-            return GEO_PARSE_WKB_SYNTAX_ERROR;
+            return static_cast<int64_t>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
         }
 
         auto ret = ByteOrderValues::getLong(buf, byteOrder);
@@ -73,7 +73,7 @@ public:
 
     double readDouble() {
         if (size() < 8) {
-            return GEO_PARSE_WKB_SYNTAX_ERROR;
+            return static_cast<double>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
         }
         auto ret = ByteOrderValues::getDouble(buf, byteOrder);
         buf += 8;
@@ -83,7 +83,7 @@ public:
     size_t size() const { return static_cast<size_t>(end - buf); };
 
 private:
-    int byteOrder;
+    ByteOrderValues::EndianType byteOrder;
     const unsigned char* buf = nullptr;
     const unsigned char* end = nullptr;
 };
diff --git a/be/src/exprs/function/geo/ByteOrderValues.cpp b/be/src/exprs/function/geo/ByteOrderValues.cpp
index b47321aed4a..c5a52a64f1c 100644
--- a/be/src/exprs/function/geo/ByteOrderValues.cpp
+++ b/be/src/exprs/function/geo/ByteOrderValues.cpp
@@ -23,33 +23,33 @@
 
 namespace doris {
 
-int32_t ByteOrderValues::getInt(const unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+int32_t ByteOrderValues::getInt(const unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         return ((int32_t)(buf[0] & 0xff) << 24) | ((int32_t)(buf[1] & 0xff) << 16) |
                ((int32_t)(buf[2] & 0xff) << 8) | ((int32_t)(buf[3] & 0xff));
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         return ((int32_t)(buf[3] & 0xff) << 24) | ((int32_t)(buf[2] & 0xff) << 16) |
                ((int32_t)(buf[1] & 0xff) << 8) | ((int32_t)(buf[0] & 0xff));
     }
 }
 
-uint32_t ByteOrderValues::getUnsigned(const unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+uint32_t ByteOrderValues::getUnsigned(const unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         return ((uint32_t)(buf[0] & 0xff) << 24) | ((uint32_t)(buf[1] & 0xff) << 16) |
                ((uint32_t)(buf[2] & 0xff) << 8) | ((uint32_t)(buf[3] & 0xff));
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         return ((uint32_t)(buf[3] & 0xff) << 24) | ((uint32_t)(buf[2] & 0xff) << 16) |
                ((uint32_t)(buf[1] & 0xff) << 8) | ((uint32_t)(buf[0] & 0xff));
     }
 }
 
-void ByteOrderValues::putInt(int32_t intValue, unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+void ByteOrderValues::putInt(int32_t intValue, unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         buf[0] = (unsigned char)(intValue >> 24);
         buf[1] = (unsigned char)(intValue >> 16);
         buf[2] = (unsigned char)(intValue >> 8);
         buf[3] = (unsigned char)intValue;
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         buf[3] = (unsigned char)(intValue >> 24);
         buf[2] = (unsigned char)(intValue >> 16);
         buf[1] = (unsigned char)(intValue >> 8);
@@ -57,13 +57,13 @@ void ByteOrderValues::putInt(int32_t intValue, unsigned char* buf, int byteOrder
     }
 }
 
-void ByteOrderValues::putUnsigned(uint32_t intValue, unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+void ByteOrderValues::putUnsigned(uint32_t intValue, unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         buf[0] = (unsigned char)(intValue >> 24);
         buf[1] = (unsigned char)(intValue >> 16);
         buf[2] = (unsigned char)(intValue >> 8);
         buf[3] = (unsigned char)intValue;
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         buf[3] = (unsigned char)(intValue >> 24);
         buf[2] = (unsigned char)(intValue >> 16);
         buf[1] = (unsigned char)(intValue >> 8);
@@ -71,13 +71,13 @@ void ByteOrderValues::putUnsigned(uint32_t intValue, unsigned char* buf, int byt
     }
 }
 
-int64_t ByteOrderValues::getLong(const unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+int64_t ByteOrderValues::getLong(const unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         return (int64_t)(buf[0]) << 56 | (int64_t)(buf[1] & 0xff) << 48 |
                (int64_t)(buf[2] & 0xff) << 40 | (int64_t)(buf[3] & 0xff) << 32 |
                (int64_t)(buf[4] & 0xff) << 24 | (int64_t)(buf[5] & 0xff) << 16 |
                (int64_t)(buf[6] & 0xff) << 8 | (int64_t)(buf[7] & 0xff);
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         return (int64_t)(buf[7]) << 56 | (int64_t)(buf[6] & 0xff) << 48 |
                (int64_t)(buf[5] & 0xff) << 40 | (int64_t)(buf[4] & 0xff) << 32 |
                (int64_t)(buf[3] & 0xff) << 24 | (int64_t)(buf[2] & 0xff) << 16 |
@@ -85,8 +85,8 @@ int64_t ByteOrderValues::getLong(const unsigned char* buf, int byteOrder) {
     }
 }
 
-void ByteOrderValues::putLong(int64_t longValue, unsigned char* buf, int byteOrder) {
-    if (byteOrder == ENDIAN_BIG) {
+void ByteOrderValues::putLong(int64_t longValue, unsigned char* buf, EndianType byteOrder) {
+    if (byteOrder == EndianType::ENDIAN_BIG) {
         buf[0] = (unsigned char)(longValue >> 56);
         buf[1] = (unsigned char)(longValue >> 48);
         buf[2] = (unsigned char)(longValue >> 40);
@@ -95,7 +95,7 @@ void ByteOrderValues::putLong(int64_t longValue, unsigned char* buf, int byteOrd
         buf[5] = (unsigned char)(longValue >> 16);
         buf[6] = (unsigned char)(longValue >> 8);
         buf[7] = (unsigned char)longValue;
-    } else { // ENDIAN_LITTLE
+    } else { // EndianType::ENDIAN_LITTLE
         buf[0] = (unsigned char)longValue;
         buf[1] = (unsigned char)(longValue >> 8);
         buf[2] = (unsigned char)(longValue >> 16);
@@ -107,14 +107,14 @@ void ByteOrderValues::putLong(int64_t longValue, unsigned char* buf, int byteOrd
     }
 }
 
-double ByteOrderValues::getDouble(const unsigned char* buf, int byteOrder) {
+double ByteOrderValues::getDouble(const unsigned char* buf, EndianType byteOrder) {
     int64_t longValue = getLong(buf, byteOrder);
     double ret;
     std::memcpy(&ret, &longValue, sizeof(double));
     return ret;
 }
 
-void ByteOrderValues::putDouble(double doubleValue, unsigned char* buf, int byteOrder) {
+void ByteOrderValues::putDouble(double doubleValue, unsigned char* buf, EndianType byteOrder) {
     int64_t longValue;
     std::memcpy(&longValue, &doubleValue, sizeof(double));
     putLong(longValue, buf, byteOrder);
diff --git a/be/src/exprs/function/geo/ByteOrderValues.h b/be/src/exprs/function/geo/ByteOrderValues.h
index 50915953e0c..481e6704bb6 100644
--- a/be/src/exprs/function/geo/ByteOrderValues.h
+++ b/be/src/exprs/function/geo/ByteOrderValues.h
@@ -34,19 +34,19 @@ namespace doris {
  */
 class ByteOrderValues {
 public:
-    enum EndianType { ENDIAN_BIG = 0, ENDIAN_LITTLE = 1 };
+    enum class EndianType { ENDIAN_BIG = 0, ENDIAN_LITTLE = 1 };
 
-    static int32_t getInt(const unsigned char* buf, int byteOrder);
-    static void putInt(int32_t intValue, unsigned char* buf, int byteOrder);
+    static int32_t getInt(const unsigned char* buf, EndianType byteOrder);
+    static void putInt(int32_t intValue, unsigned char* buf, EndianType byteOrder);
 
-    static uint32_t getUnsigned(const unsigned char* buf, int byteOrder);
-    static void putUnsigned(uint32_t intValue, unsigned char* buf, int byteOrder);
+    static uint32_t getUnsigned(const unsigned char* buf, EndianType byteOrder);
+    static void putUnsigned(uint32_t intValue, unsigned char* buf, EndianType byteOrder);
 
-    static int64_t getLong(const unsigned char* buf, int byteOrder);
-    static void putLong(int64_t longValue, unsigned char* buf, int byteOrder);
+    static int64_t getLong(const unsigned char* buf, EndianType byteOrder);
+    static void putLong(int64_t longValue, unsigned char* buf, EndianType byteOrder);
 
-    static double getDouble(const unsigned char* buf, int byteOrder);
-    static void putDouble(double doubleValue, unsigned char* buf, int byteOrder);
+    static double getDouble(const unsigned char* buf, EndianType byteOrder);
+    static void putDouble(double doubleValue, unsigned char* buf, EndianType byteOrder);
 };
 
 } // namespace doris
diff --git a/be/src/exprs/function/geo/functions_geo.cpp b/be/src/exprs/function/geo/functions_geo.cpp
index 48177452c18..8f53b884eb9 100644
--- a/be/src/exprs/function/geo/functions_geo.cpp
+++ b/be/src/exprs/function/geo/functions_geo.cpp
@@ -64,7 +64,7 @@ struct StPoint {
         std::string buf;
         for (int row = 0; row < size; ++row) {
             auto cur_res = point.from_coord(x_col.value_at(row), y_col.value_at(row));
-            if (cur_res != GEO_PARSE_OK) {
+            if (cur_res != GeoParseStatus::GEO_PARSE_OK) {
                 null_map_data[row] = 1;
                 res->insert_default();
                 continue;
@@ -483,7 +483,7 @@ struct StCircle {
             auto radius_value = radius.value_at(row);
 
             auto value = circle.init(lng_value, lat_value, radius_value);
-            if (value != GEO_PARSE_OK) {
+            if (value != GeoParseStatus::GEO_PARSE_OK) {
                 null_map_data[row] = 1;
                 res->insert_default();
                 continue;
@@ -566,37 +566,37 @@ struct StWithinFunc {
 
 struct StGeometryFromText {
     static constexpr auto NAME = "st_geometryfromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_ANY;
 };
 
 struct StGeomFromText {
     static constexpr auto NAME = "st_geomfromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_ANY;
 };
 
 struct StLineFromText {
     static constexpr auto NAME = "st_linefromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_LINE_STRING;
 };
 
 struct StLineStringFromText {
     static constexpr auto NAME = "st_linestringfromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_LINE_STRING;
 };
 
 struct StPolygon {
     static constexpr auto NAME = "st_polygon";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_POLYGON;
 };
 
 struct StPolyFromText {
     static constexpr auto NAME = "st_polyfromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_POLYGON;
 };
 
 struct StPolygonFromText {
     static constexpr auto NAME = "st_polygonfromtext";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_POLYGON;
 };
 
 template <typename Impl>
@@ -618,8 +618,9 @@ struct StGeoFromText {
         for (int row = 0; row < size; ++row) {
             auto value = geo->get_data_at(row);
             auto shape = GeoShape::from_wkt(value.data, value.size, status);
-            if (shape == nullptr || status != GEO_PARSE_OK ||
-                (Impl::shape_type != GEO_SHAPE_ANY && shape->type() != Impl::shape_type)) {
+            if (shape == nullptr || status != GeoParseStatus::GEO_PARSE_OK ||
+                (Impl::shape_type != GeoShapeType::GEO_SHAPE_ANY &&
+                 shape->type() != Impl::shape_type)) {
                 null_map_data[row] = 1;
                 res->insert_default();
                 continue;
@@ -636,12 +637,12 @@ struct StGeoFromText {
 
 struct StGeometryFromWKB {
     static constexpr auto NAME = "st_geometryfromwkb";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_ANY;
 };
 
 struct StGeomFromWKB {
     static constexpr auto NAME = "st_geomfromwkb";
-    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+    static constexpr GeoShapeType shape_type = GeoShapeType::GEO_SHAPE_ANY;
 };
 
 template <typename Impl>
@@ -663,7 +664,7 @@ struct StGeoFromWkb {
         for (int row = 0; row < size; ++row) {
             auto value = geo->get_data_at(row);
             std::unique_ptr<GeoShape> shape = GeoShape::from_wkb(value.data, value.size, status);
-            if (shape == nullptr || status != GEO_PARSE_OK) {
+            if (shape == nullptr || status != GeoParseStatus::GEO_PARSE_OK) {
                 null_map_data[row] = 1;
                 res->insert_default();
                 continue;
@@ -1044,7 +1045,7 @@ public:
                 continue;
             }
 
-            if (shape->type() == GEO_SHAPE_MULTI_POLYGON) {
+            if (shape->type() == GeoShapeType::GEO_SHAPE_MULTI_POLYGON) {
                 auto* multi_polygon = static_cast<GeoMultiPolygon*>(shape.get());
                 const auto& polygons = multi_polygon->polygons();
 
diff --git a/be/src/exprs/function/geo/geo_common.cpp b/be/src/exprs/function/geo/geo_common.cpp
index 3b6f9211a16..cd1f1b2790c 100644
--- a/be/src/exprs/function/geo/geo_common.cpp
+++ b/be/src/exprs/function/geo/geo_common.cpp
@@ -21,25 +21,25 @@ namespace doris {
 
 std::string to_string(GeoParseStatus status) {
     switch (status) {
-    case GEO_PARSE_OK:
+    case GeoParseStatus::GEO_PARSE_OK:
         return "OK";
-    case GEO_PARSE_COORD_INVALID:
+    case GeoParseStatus::GEO_PARSE_COORD_INVALID:
         return "Coordinate invalid";
-    case GEO_PARSE_LOOP_NOT_CLOSED:
+    case GeoParseStatus::GEO_PARSE_LOOP_NOT_CLOSED:
         return "Loop is not closed";
-    case GEO_PARSE_LOOP_LACK_VERTICES:
+    case GeoParseStatus::GEO_PARSE_LOOP_LACK_VERTICES:
         return "Loop lack enough vertices";
-    case GEO_PARSE_LOOP_INVALID:
+    case GeoParseStatus::GEO_PARSE_LOOP_INVALID:
         return "Loop invalid";
-    case GEO_PARSE_POLYGON_NOT_HOLE:
+    case GeoParseStatus::GEO_PARSE_POLYGON_NOT_HOLE:
         return "Loop not contained in the first loop";
-    case GEO_PARSE_POLYLINE_LACK_VERTICES:
+    case GeoParseStatus::GEO_PARSE_POLYLINE_LACK_VERTICES:
         return "Line string lack vertices";
-    case GEO_PARSE_POLYLINE_INVALID:
+    case GeoParseStatus::GEO_PARSE_POLYLINE_INVALID:
         return "Line string invalid";
-    case GEO_PARSE_CIRCLE_INVALID:
+    case GeoParseStatus::GEO_PARSE_CIRCLE_INVALID:
         return "Circle invalid";
-    case GEO_PARSE_WKT_SYNTAX_ERROR:
+    case GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR:
         return "WKT syntax error";
     default:
         return "Unknown";
diff --git a/be/src/exprs/function/geo/geo_common.h b/be/src/exprs/function/geo/geo_common.h
index f4c78dff190..96a3cb3a14d 100644
--- a/be/src/exprs/function/geo/geo_common.h
+++ b/be/src/exprs/function/geo/geo_common.h
@@ -22,7 +22,7 @@
 
 namespace doris {
 
-enum GeoShapeType {
+enum class GeoShapeType {
     GEO_SHAPE_ANY = 0,
     GEO_SHAPE_POINT = 1,
     GEO_SHAPE_LINE_STRING = 2,
@@ -33,7 +33,7 @@ enum GeoShapeType {
     GEO_SHAPE_CIRCLE = 7,
 };
 
-enum GeoParseStatus {
+enum class GeoParseStatus {
     GEO_PARSE_OK = 0,
     GEO_PARSE_COORD_INVALID = 1,
     GEO_PARSE_LOOP_NOT_CLOSED = 2,
diff --git a/be/src/exprs/function/geo/geo_tobinary.cpp b/be/src/exprs/function/geo/geo_tobinary.cpp
index 1b34e66111c..2c507cae544 100644
--- a/be/src/exprs/function/geo/geo_tobinary.cpp
+++ b/be/src/exprs/function/geo/geo_tobinary.cpp
@@ -52,13 +52,13 @@ bool toBinary::geo_tobinary(GeoShape* shape, std::string* result) {
 
 bool toBinary::write(GeoShape* shape, ToBinaryContext* ctx) {
     switch (shape->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         return writeGeoPoint((GeoPoint*)(shape), ctx);
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         return writeGeoLine((GeoLine*)(shape), ctx);
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         return writeGeoPolygon((GeoPolygon*)(shape), ctx);
     }
     default:
@@ -98,17 +98,17 @@ bool toBinary::writeGeoPolygon(doris::GeoPolygon* polygon, ToBinaryContext* ctx)
 
 void toBinary::writeByteOrder(ToBinaryContext* ctx) {
     ctx->byteOrder = getMachineByteOrder();
-    if (ctx->byteOrder == 1) {
-        ctx->buf[0] = byteOrder::wkbNDR;
+    if (ctx->byteOrder == ByteOrderValues::EndianType::ENDIAN_LITTLE) {
+        ctx->buf[0] = static_cast<unsigned char>(byteOrder::wkbNDR);
     } else {
-        ctx->buf[0] = byteOrder::wkbXDR;
+        ctx->buf[0] = static_cast<unsigned char>(byteOrder::wkbXDR);
     }
 
     ctx->outStream->write(reinterpret_cast<char*>(ctx->buf), 1);
 }
 
-void toBinary::writeGeometryType(int typeId, ToBinaryContext* ctx) {
-    writeInt(typeId, ctx);
+void toBinary::writeGeometryType(wkbType typeId, ToBinaryContext* ctx) {
+    writeInt(static_cast<int>(typeId), ctx);
 }
 
 void toBinary::writeInt(int val, ToBinaryContext* ctx) {
diff --git a/be/src/exprs/function/geo/geo_tobinary.h b/be/src/exprs/function/geo/geo_tobinary.h
index 3d4bd1dca1d..6968d80cda4 100644
--- a/be/src/exprs/function/geo/geo_tobinary.h
+++ b/be/src/exprs/function/geo/geo_tobinary.h
@@ -25,6 +25,8 @@ struct ToBinaryContext;
 
 namespace doris {
 
+enum class wkbType : int;
+
 class GeoShape;
 class GeoPoint;
 class GeoLine;
@@ -47,7 +49,7 @@ private:
 
     static void writeByteOrder(ToBinaryContext* ctx);
 
-    static void writeGeometryType(int geometryType, ToBinaryContext* ctx);
+    static void writeGeometryType(wkbType geometryType, ToBinaryContext* ctx);
 
     static void writeInt(int intValue, ToBinaryContext* ctx);
 
diff --git a/be/src/exprs/function/geo/geo_tobinary_type.h b/be/src/exprs/function/geo/geo_tobinary_type.h
index 0f3513be88d..e94100cb690 100644
--- a/be/src/exprs/function/geo/geo_tobinary_type.h
+++ b/be/src/exprs/function/geo/geo_tobinary_type.h
@@ -17,11 +17,13 @@
 #pragma once
 #include <memory>
 
+#include "exprs/function/geo/ByteOrderValues.h"
+
 namespace doris {
 
-enum byteOrder { wkbXDR = 0, wkbNDR = 1 };
+enum class byteOrder { wkbXDR = 0, wkbNDR = 1 };
 
-enum wkbType {
+enum class wkbType : int {
     wkbPoint = 1,
     wkbLine = 2,
     wkbPolygon = 3,
@@ -34,8 +36,7 @@ enum wkbType {
 } // namespace doris
 
 struct ToBinaryContext {
-    // WKBConstants::wkbwkbXDR | WKBConstants::wkbNDR
-    int byteOrder;
+    doris::ByteOrderValues::EndianType byteOrder;
 
     unsigned char buf[8];
 
diff --git a/be/src/exprs/function/geo/geo_types.cpp b/be/src/exprs/function/geo/geo_types.cpp
index 6a48a3dc36e..8ecbcb56b43 100644
--- a/be/src/exprs/function/geo/geo_types.cpp
+++ b/be/src/exprs/function/geo/geo_types.cpp
@@ -77,15 +77,15 @@ static inline bool is_valid_lng_lat(double lng, double lat) {
     return std::abs(lng) <= 180 && std::abs(lat) <= 90;
 }
 
-// Return GEO_PARSE_OK, if and only if this can be converted to a valid S2Point
+// Return GeoParseStatus::GEO_PARSE_OK, if and only if this can be converted to a valid S2Point
 static inline GeoParseStatus to_s2point(double lng, double lat, S2Point* point) {
     if (!is_valid_lng_lat(lng, lat)) {
-        return GEO_PARSE_COORD_INVALID;
+        return GeoParseStatus::GEO_PARSE_COORD_INVALID;
     }
     S2LatLng ll = S2LatLng::FromDegrees(lat, lng);
     DCHECK(ll.is_valid()) << "invalid point, lng=" << lng << ", lat=" << lat;
     *point = ll.ToPoint();
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 double project_distance(const S2Point& point, const S2Point& lineStart, const S2Point& lineEnd) {
@@ -323,13 +323,13 @@ static GeoParseStatus to_s2loop(const GeoCoordinateList& coords, std::unique_ptr
     std::vector<S2Point> points(coords.list.size());
     for (int i = 0; i < coords.list.size(); ++i) {
         auto res = to_s2point(coords.list[i], &points[i]);
-        if (res != GEO_PARSE_OK) {
+        if (res != GeoParseStatus::GEO_PARSE_OK) {
             return res;
         }
     }
     // 2. check if it is a closed loop
     if (!is_loop_closed(points)) {
-        return GEO_PARSE_LOOP_NOT_CLOSED;
+        return GeoParseStatus::GEO_PARSE_LOOP_NOT_CLOSED;
     }
     // 3. remove duplicate points
     remove_duplicate_points(&points);
@@ -337,14 +337,14 @@ static GeoParseStatus to_s2loop(const GeoCoordinateList& coords, std::unique_ptr
     points.resize(points.size() - 1);
     // 5. check if there is enough point
     if (points.size() < 3) {
-        return GEO_PARSE_LOOP_LACK_VERTICES;
+        return GeoParseStatus::GEO_PARSE_LOOP_LACK_VERTICES;
     }
     loop->reset(new S2Loop(points));
     if (!(*loop)->IsValid()) {
-        return GEO_PARSE_LOOP_INVALID;
+        return GeoParseStatus::GEO_PARSE_LOOP_INVALID;
     }
     (*loop)->Normalize();
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 static GeoParseStatus to_s2polyline(const GeoCoordinateList& coords,
@@ -353,7 +353,7 @@ static GeoParseStatus to_s2polyline(const GeoCoordinateList& coords,
     std::vector<S2Point> points(coords.list.size());
     for (int i = 0; i < coords.list.size(); ++i) {
         auto res = to_s2point(coords.list[i], &points[i]);
-        if (res != GEO_PARSE_OK) {
+        if (res != GeoParseStatus::GEO_PARSE_OK) {
             return res;
         }
     }
@@ -361,13 +361,13 @@ static GeoParseStatus to_s2polyline(const GeoCoordinateList& coords,
     remove_duplicate_points(&points);
     // 3. check if there is enough point
     if (points.size() < 2) {
-        return GEO_PARSE_POLYLINE_LACK_VERTICES;
+        return GeoParseStatus::GEO_PARSE_POLYLINE_LACK_VERTICES;
     }
     polyline->reset(new S2Polyline(points));
     if (!(*polyline)->IsValid()) {
-        return GEO_PARSE_POLYLINE_INVALID;
+        return GeoParseStatus::GEO_PARSE_POLYLINE_INVALID;
     }
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 static GeoParseStatus to_s2polygon(const GeoCoordinateListList& coords_list,
@@ -375,15 +375,15 @@ static GeoParseStatus to_s2polygon(const GeoCoordinateListList& coords_list,
     std::vector<std::unique_ptr<S2Loop>> loops(coords_list.list.size());
     for (int i = 0; i < coords_list.list.size(); ++i) {
         auto res = to_s2loop(*coords_list.list[i], &loops[i]);
-        if (res != GEO_PARSE_OK) {
+        if (res != GeoParseStatus::GEO_PARSE_OK) {
             return res;
         }
         if (i != 0 && !(loops[0]->Contains(*loops[i]))) {
-            return GEO_PARSE_POLYGON_NOT_HOLE;
+            return GeoParseStatus::GEO_PARSE_POLYGON_NOT_HOLE;
         }
     }
     polygon->reset(new S2Polygon(std::move(loops)));
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 bool GeoShape::decode_from(const void* data, size_t size) {
@@ -392,7 +392,7 @@ bool GeoShape::decode_from(const void* data, size_t size) {
     }
     char reserved_byte = ((const char*)data)[0];
     char type_byte = ((const char*)data)[1];
-    if (reserved_byte != 0X00 || type_byte != type()) {
+    if (reserved_byte != 0X00 || type_byte != static_cast<char>(type())) {
         return false;
     }
     return decode((const char*)data + 2, size - 2);
@@ -401,7 +401,7 @@ bool GeoShape::decode_from(const void* data, size_t size) {
 void GeoShape::encode_to(std::string* buf) {
     // reserve a byte for future use
     buf->push_back(0X00);
-    buf->push_back((char)type());
+    buf->push_back(static_cast<char>(type()));
     encode(buf);
 }
 
@@ -433,24 +433,24 @@ std::unique_ptr<GeoShape> GeoShape::from_encoded(const void* ptr, size_t size) {
         return nullptr;
     }
     std::unique_ptr<GeoShape> shape;
-    switch (((const char*)ptr)[1]) {
-    case GEO_SHAPE_POINT: {
+    switch (static_cast<GeoShapeType>(((const char*)ptr)[1])) {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         shape = GeoPoint::create_unique();
         break;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         shape = GeoLine::create_unique();
         break;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         shape = GeoPolygon::create_unique();
         break;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         shape = GeoCircle::create_unique();
         break;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         shape = GeoMultiPolygon::create_unique();
         break;
     }
@@ -530,24 +530,24 @@ std::vector<std::unique_ptr<GeoCoordinateListList>> GeoMultiPolygon::to_coords()
 
 bool GeoPoint::intersects(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         // points and points are considered to intersect when they are equal
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         return *_point == *point->point();
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         return line->intersects(this);
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         return polygon->intersects(this);
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         return multi_polygon->intersects(this);
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->intersects(this);
     }
@@ -562,23 +562,23 @@ bool GeoPoint::disjoint(const GeoShape* rhs) const {
 
 bool GeoPoint::touches(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         // always returns false because the point has no boundaries
         return false;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         return line->touches(this);
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         return polygon->touches(this);
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         return multi_polygon->touches(this);
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->touches(this);
     }
@@ -693,20 +693,20 @@ GeoParseStatus GeoLine::from_coords(const GeoCoordinateList& list) {
 
 bool GeoLine::intersects(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         return compute_distance_to_line(*point->point(), _polyline.get()) < TOLERANCE;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         return is_segments_intersect(_polyline->vertex(0), _polyline->vertex(1),
                                      line->polyline()->vertex(0), line->polyline()->vertex(1));
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         return polygon->polygon()->Intersects(*_polyline);
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         for (const auto& polygon : multi_polygon->polygons()) {
             if (polygon->intersects(this)) {
@@ -715,7 +715,7 @@ bool GeoLine::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->intersects(this);
     }
@@ -730,7 +730,7 @@ bool GeoLine::disjoint(const GeoShape* rhs) const {
 
 bool GeoLine::touches(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         const S2Point& start = _polyline->vertex(0);
         const S2Point& end = _polyline->vertex(_polyline->num_vertices() - 1);
@@ -740,7 +740,7 @@ bool GeoLine::touches(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* other = assert_cast<const GeoLine*>(rhs);
 
         const S2Point& p1 = _polyline->vertex(0);
@@ -750,15 +750,15 @@ bool GeoLine::touches(const GeoShape* rhs) const {
         const S2Point& p4 = other->polyline()->vertex(1);
         return is_line_touches_line(p1, p2, p3, p4);
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         return polygon->touches(this);
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         return multi_polygon->touches(this);
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->touches(this);
     }
@@ -842,14 +842,14 @@ std::string GeoPolygon::as_wkt() const {
 
 bool GeoPolygon::intersects(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         if (is_point_in_polygon(*point->point(), _polygon.get())) {
             return true;
         }
         return polygon_touch_point(_polygon.get(), point->point());
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         std::vector<std::unique_ptr<S2Polyline>> intersect_lines =
                 _polygon->IntersectWithPolyline(*line->polyline());
@@ -874,7 +874,7 @@ bool GeoPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = assert_cast<const GeoPolygon*>(rhs);
         // When two polygons intersect only at the boundary, s2geometry may not return the correct result.
         if (!_polygon->Intersects(*other->polygon())) {
@@ -882,7 +882,7 @@ bool GeoPolygon::intersects(const GeoShape* rhs) const {
         }
         return true;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         for (const auto& other : multi_polygon->polygons()) {
             if (this->intersects(other.get())) {
@@ -891,7 +891,7 @@ bool GeoPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->intersects(this);
     }
@@ -948,11 +948,11 @@ bool GeoPolygon::polygon_touch_polygon(const S2Polygon* polygon1, const S2Polygo
 
 bool GeoPolygon::touches(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         return polygon_touch_point(_polygon.get(), point->point());
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         std::vector<std::unique_ptr<S2Polyline>> intersect_lines =
                 _polygon->IntersectWithPolyline(*line->polyline());
@@ -1001,7 +1001,7 @@ bool GeoPolygon::touches(const GeoShape* rhs) const {
         }
         return true;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = assert_cast<const GeoPolygon*>(rhs);
         const S2Polygon* polygon1 = _polygon.get();
         const S2Polygon* polygon2 = other->polygon();
@@ -1012,7 +1012,7 @@ bool GeoPolygon::touches(const GeoShape* rhs) const {
         return (intersection->GetArea() < S1Angle::Radians(TOLERANCE).radians() &&
                 polygon_touch_polygon(polygon1, polygon2));
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         bool has_touches = false;
         for (const auto& other : multi_polygon->polygons()) {
@@ -1025,7 +1025,7 @@ bool GeoPolygon::touches(const GeoShape* rhs) const {
         }
         return has_touches;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->touches(this);
     }
@@ -1036,7 +1036,7 @@ bool GeoPolygon::touches(const GeoShape* rhs) const {
 
 bool GeoPolygon::contains(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = (const GeoPoint*)rhs;
         if (!_polygon->Contains(*point->point())) {
             return false;
@@ -1055,7 +1055,7 @@ bool GeoPolygon::contains(const GeoShape* rhs) const {
         }
         return true;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = (const GeoLine*)rhs;
 
         // solve the problem caused by the `Contains(const S2Polyline)` in the S2 library
@@ -1079,11 +1079,11 @@ bool GeoPolygon::contains(const GeoShape* rhs) const {
 
         return _polygon->Contains(*line->polyline());
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = (const GeoPolygon*)rhs;
         return _polygon->Contains(*other->polygon());
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = (const GeoMultiPolygon*)rhs;
         for (const auto& other : multi_polygon->polygons()) {
             if (!this->contains(other.get())) {
@@ -1114,7 +1114,7 @@ GeoParseStatus GeoMultiPolygon::from_coords(const std::vector<GeoCoordinateListL
     for (const auto& coords_list : list) {
         std::unique_ptr<GeoPolygon> polygon = GeoPolygon::create_unique();
         auto status = polygon->from_coords(coords_list);
-        if (status != GEO_PARSE_OK) {
+        if (status != GeoParseStatus::GEO_PARSE_OK) {
             return status;
         }
         _polygons.push_back(std::move(polygon));
@@ -1128,7 +1128,7 @@ GeoParseStatus GeoMultiPolygon::check_self_intersection() {
         for (int j = i + 1; j < _polygons.size(); ++j) {
             if (_polygons[i]->intersects(_polygons[j].get())) {
                 if (!_polygons[i]->touches(_polygons[j].get())) {
-                    return GEO_PARSE_MULTIPOLYGON_OVERLAP;
+                    return GeoParseStatus::GEO_PARSE_MULTIPOLYGON_OVERLAP;
                 }
             } else {
                 continue;
@@ -1153,7 +1153,7 @@ GeoParseStatus GeoMultiPolygon::check_self_intersection() {
                                  compute_distance_to_line(p3, p1, p2) < TOLERANCE ||
                                  compute_distance_to_line(p4, p1, p2) < TOLERANCE) &&
                                 !is_line_touches_line(p1, p2, p3, p4)) {
-                                return GEO_PARSE_MULTIPOLYGON_OVERLAP;
+                                return GeoParseStatus::GEO_PARSE_MULTIPOLYGON_OVERLAP;
                             }
                         }
                     }
@@ -1161,12 +1161,12 @@ GeoParseStatus GeoMultiPolygon::check_self_intersection() {
             }
         }
     }
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 bool GeoMultiPolygon::intersects(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->intersects(point)) {
@@ -1175,7 +1175,7 @@ bool GeoMultiPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->intersects(line)) {
@@ -1184,7 +1184,7 @@ bool GeoMultiPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = assert_cast<const GeoPolygon*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->intersects(other)) {
@@ -1193,7 +1193,7 @@ bool GeoMultiPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         for (const auto& other : multi_polygon->polygons()) {
             for (const auto& polygon : this->_polygons) {
@@ -1204,7 +1204,7 @@ bool GeoMultiPolygon::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->intersects(this);
     }
@@ -1219,7 +1219,7 @@ bool GeoMultiPolygon::disjoint(const GeoShape* rhs) const {
 
 bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->touches(point)) {
@@ -1228,7 +1228,7 @@ bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         bool has_touches = false;
         for (const auto& polygon : this->_polygons) {
@@ -1241,7 +1241,7 @@ bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
         }
         return has_touches;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = assert_cast<const GeoPolygon*>(rhs);
         bool has_touches = false;
         for (const auto& polygon : this->_polygons) {
@@ -1254,7 +1254,7 @@ bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
         }
         return has_touches;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         bool has_touches = false;
         for (const auto& other : multi_polygon->polygons()) {
@@ -1269,7 +1269,7 @@ bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
         }
         return has_touches;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         return circle->touches(this);
     }
@@ -1280,7 +1280,7 @@ bool GeoMultiPolygon::touches(const GeoShape* rhs) const {
 
 bool GeoMultiPolygon::contains(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->contains(point)) {
@@ -1289,7 +1289,7 @@ bool GeoMultiPolygon::contains(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->contains(line)) {
@@ -1298,7 +1298,7 @@ bool GeoMultiPolygon::contains(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = assert_cast<const GeoPolygon*>(rhs);
         for (const auto& polygon : this->_polygons) {
             if (polygon->contains(other)) {
@@ -1307,7 +1307,7 @@ bool GeoMultiPolygon::contains(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         //All polygons in rhs need to be contained
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         for (const auto& other : multi_polygon->polygons()) {
@@ -1400,20 +1400,20 @@ bool GeoMultiPolygon::decode(const void* data, size_t size) {
 GeoParseStatus GeoCircle::init(double lng, double lat, double radius_meter) {
     S2Point center;
     auto status = to_s2point(lng, lat, &center);
-    if (status != GEO_PARSE_OK) {
+    if (status != GeoParseStatus::GEO_PARSE_OK) {
         return status;
     }
     S1Angle radius = S2Earth::ToAngle(util::units::Meters(radius_meter));
     _cap.reset(new S2Cap(center, radius));
     if (!_cap->is_valid()) {
-        return GEO_PARSE_CIRCLE_INVALID;
+        return GeoParseStatus::GEO_PARSE_CIRCLE_INVALID;
     }
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 
 bool GeoCircle::intersects(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1422,7 +1422,7 @@ bool GeoCircle::intersects(const GeoShape* rhs) const {
         double radius = S2Earth::RadiansToMeters(radius_angle.radians());
         return radius + TOLERANCE >= compute_distance_to_point(center, *point->point());
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1431,7 +1431,7 @@ bool GeoCircle::intersects(const GeoShape* rhs) const {
         double distance = compute_distance_to_line(center, line->polyline());
         return radius + TOLERANCE >= distance;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1453,7 +1453,7 @@ bool GeoCircle::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         for (const auto& polygon : multi_polygon->polygons()) {
             if (this->intersects(polygon.get())) {
@@ -1462,7 +1462,7 @@ bool GeoCircle::intersects(const GeoShape* rhs) const {
         }
         return false;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         S1ChordAngle radius_angle = _cap->radius();
         S1ChordAngle other_radius_angle = circle->circle()->radius();
@@ -1483,7 +1483,7 @@ bool GeoCircle::disjoint(const GeoShape* rhs) const {
 
 bool GeoCircle::touches(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = assert_cast<const GeoPoint*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1491,7 +1491,7 @@ bool GeoCircle::touches(const GeoShape* rhs) const {
         double radius = S2Earth::RadiansToMeters(radius_angle.radians());
         return std::abs(radius - compute_distance_to_point(center, *point->point())) < TOLERANCE;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = assert_cast<const GeoLine*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1500,7 +1500,7 @@ bool GeoCircle::touches(const GeoShape* rhs) const {
         double distance = compute_distance_to_line(center, line->polyline());
         return std::abs(radius - distance) < TOLERANCE;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = assert_cast<const GeoPolygon*>(rhs);
         const S2Point& center = _cap->center();
         S1ChordAngle radius_angle = _cap->radius();
@@ -1525,7 +1525,7 @@ bool GeoCircle::touches(const GeoShape* rhs) const {
 
         return false;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         const GeoMultiPolygon* multi_polygon = assert_cast<const GeoMultiPolygon*>(rhs);
         bool has_touches = false;
         for (const auto& polygon : multi_polygon->polygons()) {
@@ -1538,7 +1538,7 @@ bool GeoCircle::touches(const GeoShape* rhs) const {
         }
         return has_touches;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = assert_cast<const GeoCircle*>(rhs);
         S1ChordAngle radius_angle = _cap->radius();
         S1ChordAngle other_radius_angle = circle->circle()->radius();
@@ -1555,7 +1555,7 @@ bool GeoCircle::touches(const GeoShape* rhs) const {
 
 bool GeoCircle::contains(const GeoShape* rhs) const {
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = (const GeoPoint*)rhs;
         return _cap->Contains(*point->point());
     }
@@ -1591,21 +1591,21 @@ double GeoCircle::getArea() const {
 bool GeoShape::ComputeArea(GeoShape* rhs, double* area, std::string square_unit) {
     double steradians;
     switch (rhs->type()) {
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = (const GeoCircle*)rhs;
         steradians = circle->getArea();
         break;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = (const GeoPolygon*)rhs;
         steradians = polygon->getArea();
         break;
     }
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         *area = 0;
         return true;
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         *area = 0;
         return true;
     }
@@ -1757,21 +1757,21 @@ double GeoCircle::Length() const {
 double GeoPoint::Distance(const GeoShape* rhs) const {
     // rhs is guaranteed to be valid by StDistance (functions_geo.cpp)
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         const GeoPoint* point = static_cast<const GeoPoint*>(rhs);
         S2LatLng this_ll = S2LatLng(*_point);
         S2LatLng other_ll = S2LatLng(*point->point());
         return S2Earth::GetDistanceMeters(this_ll, other_ll);
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = static_cast<const GeoLine*>(rhs);
         return distance_point_to_polyline(*_point, line->polyline());
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = static_cast<const GeoPolygon*>(rhs);
         return distance_point_to_polygon(*_point, polygon->polygon());
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* circle = static_cast<const GeoCircle*>(rhs);
         S2LatLng this_ll = S2LatLng(*_point);
         S2LatLng center_ll = S2LatLng(circle->circle()->center());
@@ -1784,7 +1784,7 @@ double GeoPoint::Distance(const GeoShape* rhs) const {
         }
         return dist_to_center - circle_radius;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         return rhs->Distance(this); // Delegate to MultiPolygon's implementation
     }
     default:
@@ -1795,10 +1795,10 @@ double GeoPoint::Distance(const GeoShape* rhs) const {
 double GeoLine::Distance(const GeoShape* rhs) const {
     // rhs is guaranteed to be valid by StDistance (functions_geo.cpp)
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         return rhs->Distance(this); // Reuse Point's Distance implementation
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* other_line = static_cast<const GeoLine*>(rhs);
         if (_polyline->Intersects(*other_line->polyline())) {
             return 0.0;
@@ -1824,13 +1824,13 @@ double GeoLine::Distance(const GeoShape* rhs) const {
         }
         return min_distance;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         return rhs->Distance(this); // Delegate to Polygon's implementation
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         return rhs->Distance(this); // Delegate to Circle's implementation
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         return rhs->Distance(this); // Delegate to MultiPolygon's implementation
     }
     default:
@@ -1841,10 +1841,10 @@ double GeoLine::Distance(const GeoShape* rhs) const {
 double GeoPolygon::Distance(const GeoShape* rhs) const {
     // rhs is guaranteed to be valid by StDistance (functions_geo.cpp)
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         return rhs->Distance(this); // Reuse Point's Distance implementation
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = static_cast<const GeoLine*>(rhs);
         if (_polygon->Intersects(*line->polyline())) {
             return 0.0;
@@ -1872,7 +1872,7 @@ double GeoPolygon::Distance(const GeoShape* rhs) const {
         }
         return min_distance;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* other = static_cast<const GeoPolygon*>(rhs);
         if (_polygon->Intersects(*other->polygon())) {
             return 0.0;
@@ -1903,10 +1903,10 @@ double GeoPolygon::Distance(const GeoShape* rhs) const {
         }
         return min_distance;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         return rhs->Distance(this); // Delegate to Circle's implementation
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         return rhs->Distance(this); // Delegate to MultiPolygon's implementation
     }
     default:
@@ -1949,10 +1949,10 @@ double GeoCircle::Distance(const GeoShape* rhs) const {
     double circle_radius = S2Earth::ToMeters(_cap->radius());
 
     switch (rhs->type()) {
-    case GEO_SHAPE_POINT: {
+    case GeoShapeType::GEO_SHAPE_POINT: {
         return rhs->Distance(this); // Reuse Point's Distance implementation
     }
-    case GEO_SHAPE_LINE_STRING: {
+    case GeoShapeType::GEO_SHAPE_LINE_STRING: {
         const GeoLine* line = static_cast<const GeoLine*>(rhs);
         double min_distance = std::numeric_limits<double>::max();
 
@@ -1968,7 +1968,7 @@ double GeoCircle::Distance(const GeoShape* rhs) const {
         }
         return min_distance - circle_radius;
     }
-    case GEO_SHAPE_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_POLYGON: {
         const GeoPolygon* polygon = static_cast<const GeoPolygon*>(rhs);
 
         // If center is inside polygon, distance is 0
@@ -1994,7 +1994,7 @@ double GeoCircle::Distance(const GeoShape* rhs) const {
         }
         return min_distance - circle_radius;
     }
-    case GEO_SHAPE_CIRCLE: {
+    case GeoShapeType::GEO_SHAPE_CIRCLE: {
         const GeoCircle* other = static_cast<const GeoCircle*>(rhs);
         double other_radius = S2Earth::ToMeters(other->circle()->radius());
         S2LatLng this_center_ll = S2LatLng(_cap->center());
@@ -2008,7 +2008,7 @@ double GeoCircle::Distance(const GeoShape* rhs) const {
         }
         return dist_centers - sum_radii;
     }
-    case GEO_SHAPE_MULTI_POLYGON: {
+    case GeoShapeType::GEO_SHAPE_MULTI_POLYGON: {
         return rhs->Distance(this); // Delegate to MultiPolygon's implementation
     }
     default:
diff --git a/be/src/exprs/function/geo/geo_types.h b/be/src/exprs/function/geo/geo_types.h
index c971fc9b61d..b16f8cb1eb9 100644
--- a/be/src/exprs/function/geo/geo_types.h
+++ b/be/src/exprs/function/geo/geo_types.h
@@ -107,7 +107,7 @@ public:
     bool disjoint(const GeoShape* rhs) const override;
     bool touches(const GeoShape* rhs) const override;
 
-    GeoShapeType type() const override { return GEO_SHAPE_POINT; }
+    GeoShapeType type() const override { return GeoShapeType::GEO_SHAPE_POINT; }
 
     const S2Point* point() const { return _point.get(); }
 
@@ -156,7 +156,7 @@ public:
     bool disjoint(const GeoShape* rhs) const override;
     bool touches(const GeoShape* rhs) const override;
 
-    GeoShapeType type() const override { return GEO_SHAPE_LINE_STRING; }
+    GeoShapeType type() const override { return GeoShapeType::GEO_SHAPE_LINE_STRING; }
     const S2Polyline* polyline() const { return _polyline.get(); }
 
     std::string GeometryType() const override { return "ST_LINESTRING"; }
@@ -191,7 +191,7 @@ public:
     GeoParseStatus from_coords(const GeoCoordinateListList& list);
     std::unique_ptr<GeoCoordinateListList> to_coords() const;
 
-    GeoShapeType type() const override { return GEO_SHAPE_POLYGON; }
+    GeoShapeType type() const override { return GeoShapeType::GEO_SHAPE_POLYGON; }
     const S2Polygon* polygon() const { return _polygon.get(); }
 
     bool intersects(const GeoShape* rhs) const override;
@@ -232,7 +232,7 @@ public:
     GeoParseStatus from_coords(const std::vector<GeoCoordinateListList>& list);
     std::vector<std::unique_ptr<GeoCoordinateListList>> to_coords() const;
 
-    GeoShapeType type() const override { return GEO_SHAPE_MULTI_POLYGON; }
+    GeoShapeType type() const override { return GeoShapeType::GEO_SHAPE_MULTI_POLYGON; }
     const std::vector<std::unique_ptr<GeoPolygon>>& polygons() const { return _polygons; }
 
     bool intersects(const GeoShape* rhs) const override;
@@ -266,7 +266,7 @@ public:
 
     GeoParseStatus init(double lng, double lat, double radius);
 
-    GeoShapeType type() const override { return GEO_SHAPE_CIRCLE; }
+    GeoShapeType type() const override { return GeoShapeType::GEO_SHAPE_CIRCLE; }
 
     const S2Cap* circle() const { return _cap.get(); }
 
diff --git a/be/src/exprs/function/geo/machine.h b/be/src/exprs/function/geo/machine.h
index f40f7b9529e..9c31746cf3e 100644
--- a/be/src/exprs/function/geo/machine.h
+++ b/be/src/exprs/function/geo/machine.h
@@ -17,13 +17,16 @@
 
 #pragma once
 
+#include "exprs/function/geo/ByteOrderValues.h"
+
 namespace doris {
 /**
  * Check endianness of current machine.
  * @return 0 for big_endian | xdr; 1 == little_endian | ndr
  */
-inline int getMachineByteOrder() {
+inline ByteOrderValues::EndianType getMachineByteOrder() {
     static int endian_check = 1; // don't modify !!
-    return *((char*)&endian_check);
+    return *((char*)&endian_check) == 0 ? ByteOrderValues::EndianType::ENDIAN_BIG
+                                        : ByteOrderValues::EndianType::ENDIAN_LITTLE;
 }
 } // namespace doris
diff --git a/be/src/exprs/function/geo/wkb_parse.cpp b/be/src/exprs/function/geo/wkb_parse.cpp
index 390807379d9..ff955455d3a 100644
--- a/be/src/exprs/function/geo/wkb_parse.cpp
+++ b/be/src/exprs/function/geo/wkb_parse.cpp
@@ -72,7 +72,7 @@ unsigned char ASCIIHexToUChar(char val) {
     case 'f':
         return 15;
     default:
-        return GEO_PARSE_WKB_SYNTAX_ERROR;
+        return static_cast<unsigned char>(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR);
     }
 }
 
@@ -80,7 +80,7 @@ GeoParseStatus WkbParse::parse_wkb(std::istream& is, std::unique_ptr<GeoShape>&
     WkbParseContext ctx;
 
     WkbParse::read_hex(is, ctx);
-    if (ctx.parse_status == GEO_PARSE_OK) {
+    if (ctx.parse_status == GeoParseStatus::GEO_PARSE_OK) {
         shape = std::move(ctx.shape);
     }
     return ctx.parse_status;
@@ -98,7 +98,7 @@ void WkbParse::read_hex(std::istream& is, WkbParseContext& ctx) {
 
         const int input_low = is.get();
         if (input_low == std::char_traits<char>::eof()) {
-            ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+            ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
             return;
         }
 
@@ -123,19 +123,19 @@ void WkbParse::read(std::istream& is, WkbParseContext& ctx) {
 
     // Check if size is valid
     if (size <= 0) {
-        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
         return;
     }
 
     std::vector<unsigned char> buf(static_cast<size_t>(size));
     if (!is.read(reinterpret_cast<char*>(buf.data()), static_cast<std::streamsize>(size))) {
-        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
         return;
     }
 
     // Ensure we have at least one byte for byte order
     if (buf.empty()) {
-        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
         return;
     }
 
@@ -143,20 +143,20 @@ void WkbParse::read(std::istream& is, WkbParseContext& ctx) {
     auto byteOrder = buf[0];
 
     // Create ByteOrderDataInStream with the correct byte order
-    if (byteOrder == byteOrder::wkbNDR) {
+    if (byteOrder == static_cast<unsigned char>(byteOrder::wkbNDR)) {
         ctx.dis = ByteOrderDataInStream(buf.data(), buf.size());
-        ctx.dis.setOrder(ByteOrderValues::ENDIAN_LITTLE);
-    } else if (byteOrder == byteOrder::wkbXDR) {
+        ctx.dis.setOrder(ByteOrderValues::EndianType::ENDIAN_LITTLE);
+    } else if (byteOrder == static_cast<unsigned char>(byteOrder::wkbXDR)) {
         ctx.dis = ByteOrderDataInStream(buf.data(), buf.size());
-        ctx.dis.setOrder(ByteOrderValues::ENDIAN_BIG);
+        ctx.dis.setOrder(ByteOrderValues::EndianType::ENDIAN_BIG);
     } else {
-        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
         return;
     }
 
     std::unique_ptr<GeoShape> shape = readGeometry(ctx);
     if (!shape) {
-        ctx.parse_status = GEO_PARSE_WKB_SYNTAX_ERROR;
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
         return;
     }
 
@@ -184,7 +184,7 @@ std::unique_ptr<GeoShape> WkbParse::readGeometry(WkbParseContext& ctx) {
         }
 
         // Get the base geometry type
-        uint32_t geometryType = typeInt & WKB_TYPE_MASK;
+        auto geometryType = static_cast<wkbType>(typeInt & WKB_TYPE_MASK);
 
         std::unique_ptr<GeoShape> shape;
 
@@ -216,7 +216,7 @@ std::unique_ptr<GeoPoint> WkbParse::readPoint(WkbParseContext& ctx) {
     }
 
     std::unique_ptr<GeoPoint> point = GeoPoint::create_unique();
-    if (!point || point->from_coord(coords.list[0]) != GEO_PARSE_OK) {
+    if (!point || point->from_coord(coords.list[0]) != GeoParseStatus::GEO_PARSE_OK) {
         return nullptr;
     }
 
@@ -225,7 +225,7 @@ std::unique_ptr<GeoPoint> WkbParse::readPoint(WkbParseContext& ctx) {
 
 std::unique_ptr<GeoLine> WkbParse::readLine(WkbParseContext& ctx) {
     uint32_t size = ctx.dis.readUnsigned();
-    if (minMemSize(wkbLine, size, ctx) != GEO_PARSE_OK) {
+    if (minMemSize(wkbType::wkbLine, size, ctx) != GeoParseStatus::GEO_PARSE_OK) {
         return nullptr;
     }
 
@@ -235,7 +235,7 @@ std::unique_ptr<GeoLine> WkbParse::readLine(WkbParseContext& ctx) {
     }
 
     std::unique_ptr<GeoLine> line = GeoLine::create_unique();
-    if (!line || line->from_coords(coords) != GEO_PARSE_OK) {
+    if (!line || line->from_coords(coords) != GeoParseStatus::GEO_PARSE_OK) {
         return nullptr;
     }
 
@@ -244,7 +244,7 @@ std::unique_ptr<GeoLine> WkbParse::readLine(WkbParseContext& ctx) {
 
 std::unique_ptr<GeoPolygon> WkbParse::readPolygon(WkbParseContext& ctx) {
     uint32_t num_loops = ctx.dis.readUnsigned();
-    if (minMemSize(wkbPolygon, num_loops, ctx) != GEO_PARSE_OK) {
+    if (minMemSize(wkbType::wkbPolygon, num_loops, ctx) != GeoParseStatus::GEO_PARSE_OK) {
         return nullptr;
     }
 
@@ -264,7 +264,7 @@ std::unique_ptr<GeoPolygon> WkbParse::readPolygon(WkbParseContext& ctx) {
     }
 
     std::unique_ptr<GeoPolygon> polygon = GeoPolygon::create_unique();
-    if (!polygon || polygon->from_coords(coordss) != GEO_PARSE_OK) {
+    if (!polygon || polygon->from_coords(coordss) != GeoParseStatus::GEO_PARSE_OK) {
         return nullptr;
     }
 
@@ -286,7 +286,7 @@ GeoCoordinateList WkbParse::readCoordinateList(unsigned size, WkbParseContext& c
     return coords;
 }
 
-GeoParseStatus WkbParse::minMemSize(int wkbType, uint64_t size, WkbParseContext& ctx) {
+GeoParseStatus WkbParse::minMemSize(wkbType type, uint64_t size, WkbParseContext& ctx) {
     uint64_t minSize = 0;
     constexpr uint64_t minCoordSize = 2 * sizeof(double);
     //constexpr uint64_t minPtSize = (1+4) + minCoordSize;
@@ -295,18 +295,21 @@ GeoParseStatus WkbParse::minMemSize(int wkbType, uint64_t size, WkbParseContext&
     //constexpr uint64_t minPolySize = (1+4+4); // empty polygon
     //constexpr uint64_t minGeomSize = minLineSize;
 
-    switch (wkbType) {
-    case wkbLine:
+    switch (type) {
+    case wkbType::wkbLine:
         minSize = size * minCoordSize;
         break;
-    case wkbPolygon:
+    case wkbType::wkbPolygon:
         minSize = size * minLoopSize;
         break;
+    default:
+        // Only line coordinates and polygon loops use this size check.
+        return GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
     }
     if (ctx.dis.size() < minSize) {
-        return GEO_PARSE_WKB_SYNTAX_ERROR;
+        return GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR;
     }
-    return GEO_PARSE_OK;
+    return GeoParseStatus::GEO_PARSE_OK;
 }
 bool WkbParse::readCoordinate(WkbParseContext& ctx) {
     for (std::size_t i = 0; i < ctx.inputDimension; ++i) {
diff --git a/be/src/exprs/function/geo/wkb_parse.h b/be/src/exprs/function/geo/wkb_parse.h
index c992e5a6fa3..dcc07ae27ab 100644
--- a/be/src/exprs/function/geo/wkb_parse.h
+++ b/be/src/exprs/function/geo/wkb_parse.h
@@ -28,6 +28,8 @@ struct WkbParseContext;
 
 namespace doris {
 
+enum class wkbType : int;
+
 class GeoShape;
 class GeoLine;
 class GeoPoint;
@@ -63,7 +65,7 @@ private:
 
     static GeoCoordinateList readCoordinateList(unsigned size, WkbParseContext& ctx);
 
-    static GeoParseStatus minMemSize(int wkbType, uint64_t size, WkbParseContext& ctx);
+    static GeoParseStatus minMemSize(wkbType type, uint64_t size, WkbParseContext& ctx);
 
     static bool readCoordinate(WkbParseContext& ctx);
 };
diff --git a/be/src/exprs/function/geo/wkb_parse_ctx.h b/be/src/exprs/function/geo/wkb_parse_ctx.h
index 44a140675d2..472b1a78ecd 100644
--- a/be/src/exprs/function/geo/wkb_parse_ctx.h
+++ b/be/src/exprs/function/geo/wkb_parse_ctx.h
@@ -34,5 +34,5 @@ struct WkbParseContext {
     int srid;
 
     std::unique_ptr<doris::GeoShape> shape = nullptr;
-    doris::GeoParseStatus parse_status = doris::GEO_PARSE_OK;
+    doris::GeoParseStatus parse_status = doris::GeoParseStatus::GEO_PARSE_OK;
 };
diff --git a/be/src/exprs/function/geo/wkt_parse.cpp b/be/src/exprs/function/geo/wkt_parse.cpp
index 1a1721af0ec..d38e3857ce5 100644
--- a/be/src/exprs/function/geo/wkt_parse.cpp
+++ b/be/src/exprs/function/geo/wkt_parse.cpp
@@ -32,14 +32,14 @@ namespace doris {
 GeoParseStatus WktParse::parse_wkt(const char* str, size_t len, std::unique_ptr<GeoShape>& shape) {
     WktParseContext ctx;
 
-    if (wkt_parse(str, len, ctx) == GEO_PARSE_OK) {
+    if (wkt_parse(str, len, ctx) == 0) {
         shape = std::move(ctx.shape);
-    } else if (ctx.parse_status == GEO_PARSE_OK) {
+    } else if (ctx.parse_status == GeoParseStatus::GEO_PARSE_OK) {
         /// For Syntax errors(e.g., `POIN(1 2)`, `POINT(1, 2)`)
         /// wkt_parse won't set parse_status, so we need to set it here.
         /// For semantic errors (e.g., invalid coordinates)
-        /// wkt_parse will be set to GEO_PARSE_COORD_INVALID
-        ctx.parse_status = GEO_PARSE_WKT_SYNTAX_ERROR;
+        /// wkt_parse will be set to GeoParseStatus::GEO_PARSE_COORD_INVALID
+        ctx.parse_status = GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR;
     }
     return ctx.parse_status;
 }
diff --git a/be/src/exprs/function/geo/wkt_parse_ctx.h b/be/src/exprs/function/geo/wkt_parse_ctx.h
index ef45a5d5553..5d47060d7dd 100644
--- a/be/src/exprs/function/geo/wkt_parse_ctx.h
+++ b/be/src/exprs/function/geo/wkt_parse_ctx.h
@@ -26,5 +26,5 @@ typedef void* yyscan_t;
 struct WktParseContext {
     yyscan_t scaninfo;
     std::unique_ptr<doris::GeoShape> shape = nullptr;
-    doris::GeoParseStatus parse_status = doris::GEO_PARSE_OK;
+    doris::GeoParseStatus parse_status = doris::GeoParseStatus::GEO_PARSE_OK;
 };
diff --git a/be/src/exprs/function/geo/wkt_yacc.y b/be/src/exprs/function/geo/wkt_yacc.y
index 5b2cb89bfa6..a1ee084ea35 100644
--- a/be/src/exprs/function/geo/wkt_yacc.y
+++ b/be/src/exprs/function/geo/wkt_yacc.y
@@ -66,7 +66,7 @@ wkt_::parser::symbol_type wkt_lex(WktParseContext* ctx, yyscan_t scanner);
 
 namespace wkt_ {
     // For syntax errors(e.g., `POIN(1 2)`, `POINT(1, 2)`), parser::error() does nothing.
-    // The parse_wkt() function will set ctx.parse_status to GEO_PARSE_WKT_SYNTAX_ERROR.
+    // The parse_wkt() function will set ctx.parse_status to GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR.
     // For semantic errors (e.g., invalid coordinates), ctx.parse_status is set
     // in the grammar rules before calling YYABORT.
     void parser::error(const std::string& msg) {}
@@ -115,7 +115,7 @@ point:
         std::unique_ptr<doris::GeoPoint> point = doris::GeoPoint::create_unique();
         const doris::GeoCoordinate& coord = *$3;
         ctx->parse_status = point->from_coord(coord);
-        if (ctx->parse_status != doris::GEO_PARSE_OK) {
+        if (ctx->parse_status != doris::GeoParseStatus::GEO_PARSE_OK) {
             YYABORT;
         }
         std::unique_ptr<doris::GeoShape> shape = std::move(point);
@@ -130,7 +130,7 @@ linestring:
         std::unique_ptr<doris::GeoCoordinateList> list = std::move($3);
         std::unique_ptr<doris::GeoLine> line = doris::GeoLine::create_unique();
         ctx->parse_status = line->from_coords(*list);
-        if (ctx->parse_status != doris::GEO_PARSE_OK) {
+        if (ctx->parse_status != doris::GeoParseStatus::GEO_PARSE_OK) {
             YYABORT;
         }
         std::unique_ptr<doris::GeoShape> shape = std::move(line);
@@ -145,7 +145,7 @@ polygon:
         std::unique_ptr<doris::GeoCoordinateListList> list = std::move($3);
         std::unique_ptr<doris::GeoPolygon> polygon = doris::GeoPolygon::create_unique();
         ctx->parse_status = polygon->from_coords(*list);
-        if (ctx->parse_status != doris::GEO_PARSE_OK) {
+        if (ctx->parse_status != doris::GeoParseStatus::GEO_PARSE_OK) {
             YYABORT;
         }
         std::unique_ptr<doris::GeoShape> shape = std::move(polygon);
@@ -160,7 +160,7 @@ multi_polygon:
         std::unique_ptr<std::vector<doris::GeoCoordinateListList>> list = std::move($3);
         std::unique_ptr<doris::GeoMultiPolygon> multi_polygon = doris::GeoMultiPolygon::create_unique();
         ctx->parse_status = multi_polygon->from_coords(*list);
-        if (ctx->parse_status != doris::GEO_PARSE_OK) {
+        if (ctx->parse_status != doris::GeoParseStatus::GEO_PARSE_OK) {
             YYABORT;
         }
         std::unique_ptr<doris::GeoShape> shape = std::move(multi_polygon);
@@ -228,4 +228,3 @@ coordinate:
         yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinate>>(std::move(coord));
     }
     ;
-
diff --git a/be/src/exprs/function/in.h b/be/src/exprs/function/in.h
index 10e101324f6..f2a62dc48f6 100644
--- a/be/src/exprs/function/in.h
+++ b/be/src/exprs/function/in.h
@@ -102,7 +102,7 @@ public:
     }
 
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             return Status::OK();
         }
         // Binary IO must not route IN through the shared string/storage predicate implementation.
@@ -200,7 +200,7 @@ public:
     Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
                         uint32_t result, size_t input_rows_count) const override {
         auto* in_state = reinterpret_cast<InState*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         if (!in_state) {
             return Status::RuntimeError("funciton context for function '{}' must have Set;",
                                         get_name());
diff --git a/be/src/exprs/function/like.cpp b/be/src/exprs/function/like.cpp
index de0bc7a5469..bdff040c190 100644
--- a/be/src/exprs/function/like.cpp
+++ b/be/src/exprs/function/like.cpp
@@ -614,7 +614,7 @@ Status FunctionLikeBase::execute_impl(FunctionContext* context, Block& block,
     // set default value to 0, and match functions only need to set 1/true
     vec_res.resize_fill(input_rows_count);
     auto* state = reinterpret_cast<LikeState*>(
-            context->get_function_state(FunctionContext::THREAD_LOCAL));
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     const auto pattern_col = block.get_by_position(arguments[1]).column;
     if (const auto* str_patterns = check_and_get_column<ColumnString>(pattern_col.get())) {
         RETURN_IF_ERROR(vector_non_const(*values, *str_patterns, vec_res, state, input_rows_count));
@@ -1013,7 +1013,7 @@ Status FunctionLike::construct_like_const_state(FunctionContext* context, const
 }
 
 Status FunctionLike::open(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
-    if (scope != FunctionContext::THREAD_LOCAL) {
+    if (scope != FunctionContext::FunctionStateScope::THREAD_LOCAL) {
         return Status::OK();
     }
     std::shared_ptr<LikeState> state = std::make_shared<LikeState>();
@@ -1044,7 +1044,7 @@ Status FunctionLike::open(FunctionContext* context, FunctionContext::FunctionSta
 
 Status FunctionRegexpLike::open(FunctionContext* context,
                                 FunctionContext::FunctionStateScope scope) {
-    if (scope != FunctionContext::THREAD_LOCAL) {
+    if (scope != FunctionContext::FunctionStateScope::THREAD_LOCAL) {
         return Status::OK();
     }
     std::shared_ptr<LikeState> state = std::make_shared<LikeState>();
diff --git a/be/src/exprs/function/match.cpp b/be/src/exprs/function/match.cpp
index eff6b2b9318..6af18b0f1f8 100644
--- a/be/src/exprs/function/match.cpp
+++ b/be/src/exprs/function/match.cpp
@@ -44,10 +44,10 @@ const InvertedIndexAnalyzerCtx* get_match_analyzer_ctx(FunctionContext* context)
         return nullptr;
     }
     const auto* analyzer_ctx = reinterpret_cast<const InvertedIndexAnalyzerCtx*>(
-            context->get_function_state(FunctionContext::THREAD_LOCAL));
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     if (analyzer_ctx == nullptr) {
         analyzer_ctx = reinterpret_cast<const InvertedIndexAnalyzerCtx*>(
-                context->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     }
     return analyzer_ctx;
 }
diff --git a/be/src/exprs/function/random.cpp b/be/src/exprs/function/random.cpp
index 9b5b39e2385..071abc1cb04 100644
--- a/be/src/exprs/function/random.cpp
+++ b/be/src/exprs/function/random.cpp
@@ -64,7 +64,7 @@ public:
     Status open(FunctionContext* context, FunctionContext::FunctionStateScope scope) override {
         std::shared_ptr<State> state = std::make_shared<State>();
         context->set_function_state(scope, state);
-        if (scope == FunctionContext::THREAD_LOCAL) {
+        if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL) {
             if (context->get_num_args() == 1) {
                 // This is a call to RandSeed, initialize the seed. The seed is a constant, but a
                 // constant expression such as an arithmetic one is not evaluated in open. Then the
@@ -107,7 +107,7 @@ private:
         auto& res_data = res_column->get_data();
 
         auto* state = reinterpret_cast<State*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         DCHECK(state != nullptr);
         if (input_rows_count == 0) {
             block.replace_by_position(result, std::move(res_column));
@@ -142,7 +142,7 @@ private:
         auto& res_data = res_column->get_data();
 
         auto* state = reinterpret_cast<State*>(
-                context->get_function_state(FunctionContext::THREAD_LOCAL));
+                context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
         DCHECK(state != nullptr);
         if (state->seed_in_execute && input_rows_count > 0) {
             state->generator.seed(get_seed(*block.get_by_position(arguments[0]).column));
diff --git a/be/src/exprs/function_context.cpp b/be/src/exprs/function_context.cpp
index 8c1faa7d441..74bea9af90a 100644
--- a/be/src/exprs/function_context.cpp
+++ b/be/src/exprs/function_context.cpp
@@ -64,15 +64,15 @@ std::unique_ptr<FunctionContext> FunctionContext::clone() {
 
 void FunctionContext::set_function_state(FunctionStateScope scope, std::shared_ptr<void> ptr) {
     switch (scope) {
-    case THREAD_LOCAL:
+    case FunctionStateScope::THREAD_LOCAL:
         _thread_local_fn_state = std::move(ptr);
         break;
-    case FRAGMENT_LOCAL:
+    case FunctionStateScope::FRAGMENT_LOCAL:
         _fragment_local_fn_state = std::move(ptr);
         break;
     default:
         std::stringstream ss;
-        ss << "Unknown FunctionStateScope: " << scope;
+        ss << "Unknown FunctionStateScope: " << static_cast<int>(scope);
         set_error(ss.str().c_str());
     }
 }
@@ -136,9 +136,9 @@ const DataTypePtr FunctionContext::get_return_type() const {
 
 void* FunctionContext::get_function_state(FunctionStateScope scope) const {
     switch (scope) {
-    case THREAD_LOCAL:
+    case FunctionStateScope::THREAD_LOCAL:
         return _thread_local_fn_state.get();
-    case FRAGMENT_LOCAL:
+    case FunctionStateScope::FRAGMENT_LOCAL:
         return _fragment_local_fn_state.get();
     default:
         // TODO: signal error somehow
diff --git a/be/src/exprs/function_context.h b/be/src/exprs/function_context.h
index 69d6dfa6187..bc892991a49 100644
--- a/be/src/exprs/function_context.h
+++ b/be/src/exprs/function_context.h
@@ -42,7 +42,7 @@ using DataTypePtr = std::shared_ptr<const IDataType>;
 // and manage memory.
 class FunctionContext {
 public:
-    enum FunctionStateScope {
+    enum class FunctionStateScope {
         /// Indicates that function state for this FunctionContext's UDF is shared across
         /// plan fragment (a query is divided into multiple plan fragments, each of which
         /// is responsible for a part of query execution). Within plan fragment, there
diff --git a/be/src/exprs/json_functions.h b/be/src/exprs/json_functions.h
index 11970eb8c46..11084fd0454 100644
--- a/be/src/exprs/json_functions.h
+++ b/be/src/exprs/json_functions.h
@@ -39,14 +39,6 @@ class value;
 
 namespace doris {
 
-enum JsonFunctionType {
-    JSON_FUN_INT = 0,
-    JSON_FUN_DOUBLE,
-    JSON_FUN_STRING,
-
-    JSON_FUN_UNKNOWN //The last
-};
-
 struct JsonPath {
     std::string key; // key of a json object
     int idx;         // array index of a json array, -1 means not set, -2 means *
diff --git a/be/src/exprs/vcase_expr.cpp b/be/src/exprs/vcase_expr.cpp
index ebab392b68f..af1abd5aa18 100644
--- a/be/src/exprs/vcase_expr.cpp
+++ b/be/src/exprs/vcase_expr.cpp
@@ -63,7 +63,7 @@ Status VCaseExpr::open(RuntimeState* state, VExprContext* context,
     for (auto& i : _children) {
         RETURN_IF_ERROR(i->open(state, context, scope));
     }
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/exprs/vcast_expr.cpp b/be/src/exprs/vcast_expr.cpp
index 09681a46dd3..01e9622ee15 100644
--- a/be/src/exprs/vcast_expr.cpp
+++ b/be/src/exprs/vcast_expr.cpp
@@ -94,7 +94,7 @@ doris::Status VCastExpr::open(doris::RuntimeState* state, VExprContext* context,
         context->fn_context(_fn_context_index)->set_enable_strict_mode(true);
     }
     RETURN_IF_ERROR(VExpr::init_function_context(state, context, scope, _function));
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/exprs/vectorized_fn_call.cpp b/be/src/exprs/vectorized_fn_call.cpp
index eeab5a03fe1..3b98c6fabf3 100644
--- a/be/src/exprs/vectorized_fn_call.cpp
+++ b/be/src/exprs/vectorized_fn_call.cpp
@@ -362,7 +362,7 @@ Status VectorizedFnCall::open(RuntimeState* state, VExprContext* context,
         RETURN_IF_ERROR(i->open(state, context, scope));
     }
     RETURN_IF_ERROR(VExpr::init_function_context(state, context, scope, _function));
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/exprs/vexpr.cpp b/be/src/exprs/vexpr.cpp
index 44dd5f9cb21..f2cddfdd2d5 100644
--- a/be/src/exprs/vexpr.cpp
+++ b/be/src/exprs/vexpr.cpp
@@ -469,7 +469,7 @@ Status VExpr::open(RuntimeState* state, VExprContext* context,
     for (auto& i : _children) {
         RETURN_IF_ERROR(i->open(state, context, scope));
     }
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     return Status::OK();
@@ -865,7 +865,7 @@ Status VExpr::init_function_context(RuntimeState* state, VExprContext* context,
                                     FunctionContext::FunctionStateScope scope,
                                     const FunctionBasePtr& function) const {
     FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         std::vector<std::shared_ptr<ColumnPtrWrapper>> constant_cols;
         for (auto c : _children) {
             std::shared_ptr<ColumnPtrWrapper> const_col;
@@ -875,10 +875,11 @@ Status VExpr::init_function_context(RuntimeState* state, VExprContext* context,
         fn_ctx->set_constant_cols(constant_cols);
     }
 
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
-        RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
+        RETURN_IF_ERROR(
+                function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     }
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
     return Status::OK();
 }
 
@@ -887,9 +888,11 @@ void VExpr::close_function_context(VExprContext* context, FunctionContext::Funct
     if (_fn_context_index != -1) {
         FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
         // `close_function_context` is called in VExprContext's destructor so do not throw exceptions here.
-        static_cast<void>(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        if (scope == FunctionContext::FRAGMENT_LOCAL) {
-            static_cast<void>(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(
+                function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
+            static_cast<void>(
+                    function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         }
     }
 }
diff --git a/be/src/exprs/vexpr_context.cpp b/be/src/exprs/vexpr_context.cpp
index c7f83e22ddf..fcda9757238 100644
--- a/be/src/exprs/vexpr_context.cpp
+++ b/be/src/exprs/vexpr_context.cpp
@@ -143,7 +143,8 @@ Status VExprContext::open(RuntimeState* state) {
     // Fragment-local state is only initialized for original contexts. Clones inherit the
     // original's fragment state and only need to have thread-local state initialized.
     FunctionContext::FunctionStateScope scope =
-            _is_clone ? FunctionContext::THREAD_LOCAL : FunctionContext::FRAGMENT_LOCAL;
+            _is_clone ? FunctionContext::FunctionStateScope::THREAD_LOCAL
+                      : FunctionContext::FunctionStateScope::FRAGMENT_LOCAL;
     Status st;
     RETURN_IF_CATCH_EXCEPTION({ st = _root->open(state, this, scope); });
     return st;
@@ -155,7 +156,8 @@ void VExprContext::close() {
         return;
     }
     FunctionContext::FunctionStateScope scope =
-            _is_clone ? FunctionContext::THREAD_LOCAL : FunctionContext::FRAGMENT_LOCAL;
+            _is_clone ? FunctionContext::FunctionStateScope::THREAD_LOCAL
+                      : FunctionContext::FunctionStateScope::FRAGMENT_LOCAL;
     _root->close(this, scope);
 }
 
@@ -176,7 +178,7 @@ Status VExprContext::clone(RuntimeState* state, VExprContextSPtr& new_ctx) {
     // The object of segment_v2::AnnRangeSearchRuntime is not shared by threads.
     new_ctx->_ann_range_search_runtime = this->_ann_range_search_runtime;
 
-    return _root->open(state, new_ctx.get(), FunctionContext::THREAD_LOCAL);
+    return _root->open(state, new_ctx.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
 }
 
 void VExprContext::clone_fn_contexts(VExprContext* other) {
diff --git a/be/src/exprs/vexpr_context.h b/be/src/exprs/vexpr_context.h
index 6abe282de05..9e0245a4bc4 100644
--- a/be/src/exprs/vexpr_context.h
+++ b/be/src/exprs/vexpr_context.h
@@ -355,7 +355,8 @@ public:
     }
 
     FunctionContext::FunctionStateScope get_function_state_scope() const {
-        return _is_clone ? FunctionContext::THREAD_LOCAL : FunctionContext::FRAGMENT_LOCAL;
+        return _is_clone ? FunctionContext::FunctionStateScope::THREAD_LOCAL
+                         : FunctionContext::FunctionStateScope::FRAGMENT_LOCAL;
     }
 
     void clone_fn_contexts(VExprContext* other);
diff --git a/be/src/exprs/vin_predicate.cpp b/be/src/exprs/vin_predicate.cpp
index 2186144d38a..a219c2ab957 100644
--- a/be/src/exprs/vin_predicate.cpp
+++ b/be/src/exprs/vin_predicate.cpp
@@ -138,13 +138,13 @@ Status VInPredicate::open(RuntimeState* state, VExprContext* context,
         RETURN_IF_ERROR(child->open(state, context, scope));
     }
     RETURN_IF_ERROR(VExpr::init_function_context(state, context, scope, _function));
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
 
     _is_args_all_constant = std::all_of(_children.begin() + 1, _children.end(),
                                         [](const VExprSPtr& expr) { return expr->is_constant(); });
-    if (scope == FunctionContext::FRAGMENT_LOCAL && _is_args_all_constant &&
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL && _is_args_all_constant &&
         _zonemap_min_max == nullptr) {
         _prepare_zonemap_min_max(context);
     }
@@ -186,8 +186,8 @@ void VInPredicate::_prepare_zonemap_min_max(VExprContext* context) {
     DORIS_CHECK(context != nullptr);
     auto* fn_ctx = context->fn_context(_fn_context_index);
     DORIS_CHECK(fn_ctx != nullptr);
-    auto* in_state =
-            reinterpret_cast<InState*>(fn_ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+    auto* in_state = reinterpret_cast<InState*>(
+            fn_ctx->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     DORIS_CHECK(in_state != nullptr);
     DORIS_CHECK(in_state->use_set);
     DORIS_CHECK(in_state->hybrid_set != nullptr);
diff --git a/be/src/exprs/vmatch_predicate.cpp b/be/src/exprs/vmatch_predicate.cpp
index f5adc50a1bc..cacccf55359 100644
--- a/be/src/exprs/vmatch_predicate.cpp
+++ b/be/src/exprs/vmatch_predicate.cpp
@@ -154,10 +154,11 @@ Status VMatchPredicate::open(RuntimeState* state, VExprContext* context,
         RETURN_IF_ERROR(i->open(state, context, scope));
     }
     RETURN_IF_ERROR(VExpr::init_function_context(state, context, scope, _function));
-    if (scope == FunctionContext::THREAD_LOCAL || scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::THREAD_LOCAL ||
+        scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         context->fn_context(_fn_context_index)->set_function_state(scope, _analyzer_ctx);
     }
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/format_v2/expr/cast.cpp b/be/src/format_v2/expr/cast.cpp
index c1435732a9e..4a5ce6b59d0 100644
--- a/be/src/format_v2/expr/cast.cpp
+++ b/be/src/format_v2/expr/cast.cpp
@@ -76,7 +76,7 @@ Status Cast::open(RuntimeState* state, VExprContext* context,
         RETURN_IF_ERROR(i->open(state, context, scope));
     }
     RETURN_IF_ERROR(VExpr::init_function_context(state, context, scope, _function));
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/format_v2/expr/equality_delete_predicate.cpp b/be/src/format_v2/expr/equality_delete_predicate.cpp
index 7516be67aa5..b69a1d12c90 100644
--- a/be/src/format_v2/expr/equality_delete_predicate.cpp
+++ b/be/src/format_v2/expr/equality_delete_predicate.cpp
@@ -124,7 +124,7 @@ Status EqualityDeletePredicate::open(RuntimeState* state, VExprContext* context,
     for (auto& child : _children) {
         RETURN_IF_ERROR(child->open(state, context, scope));
     }
-    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+    if (scope == FunctionContext::FunctionStateScope::FRAGMENT_LOCAL) {
         RETURN_IF_ERROR(VExpr::get_const_col(context, nullptr));
     }
     _open_finished = true;
diff --git a/be/src/storage/predicate/like_column_predicate.cpp b/be/src/storage/predicate/like_column_predicate.cpp
index f5d468dd9bf..8aa348b5b85 100644
--- a/be/src/storage/predicate/like_column_predicate.cpp
+++ b/be/src/storage/predicate/like_column_predicate.cpp
@@ -29,7 +29,7 @@ LikeColumnPredicate::LikeColumnPredicate(bool opposite, uint32_t column_id, std:
                                          doris::FunctionContext* fn_ctx, doris::StringRef val)
         : ColumnPredicate(column_id, col_name, TYPE_STRING, opposite), pattern(val) {
     _state = reinterpret_cast<StateType*>(
-            fn_ctx->get_function_state(doris::FunctionContext::THREAD_LOCAL));
+            fn_ctx->get_function_state(doris::FunctionContext::FunctionStateScope::THREAD_LOCAL));
     THROW_IF_ERROR(_state->search_state.clone(_like_state));
 }
 
diff --git a/be/test/ai/ai_request_executor_test.cpp b/be/test/ai/ai_request_executor_test.cpp
index 0439221a982..56dc7a1c4f5 100644
--- a/be/test/ai/ai_request_executor_test.cpp
+++ b/be/test/ai/ai_request_executor_test.cpp
@@ -194,8 +194,10 @@ protected:
         auto second_context = context->clone();
         if (share_executor) {
             auto shared_executor = std::make_shared<AIRequestExecutor>();
-            context->set_function_state(FunctionContext::THREAD_LOCAL, shared_executor);
-            second_context->set_function_state(FunctionContext::THREAD_LOCAL, shared_executor);
+            context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL,
+                                        shared_executor);
+            second_context->set_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL,
+                                               shared_executor);
         }
         std::mutex gate_mutex;
         std::condition_variable gate;
@@ -220,8 +222,9 @@ protected:
         EXPECT_TRUE(first.get().ok());
         EXPECT_TRUE(second.get().ok());
         EXPECT_TRUE(both_arrived);
-        EXPECT_EQ(context->get_function_state(FunctionContext::THREAD_LOCAL) ==
-                          second_context->get_function_state(FunctionContext::THREAD_LOCAL),
+        EXPECT_EQ(context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL) ==
+                          second_context->get_function_state(
+                                  FunctionContext::FunctionStateScope::THREAD_LOCAL),
                   share_executor);
         EXPECT_EQ(connection_count(), 2);
         handler.on_request = {};
@@ -308,7 +311,8 @@ TEST_F(AIRequestExecutorTest, ScalarReusesConnectionAcrossBatchesAndBlocksWithNu
     EXPECT_NE(handler.bodies[0].find("first"), std::string::npos);
     EXPECT_NE(handler.bodies[1].find("second"), std::string::npos);
     std::weak_ptr<void> owner = context->_thread_local_fn_state;
-    ASSERT_TRUE(function.close(context.get(), FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function.close(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     EXPECT_TRUE(owner.expired());
 }
 
diff --git a/be/test/exec/operator/scan_normalize_predicate_test.cpp b/be/test/exec/operator/scan_normalize_predicate_test.cpp
index 6377e88f120..064cbfc54db 100644
--- a/be/test/exec/operator/scan_normalize_predicate_test.cpp
+++ b/be/test/exec/operator/scan_normalize_predicate_test.cpp
@@ -515,7 +515,7 @@ TEST_F(ScanNormalizePredicate, test_is_predicate_acting_on_slot6) {
 
         auto* state = reinterpret_cast<InState*>(
                 ctx->fn_context(fn_in->fn_context_index())
-                        ->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                        ->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
         state->use_set = false;
 
@@ -573,7 +573,7 @@ TEST_F(ScanNormalizePredicate, test_is_predicate_acting_on_slot7) {
 
         auto* state = reinterpret_cast<InState*>(
                 ctx->fn_context(fn_in->fn_context_index())
-                        ->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                        ->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
         state->use_set = true;
         state->hybrid_set->insert(nullptr, 0);
diff --git a/be/test/exec/runtime_filter/runtime_filter_expr_sampling_test.cpp b/be/test/exec/runtime_filter/runtime_filter_expr_sampling_test.cpp
index 8af2575ff15..700bb34d78c 100644
--- a/be/test/exec/runtime_filter/runtime_filter_expr_sampling_test.cpp
+++ b/be/test/exec/runtime_filter/runtime_filter_expr_sampling_test.cpp
@@ -93,9 +93,9 @@ TEST_F(RuntimeFilterExprSamplingTest, open_propagates_sampling_frequency) {
 
     RowDescriptor row_desc;
     ASSERT_TRUE(wrapper->prepare(_runtime_states[0].get(), row_desc, context.get()).ok());
-    ASSERT_TRUE(
-            wrapper->open(_runtime_states[0].get(), context.get(), FunctionContext::FRAGMENT_LOCAL)
-                    .ok());
+    ASSERT_TRUE(wrapper->open(_runtime_states[0].get(), context.get(),
+                              FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                        .ok());
 
     // After open(), sampling_frequency should be propagated from RuntimeFilterExpr
     // to VExprContext. Verify by accumulating low-selectivity data and checking
@@ -125,9 +125,9 @@ TEST_F(RuntimeFilterExprSamplingTest, default_sampling_frequency_disables_optimi
     auto context = std::make_shared<VExprContext>(wrapper);
     RowDescriptor row_desc;
     ASSERT_TRUE(wrapper->prepare(_runtime_states[0].get(), row_desc, context.get()).ok());
-    ASSERT_TRUE(
-            wrapper->open(_runtime_states[0].get(), context.get(), FunctionContext::FRAGMENT_LOCAL)
-                    .ok());
+    ASSERT_TRUE(wrapper->open(_runtime_states[0].get(), context.get(),
+                              FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                        .ok());
 
     // Even with low-selectivity data, always_true should NOT be detected
     // because sampling is disabled
@@ -158,9 +158,9 @@ TEST_F(RuntimeFilterExprSamplingTest, sampling_frequency_survives_context_recrea
     auto context1 = std::make_shared<VExprContext>(wrapper);
     RowDescriptor row_desc;
     ASSERT_TRUE(wrapper->prepare(_runtime_states[0].get(), row_desc, context1.get()).ok());
-    ASSERT_TRUE(
-            wrapper->open(_runtime_states[0].get(), context1.get(), FunctionContext::FRAGMENT_LOCAL)
-                    .ok());
+    ASSERT_TRUE(wrapper->open(_runtime_states[0].get(), context1.get(),
+                              FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                        .ok());
 
     // Create a brand new non-clone VExprContext with the same RuntimeFilterExpr,
     // matching the production path in _append_rf_into_conjuncts which calls
diff --git a/be/test/exec/sink/vrow_distribution_test.cpp b/be/test/exec/sink/vrow_distribution_test.cpp
index d0211a15f67..8e7e2d817f3 100644
--- a/be/test/exec/sink/vrow_distribution_test.cpp
+++ b/be/test/exec/sink/vrow_distribution_test.cpp
@@ -80,8 +80,8 @@ std::unique_ptr<VRowDistributionHarness> _build_vrow_distribution_harness(
     EXPECT_TRUE(st.ok()) << st.to_string();
 
     h->location = std::make_unique<OlapTableLocationParam>(tlocation);
-    h->tablet_finder = std::make_unique<OlapTabletFinder>(h->vpartition.get(),
-                                                          OlapTabletFinder::FIND_TABLET_EVERY_ROW);
+    h->tablet_finder = std::make_unique<OlapTabletFinder>(
+            h->vpartition.get(), OlapTabletFinder::FindTabletMode::FIND_TABLET_EVERY_ROW);
     h->block_convertor = std::make_unique<OlapTableBlockConvertor>(h->schema->tuple_desc());
 
     h->output_row_desc = std::make_unique<RowDescriptor>(
diff --git a/be/test/exprs/function/function_array_cross_product_test.cpp b/be/test/exprs/function/function_array_cross_product_test.cpp
index f53a4f04cb5..ee2c5d186ca 100644
--- a/be/test/exprs/function/function_array_cross_product_test.cpp
+++ b/be/test/exprs/function/function_array_cross_product_test.cpp
@@ -86,12 +86,12 @@ Status execute_cross_product(const std::string& func_name, ColumnPtr lhs, Column
 
     FunctionUtils fn_utils(result_type, {lhs_type, rhs_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
     block->insert({nullptr, result_type, "result"});
     auto st = function->execute(fn_ctx, *block, {0, 1}, 2, rows);
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     return st;
 }
 
diff --git a/be/test/exprs/function/function_array_cum_sum_test.cpp b/be/test/exprs/function/function_array_cum_sum_test.cpp
index d990528d93e..8331b7ec908 100644
--- a/be/test/exprs/function/function_array_cum_sum_test.cpp
+++ b/be/test/exprs/function/function_array_cum_sum_test.cpp
@@ -56,15 +56,15 @@ static std::vector<std::string> run_array_cum_sum(const std::vector<TestArray>&
     FunctionUtils fn_utils(result_type, {array_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     fn_ctx->set_constant_cols({nullptr});
-    EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    EXPECT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, result_type, "result"});
     auto result_idx = block.columns() - 1;
     auto st = func->execute(fn_ctx, block, {0}, result_idx, row_size);
     EXPECT_TRUE(st.ok()) << st;
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     if (!st.ok()) {
         return results;
     }
diff --git a/be/test/exprs/function/function_array_except_all_test.cpp b/be/test/exprs/function/function_array_except_all_test.cpp
index abdc7576a59..91e6a939923 100644
--- a/be/test/exprs/function/function_array_except_all_test.cpp
+++ b/be/test/exprs/function/function_array_except_all_test.cpp
@@ -57,12 +57,12 @@ void check_array_except_all(const DataTypePtr& array_type, const TestArray& left
 
     FunctionUtils function_utils(array_type, {array_type, array_type}, false);
     auto* context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     block.insert({nullptr, array_type, "result"});
     ASSERT_TRUE(function->execute(context, block, {0, 1}, 2, row_count).ok());
-    ASSERT_TRUE(function->close(context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->close(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
 
     MutableColumnPtr expected_column = array_type->create_column();
     ASSERT_TRUE(insert_cell(expected_column, array_type, expected));
diff --git a/be/test/exprs/function/function_array_range_test.cpp b/be/test/exprs/function/function_array_range_test.cpp
index c91d17918ca..bd96f1d63a5 100644
--- a/be/test/exprs/function/function_array_range_test.cpp
+++ b/be/test/exprs/function/function_array_range_test.cpp
@@ -90,13 +90,13 @@ void check_range(const std::string& name, const std::vector<RangeRow>& rows,
     ASSERT_NE(function, nullptr);
     FunctionUtils utils(result_type, arg_types, false);
     auto* context = utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     block.insert({nullptr, result_type, "result"});
     auto status = function->execute(context, block, arguments,
                                     static_cast<uint32_t>(argument_count), rows.size());
-    ASSERT_TRUE(function->close(context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->close(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
     if (expect_size_error) {
         ASSERT_FALSE(status.ok());
         EXPECT_NE(status.to_string().find("Array size exceeds the limit"), std::string::npos);
diff --git a/be/test/exprs/function/function_array_remove_test.cpp b/be/test/exprs/function/function_array_remove_test.cpp
index 772a93943df..7be1f72bef1 100644
--- a/be/test/exprs/function/function_array_remove_test.cpp
+++ b/be/test/exprs/function/function_array_remove_test.cpp
@@ -67,14 +67,14 @@ static void check_array_remove_case(DataTypePtr array_type, DataTypePtr element_
     FunctionUtils fn_utils(return_type, arg_types, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     fn_ctx->set_constant_cols(constant_cols);
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto result_idx = block.columns() - 1;
     ASSERT_TRUE(func->execute(fn_ctx, block, arguments, result_idx, row_size).ok());
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     MutableColumnPtr expected_column = return_type->create_column();
     ASSERT_TRUE(insert_cell(expected_column, return_type, expected));
diff --git a/be/test/exprs/function/function_array_shuffle_test.cpp b/be/test/exprs/function/function_array_shuffle_test.cpp
index d4f1313cde3..149cf1a7d40 100644
--- a/be/test/exprs/function/function_array_shuffle_test.cpp
+++ b/be/test/exprs/function/function_array_shuffle_test.cpp
@@ -103,14 +103,14 @@ static Status run_array_shuffle(const std::vector<TestArray>& arrays, bool const
     FunctionUtils fn_utils(return_type, arg_types, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     fn_ctx->set_constant_cols(constant_cols);
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
     block.insert({nullptr, return_type, "result"});
     auto result_idx = block.columns() - 1;
     RETURN_IF_ERROR(func->execute(fn_ctx, block, arguments, result_idx, row_size));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     const auto& result_column = *block.get_by_position(result_idx).column;
     for (size_t i = 0; i < row_size; ++i) {
diff --git a/be/test/exprs/function/function_array_split_test.cpp b/be/test/exprs/function/function_array_split_test.cpp
index a6991c5e6c2..a303f528aae 100644
--- a/be/test/exprs/function/function_array_split_test.cpp
+++ b/be/test/exprs/function/function_array_split_test.cpp
@@ -121,12 +121,12 @@ Status execute_array_split(const std::string& name, ColumnPtr source, ColumnPtr
 
     FunctionUtils fn_utils(result_type, {source_type, predicate_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
     block->insert({nullptr, result_type, "result"});
     auto status = function->execute(fn_ctx, *block, {0, 1}, 2, input_rows_count);
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     return status;
 }
 
diff --git a/be/test/exprs/function/function_array_trim_test.cpp b/be/test/exprs/function/function_array_trim_test.cpp
index ead082e9ed1..440a5c2c7e7 100644
--- a/be/test/exprs/function/function_array_trim_test.cpp
+++ b/be/test/exprs/function/function_array_trim_test.cpp
@@ -73,15 +73,20 @@ static void check_array_trim_case(const DataSet& data_set, bool const_array, boo
     FunctionUtils function_utils(array_type, {array_type, size_type}, false);
     auto* function_context = function_utils.get_fn_ctx();
     function_context->set_constant_cols(constant_columns);
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
 
     block.insert({nullptr, array_type, "result"});
     const auto result = block.columns() - 1;
     ASSERT_TRUE(function->execute(function_context, block, {0, 1}, result, row_size).ok());
 
-    static_cast<void>(function->close(function_context, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(function->close(function_context, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(
+            function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     MutableColumnPtr expected_column = array_type->create_column();
     for (const auto& row : data_set) {
diff --git a/be/test/exprs/function/function_array_zip_test.cpp b/be/test/exprs/function/function_array_zip_test.cpp
index 1a6b5d6c441..b0553f66ede 100644
--- a/be/test/exprs/function/function_array_zip_test.cpp
+++ b/be/test/exprs/function/function_array_zip_test.cpp
@@ -86,12 +86,12 @@ Status execute_array_zip(ColumnPtr lhs, ColumnPtr rhs, const DataTypePtr& lhs_ty
 
     FunctionUtils fn_utils(result_type, {lhs_type, rhs_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
     block->insert({nullptr, result_type, "result"});
     auto status = function->execute(fn_ctx, *block, {0, 1}, 2, rows);
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    RETURN_IF_ERROR(function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     return status;
 }
 
diff --git a/be/test/exprs/function/function_constant_argument_test.cpp b/be/test/exprs/function/function_constant_argument_test.cpp
index d8341e7a0ed..b0fff06b039 100644
--- a/be/test/exprs/function/function_constant_argument_test.cpp
+++ b/be/test/exprs/function/function_constant_argument_test.cpp
@@ -72,8 +72,9 @@ protected:
         FunctionUtils fn_utils(return_type, arg_types, false);
         auto* fn_ctx = fn_utils.get_fn_ctx();
         fn_ctx->set_constant_cols(constant_cols);
-        RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        RETURN_IF_ERROR(
+                function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        RETURN_IF_ERROR(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
         Status status;
         for (auto& block : blocks) {
             size_t rows = block.rows();
@@ -83,8 +84,10 @@ protected:
                 break;
             }
         }
-        static_cast<void>(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(
+                function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(
+                function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         return status;
     }
 
diff --git a/be/test/exprs/function/function_geo_test.cpp b/be/test/exprs/function/function_geo_test.cpp
index b4993a231e8..1bae14ba215 100644
--- a/be/test/exprs/function/function_geo_test.cpp
+++ b/be/test/exprs/function/function_geo_test.cpp
@@ -43,7 +43,7 @@ TEST(VGeoFunctionsTest, function_geo_st_point_test) {
 
     GeoPoint point;
     auto cur_res = point.from_coord(24.7, 56.7);
-    EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
     std::string buf;
     point.encode_to(&buf);
 
@@ -84,7 +84,7 @@ TEST(VGeoFunctionsTest, function_geo_st_as_text) {
 
         GeoPoint point;
         auto cur_res = point.from_coord(24.7, 56.7);
-        EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
         std::string buf;
         point.encode_to(&buf);
 
@@ -101,7 +101,7 @@ TEST(VGeoFunctionsTest, function_geo_st_as_wkt) {
 
         GeoPoint point;
         auto cur_res = point.from_coord(24.7, 56.7);
-        EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
         std::string buf;
         point.encode_to(&buf);
 
@@ -118,7 +118,7 @@ TEST(VGeoFunctionsTest, function_geo_st_x) {
 
         GeoPoint point;
         auto cur_res = point.from_coord(24.7, 56.7);
-        EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
         std::string buf;
         point.encode_to(&buf);
 
@@ -135,7 +135,7 @@ TEST(VGeoFunctionsTest, function_geo_st_y) {
 
         GeoPoint point;
         auto cur_res = point.from_coord(24.7, 56.7);
-        EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
         std::string buf;
         point.encode_to(&buf);
 
@@ -195,13 +195,13 @@ TEST(VGeoFunctionsTest, function_geo_st_angle) {
 
         GeoPoint point1;
         auto cur_res1 = point1.from_coord(1, 0);
-        EXPECT_TRUE(cur_res1 == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res1 == GeoParseStatus::GEO_PARSE_OK);
         GeoPoint point2;
         auto cur_res2 = point2.from_coord(0, 0);
-        EXPECT_TRUE(cur_res2 == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res2 == GeoParseStatus::GEO_PARSE_OK);
         GeoPoint point3;
         auto cur_res3 = point3.from_coord(0, 1);
-        EXPECT_TRUE(cur_res3 == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res3 == GeoParseStatus::GEO_PARSE_OK);
         std::string buf1;
         point1.encode_to(&buf1);
         std::string buf2;
@@ -222,10 +222,10 @@ TEST(VGeoFunctionsTest, function_geo_st_azimuth) {
     std::string func_name = "st_azimuth";
     GeoPoint point1;
     auto cur_res1 = point1.from_coord(0, 0);
-    EXPECT_TRUE(cur_res1 == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res1 == GeoParseStatus::GEO_PARSE_OK);
     GeoPoint point2;
     auto cur_res2 = point2.from_coord(1, 0);
-    EXPECT_TRUE(cur_res2 == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res2 == GeoParseStatus::GEO_PARSE_OK);
 
     std::string buf1;
     point1.encode_to(&buf1);
@@ -272,18 +272,18 @@ TEST(VGeoFunctionsTest, function_geo_st_contains) {
 
     std::string shape1 = std::string("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))");
     std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(shape1.data(), shape1.size(), status));
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
     shape->encode_to(&buf1);
 
     GeoPoint point1;
     status = point1.from_coord(5, 5);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     point1.encode_to(&buf2);
 
     GeoPoint point2;
     status = point2.from_coord(50, 50);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     point2.encode_to(&buf3);
 
     DataSet data_set = {{{buf1, buf2}, (uint8_t)1},
@@ -326,7 +326,7 @@ TEST(VGeoFunctionsTest, function_geo_st_circle) {
         GeoCircle circle;
         std::string buf;
         auto value = circle.init(111, 64, 10000);
-        EXPECT_TRUE(value == GEO_PARSE_OK);
+        EXPECT_TRUE(value == GeoParseStatus::GEO_PARSE_OK);
         circle.encode_to(&buf);
         DataSet data_set = {{{(double)111, (double)64, (double)10000}, buf},
                             {{Null(), (double)64, (double)10000}, Null()},
@@ -347,7 +347,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geometryfromtext) {
         std::string input = "LINESTRING (1 1, 2 2)";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{std::string("LINESTRING (1 1, 2 2)")}, buf}, {{Null()}, Null()}};
 
@@ -365,7 +365,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geomfromtext) {
         std::string input = "LINESTRING (1 1, 2 2)";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{std::string("LINESTRING (1 1, 2 2)")}, buf}, {{Null()}, Null()}};
 
@@ -383,7 +383,7 @@ TEST(VGeoFunctionsTest, function_geo_st_linefromtext) {
         std::string input = "LINESTRING (1 1, 2 2)";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{std::string("LINESTRING (1 1, 2 2)")}, buf}, {{Null()}, Null()}};
 
@@ -401,7 +401,7 @@ TEST(VGeoFunctionsTest, function_geo_st_polygon) {
         std::string input = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{std::string("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")}, buf},
                             {{Null()}, Null()}};
@@ -420,7 +420,7 @@ TEST(VGeoFunctionsTest, function_geo_st_polygonfromtext) {
         std::string input = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{std::string("POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))")}, buf},
                             {{Null()}, Null()}};
@@ -436,7 +436,7 @@ TEST(VGeoFunctionsTest, function_geo_st_area_square_meters) {
 
         GeoCircle circle;
         auto cur_res = circle.init(0, 0, 1);
-        EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+        EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
         std::string buf;
         circle.encode_to(&buf);
         DataSet data_set = {{{buf}, (double)3.1415926535897869}, {{Null()}, Null()}};
@@ -455,7 +455,7 @@ TEST(VGeoFunctionsTest, function_geo_st_area_square_km) {
         std::string input = "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))";
         std::unique_ptr<GeoShape> shape(GeoShape::from_wkt(input.data(), input.size(), status));
         EXPECT_TRUE(shape != nullptr);
-        EXPECT_TRUE(status == GEO_PARSE_OK);
+        EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
         shape->encode_to(&buf);
         DataSet data_set = {{{buf}, (double)12364.036567076409}, {{Null()}, Null()}};
 
diff --git a/be/test/exprs/function/function_hash_test.cpp b/be/test/exprs/function/function_hash_test.cpp
index 2d3f2ad1cc0..533292f0efa 100644
--- a/be/test/exprs/function/function_hash_test.cpp
+++ b/be/test/exprs/function/function_hash_test.cpp
@@ -187,16 +187,16 @@ TEST(HashFunctionTest, murmur_hash_3_128_empty_arguments_test) {
 
         FunctionUtils fn_utils(return_type, {}, false);
         auto* fn_ctx = fn_utils.get_fn_ctx();
-        ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-        ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+        ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+        ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
         block.insert({nullptr, return_type, "result"});
         const auto st = func->execute(fn_ctx, block, {}, 0, 1);
         EXPECT_FALSE(st.ok());
         EXPECT_NE(st.to_string().find("requires at least one argument"), std::string::npos);
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     check_empty_arguments("murmur_hash3_128", std::make_shared<DataTypeInt128>());
diff --git a/be/test/exprs/function/function_if_test.cpp b/be/test/exprs/function/function_if_test.cpp
index 83c2a6f1fca..e06aadb4d8b 100644
--- a/be/test/exprs/function/function_if_test.cpp
+++ b/be/test/exprs/function/function_if_test.cpp
@@ -74,12 +74,12 @@ TEST(FunctionIfTest, NullableConditionNotPolluteSharedNestedColumn) {
 
     FunctionUtils fn_utils(bool_type, {nullable_bool_type, bool_type, bool_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     auto st = func->execute(fn_ctx, block, {0, 1, 2}, 3, 2);
     ASSERT_TRUE(st.ok()) << st.to_string();
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     const auto& result_data =
             assert_cast<const ColumnUInt8&>(*block.get_by_position(3).column).get_data();
diff --git a/be/test/exprs/function/function_jsonb_test.cpp b/be/test/exprs/function/function_jsonb_test.cpp
index 51b68c976c4..4ef40ee3e1f 100644
--- a/be/test/exprs/function/function_jsonb_test.cpp
+++ b/be/test/exprs/function/function_jsonb_test.cpp
@@ -89,14 +89,14 @@ Status execute_json_keys_with_path(ColumnPtr path_column, size_t rows) {
 
     FunctionUtils fn_utils(return_type, {jsonb_type, path_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0, 1}, block.columns() - 1, rows);
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     return st;
 }
 
@@ -197,8 +197,8 @@ TEST(FunctionJsonbTEST, JsonbParseConstNullableInputWithNonConstDefaultMultiRows
 
     FunctionUtils fn_utils(return_type, {input_type, default_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto result = block.columns() - 1;
@@ -217,8 +217,8 @@ TEST(FunctionJsonbTEST, JsonbParseConstNullableInputWithNonConstDefaultMultiRows
         EXPECT_EQ(0, result_col->compare_at(i, i, *expected_col, 1));
     }
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 TEST(FunctionJsonbTEST, JsonbParseErrorToNullTest) {
@@ -957,9 +957,9 @@ TEST(FunctionJsonbTEST, JsonLength) {
     FunctionUtils fn_utils(return_type, arg_types, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     //     fn_ctx->set_constant_cols(constant_cols);
-    auto st = func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
+    auto st = func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     ASSERT_TRUE(st.ok()) << "open failed: " << st.to_string();
-    st = func->open(fn_ctx, FunctionContext::THREAD_LOCAL);
+    st = func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL);
     ASSERT_TRUE(st.ok()) << "open failed: " << st.to_string();
 
     block.insert({nullptr, return_type, "result"});
@@ -990,8 +990,8 @@ TEST(FunctionJsonbTEST, JsonLengthConstNullablePathMultiRows) {
 
     FunctionUtils fn_utils(return_type, {jsonb_type, path_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     ASSERT_TRUE(func->execute(fn_ctx, block, {0, 1}, 2, rows).ok());
@@ -1021,8 +1021,8 @@ TEST(FunctionJsonbTEST, JsonLengthConstJsonVaryingPathMultiRows) {
 
     FunctionUtils fn_utils(return_type, {jsonb_type, path_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     ASSERT_TRUE(func->execute(fn_ctx, block, {0, 1}, 2, rows).ok());
@@ -1090,9 +1090,9 @@ TEST(FunctionJsonbTEST, JsonContains) {
     FunctionUtils fn_utils(return_type, arg_types, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     //     fn_ctx->set_constant_cols(constant_cols);
-    auto st = func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
+    auto st = func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL);
     ASSERT_TRUE(st.ok()) << "open failed: " << st.to_string();
-    st = func->open(fn_ctx, FunctionContext::THREAD_LOCAL);
+    st = func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL);
     ASSERT_TRUE(st.ok()) << "open failed: " << st.to_string();
 
     block.insert({nullptr, return_type, "result"});
@@ -1127,8 +1127,8 @@ TEST(FunctionJsonbTEST, JsonContainsConstNullablePathMultiRows) {
 
     FunctionUtils fn_utils(return_type, {jsonb_type, jsonb_type, path_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     ASSERT_TRUE(func->execute(fn_ctx, block, {0, 1, 2}, 3, rows).ok());
diff --git a/be/test/exprs/function/function_like_test.cpp b/be/test/exprs/function/function_like_test.cpp
index 63b51912180..42fb0be73ed 100644
--- a/be/test/exprs/function/function_like_test.cpp
+++ b/be/test/exprs/function/function_like_test.cpp
@@ -89,7 +89,8 @@ Status execute_single_pattern(const TQueryOptions& query_options, const std::str
     context->set_constant_cols(constant_columns);
 
     Function function;
-    RETURN_IF_ERROR(function.open(context.get(), FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(
+            function.open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
     Block block;
     block.insert({std::move(values), string_type, "value"});
@@ -148,7 +149,7 @@ void check_constant_pattern_batch(const std::vector<std::string>& values,
     context->set_constant_cols(constant_columns);
 
     Function function;
-    auto status = function.open(context.get(), FunctionContext::THREAD_LOCAL);
+    auto status = function.open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
     ASSERT_TRUE(status.ok()) << status.to_string();
 
     Block block;
@@ -624,8 +625,10 @@ TEST(FunctionLikeTest, regexp_extract_all_array) { // NOLINT(readability-functio
         fn_ctx->set_constant_cols(
                 {nullptr, std::make_shared<ColumnPtrWrapper>(block.get_by_position(1).column)});
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, {0, 1}, 2, 1));
 
         auto result_col = block.get_by_position(2).column;
@@ -639,8 +642,8 @@ TEST(FunctionLikeTest, regexp_extract_all_array) { // NOLINT(readability-functio
                     << "input: '" << str << "', pattern: '" << pattern << "'";
         }
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     run_case("x=a3&x=18abc&x=2&y=3&x=4&x=17bcd", "x=([0-9]+)([a-z]+)", R"(["18", "17"])");
@@ -702,15 +705,17 @@ TEST(FunctionLikeTest, regexp_extract_all_array) { // NOLINT(readability-functio
         fn_ctx->set_constant_cols(
                 {nullptr, std::make_shared<ColumnPtrWrapper>(block.get_by_position(1).column)});
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, {0, 1}, 2, 1));
 
         EXPECT_TRUE(block.get_by_position(2).column->is_null_at(0))
                 << "Expected null for null_str=" << null_str << " null_pattern=" << null_pattern;
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     // NULL input string → null result
@@ -740,12 +745,14 @@ TEST(FunctionLikeTest, regexp_extract_all_array) { // NOLINT(readability-functio
         fn_ctx->set_constant_cols(
                 {nullptr, std::make_shared<ColumnPtrWrapper>(block.get_by_position(1).column)});
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
         // Invalid pattern should cause open() to fail for THREAD_LOCAL scope
-        EXPECT_NE(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        EXPECT_NE(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     }
 }
 
@@ -782,8 +789,10 @@ TEST(FunctionLikeTest, regexp_extract_all_boost_zero_width_match) {
         fn_ctx->set_constant_cols(
                 {nullptr, std::make_shared<ColumnPtrWrapper>(block.get_by_position(1).column)});
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, {0, 1}, 2, 1));
 
         auto result_col = block.get_by_position(2).column;
@@ -792,8 +801,8 @@ TEST(FunctionLikeTest, regexp_extract_all_boost_zero_width_match) {
         EXPECT_EQ(expected, return_type->to_string(*result_col, 0))
                 << func_name << " input: '" << str << "', pattern: '" << pattern << "'";
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     auto string_type = make_nullable(std::make_shared<DataTypeString>());
@@ -968,16 +977,18 @@ TEST(FunctionLikeTest, regexp_invalid_column_pattern_fails) {
         auto* fn_ctx = fn_utils.get_fn_ctx();
         fn_ctx->set_constant_cols(constant_cols);
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
         auto st = func->execute(fn_ctx, block, arguments, result, strs.size());
         EXPECT_TRUE(st.is<ErrorCode::INVALID_ARGUMENT>()) << func_name << ": " << st;
         EXPECT_NE(st.to_string().find(expected_error), std::string::npos)
                 << func_name << ": " << st;
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     auto nullable_str = make_nullable(str_type);
@@ -1091,8 +1102,12 @@ TEST(FunctionLikeTest, regexp_null_pattern_hides_invalid_payload) {
         auto* fn_ctx = fn_utils.get_fn_ctx();
         fn_ctx->set_constant_cols(constant_cols);
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL)) << func_name;
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL)) << func_name;
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL))
+                << func_name;
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL))
+                << func_name;
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, arguments, result, strs.size()))
                 << func_name;
 
@@ -1108,8 +1123,8 @@ TEST(FunctionLikeTest, regexp_null_pattern_hides_invalid_payload) {
         }
         EXPECT_TRUE(result_column->is_null_at(1)) << func_name;
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     for (const char* func_name : {"regexp_extract", "regexp_extract_or_null"}) {
@@ -1223,8 +1238,10 @@ TEST(FunctionLikeTest, regexp_count_non_nullable_arguments) {
         auto* fn_ctx = fn_utils.get_fn_ctx();
         fn_ctx->set_constant_cols(constant_cols);
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, arguments, result, strs.size()));
 
         const auto& result_column = block.get_by_position(result).column;
@@ -1241,8 +1258,8 @@ TEST(FunctionLikeTest, regexp_count_non_nullable_arguments) {
             EXPECT_EQ(expected[i], data[i]) << "row " << i;
         }
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     for (const auto& return_type : {DataTypePtr(int32_type), make_nullable(int32_type)}) {
@@ -1312,8 +1329,12 @@ TEST(FunctionLikeTest, regexp_non_nullable_arguments) {
         auto* fn_ctx = fn_utils.get_fn_ctx();
         fn_ctx->set_constant_cols(constant_cols);
 
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL)) << func_name;
-        ASSERT_EQ(Status::OK(), func->open(fn_ctx, FunctionContext::THREAD_LOCAL)) << func_name;
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL))
+                << func_name;
+        ASSERT_EQ(Status::OK(),
+                  func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL))
+                << func_name;
         ASSERT_EQ(Status::OK(), func->execute(fn_ctx, block, arguments, result, strs.size()))
                 << func_name;
 
@@ -1330,8 +1351,8 @@ TEST(FunctionLikeTest, regexp_non_nullable_arguments) {
             }
         }
 
-        static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-        static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+        static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     };
 
     auto nullable_array = make_nullable(std::make_shared<DataTypeArray>(nullable_str));
diff --git a/be/test/exprs/function/function_match_test.cpp b/be/test/exprs/function/function_match_test.cpp
index 8add5fc8f7f..476a3fa9b9b 100644
--- a/be/test/exprs/function/function_match_test.cpp
+++ b/be/test/exprs/function/function_match_test.cpp
@@ -825,7 +825,7 @@ TEST(FunctionMatchTest, null_array_elements_do_not_match_hidden_payload) {
             &runtime_state, std::make_shared<DataTypeUInt8>(), {array_type, string_type});
     auto analyzer_ctx = std::make_shared<InvertedIndexAnalyzerCtx>();
     analyzer_ctx->parser_type = InvertedIndexParserType::PARSER_NONE;
-    context->set_function_state(FunctionContext::FRAGMENT_LOCAL, analyzer_ctx);
+    context->set_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL, analyzer_ctx);
 
     auto check_match = [&](const FunctionMatchBase& function) {
         auto values = ColumnString::create();
diff --git a/be/test/exprs/function/function_math_test.cpp b/be/test/exprs/function/function_math_test.cpp
index cdf4346cfa1..463d9bf4a5c 100644
--- a/be/test/exprs/function/function_math_test.cpp
+++ b/be/test/exprs/function/function_math_test.cpp
@@ -387,11 +387,11 @@ static void check_pow_square_column_shapes(const std::string& name, bool nullabl
     block.insert({nullptr, type, "result"});
     FunctionUtils fn_utils(type, {type, type}, false);
     auto* context = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->open(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     const auto status = function->execute(context, block, {0, 1}, 2, rows);
-    EXPECT_TRUE(function->close(context, FunctionContext::THREAD_LOCAL).ok());
-    EXPECT_TRUE(function->close(context, FunctionContext::FRAGMENT_LOCAL).ok());
+    EXPECT_TRUE(function->close(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
+    EXPECT_TRUE(function->close(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
     ASSERT_TRUE(status.ok()) << status.to_string();
     auto result = block.get_by_position(2).column->convert_to_full_column_if_const();
     check_pow_square_result(*result, values, nullable, const_mask & 1);
@@ -762,13 +762,13 @@ TEST(MathFunctionTest, uniform_mixed_const_probe_test) {
     };
     fn_ctx->set_constant_cols(constant_cols);
 
-    ASSERT_TRUE(function->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(function->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     auto exec_status = function->execute(fn_ctx, block, {0, 1, 2}, 3, 3);
 
-    static_cast<void>(function->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(function->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(function->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     ASSERT_TRUE(exec_status.ok()) << exec_status.to_string();
 
diff --git a/be/test/exprs/function/function_test_util.h b/be/test/exprs/function/function_test_util.h
index 95fa7b2b6be..72473ba3455 100644
--- a/be/test/exprs/function/function_test_util.h
+++ b/be/test/exprs/function/function_test_util.h
@@ -409,8 +409,8 @@ Status check_function(const std::string& func_name, const InputTypeSet& input_ty
     FunctionUtils fn_utils(fn_ctx_return, arg_types, is_strict_mode);
     auto* fn_ctx = fn_utils.get_fn_ctx();
     fn_ctx->set_constant_cols(constant_cols);
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
-    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
+    RETURN_IF_ERROR(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
 
     block.insert({nullptr, return_type, "result"});
 
@@ -427,8 +427,8 @@ Status check_function(const std::string& func_name, const InputTypeSet& input_ty
         }
     }
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     // 3.0. create expected result column in block
     DataTypePtr result_type_ptr;
diff --git a/be/test/exprs/function/function_time_test.cpp b/be/test/exprs/function/function_time_test.cpp
index 7f0a343f71d..62d5acfb7b5 100644
--- a/be/test/exprs/function/function_time_test.cpp
+++ b/be/test/exprs/function/function_time_test.cpp
@@ -2024,8 +2024,8 @@ TEST(VTimestampFunctionsTest, curtime_test) {
         FunctionUtils fn_utils(fn_ctx_return, arg_types, false);
         auto* fn_ctx = fn_utils.get_fn_ctx();
 
-        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
         block.insert({nullptr, return_type, "result"});
         ColumnNumbers args;
@@ -2040,8 +2040,8 @@ TEST(VTimestampFunctionsTest, curtime_test) {
             EXPECT_LE(time_value, 24.0 * 3600 * 1000000);
         }
 
-        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
-        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
+        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
+        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
     }
 
     // Test curtime with precision
@@ -2067,8 +2067,8 @@ TEST(VTimestampFunctionsTest, curtime_test) {
         FunctionUtils fn_utils(fn_ctx_return, arg_types, false);
         auto* fn_ctx = fn_utils.get_fn_ctx();
 
-        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+        EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
         block.insert({nullptr, return_type, "result"});
         ColumnNumbers args = {0};
@@ -2083,8 +2083,8 @@ TEST(VTimestampFunctionsTest, curtime_test) {
             EXPECT_LE(time_value, 24.0 * 3600 * 1000000);
         }
 
-        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
-        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
+        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
+        EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
     }
 }
 
diff --git a/be/test/exprs/function/function_varbinary_test.cpp b/be/test/exprs/function/function_varbinary_test.cpp
index 3de706661ec..d9fadb9c50e 100644
--- a/be/test/exprs/function/function_varbinary_test.cpp
+++ b/be/test/exprs/function/function_varbinary_test.cpp
@@ -32,9 +32,13 @@ TEST(function_binary_test, in_and_not_in_are_not_supported) {
         const DataTypes arguments {type, type};
         auto context = FunctionContext::create_context(
                 &state, make_nullable(std::make_shared<DataTypeUInt8>()), arguments);
-        EXPECT_EQ(FunctionIn<false>().open(context.get(), FunctionContext::FRAGMENT_LOCAL).code(),
+        EXPECT_EQ(FunctionIn<false>()
+                          .open(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                          .code(),
                   ErrorCode::NOT_IMPLEMENTED_ERROR);
-        EXPECT_EQ(FunctionIn<true>().open(context.get(), FunctionContext::FRAGMENT_LOCAL).code(),
+        EXPECT_EQ(FunctionIn<true>()
+                          .open(context.get(), FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                          .code(),
                   ErrorCode::NOT_IMPLEMENTED_ERROR);
     }
 }
diff --git a/be/test/exprs/function/function_variant_parse_test.cpp b/be/test/exprs/function/function_variant_parse_test.cpp
index fa016667692..9cdfcbccc7c 100644
--- a/be/test/exprs/function/function_variant_parse_test.cpp
+++ b/be/test/exprs/function/function_variant_parse_test.cpp
@@ -99,11 +99,12 @@ ExecutionResult execute_parse(std::string_view function_name, ColumnPtr input,
 
     FunctionUtils function_utils(result_type, {input_type}, false);
     FunctionContext* context = function_utils.get_fn_ctx();
-    DORIS_CHECK(function->open(context, FunctionContext::FRAGMENT_LOCAL).ok());
-    DORIS_CHECK(function->open(context, FunctionContext::THREAD_LOCAL).ok());
+    DORIS_CHECK(function->open(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    DORIS_CHECK(function->open(context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
     Status status = function->execute(context, block, {0}, 1, rows);
-    static_cast<void>(function->close(context, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(function->close(context, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(function->close(context, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(
+            function->close(context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
     return {.status = std::move(status),
             .output = block.get_by_position(1).column,
             .return_type = function->get_return_type()};
diff --git a/be/test/exprs/function/geo/functions_geo_test.cpp b/be/test/exprs/function/geo/functions_geo_test.cpp
index 0dce1c876ab..bf25ed2baa9 100644
--- a/be/test/exprs/function/geo/functions_geo_test.cpp
+++ b/be/test/exprs/function/geo/functions_geo_test.cpp
@@ -51,7 +51,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numgeometries_point) {
 
     GeoPoint point;
     auto cur_res = point.from_coord(24.7, 56.7);
-    EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
     std::string buf;
     point.encode_to(&buf);
 
@@ -67,7 +67,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numgeometries_linestring) {
     GeoParseStatus status;
     std::string linestring_wkt = "LINESTRING (30 10, 10 30, 40 40)";
     auto shape = GeoShape::from_wkt(linestring_wkt.data(), linestring_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -86,7 +86,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numgeometries_polygon) {
     GeoParseStatus status;
     std::string polygon_wkt = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))";
     auto shape = GeoShape::from_wkt(polygon_wkt.data(), polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -107,7 +107,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numgeometries_multipolygon) {
             "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 "
             "20)))";
     auto shape = GeoShape::from_wkt(multi_polygon_wkt.data(), multi_polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -138,7 +138,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numpoints_point) {
 
     GeoPoint point;
     auto cur_res = point.from_coord(24.7, 56.7);
-    EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
     std::string buf;
     point.encode_to(&buf);
 
@@ -155,7 +155,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numpoints_linestring) {
     GeoParseStatus status;
     std::string linestring_wkt = "LINESTRING (30 10, 10 30, 40 40)";
     auto shape = GeoShape::from_wkt(linestring_wkt.data(), linestring_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -174,7 +174,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numpoints_polygon) {
     GeoParseStatus status;
     std::string polygon_wkt = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))";
     auto shape = GeoShape::from_wkt(polygon_wkt.data(), polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -195,7 +195,7 @@ TEST(VGeoFunctionsTest, function_geo_st_numpoints_multipolygon) {
             "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 "
             "20)))";
     auto shape = GeoShape::from_wkt(multi_polygon_wkt.data(), multi_polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string buf;
@@ -227,7 +227,7 @@ TEST(VGeoFunctionsTest, function_geo_st_isclosed) {
     auto encode_wkt = [](const std::string& wkt) {
         GeoParseStatus status;
         auto shape = GeoShape::from_wkt(wkt.data(), wkt.size(), status);
-        EXPECT_EQ(status, GEO_PARSE_OK);
+        EXPECT_EQ(status, GeoParseStatus::GEO_PARSE_OK);
         EXPECT_NE(shape, nullptr);
 
         std::string buf;
@@ -258,7 +258,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_point) {
     // Prepare input: a single point
     GeoPoint point;
     auto cur_res = point.from_coord(24.7, 56.7);
-    EXPECT_TRUE(cur_res == GEO_PARSE_OK);
+    EXPECT_TRUE(cur_res == GeoParseStatus::GEO_PARSE_OK);
     std::string point_buf;
     point.encode_to(&point_buf);
 
@@ -278,8 +278,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_point) {
 
     FunctionUtils fn_utils(return_type, {input_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0}, block.columns() - 1, 1);
@@ -293,8 +293,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_point) {
     auto* nullable_col = assert_cast<const ColumnNullable*>(result_col.get());
     EXPECT_FALSE(nullable_col->is_null_at(0));
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 TEST(VGeoFunctionsTest, function_geo_st_geometries_multipolygon) {
@@ -306,7 +306,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_multipolygon) {
             "MULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 "
             "20)))";
     auto shape = GeoShape::from_wkt(multi_polygon_wkt.data(), multi_polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string multi_buf;
@@ -328,8 +328,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_multipolygon) {
 
     FunctionUtils fn_utils(return_type, {input_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0}, block.columns() - 1, 1);
@@ -349,8 +349,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_multipolygon) {
     auto& offsets = array_col->get_offsets();
     EXPECT_EQ(offsets[0], 2); // 2 polygons in the array
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 TEST(VGeoFunctionsTest, function_geo_st_geometries_null_input) {
@@ -372,8 +372,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_null_input) {
 
     FunctionUtils fn_utils(return_type, {input_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0}, block.columns() - 1, 1);
@@ -385,8 +385,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_null_input) {
     // Result column may be ColumnConst (optimization for all-null input) or ColumnNullable
     EXPECT_TRUE(result_col->is_null_at(0));
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 TEST(VGeoFunctionsTest, function_geo_st_geometries_invalid) {
@@ -413,8 +413,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_invalid) {
 
     FunctionUtils fn_utils(return_type, {input_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0}, block.columns() - 1, 1);
@@ -426,8 +426,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_invalid) {
     auto* nullable_col = assert_cast<const ColumnNullable*>(result_col.get());
     EXPECT_TRUE(nullable_col->is_null_at(0));
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 TEST(VGeoFunctionsTest, function_geo_st_geometries_single_polygon) {
@@ -437,7 +437,7 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_single_polygon) {
     GeoParseStatus status;
     std::string polygon_wkt = "POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))";
     auto shape = GeoShape::from_wkt(polygon_wkt.data(), polygon_wkt.size(), status);
-    EXPECT_TRUE(status == GEO_PARSE_OK);
+    EXPECT_TRUE(status == GeoParseStatus::GEO_PARSE_OK);
     EXPECT_TRUE(shape != nullptr);
 
     std::string polygon_buf;
@@ -459,8 +459,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_single_polygon) {
 
     FunctionUtils fn_utils(return_type, {input_type}, false);
     auto* fn_ctx = fn_utils.get_fn_ctx();
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(func->open(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 
     block.insert({nullptr, return_type, "result"});
     auto st = func->execute(fn_ctx, block, {0}, block.columns() - 1, 1);
@@ -480,8 +480,8 @@ TEST(VGeoFunctionsTest, function_geo_st_geometries_single_polygon) {
     auto& offsets = array_col->get_offsets();
     EXPECT_EQ(offsets[0], 1); // 1 polygon in the array
 
-    static_cast<void>(func->close(fn_ctx, FunctionContext::THREAD_LOCAL));
-    static_cast<void>(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    static_cast<void>(func->close(fn_ctx, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 }
 
 } // namespace doris
diff --git a/be/test/exprs/function/geo/geo_types_test.cpp b/be/test/exprs/function/geo/geo_types_test.cpp
index abc274ccca1..695040f73e8 100644
--- a/be/test/exprs/function/geo/geo_types_test.cpp
+++ b/be/test/exprs/function/geo/geo_types_test.cpp
@@ -38,7 +38,7 @@ TEST_F(GeoTypesTest, point_normal) {
     {
         GeoPoint point;
         auto status = point.from_coord(116.123, 63.546);
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_STREQ("POINT (116.123 63.546)", point.as_wkt().c_str());
 
         std::string buf;
@@ -60,7 +60,7 @@ TEST_F(GeoTypesTest, point_normal) {
         coord.x = 116.123;
         coord.y = 63.546;
         auto status = point.from_coord(coord);
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_STREQ("POINT (116.123 63.546)", point.as_wkt().c_str());
     }
 }
@@ -69,7 +69,7 @@ TEST_F(GeoTypesTest, point_invalid) {
     GeoPoint point;
 
     auto status = point.from_coord(200, 88);
-    EXPECT_NE(GEO_PARSE_OK, status);
+    EXPECT_NE(GeoParseStatus::GEO_PARSE_OK, status);
 }
 
 TEST_F(GeoTypesTest, linestring) {
@@ -77,7 +77,7 @@ TEST_F(GeoTypesTest, linestring) {
     GeoParseStatus status;
     auto line = GeoShape::from_wkt(wkt, strlen(wkt), status);
     EXPECT_NE(nullptr, line.get());
-    EXPECT_EQ(GEO_SHAPE_LINE_STRING, line->type());
+    EXPECT_EQ(GeoShapeType::GEO_SHAPE_LINE_STRING, line->type());
 
     EXPECT_STREQ(wkt, line->as_wkt().c_str());
 
@@ -162,7 +162,7 @@ TEST_F(GeoTypesTest, point_intersects) {
     {
         auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, shape.get());
-        EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_POLYGON, shape->type());
     }
     {
         buf.resize(buf.size() - 1);
@@ -290,7 +290,7 @@ TEST_F(GeoTypesTest, linestring_intersects) {
     {
         auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_LINE_STRING, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_LINE_STRING, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
@@ -466,7 +466,7 @@ TEST_F(GeoTypesTest, polygon_intersects) {
     {
         auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_POLYGON, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_POLYGON, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
@@ -616,7 +616,7 @@ TEST_F(GeoTypesTest, multipolygon_intersects) {
     {
         auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_MULTI_POLYGON, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_MULTI_POLYGON, decoded->type());
 
         GeoPoint point;
         point.from_coord(20, 5);
@@ -634,7 +634,7 @@ TEST_F(GeoTypesTest, circle_intersect) {
 
     GeoCircle circle;
     auto res = circle.init(0, 0, 10);
-    EXPECT_EQ(GEO_PARSE_OK, res);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
 
     // ======================
     // Circle vs Point
@@ -770,7 +770,7 @@ TEST_F(GeoTypesTest, point_touches) {
     {
         auto shape = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, shape.get());
-        EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_POLYGON, shape->type());
     }
     {
         buf.resize(buf.size() - 1);
@@ -916,7 +916,7 @@ TEST_F(GeoTypesTest, linestring_touches) {
     {
         auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_LINE_STRING, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_LINE_STRING, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
@@ -1092,7 +1092,7 @@ TEST_F(GeoTypesTest, polygon_touches) {
     {
         auto decoded = GeoShape::from_encoded(buf.data(), buf.size());
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_POLYGON, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_POLYGON, decoded->type());
     }
     {
         buf.resize(buf.size() - 2);
@@ -1239,7 +1239,7 @@ TEST_F(GeoTypesTest, multipolygon_touches) {
     {
         auto decoded(GeoShape::from_encoded(buf.data(), buf.size()));
         ASSERT_NE(nullptr, decoded.get());
-        EXPECT_EQ(GEO_SHAPE_MULTI_POLYGON, decoded->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_MULTI_POLYGON, decoded->type());
 
         GeoPoint point;
         point.from_coord(10, 5);
@@ -1257,7 +1257,7 @@ TEST_F(GeoTypesTest, circle_touches) {
 
     GeoCircle circle;
     auto res = circle.init(0, 0, 10);
-    EXPECT_EQ(GEO_PARSE_OK, res);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
 
     // ======================
     // Circle vs Point
@@ -1280,7 +1280,7 @@ TEST_F(GeoTypesTest, circle_touches) {
     {
         GeoCircle circle2;
         auto res = circle2.init(1, 1, 1);
-        EXPECT_EQ(GEO_PARSE_OK, res);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
         GeoPoint point;
         point.from_coord(2, 1);
         EXPECT_TRUE(circle2.touches(&point));
@@ -1394,7 +1394,7 @@ TEST_F(GeoTypesTest, test_geometry_type) {
     {
         GeoCircle circle;
         auto res = circle.init(110.123, 64, 1000);
-        EXPECT_EQ(GEO_PARSE_OK, res);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
         EXPECT_STREQ("ST_CIRCLE", circle.GeometryType().c_str());
     }
 }
@@ -1463,7 +1463,7 @@ TEST_F(GeoTypesTest, test_length) {
     {
         GeoCircle circle;
         auto res = circle.init(0, 0, 1000); // 1000 meters radius
-        EXPECT_EQ(GEO_PARSE_OK, res);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
         double circumference = circle.Length();
         EXPECT_GT(circumference, 0.0);
         // Expected circumference: 2 * pi * 1000 ≈ 6283 meters
@@ -1914,7 +1914,7 @@ TEST_F(GeoTypesTest, polygon_contains) {
 
     {
         auto shape(GeoShape::from_encoded(buf.data(), buf.size()));
-        EXPECT_EQ(GEO_SHAPE_POLYGON, shape->type());
+        EXPECT_EQ(GeoShapeType::GEO_SHAPE_POLYGON, shape->type());
         LOG(INFO) << "polygon=" << shape->as_wkt();
     }
 
@@ -1930,21 +1930,21 @@ TEST_F(GeoTypesTest, polygon_parse_fail) {
         const char* wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50), (10 10 01))";
         GeoParseStatus status;
         auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_WKT_SYNTAX_ERROR, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR, status);
         EXPECT_EQ(nullptr, polygon.get());
     }
     {
         const char* wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50))";
         GeoParseStatus status;
         auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_LOOP_NOT_CLOSED, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_LOOP_NOT_CLOSED, status);
         EXPECT_EQ(nullptr, polygon.get());
     }
     {
         const char* wkt = "POLYGON ((10 10, 50 10, 10 10))";
         GeoParseStatus status;
         auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_LOOP_LACK_VERTICES, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_LOOP_LACK_VERTICES, status);
         EXPECT_EQ(nullptr, polygon.get());
     }
 }
@@ -1955,7 +1955,7 @@ TEST_F(GeoTypesTest, polygon_hole_contains) {
             "20))";
     GeoParseStatus status;
     auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     EXPECT_NE(nullptr, polygon);
 
     {
@@ -2006,7 +2006,7 @@ TEST_F(GeoTypesTest, within) {
                 "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10), (20 20, 40 20, 40 40, 20 40, 20 "
                 "20))";
         auto polygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_NE(nullptr, polygon.get());
 
         GeoPoint point;
@@ -2070,7 +2070,7 @@ TEST_F(GeoTypesTest, within) {
 
         const char* wkt = "LINESTRING (2 5, 8 5)";
         auto line(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(line->within(polygon.get()));
     }
     {
@@ -2082,22 +2082,22 @@ TEST_F(GeoTypesTest, within) {
 
         const char* wkt_line = "LINESTRING(2 2, 8 2)";
         auto line(GeoShape::from_wkt(wkt_line, strlen(wkt_line), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(line->within(multipolygon.get()));
 
         wkt_line = "LINESTRING(16 6, 19 9)";
         auto line2(GeoShape::from_wkt(wkt_line, strlen(wkt_line), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(line2->within(multipolygon.get()));
 
         wkt_line = "LINESTRING(5 5, 16 7)";
         auto line3(GeoShape::from_wkt(wkt_line, strlen(wkt_line), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(line3->within(multipolygon.get()));
 
         wkt_line = "LINESTRING(0 0, 0 10)";
         auto line4(GeoShape::from_wkt(wkt_line, strlen(wkt_line), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(line4->within(multipolygon.get()));
     }
 
@@ -2112,17 +2112,17 @@ TEST_F(GeoTypesTest, within) {
 
         const char* wkt = "POLYGON ((3 3, 7 3, 7 7, 3 7, 3 3))";
         auto inner(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(inner->within(outer.get()));
 
         wkt = "POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))";
         auto overlapping(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(overlapping->within(outer.get()));
 
         wkt = "POLYGON ((20 20, 30 20, 30 30, 20 30, 20 20))";
         auto separate(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(separate->within(outer.get()));
     }
     {
@@ -2134,17 +2134,17 @@ TEST_F(GeoTypesTest, within) {
 
         const char* wkt_inner = "POLYGON((1 1, 1 9, 9 9, 9 1, 1 1))";
         auto inner(GeoShape::from_wkt(wkt_inner, strlen(wkt_inner), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(inner->within(multipolygon.get()));
 
         wkt_inner = "POLYGON((16 6, 16 9, 19 9, 19 6, 16 6))";
         auto inner2(GeoShape::from_wkt(wkt_inner, strlen(wkt_inner), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(inner2->within(multipolygon.get()));
 
         wkt_inner = "POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))";
         auto inner3(GeoShape::from_wkt(wkt_inner, strlen(wkt_inner), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(inner3->within(multipolygon.get()));
     }
 
@@ -2159,12 +2159,12 @@ TEST_F(GeoTypesTest, within) {
 
         const char* wkt = "MULTIPOLYGON(((2 2, 4 2, 4 4, 2 4, 2 2)), ((6 6, 8 6, 8 8, 6 8, 6 6)))";
         auto inner(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(inner->within(outer.get()));
 
         wkt = "MULTIPOLYGON(((2 2, 4 2, 4 4, 2 4, 2 2)), ((15 15, 25 15, 25 25, 15 25, 15 15)))";
         auto partial(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(partial->within(outer.get()));
     }
     {
@@ -2177,17 +2177,17 @@ TEST_F(GeoTypesTest, within) {
         const char* wkt =
                 "MULTIPOLYGON(((1 1, 1 9, 9 9, 9 1, 1 1)), ((16 6, 16 9, 19 9, 19 6, 16 6)))";
         auto inner(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_TRUE(inner->within(outer.get()));
 
         wkt = "MULTIPOLYGON(((1 1, 1 5, 5 5, 5 1, 1 1)), ((12 6, 12 9, 14 9, 14 6, 12 6)))";
         auto inner2(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(inner2->within(outer.get()));
 
         wkt = "MULTIPOLYGON(((1 1, 1 4, 4 4, 4 1, 1 1)), ((5 5, 5 11, 12 11, 12 5, 5 5)))";
         auto inner3(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_OK, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
         EXPECT_FALSE(inner3->within(outer.get()));
     }
 }
@@ -2197,21 +2197,21 @@ TEST_F(GeoTypesTest, multipolygon_parse_fail) {
         const char* wkt = "MULTIPOLYGON (((10 10, 50 10, 50 50, 10 50), (10 10 01)))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_WKT_SYNTAX_ERROR, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt = "MULTIPOLYGON (((10 10, 50 10, 50 50, 10 50)))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_LOOP_NOT_CLOSED, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_LOOP_NOT_CLOSED, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt = "MULTIPOLYGON (((10 10, 50 10, 10 10)))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_LOOP_LACK_VERTICES, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_LOOP_LACK_VERTICES, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
@@ -2221,7 +2221,7 @@ TEST_F(GeoTypesTest, multipolygon_parse_fail) {
                 "5)))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
@@ -2230,14 +2230,14 @@ TEST_F(GeoTypesTest, multipolygon_parse_fail) {
                 "6)))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_MULTIPOLYGON_OVERLAP, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
     {
         const char* wkt = "MULTIPOLYGON((()))";
         GeoParseStatus status;
         auto multipolygon(GeoShape::from_wkt(wkt, strlen(wkt), status));
-        EXPECT_EQ(GEO_PARSE_WKT_SYNTAX_ERROR, status);
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKT_SYNTAX_ERROR, status);
         EXPECT_EQ(nullptr, multipolygon.get());
     }
 }
@@ -2245,7 +2245,7 @@ TEST_F(GeoTypesTest, multipolygon_parse_fail) {
 TEST_F(GeoTypesTest, circle) {
     GeoCircle circle;
     auto res = circle.init(110.123, 64, 1000);
-    EXPECT_EQ(GEO_PARSE_OK, res);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, res);
 
     std::string buf;
     circle.encode_to(&buf);
diff --git a/be/test/exprs/function/geo/wkb_parse_test.cpp b/be/test/exprs/function/geo/wkb_parse_test.cpp
index dfea9031b23..d23a9151605 100644
--- a/be/test/exprs/function/geo/wkb_parse_test.cpp
+++ b/be/test/exprs/function/geo/wkb_parse_test.cpp
@@ -40,9 +40,9 @@ TEST_F(WkbParseTest, parse_point_little_endian_ndr) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     ASSERT_NE(nullptr, shape);
-    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+    EXPECT_EQ(GeoShapeType::GEO_SHAPE_POINT, shape->type());
     EXPECT_STREQ("POINT (1 2)", shape->as_wkt().c_str());
 }
 
@@ -53,9 +53,9 @@ TEST_F(WkbParseTest, parse_point_big_endian_xdr) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     ASSERT_NE(nullptr, shape);
-    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+    EXPECT_EQ(GeoShapeType::GEO_SHAPE_POINT, shape->type());
     EXPECT_STREQ("POINT (1 2)", shape->as_wkt().c_str());
 }
 
@@ -66,7 +66,7 @@ TEST_F(WkbParseTest, parse_invalid_byte_order_ff) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -77,7 +77,7 @@ TEST_F(WkbParseTest, parse_invalid_byte_order_02) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -87,7 +87,7 @@ TEST_F(WkbParseTest, parse_empty_stream) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -98,7 +98,7 @@ TEST_F(WkbParseTest, parse_insufficient_data) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -109,7 +109,7 @@ TEST_F(WkbParseTest, parse_odd_length_hex) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -121,7 +121,7 @@ TEST_F(WkbParseTest, parse_linestring_little_endian) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     ASSERT_NE(nullptr, shape);
 }
 
@@ -135,7 +135,8 @@ TEST_F(WkbParseTest, test_byte_order_coverage_multiple_invalid) {
         std::unique_ptr<GeoShape> shape;
         auto status = WkbParse::parse_wkb(ss, shape);
 
-        EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status) << "Failed for byte order prefix: " << prefix;
+        EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status)
+                << "Failed for byte order prefix: " << prefix;
         EXPECT_EQ(nullptr, shape) << "Failed for byte order prefix: " << prefix;
     }
 }
@@ -147,7 +148,7 @@ TEST_F(WkbParseTest, parse_unsupported_geometry_type) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
@@ -158,9 +159,9 @@ TEST_F(WkbParseTest, parse_geometry_with_srid) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     ASSERT_NE(nullptr, shape);
-    EXPECT_EQ(GEO_SHAPE_POINT, shape->type());
+    EXPECT_EQ(GeoShapeType::GEO_SHAPE_POINT, shape->type());
 }
 
 TEST_F(WkbParseTest, parse_polygon_insufficient_points) {
@@ -172,8 +173,8 @@ TEST_F(WkbParseTest, parse_polygon_insufficient_points) {
     std::unique_ptr<GeoShape> shape;
     auto status = WkbParse::parse_wkb(ss, shape);
 
-    EXPECT_EQ(GEO_PARSE_WKB_SYNTAX_ERROR, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_WKB_SYNTAX_ERROR, status);
     EXPECT_EQ(nullptr, shape);
 }
 
-} // namespace doris
\ No newline at end of file
+} // namespace doris
diff --git a/be/test/exprs/function/geo/wkt_parse_test.cpp b/be/test/exprs/function/geo/wkt_parse_test.cpp
index 0de9923f9ba..caa1b2b56c5 100644
--- a/be/test/exprs/function/geo/wkt_parse_test.cpp
+++ b/be/test/exprs/function/geo/wkt_parse_test.cpp
@@ -42,7 +42,7 @@ TEST_F(WktParseTest, normal) {
 
     std::unique_ptr<GeoShape> shape;
     auto status = WktParse::parse_wkt(wkt, strlen(wkt), shape);
-    EXPECT_EQ(GEO_PARSE_OK, status);
+    EXPECT_EQ(GeoParseStatus::GEO_PARSE_OK, status);
     EXPECT_NE(nullptr, shape);
     LOG(INFO) << "parse result: " << shape->to_string();
 }
@@ -52,7 +52,7 @@ TEST_F(WktParseTest, invalid_wkt) {
 
     std::unique_ptr<GeoShape> shape;
     auto status = WktParse::parse_wkt(wkt, strlen(wkt), shape);
-    EXPECT_NE(GEO_PARSE_OK, status);
+    EXPECT_NE(GeoParseStatus::GEO_PARSE_OK, status);
     EXPECT_EQ(nullptr, shape);
 }
 
diff --git a/be/test/exprs/lambda_function/array_map_function_test.cpp b/be/test/exprs/lambda_function/array_map_function_test.cpp
index 137994e06bf..a0f09de3a6f 100644
--- a/be/test/exprs/lambda_function/array_map_function_test.cpp
+++ b/be/test/exprs/lambda_function/array_map_function_test.cpp
@@ -691,7 +691,8 @@ static void open_expr(const VExprSPtr& expr, VExprContext* context) {
     RuntimeState state;
     RowDescriptor row_desc;
     ASSERT_TRUE(expr->prepare(&state, row_desc, context).ok());
-    ASSERT_TRUE(expr->open(&state, context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            expr->open(&state, context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 }
 
 static void open_expr_with_batch_size(const VExprSPtr& expr, VExprContext* context,
@@ -702,7 +703,8 @@ static void open_expr_with_batch_size(const VExprSPtr& expr, VExprContext* conte
     state.set_query_options(query_options);
     RowDescriptor row_desc;
     ASSERT_TRUE(expr->prepare(&state, row_desc, context).ok());
-    ASSERT_TRUE(expr->open(&state, context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            expr->open(&state, context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 }
 
 static void open_expr_with_block_budget(const VExprSPtr& expr, VExprContext* context,
@@ -714,7 +716,8 @@ static void open_expr_with_block_budget(const VExprSPtr& expr, VExprContext* con
     state.set_query_options(query_options);
     RowDescriptor row_desc;
     ASSERT_TRUE(expr->prepare(&state, row_desc, context).ok());
-    ASSERT_TRUE(expr->open(&state, context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            expr->open(&state, context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 }
 
 static const ColumnInt32& get_int_array_values(const ColumnPtr& result) {
@@ -868,12 +871,18 @@ TEST(ArrayEnumerateUniqFunctionTest, MappedAndOriginalNullableArraysUseLogicalRo
     FunctionUtils function_utils(result_type, {nullable_array_int_type, nullable_array_int_type},
                                  false);
     auto* function_context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
     block.insert({nullptr, result_type, "result"});
     status = function->execute(function_context, block, {0, 1}, 2, 2);
-    ASSERT_TRUE(function->close(function_context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
+    ASSERT_TRUE(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
     ASSERT_TRUE(status.ok()) << status.to_string();
 
     const auto& result = assert_cast<const ColumnNullable&>(*block.get_by_position(2).column);
@@ -906,12 +915,18 @@ TEST(ArrayEnumerateUniqFunctionTest, EqualHiddenOffsetsReuseInputOffsets) {
     FunctionUtils function_utils(result_type, {nullable_array_int_type, nullable_array_int_type},
                                  false);
     auto* function_context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
     block.insert({nullptr, result_type, "result"});
     auto status = function->execute(function_context, block, {0, 1}, 2, 2);
-    ASSERT_TRUE(function->close(function_context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
+    ASSERT_TRUE(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
     ASSERT_TRUE(status.ok()) << status.to_string();
 
     const auto& result = assert_cast<const ColumnNullable&>(*block.get_by_position(2).column);
@@ -951,8 +966,11 @@ TEST(ArrayEnumerateUniqFunctionTest, ValidatesLateMismatchBeforeCompacting) {
 
     FunctionUtils function_utils(result_type, {nullable_array_int_type, array_int_type}, false);
     auto* function_context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
     block.insert({nullptr, result_type, "result"});
 
     auto tracker = MemTrackerLimiter::create_shared(MemTrackerLimiter::Type::OTHER,
@@ -964,8 +982,11 @@ TEST(ArrayEnumerateUniqFunctionTest, ValidatesLateMismatchBeforeCompacting) {
     thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
     const int64_t execution_peak = tracker->peak_consumption() - baseline;
 
-    ASSERT_TRUE(function->close(function_context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
+    ASSERT_TRUE(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
     ASSERT_FALSE(status.ok());
     EXPECT_NE(status.to_string().find("must be equal"), std::string::npos) << status;
     EXPECT_LT(execution_peak, max_execution_bytes);
@@ -1003,12 +1024,18 @@ TEST(ArraySortByFunctionTest, MappedAndOriginalNullableArraysUseLogicalRowOffset
     FunctionUtils function_utils(nullable_array_int_type,
                                  {nullable_array_int_type, nullable_array_int_type}, false);
     auto* function_context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
     block.insert({nullptr, nullable_array_int_type, "result"});
     status = function->execute(function_context, block, {0, 1}, 2, 2);
-    ASSERT_TRUE(function->close(function_context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
+    ASSERT_TRUE(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
     ASSERT_TRUE(status.ok()) << status.to_string();
 
     const auto& result = assert_cast<const ColumnNullable&>(*block.get_by_position(2).column);
@@ -1049,16 +1076,22 @@ TEST(ArrayEnumerateUniqFunctionTest, AllNullLaterArgumentSkipsEarlierConstantExp
 
     FunctionUtils function_utils(result_type, {array_int_type, nullable_array_int_type}, false);
     auto* function_context = function_utils.get_fn_ctx();
-    ASSERT_TRUE(function->open(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
-    ASSERT_TRUE(function->open(function_context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            function->open(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
+    ASSERT_TRUE(function->open(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
     block.insert({nullptr, result_type, "result"});
     thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
     const int64_t baseline = tracker->consumption();
     auto status = function->execute(function_context, block, {0, 1}, 2, row_count);
     thread_context()->thread_mem_tracker_mgr->flush_untracked_mem();
     const int64_t execution_peak = tracker->peak_consumption() - baseline;
-    ASSERT_TRUE(function->close(function_context, FunctionContext::THREAD_LOCAL).ok());
-    ASSERT_TRUE(function->close(function_context, FunctionContext::FRAGMENT_LOCAL).ok());
+    ASSERT_TRUE(function->close(function_context, FunctionContext::FunctionStateScope::THREAD_LOCAL)
+                        .ok());
+    ASSERT_TRUE(
+            function->close(function_context, FunctionContext::FunctionStateScope::FRAGMENT_LOCAL)
+                    .ok());
 
     ASSERT_TRUE(status.ok()) << status.to_string();
     EXPECT_TRUE(block.get_by_position(2).column->only_null());
diff --git a/be/test/exprs/vcolumn_ref_test.cpp b/be/test/exprs/vcolumn_ref_test.cpp
index c8eaa609498..84881eb0a04 100644
--- a/be/test/exprs/vcolumn_ref_test.cpp
+++ b/be/test/exprs/vcolumn_ref_test.cpp
@@ -82,7 +82,8 @@ static void open_expr(const VExprSPtr& expr, VExprContext* context) {
     RuntimeState state;
     RowDescriptor row_desc;
     ASSERT_TRUE(expr->prepare(&state, row_desc, context).ok());
-    ASSERT_TRUE(expr->open(&state, context, FunctionContext::THREAD_LOCAL).ok());
+    ASSERT_TRUE(
+            expr->open(&state, context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
 }
 
 static std::vector<int32_t> get_int_values(const ColumnPtr& column) {
diff --git a/be/test/format_v2/expr/delete_predicate_test.cpp b/be/test/format_v2/expr/delete_predicate_test.cpp
index 2f8d4af0f5b..d3db90d698a 100644
--- a/be/test/format_v2/expr/delete_predicate_test.cpp
+++ b/be/test/format_v2/expr/delete_predicate_test.cpp
@@ -184,9 +184,10 @@ TEST_F(DeletePredicateTest, LifecycleAndDebugString) {
     EXPECT_EQ(delete_predicate.expr_name(), "DeletePredicate");
     EXPECT_EQ(delete_predicate.debug_string(), "DeletePredicate");
 
-    status = delete_predicate.open(nullptr, &context, FunctionContext::THREAD_LOCAL);
+    status = delete_predicate.open(nullptr, &context,
+                                   FunctionContext::FunctionStateScope::THREAD_LOCAL);
     ASSERT_TRUE(status.ok()) << status;
-    delete_predicate.close(&context, FunctionContext::THREAD_LOCAL);
+    delete_predicate.close(&context, FunctionContext::FunctionStateScope::THREAD_LOCAL);
 }
 
 } // namespace doris::format
diff --git a/be/test/storage/index/inverted/query/logical/gram/regex_gram_recall_test.cpp b/be/test/storage/index/inverted/query/logical/gram/regex_gram_recall_test.cpp
index fc93b0a9a8a..b4bb3d3ff64 100644
--- a/be/test/storage/index/inverted/query/logical/gram/regex_gram_recall_test.cpp
+++ b/be/test/storage/index/inverted/query/logical/gram/regex_gram_recall_test.cpp
@@ -149,9 +149,10 @@ Status scalar_matches(const std::string& pattern, const std::vector<std::string>
     context->set_constant_cols(constant_columns);
 
     Function function;
-    RETURN_IF_ERROR(function.open(context.get(), FunctionContext::THREAD_LOCAL));
-    const auto* state =
-            static_cast<LikeState*>(context->get_function_state(FunctionContext::THREAD_LOCAL));
+    RETURN_IF_ERROR(
+            function.open(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL));
+    const auto* state = static_cast<LikeState*>(
+            context->get_function_state(FunctionContext::FunctionStateScope::THREAD_LOCAL));
     check_scalar_path(*state, path);
     Block block;
     block.insert({std::move(values), string_type, "value"});
@@ -166,7 +167,7 @@ Status scalar_matches(const std::string& pattern, const std::vector<std::string>
                                                StringRef(pattern), &scalar_result));
         EXPECT_EQ(scalar_result != 0, matches->back()) << "row " << i;
     }
-    return function.close(context.get(), FunctionContext::THREAD_LOCAL);
+    return function.close(context.get(), FunctionContext::FunctionStateScope::THREAD_LOCAL);
 }
 
 // Interpret the public boolean query without reusing its compiler or simplifier.
diff --git a/be/test/testutil/mock/mock_in_expr.cpp b/be/test/testutil/mock/mock_in_expr.cpp
index 44b0aaa58c7..4647b34933c 100644
--- a/be/test/testutil/mock/mock_in_expr.cpp
+++ b/be/test/testutil/mock/mock_in_expr.cpp
@@ -47,7 +47,7 @@ TEST(MockInExprTest, test) {
     {
         auto* state = reinterpret_cast<InState*>(
                 expr_ctx->fn_context(in->fn_context_index())
-                        ->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                        ->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
         state->use_set = true;
         state->hybrid_set.reset(create_set(TYPE_BIGINT, 0, true));
@@ -61,7 +61,7 @@ TEST(MockInExprTest, create_with_ctx) {
 
     auto* state = reinterpret_cast<InState*>(
             expr_ctx->fn_context(pred->fn_context_index())
-                    ->get_function_state(FunctionContext::FRAGMENT_LOCAL));
+                    ->get_function_state(FunctionContext::FunctionStateScope::FRAGMENT_LOCAL));
 
     EXPECT_TRUE(state->use_set);
 }


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