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

xuyang pushed a commit to branch struct-type
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/struct-type by this push:
     new cd5a6b0895 [fix](complex_type) fix clone_type_info function return 
default scalar type (#16400)
cd5a6b0895 is described below

commit cd5a6b0895cfb248b6451fc4b84027955b716f83
Author: amory <wangqian...@selectdb.com>
AuthorDate: Mon Feb 6 10:50:46 2023 +0800

    [fix](complex_type) fix clone_type_info function return default scalar type 
(#16400)
---
 be/src/olap/types.cpp      |  11 +-
 be/src/runtime/types.cpp   | 114 +++++++--------
 be/src/vec/exprs/vexpr.cpp | 337 ++++++++++++++++++++++-----------------------
 3 files changed, 231 insertions(+), 231 deletions(-)

diff --git a/be/src/olap/types.cpp b/be/src/olap/types.cpp
index bee790e066..0ccf4b98b1 100644
--- a/be/src/olap/types.cpp
+++ b/be/src/olap/types.cpp
@@ -262,14 +262,13 @@ TypeInfoPtr get_type_info(const TabletColumn* col) {
 }
 
 TypeInfoPtr clone_type_info(const TypeInfo* type_info) {
-    if (is_scalar_type(type_info->type())) {
-        return create_static_type_info_ptr(type_info);
-    } else if (type_info->type() == OLAP_FIELD_TYPE_MAP) {
+    auto type = type_info->type();
+    if (UNLIKELY(type == OLAP_FIELD_TYPE_MAP)) {
         const auto map_type_info = dynamic_cast<const MapTypeInfo*>(type_info);
         return create_dynamic_type_info_ptr(
                 new 
MapTypeInfo(clone_type_info(map_type_info->get_key_type_info()),
                                 
clone_type_info(map_type_info->get_value_type_info())));
-    } else if (type_info->type() == OLAP_FIELD_TYPE_STRUCT) {
+    } else if (UNLIKELY(type == OLAP_FIELD_TYPE_STRUCT)) {
         const auto struct_type_info = dynamic_cast<const 
StructTypeInfo*>(type_info);
         std::vector<TypeInfoPtr> clone_type_infos;
         const std::vector<TypeInfoPtr>* sub_type_infos = 
struct_type_info->type_infos();
@@ -278,10 +277,12 @@ TypeInfoPtr clone_type_info(const TypeInfo* type_info) {
             
clone_type_infos.push_back(clone_type_info((*sub_type_infos)[i].get()));
         }
         return create_dynamic_type_info_ptr(new 
StructTypeInfo(clone_type_infos));
-    } else if (type_info->type() == OLAP_FIELD_TYPE_ARRAY) {
+    } else if (UNLIKELY(type == OLAP_FIELD_TYPE_ARRAY)) {
         const auto array_type_info = dynamic_cast<const 
ArrayTypeInfo*>(type_info);
         return create_dynamic_type_info_ptr(
                 new 
ArrayTypeInfo(clone_type_info(array_type_info->item_type_info())));
+    } else {
+        return create_static_type_info_ptr(type_info);
     }
 }
 
diff --git a/be/src/runtime/types.cpp b/be/src/runtime/types.cpp
index 2945bfd33f..002fe1ed07 100644
--- a/be/src/runtime/types.cpp
+++ b/be/src/runtime/types.cpp
@@ -252,67 +252,67 @@ TypeDescriptor::TypeDescriptor(const 
google::protobuf::RepeatedPtrField<PTypeNod
     default:
         DCHECK(false) << node.type();
     }
-    }
+}
 
-    std::string TypeDescriptor::debug_string() const {
-        std::stringstream ss;
-        switch (type) {
-        case TYPE_CHAR:
-            ss << "CHAR(" << len << ")";
-            return ss.str();
-        case TYPE_DECIMALV2:
-            ss << "DECIMALV2(" << precision << ", " << scale << ")";
-            return ss.str();
-        case TYPE_DECIMAL32:
-            ss << "DECIMAL32(" << precision << ", " << scale << ")";
-            return ss.str();
-        case TYPE_DECIMAL64:
-            ss << "DECIMAL64(" << precision << ", " << scale << ")";
-            return ss.str();
-        case TYPE_DECIMAL128I:
-            ss << "DECIMAL128(" << precision << ", " << scale << ")";
-            return ss.str();
-        case TYPE_ARRAY: {
-            ss << "ARRAY<" << children[0].debug_string() << ">";
-            return ss.str();
-        }
-        case TYPE_MAP:
-            ss << "MAP<" << children[0].debug_string() << ", " << 
children[1].debug_string() << ">";
-            return ss.str();
-        case TYPE_STRUCT: {
-            ss << "STRUCT<";
-            for (size_t i = 0; i < children.size(); i++) {
-                ss << field_names[i];
-                ss << ":";
-                ss << children[i].debug_string();
-                if (i != children.size() - 1) {
-                    ss << ",";
-                }
+std::string TypeDescriptor::debug_string() const {
+    std::stringstream ss;
+    switch (type) {
+    case TYPE_CHAR:
+        ss << "CHAR(" << len << ")";
+        return ss.str();
+    case TYPE_DECIMALV2:
+        ss << "DECIMALV2(" << precision << ", " << scale << ")";
+        return ss.str();
+    case TYPE_DECIMAL32:
+        ss << "DECIMAL32(" << precision << ", " << scale << ")";
+        return ss.str();
+    case TYPE_DECIMAL64:
+        ss << "DECIMAL64(" << precision << ", " << scale << ")";
+        return ss.str();
+    case TYPE_DECIMAL128I:
+        ss << "DECIMAL128(" << precision << ", " << scale << ")";
+        return ss.str();
+    case TYPE_ARRAY: {
+        ss << "ARRAY<" << children[0].debug_string() << ">";
+        return ss.str();
+    }
+    case TYPE_MAP:
+        ss << "MAP<" << children[0].debug_string() << ", " << 
children[1].debug_string() << ">";
+        return ss.str();
+    case TYPE_STRUCT: {
+        ss << "STRUCT<";
+        for (size_t i = 0; i < children.size(); i++) {
+            ss << field_names[i];
+            ss << ":";
+            ss << children[i].debug_string();
+            if (i != children.size() - 1) {
+                ss << ",";
             }
-            ss << ">";
-            return ss.str();
-        }
-        default:
-            return type_to_string(type);
         }
+        ss << ">";
+        return ss.str();
     }
-
-    std::ostream& operator<<(std::ostream& os, const TypeDescriptor& type) {
-        os << type.debug_string();
-        return os;
+    default:
+        return type_to_string(type);
     }
+}
 
-    TTypeDesc create_type_desc(PrimitiveType type, int precision, int scale) {
-        TTypeDesc type_desc;
-        std::vector<TTypeNode> node_type;
-        node_type.emplace_back();
-        TScalarType scalarType;
-        scalarType.__set_type(to_thrift(type));
-        scalarType.__set_len(-1);
-        scalarType.__set_precision(precision);
-        scalarType.__set_scale(scale);
-        node_type.back().__set_scalar_type(scalarType);
-        type_desc.__set_types(node_type);
-        return type_desc;
-    }
+std::ostream& operator<<(std::ostream& os, const TypeDescriptor& type) {
+    os << type.debug_string();
+    return os;
+}
+
+TTypeDesc create_type_desc(PrimitiveType type, int precision, int scale) {
+    TTypeDesc type_desc;
+    std::vector<TTypeNode> node_type;
+    node_type.emplace_back();
+    TScalarType scalarType;
+    scalarType.__set_type(to_thrift(type));
+    scalarType.__set_len(-1);
+    scalarType.__set_precision(precision);
+    scalarType.__set_scale(scale);
+    node_type.back().__set_scalar_type(scalarType);
+    type_desc.__set_types(node_type);
+    return type_desc;
+}
 } // namespace doris
diff --git a/be/src/vec/exprs/vexpr.cpp b/be/src/vec/exprs/vexpr.cpp
index b9a3a80c74..9969e4b568 100644
--- a/be/src/vec/exprs/vexpr.cpp
+++ b/be/src/vec/exprs/vexpr.cpp
@@ -175,220 +175,219 @@ Status VExpr::create_expr(doris::ObjectPool* pool, 
const doris::TExprNode& texpr
     default:
         return Status::InternalError("Unknown expr node type: {}", 
texpr_node.node_type);
     }
-        return Status::OK();
-    }
+    return Status::OK();
+}
 
-    Status VExpr::create_tree_from_thrift(doris::ObjectPool * pool,
-                                          const std::vector<doris::TExprNode>& 
nodes, VExpr* parent,
-                                          int* node_idx, VExpr** root_expr, 
VExprContext** ctx) {
-        // propagate error case
+Status VExpr::create_tree_from_thrift(doris::ObjectPool* pool,
+                                      const std::vector<doris::TExprNode>& 
nodes, VExpr* parent,
+                                      int* node_idx, VExpr** root_expr, 
VExprContext** ctx) {
+    // propagate error case
+    if (*node_idx >= nodes.size()) {
+        return Status::InternalError("Failed to reconstruct expression tree 
from thrift.");
+    }
+    int num_children = nodes[*node_idx].num_children;
+    VExpr* expr = nullptr;
+    RETURN_IF_ERROR(create_expr(pool, nodes[*node_idx], &expr));
+    DCHECK(expr != nullptr);
+    if (parent != nullptr) {
+        parent->add_child(expr);
+    } else {
+        DCHECK(root_expr != nullptr);
+        DCHECK(ctx != nullptr);
+        *root_expr = expr;
+        *ctx = pool->add(new VExprContext(expr));
+    }
+    for (int i = 0; i < num_children; i++) {
+        *node_idx += 1;
+        RETURN_IF_ERROR(create_tree_from_thrift(pool, nodes, expr, node_idx, 
nullptr, nullptr));
+        // we are expecting a child, but have used all nodes
+        // this means we have been given a bad tree and must fail
         if (*node_idx >= nodes.size()) {
             return Status::InternalError("Failed to reconstruct expression 
tree from thrift.");
         }
-        int num_children = nodes[*node_idx].num_children;
-        VExpr* expr = nullptr;
-        RETURN_IF_ERROR(create_expr(pool, nodes[*node_idx], &expr));
-        DCHECK(expr != nullptr);
-        if (parent != nullptr) {
-            parent->add_child(expr);
-        } else {
-            DCHECK(root_expr != nullptr);
-            DCHECK(ctx != nullptr);
-            *root_expr = expr;
-            *ctx = pool->add(new VExprContext(expr));
-        }
-        for (int i = 0; i < num_children; i++) {
-            *node_idx += 1;
-            RETURN_IF_ERROR(create_tree_from_thrift(pool, nodes, expr, 
node_idx, nullptr, nullptr));
-            // we are expecting a child, but have used all nodes
-            // this means we have been given a bad tree and must fail
-            if (*node_idx >= nodes.size()) {
-                return Status::InternalError("Failed to reconstruct expression 
tree from thrift.");
-            }
-        }
-        return Status::OK();
     }
+    return Status::OK();
+}
 
-    Status VExpr::create_expr_tree(doris::ObjectPool * pool, const 
doris::TExpr& texpr,
-                                   VExprContext** ctx) {
-        if (texpr.nodes.size() == 0) {
-            *ctx = nullptr;
-            return Status::OK();
-        }
-        int node_idx = 0;
-        VExpr* e = nullptr;
-        Status status = create_tree_from_thrift(pool, texpr.nodes, nullptr, 
&node_idx, &e, ctx);
-        if (status.ok() && node_idx + 1 != texpr.nodes.size()) {
-            status = Status::InternalError(
-                    "Expression tree only partially reconstructed. Not all 
thrift nodes were "
-                    "used.");
-        }
-        if (!status.ok()) {
-            LOG(ERROR) << "Could not construct expr tree.\n"
-                       << status << "\n"
-                       << apache::thrift::ThriftDebugString(texpr);
-        }
-        return status;
+Status VExpr::create_expr_tree(doris::ObjectPool* pool, const doris::TExpr& 
texpr,
+                               VExprContext** ctx) {
+    if (texpr.nodes.size() == 0) {
+        *ctx = nullptr;
+        return Status::OK();
     }
+    int node_idx = 0;
+    VExpr* e = nullptr;
+    Status status = create_tree_from_thrift(pool, texpr.nodes, nullptr, 
&node_idx, &e, ctx);
+    if (status.ok() && node_idx + 1 != texpr.nodes.size()) {
+        status = Status::InternalError(
+                "Expression tree only partially reconstructed. Not all thrift 
nodes were "
+                "used.");
+    }
+    if (!status.ok()) {
+        LOG(ERROR) << "Could not construct expr tree.\n"
+                   << status << "\n"
+                   << apache::thrift::ThriftDebugString(texpr);
+    }
+    return status;
+}
 
-    Status VExpr::create_expr_trees(ObjectPool * pool, const 
std::vector<doris::TExpr>& texprs,
-                                    std::vector<VExprContext*>* ctxs) {
-        ctxs->clear();
-        for (int i = 0; i < texprs.size(); ++i) {
-            VExprContext* ctx = nullptr;
-            RETURN_IF_ERROR(create_expr_tree(pool, texprs[i], &ctx));
-            ctxs->push_back(ctx);
-        }
-        return Status::OK();
+Status VExpr::create_expr_trees(ObjectPool* pool, const 
std::vector<doris::TExpr>& texprs,
+                                std::vector<VExprContext*>* ctxs) {
+    ctxs->clear();
+    for (int i = 0; i < texprs.size(); ++i) {
+        VExprContext* ctx = nullptr;
+        RETURN_IF_ERROR(create_expr_tree(pool, texprs[i], &ctx));
+        ctxs->push_back(ctx);
     }
+    return Status::OK();
+}
 
-    Status VExpr::prepare(const std::vector<VExprContext*>& ctxs, 
RuntimeState* state,
-                          const RowDescriptor& row_desc) {
-        for (auto ctx : ctxs) {
-            RETURN_IF_ERROR(ctx->prepare(state, row_desc));
-        }
-        return Status::OK();
+Status VExpr::prepare(const std::vector<VExprContext*>& ctxs, RuntimeState* 
state,
+                      const RowDescriptor& row_desc) {
+    for (auto ctx : ctxs) {
+        RETURN_IF_ERROR(ctx->prepare(state, row_desc));
     }
+    return Status::OK();
+}
 
-    void VExpr::close(const std::vector<VExprContext*>& ctxs, RuntimeState* 
state) {
-        for (auto ctx : ctxs) {
-            ctx->close(state);
-        }
+void VExpr::close(const std::vector<VExprContext*>& ctxs, RuntimeState* state) 
{
+    for (auto ctx : ctxs) {
+        ctx->close(state);
     }
+}
 
-    Status VExpr::open(const std::vector<VExprContext*>& ctxs, RuntimeState* 
state) {
-        for (int i = 0; i < ctxs.size(); ++i) {
-            RETURN_IF_ERROR(ctxs[i]->open(state));
-        }
-        return Status::OK();
+Status VExpr::open(const std::vector<VExprContext*>& ctxs, RuntimeState* 
state) {
+    for (int i = 0; i < ctxs.size(); ++i) {
+        RETURN_IF_ERROR(ctxs[i]->open(state));
     }
+    return Status::OK();
+}
 
-    Status VExpr::clone_if_not_exists(const std::vector<VExprContext*>& ctxs, 
RuntimeState* state,
-                                      std::vector<VExprContext*>* new_ctxs) {
-        DCHECK(new_ctxs != nullptr);
-        if (!new_ctxs->empty()) {
-            // 'ctxs' was already cloned into '*new_ctxs', nothing to do.
-            DCHECK_EQ(new_ctxs->size(), ctxs.size());
-            for (int i = 0; i < new_ctxs->size(); ++i) {
-                DCHECK((*new_ctxs)[i]->_is_clone);
-            }
-            return Status::OK();
-        }
-        new_ctxs->resize(ctxs.size());
-        for (int i = 0; i < ctxs.size(); ++i) {
-            RETURN_IF_ERROR(ctxs[i]->clone(state, &(*new_ctxs)[i]));
+Status VExpr::clone_if_not_exists(const std::vector<VExprContext*>& ctxs, 
RuntimeState* state,
+                                  std::vector<VExprContext*>* new_ctxs) {
+    DCHECK(new_ctxs != nullptr);
+    if (!new_ctxs->empty()) {
+        // 'ctxs' was already cloned into '*new_ctxs', nothing to do.
+        DCHECK_EQ(new_ctxs->size(), ctxs.size());
+        for (int i = 0; i < new_ctxs->size(); ++i) {
+            DCHECK((*new_ctxs)[i]->_is_clone);
         }
         return Status::OK();
     }
-    std::string VExpr::debug_string() const {
-        // TODO: implement partial debug string for member vars
-        std::stringstream out;
-        out << " type=" << _type.debug_string();
-        out << " codegen="
-            << "false";
-
-        if (!_children.empty()) {
-            out << " children=" << debug_string(_children);
-        }
+    new_ctxs->resize(ctxs.size());
+    for (int i = 0; i < ctxs.size(); ++i) {
+        RETURN_IF_ERROR(ctxs[i]->clone(state, &(*new_ctxs)[i]));
+    }
+    return Status::OK();
+}
+std::string VExpr::debug_string() const {
+    // TODO: implement partial debug string for member vars
+    std::stringstream out;
+    out << " type=" << _type.debug_string();
+    out << " codegen="
+        << "false";
 
-        return out.str();
+    if (!_children.empty()) {
+        out << " children=" << debug_string(_children);
     }
 
-    std::string VExpr::debug_string(const std::vector<VExpr*>& exprs) {
-        std::stringstream out;
-        out << "[";
+    return out.str();
+}
 
-        for (int i = 0; i < exprs.size(); ++i) {
-            out << (i == 0 ? "" : " ") << exprs[i]->debug_string();
-        }
+std::string VExpr::debug_string(const std::vector<VExpr*>& exprs) {
+    std::stringstream out;
+    out << "[";
 
-        out << "]";
-        return out.str();
+    for (int i = 0; i < exprs.size(); ++i) {
+        out << (i == 0 ? "" : " ") << exprs[i]->debug_string();
     }
 
-    std::string VExpr::debug_string(const std::vector<VExprContext*>& ctxs) {
-        std::vector<VExpr*> exprs;
-        for (int i = 0; i < ctxs.size(); ++i) {
-            exprs.push_back(ctxs[i]->root());
-        }
-        return debug_string(exprs);
+    out << "]";
+    return out.str();
+}
+
+std::string VExpr::debug_string(const std::vector<VExprContext*>& ctxs) {
+    std::vector<VExpr*> exprs;
+    for (int i = 0; i < ctxs.size(); ++i) {
+        exprs.push_back(ctxs[i]->root());
     }
+    return debug_string(exprs);
+}
 
-    bool VExpr::is_constant() const {
-        for (int i = 0; i < _children.size(); ++i) {
-            if (!_children[i]->is_constant()) {
-                return false;
-            }
+bool VExpr::is_constant() const {
+    for (int i = 0; i < _children.size(); ++i) {
+        if (!_children[i]->is_constant()) {
+            return false;
         }
-
-        return true;
     }
 
-    Status VExpr::get_const_col(VExprContext * context, ColumnPtrWrapper * 
*output) {
-        *output = nullptr;
-        if (!is_constant()) {
-            return Status::OK();
-        }
+    return true;
+}
 
-        if (_constant_col != nullptr) {
-            *output = _constant_col.get();
-            return Status::OK();
-        }
+Status VExpr::get_const_col(VExprContext* context, ColumnPtrWrapper** output) {
+    *output = nullptr;
+    if (!is_constant()) {
+        return Status::OK();
+    }
 
-        int result = -1;
-        Block block;
-        // If block is empty, some functions will produce no result. So we 
insert a column with
-        // single value here.
-        block.insert({ColumnUInt8::create(1), 
std::make_shared<DataTypeUInt8>(), ""});
-        RETURN_IF_ERROR(execute(context, &block, &result));
-        DCHECK(result != -1);
-        const auto& column = block.get_by_position(result).column;
-        _constant_col = std::make_shared<ColumnPtrWrapper>(column);
+    if (_constant_col != nullptr) {
         *output = _constant_col.get();
         return Status::OK();
     }
 
-    void VExpr::register_function_context(doris::RuntimeState * state, 
VExprContext * context) {
-        FunctionContext::TypeDesc return_type = 
AnyValUtil::column_type_to_type_desc(_type);
-        std::vector<FunctionContext::TypeDesc> arg_types;
-        for (int i = 0; i < _children.size(); ++i) {
-            
arg_types.push_back(AnyValUtil::column_type_to_type_desc(_children[i]->type()));
-        }
+    int result = -1;
+    Block block;
+    // If block is empty, some functions will produce no result. So we insert 
a column with
+    // single value here.
+    block.insert({ColumnUInt8::create(1), std::make_shared<DataTypeUInt8>(), 
""});
+    RETURN_IF_ERROR(execute(context, &block, &result));
+    DCHECK(result != -1);
+    const auto& column = block.get_by_position(result).column;
+    _constant_col = std::make_shared<ColumnPtrWrapper>(column);
+    *output = _constant_col.get();
+    return Status::OK();
+}
 
-        _fn_context_index = context->register_func(state, return_type, 
arg_types, 0);
+void VExpr::register_function_context(doris::RuntimeState* state, 
VExprContext* context) {
+    FunctionContext::TypeDesc return_type = 
AnyValUtil::column_type_to_type_desc(_type);
+    std::vector<FunctionContext::TypeDesc> arg_types;
+    for (int i = 0; i < _children.size(); ++i) {
+        
arg_types.push_back(AnyValUtil::column_type_to_type_desc(_children[i]->type()));
     }
 
-    Status VExpr::init_function_context(VExprContext * context,
-                                        FunctionContext::FunctionStateScope 
scope,
-                                        const FunctionBasePtr& function) const 
{
-        FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
-        if (scope == FunctionContext::FRAGMENT_LOCAL) {
-            std::vector<ColumnPtrWrapper*> constant_cols;
-            for (auto c : _children) {
-                ColumnPtrWrapper* const_col_wrapper = nullptr;
-                RETURN_IF_ERROR(c->get_const_col(context, &const_col_wrapper));
-                constant_cols.push_back(const_col_wrapper);
-            }
-            fn_ctx->impl()->set_constant_cols(constant_cols);
-        }
+    _fn_context_index = context->register_func(state, return_type, arg_types, 
0);
+}
 
-        if (scope == FunctionContext::FRAGMENT_LOCAL) {
-            RETURN_IF_ERROR(function->prepare(fn_ctx, 
FunctionContext::FRAGMENT_LOCAL));
+Status VExpr::init_function_context(VExprContext* context,
+                                    FunctionContext::FunctionStateScope scope,
+                                    const FunctionBasePtr& function) const {
+    FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
+    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+        std::vector<ColumnPtrWrapper*> constant_cols;
+        for (auto c : _children) {
+            ColumnPtrWrapper* const_col_wrapper = nullptr;
+            RETURN_IF_ERROR(c->get_const_col(context, &const_col_wrapper));
+            constant_cols.push_back(const_col_wrapper);
         }
-        RETURN_IF_ERROR(function->prepare(fn_ctx, 
FunctionContext::THREAD_LOCAL));
-        return Status::OK();
+        fn_ctx->impl()->set_constant_cols(constant_cols);
+    }
+
+    if (scope == FunctionContext::FRAGMENT_LOCAL) {
+        RETURN_IF_ERROR(function->prepare(fn_ctx, 
FunctionContext::FRAGMENT_LOCAL));
     }
+    RETURN_IF_ERROR(function->prepare(fn_ctx, FunctionContext::THREAD_LOCAL));
+    return Status::OK();
+}
 
-    void VExpr::close_function_context(VExprContext * context,
-                                       FunctionContext::FunctionStateScope 
scope,
-                                       const FunctionBasePtr& function) const {
-        if (_fn_context_index != -1 && !context->_stale) {
-            FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
-            function->close(fn_ctx, FunctionContext::THREAD_LOCAL);
-            if (scope == FunctionContext::FRAGMENT_LOCAL) {
-                function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
-            }
+void VExpr::close_function_context(VExprContext* context, 
FunctionContext::FunctionStateScope scope,
+                                   const FunctionBasePtr& function) const {
+    if (_fn_context_index != -1 && !context->_stale) {
+        FunctionContext* fn_ctx = context->fn_context(_fn_context_index);
+        function->close(fn_ctx, FunctionContext::THREAD_LOCAL);
+        if (scope == FunctionContext::FRAGMENT_LOCAL) {
+            function->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL);
         }
     }
+}
 
 } // namespace doris::vectorized


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

Reply via email to