You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by GitBox <gi...@apache.org> on 2022/04/06 03:31:49 UTC

[GitHub] [incubator-doris] HappenLee commented on a diff in pull request #8846: [Vectorized][Function] Support all geolocation functions on vectorized engine

HappenLee commented on code in PR #8846:
URL: https://github.com/apache/incubator-doris/pull/8846#discussion_r843426176


##########
be/src/vec/functions/functions_geo.cpp:
##########
@@ -199,13 +206,338 @@ struct StDistanceSphere {
     }
 };
 
+struct StCircle {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_circle";
+    static const size_t NUM_ARGS = 3;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 3);
+        auto return_type = block.get_data_type(result);
+        auto center_lng = block.get_by_position(arguments[0])
+                                  .column->convert_to_full_column_if_const();
+        auto center_lat = block.get_by_position(arguments[1])
+                                  .column->convert_to_full_column_if_const();
+        auto radius = block.get_by_position(arguments[2])
+                              .column->convert_to_full_column_if_const();
+
+        const auto size = center_lng->size();
+
+        MutableColumnPtr res = nullptr;
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state =
+                (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoCircle circle;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                auto lng_value = center_lng->get_float64(row);
+                auto lat_value = center_lat->get_float64(row);
+                auto radius_value = radius->get_float64(row);
+
+                auto value = circle.init(lng_value, lat_value, radius_value);
+                if (value != GEO_PARSE_OK) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+                buf.clear();
+                circle.encode_to(&buf);
+                res->insert_data(buf.data(), buf.size());
+            }
+            block.replace_by_position(result, std::move(res));
+            return Status::OK();
+        } else {
+            if (state->is_null) {
+                res->insert_data(nullptr, 0);
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            } else {
+                res->insert_data(state->encoded_buf.data(), state->encoded_buf.size());
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            }
+        }
+    }
+
+    static Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+
+        if (!context->is_arg_constant(0) || !context->is_arg_constant(1)
+            || !context->is_arg_constant(2)) {
+            return Status::OK();
+        }
+
+        auto state = new StConstructState();
+        DoubleVal* lng = reinterpret_cast<DoubleVal*>(context->get_constant_arg(0));
+        DoubleVal* lat = reinterpret_cast<DoubleVal*>(context->get_constant_arg(1));
+        DoubleVal* radius = reinterpret_cast<DoubleVal*>(context->get_constant_arg(2));
+        if (lng->is_null || lat->is_null || radius->is_null) {
+            state->is_null = true;
+        } else {
+            std::unique_ptr<GeoCircle> circle(new GeoCircle());
+
+            auto res = circle->init(lng->val, lat->val, radius->val);
+            if (res != GEO_PARSE_OK) {
+                state->is_null = true;
+            } else {
+                circle->encode_to(&state->encoded_buf);
+            }
+        }
+        context->set_function_state(scope, state);
+
+        return Status::OK();
+    }
+
+    static Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+        StConstructState* state = reinterpret_cast<StConstructState*>(
+                context->get_function_state(scope));
+        delete state;
+        return Status::OK();
+    }
+};
+
+struct StContains {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_contains";
+    static const size_t NUM_ARGS = 2;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 2);
+        auto return_type = block.get_data_type(result);
+        auto shape1 = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+        auto shape2 = block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
+
+        const auto size = shape1->size();
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        auto res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StContainsState* state = (StContainsState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state != nullptr && state->is_null) {
+            res->insert_data(nullptr, 0);
+            block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+            return Status::OK();
+        }
+
+        StContainsState local_state;
+        int i;
+        GeoShape* shapes[2] = {nullptr, nullptr};
+        for (int row = 0; row < size; ++row) {
+            if (shape1->is_null_at(row) || shape2->is_null_at(row)) {
+                res->insert_data(nullptr, 0);
+                continue;
+            }
+
+            auto lhs_value = shape1->get_data_at(row);
+            auto rhs_value = shape2->get_data_at(row);
+            StringRef* strs[2] = {&lhs_value, &rhs_value};
+            for (i = 0; i < 2; ++i) {
+                if (state != nullptr && state->shapes[i] != nullptr) {
+                    shapes[i] = state->shapes[i];
+                } else {
+                    shapes[i] = local_state.shapes[i] = GeoShape::from_encoded(strs[i]->data, strs[i]->size);
+                    if (shapes[i] == nullptr) {
+                        res->insert_data(nullptr, 0);
+                        break;
+                    }
+                }
+            }
+
+            if (i == 2) {
+                auto contains_value = shapes[0]->contains(shapes[1]);
+                res->insert_data(const_cast<const char*>((char*)&contains_value), 0);
+            }
+        }
+        block.replace_by_position(result, std::move(res));
+        return Status::OK();
+    }
+
+    static Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+
+        if (!context->is_arg_constant(0) && !context->is_arg_constant(1)) {
+            return Status::OK();
+        }
+
+        auto contains_ctx = new StContainsState();
+        for (int i = 0; !contains_ctx->is_null && i < 2; ++i) {
+            if (context->is_arg_constant(i)) {
+                StringVal* str = reinterpret_cast<StringVal*>(context->get_constant_arg(i));
+                if (str->is_null) {
+                    contains_ctx->is_null = true;
+                } else {
+                    contains_ctx->shapes[i] = GeoShape::from_encoded(str->ptr, str->len);
+                    if (contains_ctx->shapes[i] == nullptr) {
+                        contains_ctx->is_null = true;
+                    }
+                }
+            }
+        }
+
+        context->set_function_state(scope, contains_ctx);
+        return Status::OK();
+    }
+
+    static Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+        StContainsState* state = reinterpret_cast<StContainsState*>(
+                context->get_function_state(scope));
+        delete state;
+        return Status::OK();
+    }
+};
+
+struct StGeometryFromText{
+    static constexpr auto NAME = "st_geometryfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+};
+
+struct StGeomFromText{
+    static constexpr auto NAME = "st_geomfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+};
+
+struct StLineFromText{
+    static constexpr auto NAME = "st_linefromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+};
+
+struct StLineStringFromText{
+    static constexpr auto NAME = "st_linestringfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+};
+
+struct StPolygon{
+    static constexpr auto NAME = "st_polygon";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+struct StPolyFromText{
+    static constexpr auto NAME = "st_polyfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+struct StPolygonFromText{
+    static constexpr auto NAME = "st_polygonfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+template<typename Impl>
+struct StGeoFromText {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = Impl::NAME;
+    static const size_t NUM_ARGS = 1;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 1);
+        auto return_type = block.get_data_type(result);
+        auto geo = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+
+        const auto size = geo->size();
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        auto res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state = (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoParseStatus status;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                if (geo->is_null_at(row)) {

Review Comment:
   why need check null in here ? Null Frameworks should help to do this ?



##########
be/src/vec/functions/functions_geo.cpp:
##########
@@ -199,13 +206,338 @@ struct StDistanceSphere {
     }
 };
 
+struct StCircle {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_circle";
+    static const size_t NUM_ARGS = 3;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 3);
+        auto return_type = block.get_data_type(result);
+        auto center_lng = block.get_by_position(arguments[0])
+                                  .column->convert_to_full_column_if_const();
+        auto center_lat = block.get_by_position(arguments[1])
+                                  .column->convert_to_full_column_if_const();
+        auto radius = block.get_by_position(arguments[2])
+                              .column->convert_to_full_column_if_const();
+
+        const auto size = center_lng->size();
+
+        MutableColumnPtr res = nullptr;
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state =
+                (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoCircle circle;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                auto lng_value = center_lng->get_float64(row);
+                auto lat_value = center_lat->get_float64(row);
+                auto radius_value = radius->get_float64(row);
+
+                auto value = circle.init(lng_value, lat_value, radius_value);
+                if (value != GEO_PARSE_OK) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+                buf.clear();
+                circle.encode_to(&buf);
+                res->insert_data(buf.data(), buf.size());
+            }
+            block.replace_by_position(result, std::move(res));
+            return Status::OK();
+        } else {
+            if (state->is_null) {
+                res->insert_data(nullptr, 0);
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            } else {
+                res->insert_data(state->encoded_buf.data(), state->encoded_buf.size());
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            }
+        }
+    }
+
+    static Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+
+        if (!context->is_arg_constant(0) || !context->is_arg_constant(1)
+            || !context->is_arg_constant(2)) {
+            return Status::OK();
+        }
+
+        auto state = new StConstructState();
+        DoubleVal* lng = reinterpret_cast<DoubleVal*>(context->get_constant_arg(0));
+        DoubleVal* lat = reinterpret_cast<DoubleVal*>(context->get_constant_arg(1));
+        DoubleVal* radius = reinterpret_cast<DoubleVal*>(context->get_constant_arg(2));
+        if (lng->is_null || lat->is_null || radius->is_null) {
+            state->is_null = true;
+        } else {
+            std::unique_ptr<GeoCircle> circle(new GeoCircle());
+
+            auto res = circle->init(lng->val, lat->val, radius->val);
+            if (res != GEO_PARSE_OK) {
+                state->is_null = true;
+            } else {
+                circle->encode_to(&state->encoded_buf);
+            }
+        }
+        context->set_function_state(scope, state);
+
+        return Status::OK();
+    }
+
+    static Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+        StConstructState* state = reinterpret_cast<StConstructState*>(
+                context->get_function_state(scope));
+        delete state;
+        return Status::OK();
+    }
+};
+
+struct StContains {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_contains";
+    static const size_t NUM_ARGS = 2;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 2);
+        auto return_type = block.get_data_type(result);
+        auto shape1 = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+        auto shape2 = block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
+
+        const auto size = shape1->size();
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        auto res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StContainsState* state = (StContainsState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state != nullptr && state->is_null) {
+            res->insert_data(nullptr, 0);
+            block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+            return Status::OK();
+        }
+
+        StContainsState local_state;
+        int i;
+        GeoShape* shapes[2] = {nullptr, nullptr};
+        for (int row = 0; row < size; ++row) {
+            if (shape1->is_null_at(row) || shape2->is_null_at(row)) {

Review Comment:
   why need check null in here ? Null Frameworks should help to do this ?



##########
be/src/vec/functions/functions_geo.cpp:
##########
@@ -199,13 +206,338 @@ struct StDistanceSphere {
     }
 };
 
+struct StCircle {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_circle";
+    static const size_t NUM_ARGS = 3;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 3);
+        auto return_type = block.get_data_type(result);
+        auto center_lng = block.get_by_position(arguments[0])
+                                  .column->convert_to_full_column_if_const();
+        auto center_lat = block.get_by_position(arguments[1])
+                                  .column->convert_to_full_column_if_const();
+        auto radius = block.get_by_position(arguments[2])
+                              .column->convert_to_full_column_if_const();
+
+        const auto size = center_lng->size();
+
+        MutableColumnPtr res = nullptr;
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state =
+                (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoCircle circle;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                auto lng_value = center_lng->get_float64(row);
+                auto lat_value = center_lat->get_float64(row);
+                auto radius_value = radius->get_float64(row);
+
+                auto value = circle.init(lng_value, lat_value, radius_value);
+                if (value != GEO_PARSE_OK) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+                buf.clear();
+                circle.encode_to(&buf);
+                res->insert_data(buf.data(), buf.size());
+            }
+            block.replace_by_position(result, std::move(res));
+            return Status::OK();

Review Comment:
   too many return `OK`



##########
be/src/vec/functions/functions_geo.cpp:
##########
@@ -199,13 +206,338 @@ struct StDistanceSphere {
     }
 };
 
+struct StCircle {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_circle";
+    static const size_t NUM_ARGS = 3;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 3);
+        auto return_type = block.get_data_type(result);
+        auto center_lng = block.get_by_position(arguments[0])
+                                  .column->convert_to_full_column_if_const();
+        auto center_lat = block.get_by_position(arguments[1])
+                                  .column->convert_to_full_column_if_const();
+        auto radius = block.get_by_position(arguments[2])
+                              .column->convert_to_full_column_if_const();
+
+        const auto size = center_lng->size();
+
+        MutableColumnPtr res = nullptr;
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state =
+                (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoCircle circle;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                auto lng_value = center_lng->get_float64(row);
+                auto lat_value = center_lat->get_float64(row);
+                auto radius_value = radius->get_float64(row);
+
+                auto value = circle.init(lng_value, lat_value, radius_value);
+                if (value != GEO_PARSE_OK) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+                buf.clear();
+                circle.encode_to(&buf);
+                res->insert_data(buf.data(), buf.size());
+            }
+            block.replace_by_position(result, std::move(res));
+            return Status::OK();
+        } else {
+            if (state->is_null) {
+                res->insert_data(nullptr, 0);
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            } else {
+                res->insert_data(state->encoded_buf.data(), state->encoded_buf.size());
+                block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+                return Status::OK();
+            }
+        }
+    }
+
+    static Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+
+        if (!context->is_arg_constant(0) || !context->is_arg_constant(1)
+            || !context->is_arg_constant(2)) {
+            return Status::OK();
+        }
+
+        auto state = new StConstructState();
+        DoubleVal* lng = reinterpret_cast<DoubleVal*>(context->get_constant_arg(0));
+        DoubleVal* lat = reinterpret_cast<DoubleVal*>(context->get_constant_arg(1));
+        DoubleVal* radius = reinterpret_cast<DoubleVal*>(context->get_constant_arg(2));
+        if (lng->is_null || lat->is_null || radius->is_null) {
+            state->is_null = true;
+        } else {
+            std::unique_ptr<GeoCircle> circle(new GeoCircle());
+
+            auto res = circle->init(lng->val, lat->val, radius->val);
+            if (res != GEO_PARSE_OK) {
+                state->is_null = true;
+            } else {
+                circle->encode_to(&state->encoded_buf);
+            }
+        }
+        context->set_function_state(scope, state);
+
+        return Status::OK();
+    }
+
+    static Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+        StConstructState* state = reinterpret_cast<StConstructState*>(
+                context->get_function_state(scope));
+        delete state;
+        return Status::OK();
+    }
+};
+
+struct StContains {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = "st_contains";
+    static const size_t NUM_ARGS = 2;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 2);
+        auto return_type = block.get_data_type(result);
+        auto shape1 = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+        auto shape2 = block.get_by_position(arguments[1]).column->convert_to_full_column_if_const();
+
+        const auto size = shape1->size();
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        auto res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StContainsState* state = (StContainsState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state != nullptr && state->is_null) {
+            res->insert_data(nullptr, 0);
+            block.replace_by_position(result, ColumnConst::create(std::move(res), size));
+            return Status::OK();
+        }
+
+        StContainsState local_state;
+        int i;
+        GeoShape* shapes[2] = {nullptr, nullptr};
+        for (int row = 0; row < size; ++row) {
+            if (shape1->is_null_at(row) || shape2->is_null_at(row)) {
+                res->insert_data(nullptr, 0);
+                continue;
+            }
+
+            auto lhs_value = shape1->get_data_at(row);
+            auto rhs_value = shape2->get_data_at(row);
+            StringRef* strs[2] = {&lhs_value, &rhs_value};
+            for (i = 0; i < 2; ++i) {
+                if (state != nullptr && state->shapes[i] != nullptr) {
+                    shapes[i] = state->shapes[i];
+                } else {
+                    shapes[i] = local_state.shapes[i] = GeoShape::from_encoded(strs[i]->data, strs[i]->size);
+                    if (shapes[i] == nullptr) {
+                        res->insert_data(nullptr, 0);
+                        break;
+                    }
+                }
+            }
+
+            if (i == 2) {
+                auto contains_value = shapes[0]->contains(shapes[1]);
+                res->insert_data(const_cast<const char*>((char*)&contains_value), 0);
+            }
+        }
+        block.replace_by_position(result, std::move(res));
+        return Status::OK();
+    }
+
+    static Status prepare(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+
+        if (!context->is_arg_constant(0) && !context->is_arg_constant(1)) {
+            return Status::OK();
+        }
+
+        auto contains_ctx = new StContainsState();
+        for (int i = 0; !contains_ctx->is_null && i < 2; ++i) {
+            if (context->is_arg_constant(i)) {
+                StringVal* str = reinterpret_cast<StringVal*>(context->get_constant_arg(i));
+                if (str->is_null) {
+                    contains_ctx->is_null = true;
+                } else {
+                    contains_ctx->shapes[i] = GeoShape::from_encoded(str->ptr, str->len);
+                    if (contains_ctx->shapes[i] == nullptr) {
+                        contains_ctx->is_null = true;
+                    }
+                }
+            }
+        }
+
+        context->set_function_state(scope, contains_ctx);
+        return Status::OK();
+    }
+
+    static Status close(FunctionContext* context, FunctionContext::FunctionStateScope scope) {
+        if (scope != FunctionContext::FRAGMENT_LOCAL) {
+            return Status::OK();
+        }
+        StContainsState* state = reinterpret_cast<StContainsState*>(
+                context->get_function_state(scope));
+        delete state;
+        return Status::OK();
+    }
+};
+
+struct StGeometryFromText{
+    static constexpr auto NAME = "st_geometryfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+};
+
+struct StGeomFromText{
+    static constexpr auto NAME = "st_geomfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_ANY;
+};
+
+struct StLineFromText{
+    static constexpr auto NAME = "st_linefromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+};
+
+struct StLineStringFromText{
+    static constexpr auto NAME = "st_linestringfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_LINE_STRING;
+};
+
+struct StPolygon{
+    static constexpr auto NAME = "st_polygon";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+struct StPolyFromText{
+    static constexpr auto NAME = "st_polyfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+struct StPolygonFromText{
+    static constexpr auto NAME = "st_polygonfromtext";
+    static constexpr GeoShapeType shape_type = GEO_SHAPE_POLYGON;
+};
+
+template<typename Impl>
+struct StGeoFromText {
+    static constexpr auto NEED_CONTEXT = true;
+    static constexpr auto NAME = Impl::NAME;
+    static const size_t NUM_ARGS = 1;
+    static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
+                          size_t result) {
+        DCHECK_EQ(arguments.size(), 1);
+        auto return_type = block.get_data_type(result);
+        auto geo = block.get_by_position(arguments[0]).column->convert_to_full_column_if_const();
+
+        const auto size = geo->size();
+        auto null_type = std::reinterpret_pointer_cast<const DataTypeNullable>(return_type);
+        auto res = ColumnNullable::create(return_type->create_column(), ColumnUInt8::create());
+
+        StConstructState* state = (StConstructState*) context->get_function_state(FunctionContext::FRAGMENT_LOCAL);
+        if (state == nullptr) {
+            GeoParseStatus status;
+            std::string buf;
+            for (int row = 0; row < size; ++row) {
+                if (geo->is_null_at(row)) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+
+                auto value = geo->get_data_at(row);
+                std::unique_ptr<GeoShape> 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)) {
+                    res->insert_data(nullptr, 0);
+                    continue;
+                }
+                buf.clear();
+                shape->encode_to(&buf);
+                res->insert_data(buf.data(), buf.size());
+            }
+            block.replace_by_position(result, std::move(res));
+            return Status::OK();

Review Comment:
   here to many `return Status::OK();` should be only one out of `if`



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


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